10 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/8dbde0261fda/ changeset: 8dbde0261fda user: james_taylor date: 2012-09-24 19:09:50 summary: Moving main webapp out of framework directory affected #: 103 files Diff too large to display. https://bitbucket.org/galaxy/galaxy-central/changeset/14878d0d6389/ changeset: 14878d0d6389 user: james_taylor date: 2012-09-24 19:27:30 summary: Extracting add ui/api controllers methods up to the framework level affected #: 2 files diff -r 8dbde0261fda8d5b955527c76043e9efc4a7aec6 -r 14878d0d63898409799c929460366e2ef46fd505 lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -6,6 +6,12 @@ import os, sys, time, socket, random, string import inspect + +from galaxy.web.base.controller import BaseUIController +from galaxy.web.base.controller import BaseAPIController +from galaxy.web.base.controller import ControllerUnavailable + + pkg_resources.require( "Cheetah" ) from Cheetah.Template import Template import base @@ -212,6 +218,7 @@ return FormBuilder( *args, **kwargs ) class WebApplication( base.WebApplication ): + def __init__( self, galaxy_app, session_cookie='galaxysession' ): base.WebApplication.__init__( self ) self.set_transaction_factory( lambda e: self.transaction_chooser( e, galaxy_app, session_cookie ) ) @@ -223,19 +230,70 @@ output_encoding = 'utf-8' ) # Security helper self.security = galaxy_app.security + def handle_controller_exception( self, e, trans, **kwargs ): + if isinstance( e, MessageException ): return trans.show_message( e.err_msg, e.type ) def make_body_iterable( self, trans, body ): + if isinstance( body, FormBuilder ): body = trans.show_form( body ) return base.WebApplication.make_body_iterable( self, trans, body ) + def transaction_chooser( self, environ, galaxy_app, session_cookie ): if 'is_api_request' in environ: return GalaxyWebAPITransaction( environ, galaxy_app, self, session_cookie ) else: return GalaxyWebUITransaction( environ, galaxy_app, self, session_cookie ) + def add_ui_controllers( self, app, package_name ): + """ + Search for UI controllers in `package_name` and add + them to the webapp. + """ + package = __import__( package_name ) + controller_dir = package.__path__[0] + for fname in os.listdir( controller_dir ): + if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ): + name = fname[:-3] + module_name = package_name + "." + name + try: + module = __import__( module_name ) + except ControllerUnavailable, exc: + log.debug("%s could not be loaded: %s" % (module_name, str(exc))) + continue + for comp in module_name.split( "." )[1:]: + module = getattr( module, comp ) + # Look for a controller inside the modules + for key in dir( module ): + T = getattr( module, key ) + if inspect.isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ): + self.add_ui_controller( name, T( app ) ) + + def add_api_controllers( self, app, package_name ): + """ + Search for UI controllers in `package_name` and add + them to the webapp. + """ + package = __import__( package_name ) + controller_dir = package.__path__[0] + for fname in os.listdir( controller_dir ): + if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ): + name = fname[:-3] + module_name = package_name + "." + name + try: + module = __import__( module_name ) + except ControllerUnavailable, exc: + log.debug("%s could not be loaded: %s" % (module_name, str(exc))) + continue + for comp in module_name.split( "." )[1:]: + module = getattr( module, comp ) + for key in dir( module ): + T = getattr( module, key ) + if inspect.isclass( T ) and T is not BaseAPIController and issubclass( T, BaseAPIController ): + self.add_api_controller( name, T( app ) ) + class GalaxyWebTransaction( base.DefaultWebTransaction ): """ Encapsulates web transaction specific state for the Galaxy application diff -r 8dbde0261fda8d5b955527c76043e9efc4a7aec6 -r 14878d0d63898409799c929460366e2ef46fd505 lib/galaxy/webapps/main/buildapp.py --- a/lib/galaxy/webapps/main/buildapp.py +++ b/lib/galaxy/webapps/main/buildapp.py @@ -22,53 +22,6 @@ import galaxy.datatypes.registry import galaxy.web.framework -def add_ui_controllers( webapp, app ): - """ - Search for controllers in the 'galaxy.web.controllers' module and add - them to the webapp. - """ - from galaxy.web.base.controller import BaseUIController - from galaxy.web.base.controller import ControllerUnavailable - import galaxy.web.controllers - controller_dir = galaxy.web.controllers.__path__[0] - for fname in os.listdir( controller_dir ): - if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ): - name = fname[:-3] - module_name = "galaxy.web.controllers." + name - try: - module = __import__( module_name ) - except ControllerUnavailable, exc: - log.debug("%s could not be loaded: %s" % (module_name, str(exc))) - continue - for comp in module_name.split( "." )[1:]: - module = getattr( module, comp ) - # Look for a controller inside the modules - for key in dir( module ): - T = getattr( module, key ) - if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ): - webapp.add_ui_controller( name, T( app ) ) - -def add_api_controllers( webapp, app ): - from galaxy.web.base.controller import BaseAPIController - from galaxy.web.base.controller import ControllerUnavailable - import galaxy.web.api - controller_dir = galaxy.web.api.__path__[0] - for fname in os.listdir( controller_dir ): - if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ): - name = fname[:-3] - module_name = "galaxy.web.api." + name - try: - module = __import__( module_name ) - except ControllerUnavailable, exc: - log.debug("%s could not be loaded: %s" % (module_name, str(exc))) - continue - for comp in module_name.split( "." )[1:]: - module = getattr( module, comp ) - for key in dir( module ): - T = getattr( module, key ) - if isclass( T ) and T is not BaseAPIController and issubclass( T, BaseAPIController ): - webapp.add_api_controller( name, T( app ) ) - def app_factory( global_conf, **kwargs ): """ Return a wsgi application serving the root object @@ -87,7 +40,7 @@ atexit.register( app.shutdown ) # Create the universe WSGI application webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxysession' ) - add_ui_controllers( webapp, app ) + webapp.add_ui_controllers( 'galaxy.webapps.main.controllers', app ) # Force /history to go to /root/history -- needed since the tests assume this webapp.add_route( '/history', controller='root', action='history' ) # These two routes handle our simple needs at the moment @@ -105,7 +58,7 @@ webapp.add_route( '/u/:username/v/:slug', controller='visualization', action='display_by_username_and_slug' ) # Add the web API - add_api_controllers( webapp, app ) + webapp.add_api_controllers( 'galaxy.webapps.main.api', app ) webapp.api_mapper.resource( 'content', 'contents', controller='library_contents', https://bitbucket.org/galaxy/galaxy-central/changeset/20e1f9fb8da9/ changeset: 20e1f9fb8da9 user: james_taylor date: 2012-09-24 20:34:25 summary: Cleaning up controller imports affected #: 13 files diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/util/backports/__init__.py --- /dev/null +++ b/lib/galaxy/util/backports/__init__.py @@ -0,0 +1,3 @@ +""" +Modules for providing backward compatibility with future versions of Python +""" \ No newline at end of file diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/util/backports/importlib/__init__.py --- /dev/null +++ b/lib/galaxy/util/backports/importlib/__init__.py @@ -0,0 +1,42 @@ +"""Backport of importlib.import_module from 3.x.""" +# While not critical (and in no way guaranteed!), it would be nice to keep this +# code compatible with Python 2.3. +import sys + +def _resolve_name(name, package, level): + """Return the absolute name of the module to be imported.""" + if not hasattr(package, 'rindex'): + raise ValueError("'package' not set to a string") + dot = len(package) + for x in xrange(level, 1, -1): + try: + dot = package.rindex('.', 0, dot) + except ValueError: + raise ValueError("attempted relative import beyond top-level " + "package") + return "%s.%s" % (package[:dot], name) + + +def import_module(name, package=None): + """Import a module. + + The 'package' argument is required when performing a relative import. It + specifies the package to use as the anchor point from which to resolve the + relative import to an absolute import. + + """ + if name.startswith('.'): + if not package: + raise TypeError("relative imports require the 'package' argument") + level = 0 + for character in name: + if character != '.': + break + level += 1 + name = _resolve_name(name[level:], package, level) + __import__(name) + return sys.modules[name] + + ## Note: this was copied from + ## http://svn.python.org/projects/python/trunk/Lib/importlib/__init__.py + ## on 24 September 2012 \ No newline at end of file diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/web/buildapp.py --- /dev/null +++ b/lib/galaxy/web/buildapp.py @@ -0,0 +1,3 @@ +"""For backward compatibility only, pulls app_factor from galaxy.webapps.main""" + +from galaxy.webapps.main.buildapp import app_factory diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -7,11 +7,6 @@ import os, sys, time, socket, random, string import inspect -from galaxy.web.base.controller import BaseUIController -from galaxy.web.base.controller import BaseAPIController -from galaxy.web.base.controller import ControllerUnavailable - - pkg_resources.require( "Cheetah" ) from Cheetah.Template import Template import base @@ -20,6 +15,7 @@ from galaxy import util from galaxy.exceptions import MessageException from galaxy.util.json import to_json_string, from_json_string +from galaxy.util.backports.importlib import import_module pkg_resources.require( "simplejson" ) import simplejson @@ -247,48 +243,50 @@ else: return GalaxyWebUITransaction( environ, galaxy_app, self, session_cookie ) - def add_ui_controllers( self, app, package_name ): + def add_ui_controllers( self, package_name, app ): """ Search for UI controllers in `package_name` and add them to the webapp. """ - package = __import__( package_name ) + from galaxy.web.base.controller import BaseUIController + from galaxy.web.base.controller import ControllerUnavailable + package = import_module( package_name ) + controller_dir = package.__path__[0] + print ">>>", controller_dir, package.__path__ + for fname in os.listdir( controller_dir ): + if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ): + name = fname[:-3] + module_name = package_name + "." + name + print package_name, name, module_name + try: + module = import_module( module_name ) + except ControllerUnavailable, exc: + log.debug("%s could not be loaded: %s" % (module_name, str(exc))) + continue + # Look for a controller inside the modules + for key in dir( module ): + T = getattr( module, key ) + if inspect.isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ): + self.add_ui_controller( name, T( app ) ) + + def add_api_controllers( self, package_name, app ): + """ + Search for UI controllers in `package_name` and add + them to the webapp. + """ + from galaxy.web.base.controller import BaseAPIController + from galaxy.web.base.controller import ControllerUnavailable + package = import_module( package_name ) controller_dir = package.__path__[0] for fname in os.listdir( controller_dir ): if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ): name = fname[:-3] module_name = package_name + "." + name try: - module = __import__( module_name ) + module = import_module( module_name ) except ControllerUnavailable, exc: log.debug("%s could not be loaded: %s" % (module_name, str(exc))) continue - for comp in module_name.split( "." )[1:]: - module = getattr( module, comp ) - # Look for a controller inside the modules - for key in dir( module ): - T = getattr( module, key ) - if inspect.isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ): - self.add_ui_controller( name, T( app ) ) - - def add_api_controllers( self, app, package_name ): - """ - Search for UI controllers in `package_name` and add - them to the webapp. - """ - package = __import__( package_name ) - controller_dir = package.__path__[0] - for fname in os.listdir( controller_dir ): - if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ): - name = fname[:-3] - module_name = package_name + "." + name - try: - module = __import__( module_name ) - except ControllerUnavailable, exc: - log.debug("%s could not be loaded: %s" % (module_name, str(exc))) - continue - for comp in module_name.split( "." )[1:]: - module = getattr( module, comp ) for key in dir( module ): T = getattr( module, key ) if inspect.isclass( T ) and T is not BaseAPIController and issubclass( T, BaseAPIController ): diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/webapps/main/api/workflows.py --- a/lib/galaxy/webapps/main/api/workflows.py +++ b/lib/galaxy/webapps/main/api/workflows.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import + """ API operations for Workflows """ @@ -11,7 +13,8 @@ from galaxy.workflow.modules import module_factory from galaxy.jobs.actions.post import ActionBox from galaxy.model.item_attrs import UsesAnnotations -from galaxy.web.controllers.workflow import attach_ordered_steps + +from ..controllers.workflow import attach_ordered_steps log = logging.getLogger(__name__) diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/webapps/main/buildapp.py --- a/lib/galaxy/webapps/main/buildapp.py +++ b/lib/galaxy/webapps/main/buildapp.py @@ -6,8 +6,6 @@ import os, os.path import sys, warnings -from inspect import isclass - from paste.request import parse_formvars from paste.util import import_string from paste import httpexceptions @@ -209,7 +207,7 @@ log.debug( "Enabling 'error' middleware" ) # Transaction logging (apache access.log style) if asbool( conf.get( 'use_translogger', True ) ): - from framework.middleware.translogger import TransLogger + from galaxy.web.framework.middleware.translogger import TransLogger app = TransLogger( app ) log.debug( "Enabling 'trans logger' middleware" ) # Config middleware just stores the paste config along with the request, diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/webapps/main/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/main/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/main/controllers/admin_toolshed.py @@ -1,5 +1,5 @@ import urllib2, tempfile -from galaxy.web.controllers.admin import * +from admin import * from galaxy.util.json import from_json_string, to_json_string from galaxy.util.shed_util import * from galaxy.tool_shed.encoding_util import * diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/webapps/main/controllers/external_service.py --- a/lib/galaxy/webapps/main/controllers/external_service.py +++ b/lib/galaxy/webapps/main/controllers/external_service.py @@ -1,9 +1,11 @@ +from __future__ import absolute_import + from galaxy.web.base.controller import * from galaxy.web.framework.helpers import time_ago, iff, grids from galaxy.model.orm import * from galaxy import model, util from galaxy.web.form_builder import * -from galaxy.web.controllers.requests_common import invalid_id_redirect +from .requests_common import invalid_id_redirect import logging, os log = logging.getLogger( __name__ ) diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/webapps/main/controllers/request_type.py --- a/lib/galaxy/webapps/main/controllers/request_type.py +++ b/lib/galaxy/webapps/main/controllers/request_type.py @@ -1,9 +1,11 @@ +from __future__ import absolute_import + from galaxy.web.base.controller import * from galaxy.web.framework.helpers import time_ago, iff, grids from galaxy.model.orm import * from galaxy import model, util from galaxy.web.form_builder import * -from galaxy.web.controllers.requests_common import invalid_id_redirect +from .requests_common import invalid_id_redirect import logging, os log = logging.getLogger( __name__ ) diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/webapps/main/controllers/requests.py --- a/lib/galaxy/webapps/main/controllers/requests.py +++ b/lib/galaxy/webapps/main/controllers/requests.py @@ -1,8 +1,10 @@ +from __future__ import absolute_import + from galaxy.web.base.controller import * from galaxy.web.framework.helpers import grids from galaxy.model.orm import * from galaxy.web.form_builder import * -from galaxy.web.controllers.requests_common import RequestsGrid +from .requests_common import RequestsGrid import logging log = logging.getLogger( __name__ ) diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/webapps/main/controllers/requests_admin.py --- a/lib/galaxy/webapps/main/controllers/requests_admin.py +++ b/lib/galaxy/webapps/main/controllers/requests_admin.py @@ -1,9 +1,11 @@ +from __future__ import absolute_import + from galaxy.web.base.controller import * from galaxy.web.framework.helpers import time_ago, iff, grids from galaxy.model.orm import * from galaxy import model, util from galaxy.web.form_builder import * -from galaxy.web.controllers.requests_common import RequestsGrid, invalid_id_redirect +from .requests_common import RequestsGrid, invalid_id_redirect from amqplib import client_0_8 as amqp import logging, os, pexpect, ConfigParser diff -r 14878d0d63898409799c929460366e2ef46fd505 -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd lib/galaxy/webapps/main/controllers/visualization.py --- a/lib/galaxy/webapps/main/controllers/visualization.py +++ b/lib/galaxy/webapps/main/controllers/visualization.py @@ -1,13 +1,16 @@ +from __future__ import absolute_import + from galaxy import model from galaxy.model.item_attrs import * from galaxy.web.base.controller import * from galaxy.web.framework.helpers import time_ago, grids, iff from galaxy.util.sanitize_html import sanitize_html -from galaxy.web.controllers.library import LibraryListGrid from galaxy.visualization.genomes import decode_dbkey from galaxy.visualization.genome.visual_analytics import get_dataset_job from galaxy.visualization.data_providers.basic import ColumnDataProvider +from .library import LibraryListGrid + # # -- Grids -- # https://bitbucket.org/galaxy/galaxy-central/changeset/08dbb6b88aeb/ changeset: 08dbb6b88aeb user: james_taylor date: 2012-09-28 21:10:28 summary: Automated merge with ssh://bitbucket.org/james_taylor/galaxy-webapp-refactoring affected #: 107 files diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -1278,6 +1278,18 @@ was converted successfully. """ + # FIXME: copied from controller.py + messages = Bunch( + PENDING = "pending", + NO_DATA = "no data", + NO_CHROMOSOME = "no chromosome", + NO_CONVERTER = "no converter", + NO_TOOL = "no tool", + DATA = "data", + ERROR = "error", + OK = "ok" + ) + # Get converted dataset; this will start the conversion if necessary. try: converted_dataset = self.get_converted_dataset( trans, target_type ) @@ -1785,6 +1797,7 @@ # we'll return the next available info_association in the inheritable hierarchy. # True is also returned if the info_association was inherited, and False if not. # This enables us to eliminate displaying any contents of the inherited template. + # SM: Accessing self.info_association can cause a query to be emitted if self.info_association: return self.info_association[0], inherited if restrict: diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/security/__init__.py --- a/lib/galaxy/security/__init__.py +++ b/lib/galaxy/security/__init__.py @@ -225,13 +225,16 @@ # If role.type is neither private nor sharing, it's ok to display return True return role.type != self.model.Role.types.PRIVATE and role.type != self.model.Role.types.SHARING + def allow_action( self, roles, action, item ): """ Method for checking a permission for the current user ( based on roles ) to perform a specific action on an item, which must be one of: Dataset, Library, LibraryFolder, LibraryDataset, LibraryDatasetDatasetAssociation """ + # SM: Note that calling get_item_actions will emit a query. item_actions = self.get_item_actions( action, item ) + if not item_actions: return action.model == 'restrict' ret_val = False @@ -249,8 +252,189 @@ ret_val = True break return ret_val - def can_access_dataset( self, roles, dataset ): - return self.dataset_is_public( dataset ) or self.allow_action( roles, self.permitted_actions.DATASET_ACCESS, dataset ) + + + def get_actions_for_items( self, trans, action, permission_items ): + # TODO: Rename this; it's a replacement for get_item_actions, but it + # doesn't represent what it's really confusing. + # TODO: Make this work for other classes besides lib_datasets. + # That should be as easy as checking the type and writing a query for each; + # we're avoiding using the SQLAlchemy backrefs because they can cause lots + # of queries to be generated. + # + # Originally, get_item_actions did: + # return [ permission for permission in item.actions if permission.action == action.action ] + # The "item" can be just about anything with permissions, and referencing + # item.actions causes the item's permissions to be retrieved. + # This method will retrieve all permissions for all "items" and only + # return the permissions associated with that given action. + # We initialize the permissions list to be empty; we will return an + # empty list by default. + # + # If the dataset id has no corresponding action in its permissions, + # then the returned permissions will not carry an entry for the dataset. + ret_permissions = {} + if ( len( permission_items ) > 0 ): + if ( isinstance( permission_items[0], trans.model.LibraryDataset ) ): + ids = [ item.library_dataset_id for item in permission_items ] + permissions = trans.sa_session.query( trans.model.LibraryDatasetPermissions ) \ + .filter( and_( trans.model.LibraryDatasetPermissions.library_dataset_id.in_( ids ), + trans.model.LibraryDatasetPermissions.action == action ) ) \ + .all() + + # Massage the return data. We will return a list of permissions + # for each library dataset. So we initialize the return list to + # have an empty list for each dataset. Then each permission is + # appended to the right lib dataset. + # TODO: Consider eliminating the initialization and just return + # empty values for each library dataset id. + for item in permission_items: + ret_permissions[ item.library_dataset_id ] = [] + for permission in permissions: + ret_permissions[ permission.library_dataset_id ].append( permission ) + + # Test that we get the same response from get_item_actions each item: + test_code = False + if test_code: + try: + log.debug( "get_actions_for_items: Test start" ) + for item in permission_items: + base_result = self.get_item_actions( action, item ) + new_result = ret_permissions[ item.library_dataset_id ] + # For now, just test against LibraryDatasetIds; other classes + # are not tested yet. + if len( base_result ) == len( new_result ): + common_result = set(base_result).intersection( new_result ) + if len( common_result ) == len( base_result ): + log.debug( "Match on permissions for id %d" % + item.library_dataset_id ) + # TODO: Fix this failure message: + else: + log.debug( "Error: dataset %d; originally: %s; now: %s" + % ( item.library_dataset_id, + base_result, new_result ) ) + else: + log.debug( "Error: dataset %d: had %d entries, now %d entries" + % ( item.library_dataset_id, len( base_result ), + len( new_result ) ) ) + log.debug( "get_actions_for_items: Test end" ) + except Exception as e: + log.debug( "Exception in test code: %s" % e ) + + return ret_permissions + + + def allow_action_on_libitems( self, trans, user_roles, action, items ): + """ + This should be the equivalent of allow_action defined on multiple items. + It is meant to specifically replace allow_action for multiple + LibraryDatasets, but it could be reproduced or modified for + allow_action's permitted classes - Dataset, Library, LibraryFolder, and + LDDAs. + """ + all_items_actions = self.get_actions_for_items( trans, action, items ) + + ret_allow_action = {} + # Change item to lib_dataset or vice-versa. + for item in items: + if all_items_actions.has_key( item.id ): + item_actions = all_items_actions[ item.id ] + + # For access, all of the dataset's + if self.permitted_actions.DATASET_ACCESS == action: + ret_allow_action[ item.id ] = True + for item_action in item_actions: + if item_action.role not in user_roles: + ret_allow_action[ item.id ] = False + break + + # Else look for just one dataset role to be in the list of + # acceptable user roles: + else: + ret_allow_action[ item.id ] = False + for item_action in item_actions: + if item_action.role in user_roles: + ret_allow_action[ item.id ] = True + break + + else: + if 'restrict' == action.model: + ret_allow_action[ item.id ] = True + else: + ret_allow_action[ item.id ] = False + + # Test it: the result for each dataset should match the result for + # allow_action: + test_code = False + if test_code: + log.debug( "allow_action_for_items: test start" ) + for item in items: + orig_value = self.allow_action( user_roles, action, item ) + if orig_value == ret_allow_action[ item.id ]: + log.debug( "Item %d: success" % item.id ) + else: + log.debug( "Item %d: fail: original: %s; new: %s" + % ( item.id, orig_value, ret_allow_action[ item.id ] ) ) + log.debug( "allow_action_for_items: test end" ) + return ret_allow_action + + + # DELETEME: SM: DO NOT TOUCH! This actually works. + def dataset_access_mapping( self, trans, user_roles, datasets ): + ''' + For the given list of datasets, return a mapping of the datasets' ids + to whether they can be accessed by the user or not. The datasets input + is expected to be a simple list of Dataset objects. + ''' + datasets_public_map = self.datasets_are_public( trans, datasets ) + datasets_allow_action_map = self.allow_action_on_libitems( trans, user_roles, self.permitted_actions.DATASET_ACCESS, datasets ) + can_access = {} + for dataset in datasets: + can_access[ dataset.id ] = datasets_public_map[ dataset.id ] or datasets_allow_action_map[ dataset.id ] + return can_access + + def dataset_permission_map_for_access( self, trans, user_roles, libitems ): + ''' + For a given list of library items (e.g., Datasets), return a map of the + datasets' ids to whether they can have permission to use that action + (e.g., "access" or "modify") on the dataset. The libitems input is + expected to be a simple list of library items, such as Datasets or + LibraryDatasets. + NB: This is currently only usable for Datasets; it was intended to + be used for any library item. + ''' + # Map the library items to whether they are publicly accessible or not. + # Then determine what actions are allowed on the item (in case it's not + # public). Finally, the item is accessible if it's publicly available + # or the right permissions are enabled. + # TODO: This only works for Datasets; other code is using X_is_public, + # so this will have to be rewritten to support other items. + libitems_public_map = self.datasets_are_public( trans, libitems ) + libitems_allow_action_map = self.allow_action_on_libitems( + trans, user_roles, self.permitted_actions.DATASET_ACCESS, libitems ) + can_access = {} + for libitem in libitems: + can_access[ libitem.id ] = libitems_public_map[ libitem.id ] or libitems_allow_action_map[ libitem.id ] + return can_access + + def item_permission_map_for_modify( self, trans, user_roles, libitems ): + return self.allow_action_on_libitems( + trans, user_roles, self.permitted_actions.LIBRARY_MODIFY, libitems ) + + def item_permission_map_for_manage( self, trans, user_roles, libitems ): + return self.allow_action_on_libitems( + trans, user_roles, self.permitted_actions.LIBRARY_MANAGE, libitems ) + + def item_permission_map_for_add( self, trans, user_roles, libitems ): + return self.allow_action_on_libitems( + trans, user_roles, self.permitted_actions.LIBRARY_ADD, libitems ) + + def can_access_dataset( self, user_roles, dataset ): + # SM: dataset_is_public will access dataset.actions, which is a + # backref that causes a query to be made to DatasetPermissions + retval = self.dataset_is_public( dataset ) or self.allow_action( user_roles, self.permitted_actions.DATASET_ACCESS, dataset ) + return retval + def can_manage_dataset( self, roles, dataset ): return self.allow_action( roles, self.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset ) def can_access_library( self, roles, library ): @@ -317,9 +501,14 @@ return self.allow_action( roles, self.permitted_actions.LIBRARY_MODIFY, item ) def can_manage_library_item( self, roles, item ): return self.allow_action( roles, self.permitted_actions.LIBRARY_MANAGE, item ) + def get_item_actions( self, action, item ): # item must be one of: Dataset, Library, LibraryFolder, LibraryDataset, LibraryDatasetDatasetAssociation + # SM: Accessing item.actions emits a query to Library_Dataset_Permissions + # if the item is a LibraryDataset: + # TODO: Pass in the item's actions - the item isn't needed return [ permission for permission in item.actions if permission.action == action.action ] + def guess_derived_permissions_for_datasets( self, datasets=[] ): """Returns a dict of { action : [ role, role, ... ] } for the output dataset based upon provided datasets""" perms = {} @@ -667,10 +856,55 @@ dataset = library_dataset.library_dataset_dataset_association.dataset if not dataset.purged and not self.dataset_is_public( dataset ): self.make_dataset_public( dataset ) + def dataset_is_public( self, dataset ): # A dataset is considered public if there are no "access" actions associated with it. Any # other actions ( 'manage permissions', 'edit metadata' ) are irrelevant. + # SM: Accessing dataset.actions will cause a query to be emitted. return self.permitted_actions.DATASET_ACCESS.action not in [ a.action for a in dataset.actions ] + + def datasets_are_public( self, trans, datasets ): + ''' + Given a transaction object and a list of Datasets, return + a mapping from Dataset ids to whether the Dataset is public + or not. All Dataset ids should be returned in the mapping's keys. + ''' + # We go the other way around from dataset_is_public: we start with + # all datasets being marked as public. If there is an access action + # associated with the dataset, then we mark it as nonpublic: + datasets_public = {} + dataset_ids = [ dataset.id for dataset in datasets ] + for dataset_id in dataset_ids: + datasets_public[ dataset_id ] = True + + # Now get all datasets which have DATASET_ACCESS actions: + access_data_perms = trans.sa_session.query( trans.app.model.DatasetPermissions ) \ + .filter( and_( trans.app.model.DatasetPermissions.dataset_id in dataset_ids, + trans.app.model.DatasetPermissions.action == self.permitted_actions.DATASET_ACCESS.action ) ) \ + .all() + + # Every dataset returned has "access" privileges associated with it, + # so it's not public. + for permission in access_data_perms: + datasets_public[ permission.dataset_id ] = False + + # Test code: Check if the results match up with the original: + test_code = False + if test_code: + log.debug( "datasets_are_public test: check datasets_are_public matches dataset_is_public:" ) + test_success = True + for dataset in datasets: + orig_is_public = self.dataset_is_public( dataset ) + if orig_is_public == datasets_public[ dataset.id ]: + log.debug( "\tMatch for dataset %d" % dataset.id ) + else: + success = False + log.error( "\tERROR: Did not match: single is_public: %s; multiple is_public: %s" + % ( single_is_public, datasets_public[ dataset.id ] ) ) + log.debug( "datasets_are_public: test succeeded? %s" % test_success ) + return datasets_public + + def make_dataset_public( self, dataset ): # A dataset is considered public if there are no "access" actions associated with it. Any # other actions ( 'manage permissions', 'edit metadata' ) are irrelevant. @@ -707,7 +941,7 @@ # Ensure that roles being associated with DATASET_ACCESS are a subset of the legitimate roles # derived from the roles associated with the access permission on item if it's not public. This # will keep ill-legitimate roles from being associated with the DATASET_ACCESS permission on the - # dataset (i.e., in the case where item is a library, if Role1 is associated with LIBRARY_ACCESS, + # dataset (i.e., in the case where item is .a library, if Role1 is associated with LIBRARY_ACCESS, # then only those users that have Role1 should be associated with DATASET_ACCESS. legitimate_roles = self.get_legitimate_roles( trans, item, cntrller ) ill_legitimate_roles = [] @@ -944,12 +1178,21 @@ if self.can_add_library_item( roles, folder ): return True, '' action = self.permitted_actions.DATASET_ACCESS + + # SM: TODO: This is for timing debug. Delete it later. + from datetime import datetime, timedelta + query_start = datetime.now() lddas = self.sa_session.query( self.model.LibraryDatasetDatasetAssociation ) \ .join( "library_dataset" ) \ .filter( self.model.LibraryDataset.folder == folder ) \ .join( "dataset" ) \ .options( eagerload_all( "dataset.actions" ) ) \ .all() + query_end = datetime.now() + query_delta = query_end - query_start + #log.debug( "Check folder contents: join query time: %d.%.6d sec" % + # ( query_delta.seconds, query_delta.microseconds ) ) + for ldda in lddas: ldda_access_permissions = self.get_item_actions( action, ldda.dataset ) if not ldda_access_permissions: diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/tool_shed/install_manager.py --- a/lib/galaxy/tool_shed/install_manager.py +++ b/lib/galaxy/tool_shed/install_manager.py @@ -133,6 +133,7 @@ for k, v in tool_panel_dict_for_tool_config.items(): tool_panel_dict_for_display[ k ] = v metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=self.app, + repository=tool_shed_repository, repository_clone_url=repository_clone_url, relative_install_dir=relative_install_dir, repository_files_dir=None, diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -159,6 +159,8 @@ else: panel_dict = panel_component already_loaded = False + loaded_version_key = None + lineage_id = None for lineage_id in tool.lineage_ids: if lineage_id in self.tools_by_id: loaded_version_key = 'tool_%s' % lineage_id @@ -176,7 +178,13 @@ if not inserted: # If the tool is not defined in integrated_tool_panel.xml, append it to the tool panel. panel_dict[ key ] = tool - log.debug( "Loaded tool id: %s, version: %s." % ( tool.id, tool.version ) ) + log.debug( "Loaded tool id: %s, version: %s into tool panel." % ( tool.id, tool.version ) ) + elif tool.lineage_ids.index( tool_id ) > tool.lineage_ids.index( lineage_id ): + key = 'tool_%s' % tool.id + index = panel_dict.keys().index( loaded_version_key ) + del panel_dict[ loaded_version_key ] + panel_dict.insert( index, key, tool ) + log.debug( "Loaded tool id: %s, version: %s into tool panel." % ( tool.id, tool.version ) ) def load_tool_panel( self ): for key, val in self.integrated_tool_panel.items(): if key.startswith( 'tool_' ): @@ -255,70 +263,68 @@ os.write( fd, '<?xml version="1.0"?>\n' ) os.write( fd, '<toolbox>\n' ) for key, item in self.integrated_tool_panel.items(): - if key.startswith( 'tool_' ): - if item: + if item: + if key.startswith( 'tool_' ): os.write( fd, ' <tool id="%s" />\n' % item.id ) - elif key.startswith( 'workflow_' ): - if item: + elif key.startswith( 'workflow_' ): os.write( fd, ' <workflow id="%s" />\n' % item.id ) - elif key.startswith( 'label_' ): - label_id = item.id or '' - label_text = item.text or '' - label_version = item.version or '' - os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) ) - elif key.startswith( 'section_' ): - section_id = item.id or '' - section_name = item.name or '' - section_version = item.version or '' - os.write( fd, ' <section id="%s" name="%s" version="%s">\n' % ( section_id, section_name, section_version ) ) - for section_key, section_item in item.elems.items(): - if section_key.startswith( 'tool_' ): - if section_item: - os.write( fd, ' <tool id="%s" />\n' % section_item.id ) - elif section_key.startswith( 'workflow_' ): - if section_item: - os.write( fd, ' <workflow id="%s" />\n' % section_item.id ) - elif section_key.startswith( 'label_' ): - if section_item: - label_id = section_item.id or '' - label_text = section_item.text or '' - label_version = section_item.version or '' - os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) ) - os.write( fd, ' </section>\n' ) + elif key.startswith( 'label_' ): + label_id = item.id or '' + label_text = item.text or '' + label_version = item.version or '' + os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) ) + elif key.startswith( 'section_' ): + section_id = item.id or '' + section_name = item.name or '' + section_version = item.version or '' + os.write( fd, ' <section id="%s" name="%s" version="%s">\n' % ( section_id, section_name, section_version ) ) + for section_key, section_item in item.elems.items(): + if section_key.startswith( 'tool_' ): + if section_item: + os.write( fd, ' <tool id="%s" />\n' % section_item.id ) + elif section_key.startswith( 'workflow_' ): + if section_item: + os.write( fd, ' <workflow id="%s" />\n' % section_item.id ) + elif section_key.startswith( 'label_' ): + if section_item: + label_id = section_item.id or '' + label_text = section_item.text or '' + label_version = section_item.version or '' + os.write( fd, ' <label id="%s" text="%s" version="%s" />\n' % ( label_id, label_text, label_version ) ) + os.write( fd, ' </section>\n' ) os.write( fd, '</toolbox>\n' ) os.close( fd ) shutil.move( filename, os.path.abspath( self.integrated_tool_panel_config ) ) os.chmod( self.integrated_tool_panel_config, 0644 ) def get_tool( self, tool_id, tool_version=None, get_all_versions=False ): """Attempt to locate a tool in the tool box.""" - if tool_id in self.tools_by_id: - tool = self.tools_by_id[ tool_id ] - if tool_version and tool.version == tool_version: - if get_all_versions: - return [ tool ] - else: - return tool - else: - if get_all_versions: - return [ tool ] - else: - return tool + if tool_id in self.tools_by_id and not get_all_versions: + #tool_id exactly matches an available tool by id (which is 'old' tool_id or guid) + return self.tools_by_id[ tool_id ] + #exact tool id match not found, or all versions requested, search for other options, e.g. migrated tools or different versions + rval = [] tv = self.__get_tool_version( tool_id ) if tv: tool_version_ids = tv.get_version_ids( self.app ) - if get_all_versions: - available_tool_versions = [] - for tool_version_id in tool_version_ids: - if tool_version_id in self.tools_by_id: - available_tool_versions.append( self.tools_by_id[ tool_version_id ] ) - return available_tool_versions for tool_version_id in tool_version_ids: if tool_version_id in self.tools_by_id: - tool = self.tools_by_id[ tool_version_id ] - if tool_version and tool.version == tool_version: - return tool - else: - return tool + rval.append( self.tools_by_id[ tool_version_id ] ) + if not rval: + #still no tool, do a deeper search and try to match by old ids + for tool in self.tools_by_id.itervalues(): + if tool.old_id == tool_id: + rval.append( tool ) + if rval: + if get_all_versions: + return rval + else: + if tool_version: + #return first tool with matching version + for tool in rval: + if tool.version == tool_version: + return tool + #No tool matches by version, simply return the first available tool found + return rval[0] return None def get_loaded_tools_by_lineage( self, tool_id ): """Get all loaded tools associated by lineage to the tool whose id is tool_id.""" @@ -381,7 +387,6 @@ tool.repository_owner = repository_owner tool.installed_changeset_revision = installed_changeset_revision tool.guid = guid - tool.old_id = elem.find( "id" ).text tool.version = elem.find( "version" ).text # Make sure the tool has a tool_version. if not self.__get_tool_version( tool.id ): @@ -906,8 +911,9 @@ if not self.name: raise Exception, "Missing tool 'name'" # Get the UNIQUE id for the tool + self.old_id = root.get( "id" ) if guid is None: - self.id = root.get( "id" ) + self.id = self.old_id else: self.id = guid if not self.id: diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/util/shed_util.py --- a/lib/galaxy/util/shed_util.py +++ b/lib/galaxy/util/shed_util.py @@ -31,8 +31,8 @@ '&' : '&', '\'' : ''' } MAX_CONTENT_SIZE = 32768 +NOT_TOOL_CONFIGS = [ 'datatypes_conf.xml', 'tool_dependencies.xml' ] VALID_CHARS = set( string.letters + string.digits + "'\"-=_.()/+*^,:?!#[]%\\$@;{}" ) -NOT_TOOL_CONFIGS = [ 'datatypes_conf.xml', 'tool_dependencies.xml' ] class ShedCounter( object ): def __init__( self, model ): @@ -602,7 +602,7 @@ else: tool_dependencies_dict[ 'set_environment' ] = [ requirements_dict ] return tool_dependencies_dict -def generate_metadata_for_changeset_revision( app, repository_clone_url, relative_install_dir=None, repository_files_dir=None, +def generate_metadata_for_changeset_revision( app, repository, repository_clone_url, relative_install_dir=None, repository_files_dir=None, resetting_all_metadata_on_repository=False, webapp='galaxy' ): """ Generate metadata for a repository using it's files on disk. To generate metadata for changeset revisions older than the repository tip, @@ -610,6 +610,7 @@ disk files, so the value of repository_files_dir will not always be repository.repo_path (it could be an absolute path to a temporary directory containing a clone). If it is an absolute path, the value of relative_install_dir must contain repository.repo_path. """ + readme_file_names = get_readme_file_names( repository.name ) metadata_dict = {} invalid_file_tups = [] invalid_tool_configs = [] @@ -653,14 +654,24 @@ tool_data_path=app.config.tool_data_path, tool_data_table_config_path=app.config.tool_data_table_config_path, persist=False ) - # Find all tool configs and exported workflows and add them to the repository's metadata. for root, dirs, files in os.walk( files_dir ): if root.find( '.hg' ) < 0 and root.find( 'hgrc' ) < 0: if '.hg' in dirs: dirs.remove( '.hg' ) for name in files: - # Find all tool configs. - if name not in NOT_TOOL_CONFIGS and name.endswith( '.xml' ): + # See if we have a READ_ME file. + if name.lower() in readme_file_names: + if resetting_all_metadata_on_repository: + full_path_to_readme = os.path.join( root, name ) + stripped_path_to_readme = full_path_to_readme.replace( work_dir, '' ) + if stripped_path_to_readme.startswith( '/' ): + stripped_path_to_readme = stripped_path_to_readme[ 1: ] + relative_path_to_readme = os.path.join( relative_install_dir, stripped_path_to_readme ) + else: + relative_path_to_readme = os.path.join( root, name ) + metadata_dict[ 'readme' ] = relative_path_to_readme + # See if we have a tool config. + elif name not in NOT_TOOL_CONFIGS and name.endswith( '.xml' ): full_path = os.path.abspath( os.path.join( root, name ) ) if os.path.getsize( full_path ) > 0: if not ( check_binary( full_path ) or check_image( full_path ) or check_gzip( full_path )[ 0 ] @@ -699,7 +710,7 @@ else: for tup in invalid_files_and_errors_tups: invalid_file_tups.append( tup ) - # Find all exported workflows + # Find all exported workflows. elif name.endswith( '.ga' ): relative_path = os.path.join( root, name ) if os.path.getsize( os.path.abspath( relative_path ) ) > 0: @@ -1195,6 +1206,25 @@ if contents: contents.sort() return contents +def get_repository_metadata_by_changeset_revision( trans, id, changeset_revision ): + """Get metadata for a specified repository change set from the database""" + # Make sure there are no duplicate records, and return the single unique record for the changeset_revision. Duplicate records were somehow + # created in the past. The cause of this issue has been resolved, but we'll leave this method as is for a while longer to ensure all duplicate + # records are removed. + all_metadata_records = trans.sa_session.query( trans.model.RepositoryMetadata ) \ + .filter( and_( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ), + trans.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) ) \ + .order_by( trans.model.RepositoryMetadata.table.c.update_time.desc() ) \ + .all() + if len( all_metadata_records ) > 1: + # Delete all recrds older than the last one updated. + for repository_metadata in all_metadata_records[ 1: ]: + trans.sa_session.delete( repository_metadata ) + trans.sa_session.flush() + return all_metadata_records[ 0 ] + elif all_metadata_records: + return all_metadata_records[ 0 ] + return None def get_repository_owner( cleaned_repository_url ): items = cleaned_repository_url.split( 'repos' ) repo_path = items[ 1 ] @@ -1405,6 +1435,13 @@ return shed_url # The tool shed from which the repository was originally installed must no longer be configured in tool_sheds_conf.xml. return None +def get_readme_file_names( repository_name ): + readme_files = [ 'readme', 'read_me', 'install' ] + valid_filenames = [ r for r in readme_files ] + for r in readme_files: + valid_filenames.append( '%s.txt' % r ) + valid_filenames.append( '%s.txt' % repository_name ) + return valid_filenames def handle_missing_data_table_entry( app, relative_install_dir, tool_path, repository_tools_tups ): """ Inspect each tool to see if any have input parameters that are dynamically generated select lists that require entries in the @@ -1469,7 +1506,7 @@ error, message = handle_sample_tool_data_table_conf_file( trans.app, tool_data_table_config ) tool, valid, message2 = load_tool_from_config( trans.app, tool_config_filepath ) message = concat_messages( message, message2 ) - return tool, valid, message + return tool, valid, message, sample_files def handle_sample_files_and_load_tool_from_tmp_config( trans, repo, changeset_revision, tool_config_filename, work_dir ): tool = None message = '' @@ -1490,7 +1527,7 @@ if manifest_ctx and ctx_file: tool, message2 = load_tool_from_tmp_config( trans, repo, manifest_ctx, ctx_file, work_dir ) message = concat_messages( message, message2 ) - return tool, message + return tool, message, sample_files def handle_sample_tool_data_table_conf_file( app, filename, persist=False ): """ Parse the incoming filename and add new entries to the in-memory app.tool_data_tables dictionary. If persist is True (should only occur) @@ -1907,6 +1944,19 @@ elif c not in [ '\r' ]: translated.append( '' ) return ''.join( translated ) +def translate_string( raw_text, to_html=True ): + if raw_text: + if to_html: + if len( raw_text ) <= MAX_CONTENT_SIZE: + translated_string = to_html_str( raw_text ) + else: + large_str = '\nFile contents truncated because file size is larger than maximum viewing size of %s\n' % util.nice_size( MAX_CONTENT_SIZE ) + translated_string = to_html_str( '%s%s' % ( raw_text[ 0:MAX_CONTENT_SIZE ], large_str ) ) + else: + raise Exception( "String translation currently only supports text to HTML." ) + else: + translated_string = '' + return translated_string def update_repository( repo, ctx_rev=None ): """ Update the cloned repository to changeset_revision. It is critical that the installed repository is updated to the desired diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/visualization/data_providers/basic.py --- a/lib/galaxy/visualization/data_providers/basic.py +++ b/lib/galaxy/visualization/data_providers/basic.py @@ -109,10 +109,10 @@ """ Cast value based on type. """ if type == 'int': try: val = int( val ) - except: pass + except: return None elif type == 'float': try: val = float( val ) - except: pass + except: return None return val f = open( self.original_dataset.file_name ) diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/visualization/data_providers/genome.py --- a/lib/galaxy/visualization/data_providers/genome.py +++ b/lib/galaxy/visualization/data_providers/genome.py @@ -113,7 +113,7 @@ class GenomeDataProvider( BaseDataProvider ): """ Base class for genome data providers. """ - data_type = None + dataset_type = None """ Mapping from column name to payload data; this mapping is used to create @@ -179,12 +179,21 @@ """ Returns data for complete genome. """ - dataset_summary = [] + genome_data = [] for chrom_info in chroms_info[ 'chrom_info' ]: - summary = self.get_data( chrom_info[ 'chrom' ], 0, chrom_info[ 'len' ], **kwargs ) - dataset_summary.append( summary ) + chrom = chrom_info[ 'chrom' ] + chrom_len = chrom_info[ 'len' ] + chrom_data = self.get_data( chrom, 0, chrom_len, **kwargs ) + if chrom_data: + chrom_data[ 'region' ] = "%s:%i-%i" % ( chrom, 0, chrom_len ) + chrom_data[ 'dataset_type' ] = self.dataset_type + genome_data.append( chrom_data ) - return dataset_summary + return { + 'data': genome_data, + 'dataset_type': self.dataset_type + } + def get_filters( self ): """ @@ -316,7 +325,7 @@ class TabixDataProvider( FilterableMixin, GenomeDataProvider ): - data_type = 'tabix' + dataset_type = 'tabix' """ Tabix index data provider for the Galaxy track browser. @@ -358,7 +367,7 @@ # class IntervalDataProvider( GenomeDataProvider ): - data_type = 'interval_index' + dataset_type = 'interval_index' """ Processes interval data from native format to payload format. @@ -444,7 +453,7 @@ Payload format: [ uid (offset), start, end, name, strand, thick_start, thick_end, blocks ] """ - data_type = 'interval_index' + dataset_type = 'interval_index' def get_iterator( self, chrom, start, end ): raise Exception( "Unimplemented Method" ) @@ -541,7 +550,7 @@ for large datasets. """ - data_type = 'interval_index' + dataset_type = 'interval_index' def get_iterator( self, chrom=None, start=None, end=None ): # Read first line in order to match chrom naming format. @@ -581,7 +590,7 @@ col_name_data_attr_mapping = { 'Qual' : { 'index': 6 , 'name' : 'Qual' } } - data_type = 'bai' + dataset_type = 'bai' def process_data( self, iterator, start_val=0, max_vals=None, **kwargs ): """ @@ -687,7 +696,7 @@ for large datasets. """ - data_type = 'tabix' + dataset_type = 'tabix' def get_iterator( self, chrom, start, end ): # Read first line in order to match chrom naming format. @@ -721,7 +730,7 @@ Summary tree data provider for the Galaxy track browser. """ - data_type = 'summary_tree' + dataset_type = 'summary_tree' CACHE = LRUCache( 20 ) # Store 20 recently accessed indices for performance @@ -729,7 +738,7 @@ st = summary_tree_from_file( self.converted_dataset.file_name ) return st.chrom_blocks.keys() - def get_data( self, chrom, start, end, level=None, resolution=None, detail_cutoff=None, draw_cutoff=None ): + def get_data( self, chrom, start, end, level=None, resolution=None, detail_cutoff=None, draw_cutoff=None, **kwargs ): """ Returns summary tree data for a given genomic region. """ @@ -765,7 +774,14 @@ if results == "detail" or results == "draw": return results else: - return results, stats[ level ][ "max" ], stats[ level ]["avg" ], stats[ level ][ "delta" ] + return { + 'dataset_type': self.dataset_type, + 'data': results, + 'max': stats[ level ][ "max" ], + 'avg': stats[ level ][ "avg" ], + 'delta': stats[ level ][ "delta" ], + 'level': level + } def has_data( self, chrom ): """ @@ -788,7 +804,7 @@ is reported in 1-based, closed format, i.e. SAM/BAM format. """ - data_type = 'bai' + dataset_type = 'bai' def get_filters( self ): """ @@ -970,7 +986,7 @@ class SamDataProvider( BamDataProvider ): - data_type = 'bai' + dataset_type = 'bai' def __init__( self, converted_dataset=None, original_dataset=None, dependencies=None ): """ Create SamDataProvider. """ @@ -987,7 +1003,7 @@ BBI data provider for the Galaxy track browser. """ - data_type = 'bigwig' + dataset_type = 'bigwig' def valid_chroms( self ): # No way to return this info as of now @@ -1000,6 +1016,9 @@ return all_dat is not None def get_data( self, chrom, start, end, start_val=0, max_vals=None, num_samples=1000, **kwargs ): + start = int( start ) + end = int( end ) + # Bigwig can be a standalone bigwig file, in which case we use # original_dataset, or coming from wig->bigwig conversion in # which we use converted_dataset @@ -1096,7 +1115,10 @@ # Cleanup and return. f.close() - return { 'data': result } + return { + 'data': result, + 'dataset_type': self.dataset_type + } class BigBedDataProvider( BBIDataProvider ): def _get_dataset( self ): @@ -1122,7 +1144,7 @@ """ col_name_data_attr_mapping = { 4 : { 'index': 4 , 'name' : 'Score' } } - data_type = 'interval_index' + dataset_type = 'interval_index' def write_data_to_file( self, regions, filename ): source = open( self.original_dataset.file_name ) @@ -1201,7 +1223,7 @@ for large datasets. """ - data_type = 'interval_index' + dataset_type = 'interval_index' def get_iterator( self, chrom, start, end ): """ diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/webapps/community/controllers/common.py --- a/lib/galaxy/webapps/community/controllers/common.py +++ b/lib/galaxy/webapps/community/controllers/common.py @@ -5,11 +5,11 @@ from galaxy.tools import * from galaxy.util.json import from_json_string, to_json_string from galaxy.util.hash_util import * -from galaxy.util.shed_util import check_tool_input_params, clone_repository, copy_sample_file, generate_metadata_for_changeset_revision +from galaxy.util.shed_util import check_tool_input_params, clone_repository, concat_messages, copy_sample_file, generate_metadata_for_changeset_revision from galaxy.util.shed_util import get_changectx_for_changeset, get_config_from_disk, get_configured_ui, get_file_context_from_ctx, get_named_tmpfile_from_ctx -from galaxy.util.shed_util import handle_sample_files_and_load_tool_from_disk, handle_sample_files_and_load_tool_from_tmp_config -from galaxy.util.shed_util import handle_sample_tool_data_table_conf_file, INITIAL_CHANGELOG_HASH, load_tool_from_config, reset_tool_data_tables -from galaxy.util.shed_util import reversed_upper_bounded_changelog, strip_path +from galaxy.util.shed_util import get_repository_metadata_by_changeset_revision, handle_sample_files_and_load_tool_from_disk +from galaxy.util.shed_util import handle_sample_files_and_load_tool_from_tmp_config, handle_sample_tool_data_table_conf_file, INITIAL_CHANGELOG_HASH +from galaxy.util.shed_util import load_tool_from_config, reset_tool_data_tables, reversed_upper_bounded_changelog, strip_path from galaxy.web.base.controller import * from galaxy.webapps.community import model from galaxy.model.orm import * @@ -473,25 +473,6 @@ .filter( and_( trans.model.Repository.table.c.name == name, trans.model.Repository.table.c.user_id == user.id ) ) \ .first() -def get_repository_metadata_by_changeset_revision( trans, id, changeset_revision ): - """Get metadata for a specified repository change set from the database""" - # Make sure there are no duplicate records, and return the single unique record for the changeset_revision. Duplicate records were somehow - # created in the past. The cause of this issue has been resolved, but we'll leave this method as is for a while longer to ensure all duplicate - # records are removed. - all_metadata_records = trans.sa_session.query( trans.model.RepositoryMetadata ) \ - .filter( and_( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ), - trans.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) ) \ - .order_by( trans.model.RepositoryMetadata.table.c.update_time.desc() ) \ - .all() - if len( all_metadata_records ) > 1: - # Delete all recrds older than the last one updated. - for repository_metadata in all_metadata_records[ 1: ]: - trans.sa_session.delete( repository_metadata ) - trans.sa_session.flush() - return all_metadata_records[ 0 ] - elif all_metadata_records: - return all_metadata_records[ 0 ] - return None def get_repository_metadata_by_id( trans, id ): """Get repository metadata from the database""" return trans.sa_session.query( trans.model.RepositoryMetadata ).get( trans.security.decode_id( id ) ) @@ -620,7 +601,7 @@ can_use_disk_file = can_use_tool_config_disk_file( trans, repository, repo, tool_config_filepath, changeset_revision ) if can_use_disk_file: trans.app.config.tool_data_path = work_dir - tool, valid, message = handle_sample_files_and_load_tool_from_disk( trans, repo_files_dir, tool_config_filepath, work_dir ) + tool, valid, message, sample_files = handle_sample_files_and_load_tool_from_disk( trans, repo_files_dir, tool_config_filepath, work_dir ) if tool is not None: invalid_files_and_errors_tups = check_tool_input_params( trans.app, repo_files_dir, @@ -637,7 +618,7 @@ message = concat_messages( message, message2 ) status = 'error' else: - tool, message = handle_sample_files_and_load_tool_from_tmp_config( trans, repo, changeset_revision, tool_config_filename, work_dir ) + tool, message, sample_files = handle_sample_files_and_load_tool_from_tmp_config( trans, repo, changeset_revision, tool_config_filename, work_dir ) try: shutil.rmtree( work_dir ) except: @@ -762,6 +743,7 @@ if cloned_ok: log.debug( "Generating metadata for changset revision: %s", str( ctx.rev() ) ) current_metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=trans.app, + repository=repository, repository_clone_url=repository_clone_url, relative_install_dir=repo_dir, repository_files_dir=work_dir, @@ -836,6 +818,7 @@ repo_dir = repository.repo_path repo = hg.repository( get_configured_ui(), repo_dir ) metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=trans.app, + repository=repository, repository_clone_url=repository_clone_url, relative_install_dir=repo_dir, repository_files_dir=None, diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/webapps/community/controllers/repository.py --- a/lib/galaxy/webapps/community/controllers/repository.py +++ b/lib/galaxy/webapps/community/controllers/repository.py @@ -10,9 +10,10 @@ from galaxy.util.json import from_json_string, to_json_string from galaxy.model.orm import * from galaxy.util.shed_util import create_repo_info_dict, get_changectx_for_changeset, get_configured_ui, get_repository_file_contents -from galaxy.util.shed_util import handle_sample_files_and_load_tool_from_disk, handle_sample_files_and_load_tool_from_tmp_config, INITIAL_CHANGELOG_HASH -from galaxy.util.shed_util import load_tool_from_config, NOT_TOOL_CONFIGS, open_repository_files_folder, reversed_lower_upper_bounded_changelog -from galaxy.util.shed_util import reversed_upper_bounded_changelog, strip_path, to_html_escaped, update_repository, url_join +from galaxy.util.shed_util import get_repository_metadata_by_changeset_revision, handle_sample_files_and_load_tool_from_disk +from galaxy.util.shed_util import handle_sample_files_and_load_tool_from_tmp_config, INITIAL_CHANGELOG_HASH, load_tool_from_config, NOT_TOOL_CONFIGS +from galaxy.util.shed_util import open_repository_files_folder, reversed_lower_upper_bounded_changelog, reversed_upper_bounded_changelog, strip_path +from galaxy.util.shed_util import to_html_escaped, translate_string, update_repository, url_join from galaxy.tool_shed.encoding_util import * from common import * @@ -23,7 +24,6 @@ log = logging.getLogger( __name__ ) VALID_REPOSITORYNAME_RE = re.compile( "^[a-z0-9\_]+$" ) -README_FILES = [ 'readme', 'read_me', 'install' ] class CategoryListGrid( grids.Grid ): class NameColumn( grids.TextColumn ): @@ -613,8 +613,10 @@ # Update repository files for browsing. update_repository( repo ) is_malicious = changeset_is_malicious( trans, id, repository.tip ) + metadata = self.get_metadata( trans, id, repository.tip ) return trans.fill_template( '/webapps/community/repository/browse_repository.mako', repository=repository, + metadata=metadata, commit_message=commit_message, is_malicious=is_malicious, webapp=webapp, @@ -828,9 +830,11 @@ message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) repository = get_repository( trans, id ) + metadata = self.get_metadata( trans, id, repository.tip ) if trans.user and trans.user.email: return trans.fill_template( "/webapps/community/repository/contact_owner.mako", repository=repository, + metadata=metadata, message=message, status=status ) else: @@ -939,9 +943,11 @@ repository, tool, message = load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_config ) tool_state = self.__new_state( trans ) is_malicious = changeset_is_malicious( trans, repository_id, repository.tip ) + metadata = self.get_metadata( trans, repository_id, changeset_revision ) try: return trans.fill_template( "/webapps/community/repository/tool_form.mako", repository=repository, + metadata=metadata, changeset_revision=changeset_revision, tool=tool, tool_state=tool_state, @@ -1181,6 +1187,11 @@ trans.response.headers['Pragma'] = 'no-cache' trans.response.headers['Expires'] = '0' return get_repository_file_contents( file_path ) + def get_metadata( self, trans, repository_id, changeset_revision ): + repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision ) + if repository_metadata and repository_metadata.metadata: + return repository_metadata.metadata + return None @web.json def get_repository_information( self, trans, repository_ids, changeset_revisions, **kwd ): """ @@ -1208,23 +1219,18 @@ return dict( includes_tools=includes_tools, includes_tool_dependencies=includes_tool_dependencies, repo_info_dicts=repo_info_dicts ) @web.expose def get_readme( self, trans, **kwd ): - """If the received changeset_revision includes a file named readme (case ignored), return it's contents.""" + """If the received changeset_revision includes a readme file, return it's contents.""" repository_name = kwd[ 'name' ] repository_owner = kwd[ 'owner' ] changeset_revision = kwd[ 'changeset_revision' ] - valid_filenames = [ r for r in README_FILES ] - for r in README_FILES: - valid_filenames.append( '%s.txt' % r ) - valid_filenames.append( '%s.txt' % repository_name ) repository = get_repository_by_name_and_owner( trans, repository_name, repository_owner ) - repo_dir = repository.repo_path - for root, dirs, files in os.walk( repo_dir ): - for name in files: - if name.lower() in valid_filenames: - f = open( os.path.join( root, name ), 'r' ) - text = f.read() - f.close() - return str( text ) + repository_metadata = get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision ) + metadata = repository_metadata.metadata + if metadata and 'readme' in metadata: + f = open( metadata[ 'readme' ], 'r' ) + text = f.read() + f.close() + return str( text ) return '' @web.expose def get_tool_dependencies( self, trans, **kwd ): @@ -1829,8 +1835,10 @@ display_reviews = util.string_as_bool( params.get( 'display_reviews', False ) ) rra = self.get_user_item_rating( trans.sa_session, trans.user, repository, webapp_model=trans.model ) is_malicious = changeset_is_malicious( trans, id, repository.tip ) + metadata = self.get_metadata( trans, id, repository.tip ) return trans.fill_template( '/webapps/community/repository/rate_repository.mako', repository=repository, + metadata=metadata, avg_rating=avg_rating, display_reviews=display_reviews, num_ratings=num_ratings, @@ -2156,8 +2164,10 @@ # Make sure we'll view latest changeset first. changesets.insert( 0, change_dict ) is_malicious = changeset_is_malicious( trans, id, repository.tip ) + metadata = self.get_metadata( trans, id, repository.tip ) return trans.fill_template( '/webapps/community/repository/view_changelog.mako', repository=repository, + metadata=metadata, changesets=changesets, is_malicious=is_malicious, message=message, @@ -2185,8 +2195,10 @@ for diff in patch.diff( repo, node1=ctx_parent.node(), node2=ctx.node() ): diffs.append( to_html_escaped( diff ) ) is_malicious = changeset_is_malicious( trans, id, repository.tip ) + metadata = self.get_metadata( trans, id, ctx_str ) return trans.fill_template( '/webapps/community/repository/view_changeset.mako', repository=repository, + metadata=metadata, ctx=ctx, anchors=anchors, modified=modified, @@ -2201,6 +2213,33 @@ message=message, status=status ) @web.expose + def view_readme( self, trans, id, changeset_revision, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + cntrller = params.get( 'cntrller', 'repository' ) + webapp = params.get( 'webapp', 'community' ) + repository = get_repository( trans, id ) + repository_metadata = get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision ) + metadata = repository_metadata.metadata + if metadata and 'readme' in metadata: + f = open( metadata[ 'readme' ], 'r' ) + raw_text = f.read() + f.close() + readme_text = translate_string( raw_text, to_html=True ) + else: + readme_text = '' + is_malicious = changeset_is_malicious( trans, id, changeset_revision ) + return trans.fill_template( '/webapps/community/common/view_readme.mako', + cntrller=cntrller, + repository=repository, + changeset_revision=changeset_revision, + readme_text=readme_text, + is_malicious=is_malicious, + webapp=webapp, + message=message, + status=status ) + @web.expose def view_repository( self, trans, id, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) @@ -2301,16 +2340,25 @@ can_use_disk_file = can_use_tool_config_disk_file( trans, repository, repo, full_path_to_tool_config, changeset_revision ) if can_use_disk_file: trans.app.config.tool_data_path = work_dir - tool, valid, message = handle_sample_files_and_load_tool_from_disk( trans, repo_files_dir, full_path_to_tool_config, work_dir ) + tool, valid, message, sample_files = handle_sample_files_and_load_tool_from_disk( trans, + repo_files_dir, + full_path_to_tool_config, + work_dir ) if message: status = 'error' else: - tool, message = handle_sample_files_and_load_tool_from_tmp_config( trans, repo, changeset_revision, tool_config_filename, work_dir ) + tool, message, sample_files = handle_sample_files_and_load_tool_from_tmp_config( trans, + repo, + changeset_revision, + tool_config_filename, + work_dir ) if message: status = 'error' break if guid: tool_lineage = self.get_versions_of_tool( trans, repository, repository_metadata, guid ) + else: + metadata = None is_malicious = changeset_is_malicious( trans, repository_id, repository.tip ) changeset_revision_select_field = build_changeset_revision_select_field( trans, repository, @@ -2320,6 +2368,7 @@ trans.app.config.tool_data_path = original_tool_data_path return trans.fill_template( "/webapps/community/repository/view_tool_metadata.mako", repository=repository, + metadata=metadata, tool=tool, tool_metadata_dict=tool_metadata_dict, tool_lineage=tool_lineage, diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/webapps/community/controllers/workflow.py --- a/lib/galaxy/webapps/community/controllers/workflow.py +++ b/lib/galaxy/webapps/community/controllers/workflow.py @@ -151,6 +151,7 @@ changeset_revision=repository_metadata.changeset_revision, repository_metadata_id=repository_metadata_id, workflow_name=workflow_name, + metadata=repository_metadata, webapp=webapp, message=message, status=status ) diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/webapps/main/api/datasets.py --- a/lib/galaxy/webapps/main/api/datasets.py +++ b/lib/galaxy/webapps/main/api/datasets.py @@ -139,12 +139,11 @@ if mode == "Coverage": # Get summary using minimal cutoffs. indexer = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='index' ) - summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ], detail_cutoff=0, draw_cutoff=0 ) + summary = indexer.get_data( chrom, low, high, detail_cutoff=0, draw_cutoff=0, **kwargs ) if summary == "detail": # Use maximum level of detail--2--to get summary data no matter the resolution. summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ], level=2, detail_cutoff=0, draw_cutoff=0 ) - frequencies, max_v, avg_v, delta = summary - return { 'dataset_type': indexer.data_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta } + return summary if 'index' in data_sources and data_sources['index']['name'] == "summary_tree" and mode == "Auto": # Only check for summary_tree if it's Auto mode (which is the default) @@ -153,14 +152,13 @@ indexer = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='index' ) summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ] ) if summary is None: - return { 'dataset_type': indexer.data_type, 'data': None } + return { 'dataset_type': indexer.dataset_type, 'data': None } if summary == "draw": kwargs["no_detail"] = True # meh extra_info = "no_detail" elif summary != "detail": - frequencies, max_v, avg_v, delta = summary - return { 'dataset_type': indexer.data_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta } + return summary # Get data provider. data_provider = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='data' ) @@ -171,7 +169,7 @@ # Get and return data from data_provider. result = data_provider.get_data( chrom, int( low ), int( high ), int( start_val ), int( max_vals ), **kwargs ) - result.update( { 'dataset_type': data_provider.data_type, 'extra_info': extra_info } ) + result.update( { 'dataset_type': data_provider.dataset_type, 'extra_info': extra_info } ) return result def _raw_data( self, trans, dataset, **kwargs ): diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/webapps/main/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/main/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/main/controllers/admin_toolshed.py @@ -342,8 +342,10 @@ message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) repository = get_repository( trans, kwd[ 'id' ] ) + has_readme = repository.metadata and 'readme' in repository.metadata return trans.fill_template( '/admin/tool_shed_repository/browse_repository.mako', repository=repository, + has_readme=has_readme, message=message, status=status ) @web.expose @@ -388,8 +390,11 @@ message += "Choose <b>Uninstall this tool dependency</b> from the <b>Repository Actions</b> menu, correct problems " message += "if necessary, and try installing the dependency again." status = "error" + tool_shed_repository = tool_dependency.tool_shed_repository + has_readme = tool_shed_repository.metadata and 'readme' in tool_shed_repository.metadata return trans.fill_template( '/admin/tool_shed_repository/browse_tool_dependency.mako', - repository=tool_dependency.tool_shed_repository, + repository=tool_shed_repository, + has_readme=has_readme, tool_dependency=tool_dependency, in_error_state=in_error_state, can_uninstall=can_uninstall, @@ -487,9 +492,11 @@ message=message, status=status ) ) remove_from_disk_check_box = CheckboxField( 'remove_from_disk', checked=remove_from_disk_checked ) + has_readme = tool_shed_repository.metadata and 'readme' in tool_shed_repository.metadata return trans.fill_template( '/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako', repository=tool_shed_repository, remove_from_disk_check_box=remove_from_disk_check_box, + has_readme=has_readme, message=message, status=status ) @web.expose @@ -716,6 +723,7 @@ when an admin is installing a new repository or reinstalling an uninstalled repository. """ metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=trans.app, + repository=tool_shed_repository, repository_clone_url=repository_clone_url, relative_install_dir=relative_install_dir, repository_files_dir=None, @@ -837,8 +845,10 @@ trans.sa_session.add( repository ) trans.sa_session.flush() message = "Repository metadata has been reset." + has_readme = repository.metadata and 'readme' in repository.metadata return trans.fill_template( '/admin/tool_shed_repository/manage_repository.mako', repository=repository, + has_readme=has_readme, in_error_state=in_error_state, can_install=can_install, description=description, @@ -914,14 +924,14 @@ tool_shed_repository = tool_dependency.tool_shed_repository self.tool_dependency_grid.title = "Tool shed repository '%s' tool dependencies" % tool_shed_repository.name self.tool_dependency_grid.global_actions = \ - [ grids.GridAction( label='Browse repository', + [ grids.GridAction( label='Manage repository', + url_args=dict( controller='admin_toolshed', + action='manage_repository', + id=trans.security.encode_id( tool_shed_repository.id ) ) ), + grids.GridAction( label='Browse repository', url_args=dict( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( tool_shed_repository.id ) ) ), - grids.GridAction( label='Manage repository', - url_args=dict( controller='admin_toolshed', - action='manage_repository', - id=trans.security.encode_id( tool_shed_repository.id ) ) ), grids.GridAction( label='Get repository updates', url_args=dict( controller='admin_toolshed', action='check_for_updates', @@ -934,6 +944,12 @@ url_args=dict( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( tool_shed_repository.id ) ) ) ] + if tool_shed_repository.metadata and 'readme' in tool_shed_repository.metadata: + view_readme_action = grids.GridAction( label='View README', + url_args=dict( controller='admin_toolshed', + action='view_readme', + id=trans.security.encode_id( tool_shed_repository.id ) ) ) + self.tool_dependency_grid.global_actions.insert( 1, view_readme_action ) if 'operation' in kwd: operation = kwd[ 'operation' ].lower() if not tool_dependency_ids: @@ -1010,9 +1026,8 @@ message += '<b><toolbox></b> tag that includes a <b>tool_path</b> attribute value which is a directory relative to the Galaxy installation ' message += 'directory in order to automatically install tools from a Galaxy tool shed (e.g., the file name <b>shed_tool_conf.xml</b> whose ' message += '<b><toolbox></b> tag is <b><toolbox tool_path="../shed_tools"></b>).<p/>See the ' - message += '<a href="http://wiki.g2.bx.psu.edu/Tool%20Shed#Automatic_installation_of_Galaxy_tool_..." ' - message += 'target="_blank">Automatic installation of Galaxy tool shed repository tools into a local Galaxy instance</a> section of the ' - message += '<a href="http://wiki.g2.bx.psu.edu/Tool%20Shed" target="_blank">Galaxy tool shed wiki</a> for all of the details.' + message += '<a href="http://wiki.g2.bx.psu.edu/InstallingRepositoriesToGalaxy" target="_blank">Installation of Galaxy tool shed repository tools ' + message += 'into a local Galaxy instance</a> section of the Galaxy tool shed wiki for all of the details.' return trans.show_error_message( message ) message = kwd.get( 'message', '' ) status = kwd.get( 'status', 'done' ) @@ -1182,13 +1197,7 @@ response = urllib2.urlopen( url ) raw_text = response.read() response.close() - readme_text = '' - for i, line in enumerate( raw_text ): - readme_text = '%s%s' % ( readme_text, to_html_str( line ) ) - if len( readme_text ) > MAX_CONTENT_SIZE: - large_str = '\nFile contents truncated because file size is larger than maximum viewing size of %s\n' % util.nice_size( MAX_CONTENT_SIZE ) - readme_text = '%s%s' % ( readme_text, to_html_str( large_str ) ) - break + readme_text = translate_string( raw_text, to_html=True ) else: readme_text = '' if trans.app.config.tool_dependency_dir is None: @@ -1419,8 +1428,19 @@ status = 'warning' includes_tool_dependencies = 'tool_dependencies' in metadata install_tool_dependencies_check_box = CheckboxField( 'install_tool_dependencies', checked=True ) + if metadata and 'readme' in metadata: + url = url_join( tool_shed_url, + 'repository/get_readme?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \ + ( repository.name, repository.owner, repository.installed_changeset_revision ) ) + response = urllib2.urlopen( url ) + raw_text = response.read() + response.close() + readme_text = translate_string( raw_text, to_html=True ) + else: + readme_text = '' return trans.fill_template( '/admin/tool_shed_repository/reselect_tool_panel_section.mako', repository=repository, + readme_text=readme_text, no_changes_check_box=no_changes_check_box, original_section_name=original_section_name, install_tool_dependencies_check_box=install_tool_dependencies_check_box, @@ -1528,6 +1548,8 @@ for tool_dependency_id in tool_dependency_ids: tool_dependency = get_tool_dependency( trans, tool_dependency_id ) tool_dependencies.append( tool_dependency ) + tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository + has_readme = tool_shed_repository.metadata and 'readme' in tool_shed_repository.metadata if kwd.get( 'uninstall_tool_dependencies_button', False ): errors = False # Filter tool dependencies to only those that are installed. @@ -1546,7 +1568,6 @@ status = 'error' else: message = "These tool dependencies have been uninstalled: %s" % ','.join( td.name for td in tool_dependencies_for_uninstallation ) - tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository td_ids = [ trans.security.encode_id( td.id ) for td in tool_shed_repository.tool_dependencies ] return trans.response.send_redirect( web.url_for( controller='admin_toolshed', action='manage_tool_dependencies', @@ -1554,6 +1575,9 @@ status=status, message=message ) ) return trans.fill_template( '/admin/tool_shed_repository/uninstall_tool_dependencies.mako', + repository=tool_shed_repository, + has_readme=has_readme, + tool_dependency_ids=tool_dependency_ids, tool_dependencies=tool_dependencies, message=message, status=status ) @@ -1617,27 +1641,55 @@ status=status ) ) @web.expose @web.require_admin + def view_readme( self, trans, id, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + cntrller = params.get( 'cntrller', 'admin_toolshed' ) + status = params.get( 'status', 'done' ) + repository = get_repository( trans, id ) + metadata = repository.metadata + if metadata and 'readme' in metadata: + f = open( metadata[ 'readme' ], 'r' ) + raw_text = f.read() + f.close() + readme_text = translate_string( raw_text, to_html=True ) + else: + readme_text = '' + is_malicious = False + return trans.fill_template( '/webapps/community/common/view_readme.mako', + cntrller=cntrller, + repository=repository, + changeset_revision=repository.changeset_revision, + readme_text=readme_text, + is_malicious=is_malicious, + webapp='galaxy', + message=message, + status=status ) + @web.expose + @web.require_admin def view_tool_metadata( self, trans, repository_id, tool_id, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) webapp = get_webapp( trans, **kwd ) repository = get_repository( trans, repository_id ) - metadata = {} + repository_metadata = repository.metadata + tool_metadata = {} tool_lineage = [] tool = None - if 'tools' in repository.metadata: - for tool_metadata_dict in repository.metadata[ 'tools' ]: + if 'tools' in repository_metadata: + for tool_metadata_dict in repository_metadata[ 'tools' ]: if tool_metadata_dict[ 'id' ] == tool_id: - metadata = tool_metadata_dict - tool = trans.app.toolbox.load_tool( os.path.abspath( metadata[ 'tool_config' ] ), guid=metadata[ 'guid' ] ) + tool_metadata = tool_metadata_dict + tool = trans.app.toolbox.load_tool( os.path.abspath( tool_metadata[ 'tool_config' ] ), guid=metadata[ 'guid' ] ) if tool: tool_lineage = self.get_versions_of_tool( trans.app, tool.id ) break return trans.fill_template( "/admin/tool_shed_repository/view_tool_metadata.mako", repository=repository, + repository_metadata=repository_metadata, tool=tool, - metadata=metadata, + tool_metadata=tool_metadata, tool_lineage=tool_lineage, message=message, status=status ) diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/webapps/main/controllers/library_common.py --- a/lib/galaxy/webapps/main/controllers/library_common.py +++ b/lib/galaxy/webapps/main/controllers/library_common.py @@ -92,6 +92,7 @@ #"force_history_refresh": force_history_refresh } return rval + @web.expose def browse_library( self, trans, cntrller, **kwd ): params = util.Params( kwd ) @@ -129,6 +130,7 @@ status = "info" comptypes = get_comptypes( trans ) try: + # SM: TODO: Add configuration variable asap. return trans.fill_template( '/library/common/browse_library.mako', cntrller=cntrller, use_panels=use_panels, @@ -144,6 +146,7 @@ message = 'Error attempting to display contents of library (%s): %s.' % ( str( library.name ), str( e ) ) status = 'error' default_action = params.get( 'default_action', None ) + return trans.response.send_redirect( web.url_for( use_panels=use_panels, controller=cntrller, action='browse_libraries', @@ -2534,16 +2537,57 @@ .options( eagerload_all( "actions" ) ) \ .order_by( trans.app.model.LibraryFolder.table.c.name ) \ .all() + +def map_library_datasets_to_lddas( trans, lib_datasets ): + ''' + Given a list of LibraryDatasets, return a map from the LibraryDatasets + to their LDDAs. If an LDDA does not exist for a LibraryDataset, then + there will be no entry in the return hash. + ''' + # Get a list of the LibraryDatasets' ids so that we can pass it along to + # a query to retrieve the LDDAs. This eliminates querying for each + # LibraryDataset. + lib_dataset_ids = [ x.library_dataset_dataset_association_id for x in lib_datasets ] + lddas = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \ + .filter( trans.app.model.LibraryDatasetDatasetAssociation.id.in_( lib_dataset_ids ) ) \ + .all() + + # Map the LibraryDataset to the returned LDDAs: + ret_lddas = {} + for ldda in lddas: + ret_lddas[ldda.library_dataset_id] = ldda + return ret_lddas + +def datasets_for_lddas( trans, lddas ): + ''' + Given a list of LDDAs, return a list of Datasets for them. + ''' + dataset_ids = [ x.dataset_id for x in lddas ] + datasets = trans.sa_session.query( trans.app.model.Dataset ) \ + .filter( trans.app.model.Dataset.id.in_( dataset_ids ) ) \ + .all() + return datasets + def active_folders_and_library_datasets( trans, folder ): + # SM: TODO: Eliminate timing code + from datetime import datetime, timedelta + query_start = datetime.now() folders = active_folders( trans, folder ) library_datasets = trans.sa_session.query( trans.model.LibraryDataset ) \ .filter( and_( trans.model.LibraryDataset.table.c.deleted == False, trans.model.LibraryDataset.table.c.folder_id == folder.id ) ) \ .order_by( trans.model.LibraryDataset.table.c._name ) \ .all() + query_end = datetime.now() + query_delta = query_end - query_start + #log.debug( "active_folders_and_library_datasets: %d.%.6d" % + # ( query_delta.seconds, query_delta.microseconds ) ) return folders, library_datasets + def activatable_folders_and_library_datasets( trans, folder ): folders = activatable_folders( trans, folder ) + from datetime import datetime, timedelta + query_start = datetime.now() library_datasets = trans.sa_session.query( trans.model.LibraryDataset ) \ .filter( trans.model.LibraryDataset.table.c.folder_id == folder.id ) \ .join( ( trans.model.LibraryDatasetDatasetAssociation.table, @@ -2553,6 +2597,10 @@ .filter( trans.model.Dataset.table.c.deleted == False ) \ .order_by( trans.model.LibraryDataset.table.c._name ) \ .all() + query_end = datetime.now() + query_delta = query_end - query_start + log.debug( "activatable_folders_and_library_datasets: %d.%.6d" % + ( query_delta.seconds, query_delta.microseconds ) ) return folders, library_datasets def branch_deleted( folder ): # Return True if a folder belongs to a branch that has been deleted diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/webapps/main/controllers/tool_runner.py --- a/lib/galaxy/webapps/main/controllers/tool_runner.py +++ b/lib/galaxy/webapps/main/controllers/tool_runner.py @@ -43,6 +43,7 @@ toolbox = self.get_toolbox() tool_version_select_field = None tools = [] + tool = None # Backwards compatibility for datasource tools that have default tool_id configured, but which are now using only GALAXY_URL. tool_ids = util.listify( tool_id ) for tool_id in tool_ids: @@ -50,27 +51,21 @@ tools = toolbox.get_loaded_tools_by_lineage( tool_id ) else: tools = toolbox.get_tool( tool_id, tool_version=tool_version, get_all_versions=True ) - if len( tools ) > 1: - tool_version_select_field = self.build_tool_version_select_field( tools, tool_id, set_selected ) - for tool in tools: - if tool.id == tool_id: - break - else: - tool = tools[ 0 ] - else: - tool = tools[ 0 ] - break + if tools: + tool = toolbox.get_tool( tool_id, tool_version=tool_version, get_all_versions=False ) + if len( tools ) > 1: + tool_version_select_field = self.build_tool_version_select_field( tools, tool.id, set_selected ) + break return tool_version_select_field, tools, tool @web.expose def index(self, trans, tool_id=None, from_noframe=None, **kwd): # No tool id passed, redirect to main page if tool_id is None: return trans.response.send_redirect( url_for( "/static/welcome.html" ) ) - set_selected = 'refresh' in kwd tool_version_select_field, tools, tool = self.__get_tool_components( tool_id, tool_version=None, - get_loaded_tools_by_lineage=True, - set_selected=set_selected ) + get_loaded_tools_by_lineage=False, + set_selected=True ) # No tool matching the tool id, display an error (shouldn't happen) if not tool: log.error( "index called with tool id '%s' but no such tool exists", tool_id ) diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/webapps/main/controllers/user.py --- a/lib/galaxy/webapps/main/controllers/user.py +++ b/lib/galaxy/webapps/main/controllers/user.py @@ -1,16 +1,22 @@ """ Contains the user interface in the Universe class """ + +import glob +import logging +import os +import socket +import string +import random +from galaxy import web +from galaxy import util, model +from galaxy.model.orm import and_ +from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname +from galaxy.util.json import from_json_string, to_json_string +from galaxy.web import url_for +from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin, get_webapp +from galaxy.web.form_builder import CheckboxField, build_select_field from galaxy.web.framework.helpers import time_ago, grids -from galaxy.web.base.controller import * -from galaxy.model.orm import * -from galaxy import util, model -import logging, os, string, re, socket, glob -from random import choice -from galaxy.web.form_builder import * -from galaxy.util.json import from_json_string, to_json_string -from galaxy.web.framework.helpers import iff -from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname log = logging.getLogger( __name__ ) @@ -395,6 +401,7 @@ use_panels=use_panels, message=message, status=status ) ) + @web.expose @web.require_login( 'manage OpenIDs' ) def openid_manage( self, trans, webapp='galaxy', **kwd ): @@ -409,10 +416,10 @@ action='openid_disassociate', use_panels=use_panels, id=kwd['id'] ) ) - kwd['redirect'] = kwd.get( 'redirect', url_for( controller='user', action='openid_manage', use_panels=True ) ).strip() kwd['openid_providers'] = trans.app.openid_providers return self.user_openid_grid( trans, **kwd ) + @web.expose def login( self, trans, webapp='galaxy', redirect_url='', refresh_frames=[], **kwd ): '''Handle Galaxy Log in''' @@ -423,6 +430,9 @@ header = '' user = None email = kwd.get( 'email', '' ) + #Sanitize webapp login here, once, since it can be reflected to the user in messages/etc. + #Only text is valid. + webapp = util.sanitize_text(webapp) if kwd.get( 'login_button', False ): if webapp == 'galaxy' and not refresh_frames: if trans.app.config.require_login: @@ -489,6 +499,7 @@ message += ' <a target="_top" href="%s">Click here</a> to continue to the home page.' % web.url_for( '/static/welcome.html' ) success = True return ( message, status, user, success ) + @web.expose def logout( self, trans, webapp='galaxy', logout_all=False ): if webapp == 'galaxy': @@ -509,6 +520,7 @@ message=message, status='done', active_view="user" ) + @web.expose def create( self, trans, cntrller='user', redirect_url='', refresh_frames=[], **kwd ): params = util.Params( kwd ) @@ -579,8 +591,6 @@ return trans.fill_template( '/user/register.mako', cntrller=cntrller, email=email, - password=password, - confirm=confirm, username=transform_publicname( trans, username ), subscribe_checked=subscribe_checked, user_type_fd_id_select_field=user_type_fd_id_select_field, @@ -593,6 +603,7 @@ refresh_frames=refresh_frames, message=message, status=status ) + def __register( self, trans, cntrller, subscribe_checked, **kwd ): email = util.restore_text( kwd.get( 'email', '' ) ) password = kwd.get( 'password', '' ) @@ -683,6 +694,7 @@ else: widgets = user_type_form_definition.get_widgets( None, contents={}, **kwd ) return widgets + @web.expose def manage_user_info( self, trans, cntrller, **kwd ): '''Manage a user's login, password, public username, type, addresses, etc.''' @@ -696,11 +708,6 @@ raise AssertionError, "The user id (%s) is not valid" % str( user_id ) webapp = get_webapp( trans, **kwd ) email = util.restore_text( params.get( 'email', user.email ) ) - # Do not sanitize passwords, so take from kwd - # instead of params ( which were sanitized ) - current = kwd.get( 'current', '' ) - password = kwd.get( 'password', '' ) - confirm = kwd.get( 'confirm', '' ) username = util.restore_text( params.get( 'username', '' ) ) if not username: username = user.username @@ -710,7 +717,7 @@ user_type_form_definition = self.__get_user_type_form_definition( trans, user=user, **kwd ) user_type_fd_id = params.get( 'user_type_fd_id', 'none' ) if user_type_fd_id == 'none' and user_type_form_definition is not None: - user_type_fd_id = trans.security.encode_id( user_type_form_definition.id ) + user_type_fd_id = trans.security.encode_id( user_type_form_definition.id ) user_type_fd_id_select_field = self.__build_user_type_fd_id_select_field( trans, selected_value=user_type_fd_id ) widgets = self.__get_widgets( trans, user_type_form_definition, user=user, **kwd ) # user's addresses @@ -728,14 +735,11 @@ cntrller=cntrller, user=user, email=email, - current=current, - password=password, - confirm=confirm, username=username, user_type_fd_id_select_field=user_type_fd_id_select_field, user_info_forms=user_info_forms, user_type_form_definition=user_type_form_definition, - widgets=widgets, + widgets=widgets, addresses=addresses, show_filter=show_filter, webapp=webapp, @@ -746,13 +750,11 @@ cntrller=cntrller, user=user, email=email, - current=current, - password=password, - confirm=confirm, username=username, webapp=webapp, message=message, status=status ) + # For REMOTE_USER, we need the ability to just edit the username @web.expose @web.require_login( "to manage the public name" ) @@ -911,7 +913,7 @@ chars = string.letters + string.digits new_pass = "" for i in range(15): - new_pass = new_pass + choice(chars) + new_pass = new_pass + random.choice(chars) host = trans.request.host.split(':')[0] if host == 'localhost': host = socket.getfqdn() diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/webapps/main/controllers/visualization.py --- a/lib/galaxy/webapps/main/controllers/visualization.py +++ b/lib/galaxy/webapps/main/controllers/visualization.py @@ -763,7 +763,7 @@ original_dataset=dataset, source='index' ) # HACK: pass in additional params, which are only used for summary tree data, not BBI data. - track[ 'genome_wide_data' ] = { 'data': data_provider.get_genome_data( chroms_info, level=4, detail_cutoff=0, draw_cutoff=0 ) } + track[ 'preloaded_data' ] = data_provider.get_genome_data( chroms_info, level=4, detail_cutoff=0, draw_cutoff=0 ) return trans.fill_template( 'visualization/circster.mako', viz_config=viz_config, genome=genome ) diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 lib/galaxy/workflow/modules.py --- a/lib/galaxy/workflow/modules.py +++ b/lib/galaxy/workflow/modules.py @@ -199,13 +199,9 @@ # TODO: If workflows are ever enhanced to use tool version # in addition to tool id, enhance the selection process here # to retrieve the correct version of the tool. - tool_version = Class.__get_tool_version( trans, tool_id ) - if tool_version: - tool_version_ids = tool_version.get_version_ids( trans.app ) - for tool_version_id in tool_version_ids: - if tool_version_id in trans.app.toolbox.tools_by_id: - tool_id = tool_version_id - break + tool = trans.app.toolbox.get_tool( tool_id ) + if tool: + tool_id = tool.id if ( trans.app.toolbox and tool_id in trans.app.toolbox.tools_by_id ): module = Class( trans, tool_id ) module.state = DefaultToolState() diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/june_2007_style/base.less --- a/static/june_2007_style/base.less +++ b/static/june_2007_style/base.less @@ -763,8 +763,16 @@ #search-clear-btn { position: absolute; - right: 4px; - top: 8px; + right: 5px; + top: 9px; + display: block; + font-size: 1.4em; + text-decoration: none; + color: #888; + .ficon(); + &:before { + content: "\f057"; + } } // Messages diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/june_2007_style/blue/base.css --- a/static/june_2007_style/blue/base.css +++ b/static/june_2007_style/blue/base.css @@ -715,7 +715,7 @@ .search-query{display:inline-block;padding:4px;font-size:12px;line-height:16px;color:#555555;border:1px solid #999999;padding-left:14px !important;padding-right:14px !important;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;max-width:auto;} .search-query:focus{border-color:rgba(24, 132, 218, 0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);outline:0;outline:thin dotted \9;} .search-spinner{position:absolute;display:none;right:5px;top:9px;} -#search-clear-btn{position:absolute;right:4px;top:8px;} +#search-clear-btn{position:absolute;right:5px;top:9px;display:block;font-size:1.4em;text-decoration:none;color:#888;font-family:FontAwesome;font-weight:normal;font-style:normal;display:inline-block;}#search-clear-btn:before{content:"\f057";} .errormessagelarge,.warningmessagelarge,.donemessagelarge,.infomessagelarge{padding:8px 35px 8px 14px;margin-bottom:16px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#ffffcc;border:1px solid #ffdd33;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;color:#666600;min-height:36px;padding-left:52px;background-image:url(error_large.png);background-repeat:no-repeat;background-position:10px 10px;} .errormessagelarge{background-color:#ffcccc;border-color:#ff3355;color:#660000;padding-left:52px;} .warningmessagelarge{background-image:url(warn_large.png);border-color:#aaaa66;background-color:#ffffcc;} diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/galaxy.base.js --- a/static/scripts/galaxy.base.js +++ b/static/scripts/galaxy.base.js @@ -65,15 +65,19 @@ }); }; +/** + * Sets up popupmenu rendering and binds options functions to the appropriate links + */ function make_popupmenu(button_element, initial_options) { - /* Use the $.data feature to store options with the link element. This allows options to be changed at a later time */ var element_menu_exists = (button_element.data("menu_options")); button_element.data("menu_options", initial_options); + // If element already has menu, nothing else to do since HTML and actions are already set. if (element_menu_exists) { return; } + button_element.bind("click.show_popup", function(e) { // Close existing visible menus $(".popmenu-wrapper").remove(); @@ -93,16 +97,17 @@ menu_element.append( $("<li></li>").addClass( "head" ).append( $("<a href='#'></a>").html(k) ) ); } }); - var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>" ).append( menu_element ).appendTo( "body" ); + var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>" ) + .append( menu_element ).appendTo( "body" ); var x = e.pageX - wrapper.width() / 2 ; x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 5 ); x = Math.max( x, $(document).scrollLeft() + 5 ); - wrapper.css( { + wrapper.css({ top: e.pageY, left: x - } ); + }); }, 10); setTimeout( function() { @@ -127,26 +132,53 @@ } -function make_popup_menus() { - jQuery( "div[popupmenu]" ).each( function() { +/** + * Convert two seperate (often adjacent) divs into galaxy popupmenu + * - div 1 contains a number of anchors which become the menu options + * - div 1 should have a 'popupmenu' attribute + * - this popupmenu attribute contains the id of div 2 + * - div 2 becomes the 'face' of the popupmenu + * + * NOTE: make_popup_menus finds and operates on all divs with a popupmenu attr (no need to point it at something) + * but (since that selector searches the dom on the page), you can send a parent in + * NOTE: make_popup_menus, and make_popupmenu are horrible names + */ +function make_popup_menus( parent ) { + // find all popupmenu menu divs (divs that contains anchors to be converted to menu options) + // either in the parent or the document if no parent passed + parent = parent || document; + $( parent ).find( "div[popupmenu]" ).each( function() { var options = {}; var menu = $(this); + + // find each anchor in the menu, convert them into an options map: { a.text : click_function } menu.find( "a" ).each( function() { var link = $(this), - link_dom = link.get(0); - var confirmtext = link_dom.getAttribute( "confirm" ), + // why do we need the DOM (mixed with jq)? + link_dom = link.get(0), + confirmtext = link_dom.getAttribute( "confirm" ), href = link_dom.getAttribute( "href" ), target = link_dom.getAttribute( "target" ); + + // no href - no function (gen. a label) if (!href) { options[ link.text() ] = null; + } else { options[ link.text() ] = function() { + + // if theres confirm text, send the dialog if ( !confirmtext || confirm( confirmtext ) ) { var f; + // relocate the center panel if ( target == "_parent" ) { window.parent.location = href; + + // relocate the entire window } else if ( target == "_top" ) { window.top.location = href; + + //??...wot? } else if ( target == "demo" ) { // Http request target is a window named // demolocal on the local box @@ -154,6 +186,8 @@ f = window.open( href,target ); f.creator = self; } + + // relocate this panel } else { window.location = href; } @@ -161,6 +195,7 @@ }; } }); + // locate the element with the id corresponding to the menu's popupmenu attr var box = $( "#" + menu.attr( 'popupmenu' ) ); // For menus with clickable link text, make clicking on the link go through instead @@ -170,6 +205,7 @@ return true; }); + // attach the click events and menu box building to the box element make_popupmenu(box, options); box.addClass("popup"); menu.remove(); diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/libs/underscore.js --- a/static/scripts/libs/underscore.js +++ b/static/scripts/libs/underscore.js @@ -1,10 +1,7 @@ -// Underscore.js 1.3.1 +// Underscore.js 1.4.0 +// http://underscorejs.org // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore is freely distributable under the MIT license. -// Portions of Underscore are inspired or borrowed from Prototype, -// Oliver Steele's Functional, and John Resig's Micro-Templating. -// For all details and documentation: -// http://documentcloud.github.com/underscore +// Underscore may be freely distributed under the MIT license. (function() { @@ -24,7 +21,9 @@ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; // Create quick reference variables for speed access to core prototypes. - var slice = ArrayProto.slice, + var push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, unshift = ArrayProto.unshift, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; @@ -46,7 +45,11 @@ nativeBind = FuncProto.bind; // Create a safe reference to the Underscore object for use below. - var _ = function(obj) { return new wrapper(obj); }; + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; // Export the Underscore object for **Node.js**, with // backwards-compatibility for the old `require()` API. If we're in @@ -62,7 +65,7 @@ } // Current version. - _.VERSION = '1.3.1'; + _.VERSION = '1.4.0'; // Collection Functions // -------------------- @@ -71,12 +74,11 @@ // Handles objects with the built-in `forEach`, arrays, and raw objects. // Delegates to **ECMAScript 5**'s native `forEach` if available. var each = _.each = _.forEach = function(obj, iterator, context) { - if (obj == null) return; if (nativeForEach && obj.forEach === nativeForEach) { obj.forEach(iterator, context); } else if (obj.length === +obj.length) { for (var i = 0, l = obj.length; i < l; i++) { - if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; + if (iterator.call(context, obj[i], i, obj) === breaker) return; } } else { for (var key in obj) { @@ -91,12 +93,10 @@ // Delegates to **ECMAScript 5**'s native `map` if available. _.map = _.collect = function(obj, iterator, context) { var results = []; - if (obj == null) return results; if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); each(obj, function(value, index, list) { results[results.length] = iterator.call(context, value, index, list); }); - if (obj.length === +obj.length) results.length = obj.length; return results; }; @@ -104,7 +104,6 @@ // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { var initial = arguments.length > 2; - if (obj == null) obj = []; if (nativeReduce && obj.reduce === nativeReduce) { if (context) iterator = _.bind(iterator, context); return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); @@ -125,14 +124,26 @@ // Delegates to **ECMAScript 5**'s native `reduceRight` if available. _.reduceRight = _.foldr = function(obj, iterator, memo, context) { var initial = arguments.length > 2; - if (obj == null) obj = []; if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { if (context) iterator = _.bind(iterator, context); - return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); } - var reversed = _.toArray(obj).reverse(); - if (context && !initial) iterator = _.bind(iterator, context); - return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator); + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + return memo; }; // Return the first value which passes a truth test. Aliased as `detect`. @@ -152,7 +163,6 @@ // Aliased as `select`. _.filter = _.select = function(obj, iterator, context) { var results = []; - if (obj == null) return results; if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); each(obj, function(value, index, list) { if (iterator.call(context, value, index, list)) results[results.length] = value; @@ -163,7 +173,6 @@ // Return all the elements for which a truth test fails. _.reject = function(obj, iterator, context) { var results = []; - if (obj == null) return results; each(obj, function(value, index, list) { if (!iterator.call(context, value, index, list)) results[results.length] = value; }); @@ -174,13 +183,13 @@ // Delegates to **ECMAScript 5**'s native `every` if available. // Aliased as `all`. _.every = _.all = function(obj, iterator, context) { + iterator || (iterator = _.identity); var result = true; - if (obj == null) return result; if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); each(obj, function(value, index, list) { if (!(result = result && iterator.call(context, value, index, list))) return breaker; }); - return result; + return !!result; }; // Determine if at least one element in the object matches a truth test. @@ -189,7 +198,6 @@ var any = _.some = _.any = function(obj, iterator, context) { iterator || (iterator = _.identity); var result = false; - if (obj == null) return result; if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); each(obj, function(value, index, list) { if (result || (result = iterator.call(context, value, index, list))) return breaker; @@ -197,11 +205,10 @@ return !!result; }; - // Determine if a given value is included in the array or object using `===`. - // Aliased as `contains`. - _.include = _.contains = function(obj, target) { + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { var found = false; - if (obj == null) return found; if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; found = any(obj, function(value) { return value === target; @@ -213,7 +220,7 @@ _.invoke = function(obj, method) { var args = slice.call(arguments, 2); return _.map(obj, function(value) { - return (_.isFunction(method) ? method || value : value[method]).apply(value, args); + return (_.isFunction(method) ? method : value[method]).apply(value, args); }); }; @@ -222,9 +229,25 @@ return _.map(obj, function(value){ return value[key]; }); }; + // Convenience version of a common use case of `filter`: selecting only objects + // with specific `key:value` pairs. + _.where = function(obj, attrs) { + if (_.isEmpty(attrs)) return []; + return _.filter(obj, function(value) { + for (var key in attrs) { + if (attrs[key] !== value[key]) return false; + } + return true; + }); + }; + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See: https://bugs.webkit.org/show_bug.cgi?id=80797 _.max = function(obj, iterator, context) { - if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj); + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } if (!iterator && _.isEmpty(obj)) return -Infinity; var result = {computed : -Infinity}; each(obj, function(value, index, list) { @@ -236,7 +259,9 @@ // Return the minimum element (or element-based computation). _.min = function(obj, iterator, context) { - if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } if (!iterator && _.isEmpty(obj)) return Infinity; var result = {computed : Infinity}; each(obj, function(value, index, list) { @@ -248,81 +273,107 @@ // Shuffle an array. _.shuffle = function(obj) { - var shuffled = [], rand; - each(obj, function(value, index, list) { - if (index == 0) { - shuffled[0] = value; - } else { - rand = Math.floor(Math.random() * (index + 1)); - shuffled[index] = shuffled[rand]; - shuffled[rand] = value; - } + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; }); return shuffled; }; + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + return _.isFunction(value) ? value : function(obj){ return obj[value]; }; + }; + // Sort the object's values by a criterion produced by an iterator. - _.sortBy = function(obj, iterator, context) { + _.sortBy = function(obj, value, context) { + var iterator = lookupIterator(value); return _.pluck(_.map(obj, function(value, index, list) { return { value : value, + index : index, criteria : iterator.call(context, value, index, list) }; }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index < right.index ? -1 : 1; }), 'value'); }; + // An internal function used for aggregate "group by" operations. + var group = function(obj, value, context, behavior) { + var result = {}; + var iterator = lookupIterator(value); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + // Groups the object's values by a criterion. Pass either a string attribute // to group by, or a function that returns the criterion. - _.groupBy = function(obj, val) { - var result = {}; - var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; - each(obj, function(value, index) { - var key = iterator(value, index); - (result[key] || (result[key] = [])).push(value); + _.groupBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { + (_.has(result, key) ? result[key] : (result[key] = [])).push(value); }); - return result; }; - // Use a comparator function to figure out at what index an object should - // be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iterator) { - iterator || (iterator = _.identity); + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { + if (!_.has(result, key)) result[key] = 0; + result[key]++; + }); + }; + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = iterator == null ? _.identity : lookupIterator(iterator); + var value = iterator.call(context, obj); var low = 0, high = array.length; while (low < high) { - var mid = (low + high) >> 1; - iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; } return low; }; // Safely convert anything iterable into a real, live array. - _.toArray = function(iterable) { - if (!iterable) return []; - if (iterable.toArray) return iterable.toArray(); - if (_.isArray(iterable)) return slice.call(iterable); - if (_.isArguments(iterable)) return slice.call(iterable); - return _.values(iterable); + _.toArray = function(obj) { + if (!obj) return []; + if (obj.length === +obj.length) return slice.call(obj); + return _.values(obj); }; // Return the number of elements in an object. _.size = function(obj) { - return _.toArray(obj).length; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; }; // Array Functions // --------------- // Get the first element of an array. Passing **n** will return the first N - // values in the array. Aliased as `head`. The **guard** check allows it to work - // with `_.map`. - _.first = _.head = function(array, n, guard) { + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; }; - // Returns everything but the last entry of the array. Especcialy useful on + // Returns everything but the last entry of the array. Especially useful on // the arguments object. Passing **n** will return all the values in // the array, excluding the last N. The **guard** check allows it to work with // `_.map`. @@ -340,12 +391,12 @@ } }; - // Returns everything but the first entry of the array. Aliased as `tail`. - // Especially useful on the arguments object. Passing an **index** will return - // the rest of the values in the array from that index onward. The **guard** + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** // check allows it to work with `_.map`. - _.rest = _.tail = function(array, index, guard) { - return slice.call(array, (index == null) || guard ? 1 : index); + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); }; // Trim out all falsy values from an array. @@ -353,13 +404,21 @@ return _.filter(array, function(value){ return !!value; }); }; + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + each(input, function(value) { + if (_.isArray(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + // Return a completely flattened version of an array. _.flatten = function(array, shallow) { - return _.reduce(array, function(memo, value) { - if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value)); - memo[memo.length] = value; - return memo; - }, []); + return flatten(array, shallow, []); }; // Return a version of the array that does not contain the specified value(s). @@ -370,28 +429,28 @@ // Produce a duplicate-free version of the array. If the array has already // been sorted, you have the option of using a faster algorithm. // Aliased as `unique`. - _.uniq = _.unique = function(array, isSorted, iterator) { - var initial = iterator ? _.map(array, iterator) : array; - var result = []; - _.reduce(initial, function(memo, el, i) { - if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) { - memo[memo.length] = el; - result[result.length] = array[i]; + _.uniq = _.unique = function(array, isSorted, iterator, context) { + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); } - return memo; - }, []); - return result; + }); + return results; }; // Produce an array that contains the union: each distinct element from all of // the passed-in arrays. _.union = function() { - return _.uniq(_.flatten(arguments, true)); + return _.uniq(concat.apply(ArrayProto, arguments)); }; // Produce an array that contains every item shared between all the - // passed-in arrays. (Aliased as "intersect" for back-compat.) - _.intersection = _.intersect = function(array) { + // passed-in arrays. + _.intersection = function(array) { var rest = slice.call(arguments, 1); return _.filter(_.uniq(array), function(item) { return _.every(rest, function(other) { @@ -403,8 +462,8 @@ // Take the difference between one array and a number of other arrays. // Only the elements present in just the first array will remain. _.difference = function(array) { - var rest = _.flatten(slice.call(arguments, 1)); - return _.filter(array, function(value){ return !_.include(rest, value); }); + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); }; // Zip together multiple lists into a single array -- elements that share @@ -413,10 +472,27 @@ var args = slice.call(arguments); var length = _.max(_.pluck(args, 'length')); var results = new Array(length); - for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(args, "" + i); + } return results; }; + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + var result = {}; + for (var i = 0, l = list.length; i < l; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), // we need this function. Return the position of the first occurrence of an // item in an array, or -1 if the item is not included in the array. @@ -424,23 +500,25 @@ // If the array is large and already in sort order, pass `true` // for **isSorted** to use binary search. _.indexOf = function(array, item, isSorted) { - if (array == null) return -1; - var i, l; + var i = 0, l = array.length; if (isSorted) { - i = _.sortedIndex(array, item); - return array[i] === item ? i : -1; + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } } - if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item); - for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i; + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < l; i++) if (array[i] === item) return i; return -1; }; // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. - _.lastIndexOf = function(array, item) { - if (array == null) return -1; - if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item); - var i = array.length; - while (i--) if (i in array && array[i] === item) return i; + _.lastIndexOf = function(array, item, fromIndex) { + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item, fromIndex); + var i = (fromIndex != null ? fromIndex : array.length); + while (i--) if (array[i] === item) return i; return -1; }; @@ -514,7 +592,7 @@ // it with the arguments supplied. _.delay = function(func, wait) { var args = slice.call(arguments, 2); - return setTimeout(function(){ return func.apply(func, args); }, wait); + return setTimeout(function(){ return func.apply(null, args); }, wait); }; // Defers a function, scheduling it to run after the current call stack has @@ -526,39 +604,46 @@ // Returns a function, that, when invoked, will only be triggered at most once // during a given window of time. _.throttle = function(func, wait) { - var context, args, timeout, throttling, more; + var context, args, timeout, throttling, more, result; var whenDone = _.debounce(function(){ more = throttling = false; }, wait); return function() { context = this; args = arguments; var later = function() { timeout = null; - if (more) func.apply(context, args); + if (more) { + result = func.apply(context, args); + } whenDone(); }; if (!timeout) timeout = setTimeout(later, wait); if (throttling) { more = true; } else { - func.apply(context, args); + throttling = true; + result = func.apply(context, args); } whenDone(); - throttling = true; + return result; }; }; // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for - // N milliseconds. - _.debounce = function(func, wait) { - var timeout; + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, result; return function() { var context = this, args = arguments; var later = function() { timeout = null; - func.apply(context, args); + if (!immediate) result = func.apply(context, args); }; + var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); + if (callNow) result = func.apply(context, args); + return result; }; }; @@ -569,7 +654,9 @@ return function() { if (ran) return memo; ran = true; - return memo = func.apply(this, arguments); + memo = func.apply(this, arguments); + func = null; + return memo; }; }; @@ -578,7 +665,8 @@ // conditionally execute the original function. _.wrap = function(func, wrapper) { return function() { - var args = [func].concat(slice.call(arguments, 0)); + var args = [func]; + push.apply(args, arguments); return wrapper.apply(this, args); }; }; @@ -600,7 +688,9 @@ _.after = function(times, func) { if (times <= 0) return func(); return function() { - if (--times < 1) { return func.apply(this, arguments); } + if (--times < 1) { + return func.apply(this, arguments); + } }; }; @@ -618,7 +708,23 @@ // Retrieve the values of an object's properties. _.values = function(obj) { - return _.map(obj, _.identity); + var values = []; + for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var pairs = []; + for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; + return result; }; // Return a sorted list of the function names available on the object. @@ -641,6 +747,26 @@ return obj; }; + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + // Fill in a given object with default properties. _.defaults = function(obj) { each(slice.call(arguments, 1), function(source) { @@ -665,19 +791,16 @@ return obj; }; - // Internal recursive comparison function. - function eq(a, b, stack) { + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { // Identical objects are equal. `0 === -0`, but they aren't identical. // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. if (a === b) return a !== 0 || 1 / a == 1 / b; // A strict comparison is necessary because `null == undefined`. if (a == null || b == null) return a === b; // Unwrap any wrapped objects. - if (a._chain) a = a._wrapped; - if (b._chain) b = b._wrapped; - // Invoke a custom `isEqual` method if one is provided. - if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b); - if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a); + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; // Compare `[[Class]]` names. var className = toString.call(a); if (className != toString.call(b)) return false; @@ -707,14 +830,15 @@ if (typeof a != 'object' || typeof b != 'object') return false; // Assume equality for cyclic structures. The algorithm for detecting cyclic // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - var length = stack.length; + var length = aStack.length; while (length--) { // Linear search. Performance is inversely proportional to the number of // unique nested structures. - if (stack[length] == a) return true; + if (aStack[length] == a) return bStack[length] == b; } // Add the first object to the stack of traversed objects. - stack.push(a); + aStack.push(a); + bStack.push(b); var size = 0, result = true; // Recursively compare objects and arrays. if (className == '[object Array]') { @@ -724,20 +848,24 @@ if (result) { // Deep compare the contents, ignoring non-numeric properties. while (size--) { - // Ensure commutative equality for sparse arrays. - if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break; + if (!(result = eq(a[size], b[size], aStack, bStack))) break; } } } else { - // Objects with different constructors are not equivalent. - if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false; + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } // Deep compare objects. for (var key in a) { if (_.has(a, key)) { // Count the expected number of properties. size++; // Deep compare each member. - if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break; + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; } } // Ensure that both objects contain the same number of properties. @@ -749,18 +877,20 @@ } } // Remove the first object from the stack of traversed objects. - stack.pop(); + aStack.pop(); + bStack.pop(); return result; - } + }; // Perform a deep comparison to check if two objects are equal. _.isEqual = function(a, b) { - return eq(a, b, []); + return eq(a, b, [], []); }; // Is a given array, string, or object empty? // An "empty" object has no enumerable own-properties. _.isEmpty = function(obj) { + if (obj == null) return true; if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; for (var key in obj) if (_.has(obj, key)) return false; return true; @@ -768,7 +898,7 @@ // Is a given value a DOM element? _.isElement = function(obj) { - return !!(obj && obj.nodeType == 1); + return !!(obj && obj.nodeType === 1); }; // Is a given value an array? @@ -782,35 +912,36 @@ return obj === Object(obj); }; - // Is a given variable an arguments object? - _.isArguments = function(obj) { - return toString.call(obj) == '[object Arguments]'; - }; + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. if (!_.isArguments(arguments)) { _.isArguments = function(obj) { return !!(obj && _.has(obj, 'callee')); }; } - // Is a given value a function? - _.isFunction = function(obj) { - return toString.call(obj) == '[object Function]'; + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return _.isNumber(obj) && isFinite(obj); }; - // Is a given value a string? - _.isString = function(obj) { - return toString.call(obj) == '[object String]'; - }; - - // Is a given value a number? - _.isNumber = function(obj) { - return toString.call(obj) == '[object Number]'; - }; - - // Is the given value `NaN`? + // Is the given value `NaN`? (NaN is the only number which does not equal itself). _.isNaN = function(obj) { - // `NaN` is the only value for which `===` is not reflexive. - return obj !== obj; + return _.isNumber(obj) && obj != +obj; }; // Is a given value a boolean? @@ -818,16 +949,6 @@ return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; }; - // Is a given value a date? - _.isDate = function(obj) { - return toString.call(obj) == '[object Date]'; - }; - - // Is the given value a regular expression? - _.isRegExp = function(obj) { - return toString.call(obj) == '[object RegExp]'; - }; - // Is a given value equal to null? _.isNull = function(obj) { return obj === null; @@ -838,7 +959,8 @@ return obj === void 0; }; - // Has own property? + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). _.has = function(obj, key) { return hasOwnProperty.call(obj, key); }; @@ -859,20 +981,65 @@ }; // Run a function **n** times. - _.times = function (n, iterator, context) { + _.times = function(n, iterator, context) { for (var i = 0; i < n; i++) iterator.call(context, i); }; - // Escape a string for HTML interpolation. - _.escape = function(string) { - return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/'); + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + (0 | Math.random() * (max - min + 1)); }; - // Add your own custom functions to the Underscore object, ensuring that - // they're correctly added to the OOP wrapper as well. + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named property is a function then invoke it; + // otherwise, return it. + _.result = function(object, property) { + if (object == null) return null; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. _.mixin = function(obj) { each(_.functions(obj), function(name){ - addToWrapper(name, _[name] = obj[name]); + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; }); }; @@ -895,41 +1062,72 @@ // When customizing `templateSettings`, if you don't want to define an // interpolation, evaluation or escaping regex, we need one that is // guaranteed not to match. - var noMatch = /.^/; + var noMatch = /(.)^/; - // Within an interpolation, evaluation, or escaping, remove HTML escaping - // that had been previously added. - var unescape = function(code) { - return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'"); + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' }; + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + // JavaScript micro-templating, similar to John Resig's implementation. // Underscore templating handles arbitrary delimiters, preserves whitespace, // and correctly escapes quotes within interpolated code. - _.template = function(str, data) { - var c = _.templateSettings; - var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + - 'with(obj||{}){__p.push(\'' + - str.replace(/\\/g, '\\\\') - .replace(/'/g, "\\'") - .replace(c.escape || noMatch, function(match, code) { - return "',_.escape(" + unescape(code) + "),'"; - }) - .replace(c.interpolate || noMatch, function(match, code) { - return "'," + unescape(code) + ",'"; - }) - .replace(c.evaluate || noMatch, function(match, code) { - return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('"; - }) - .replace(/\r/g, '\\r') - .replace(/\n/g, '\\n') - .replace(/\t/g, '\\t') - + "');}return __p.join('');"; - var func = new Function('obj', '_', tmpl); - if (data) return func(data, _); - return function(data) { - return func.call(this, data, _); + _.template = function(text, data, settings) { + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + source += + escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" : + interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" : + evaluate ? "';\n" + evaluate + "\n__p+='" : ''; + index = offset + match.length; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + var render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; }; // Add a "chain" function, which will delegate to the wrapper. @@ -937,29 +1135,15 @@ return _(obj).chain(); }; - // The OOP Wrapper + // OOP // --------------- - // If Underscore is called as a function, it returns a wrapped object that // can be used OO-style. This wrapper holds altered versions of all the // underscore functions. Wrapped objects may be chained. - var wrapper = function(obj) { this._wrapped = obj; }; - - // Expose `wrapper.prototype` as `_.prototype` - _.prototype = wrapper.prototype; // Helper function to continue chaining intermediate results. - var result = function(obj, chain) { - return chain ? _(obj).chain() : obj; - }; - - // A method to easily add functions to the OOP wrapper. - var addToWrapper = function(name, func) { - wrapper.prototype[name] = function() { - var args = slice.call(arguments); - unshift.call(args, this._wrapped); - return result(func.apply(_, args), this._chain); - }; + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; }; // Add all of the Underscore functions to the wrapper object. @@ -968,32 +1152,35 @@ // Add all mutator Array functions to the wrapper. each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { var method = ArrayProto[name]; - wrapper.prototype[name] = function() { - var wrapped = this._wrapped; - method.apply(wrapped, arguments); - var length = wrapped.length; - if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0]; - return result(wrapped, this._chain); + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); }; }); // Add all accessor Array functions to the wrapper. each(['concat', 'join', 'slice'], function(name) { var method = ArrayProto[name]; - wrapper.prototype[name] = function() { - return result(method.apply(this._wrapped, arguments), this._chain); + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); }; }); - // Start chaining a wrapped Underscore object. - wrapper.prototype.chain = function() { - this._chain = true; - return this; - }; + _.extend(_.prototype, { - // Extracts the result from a wrapped and chained object. - wrapper.prototype.value = function() { - return this._wrapped; - }; + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); }).call(this); diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/mvc/history.js --- a/static/scripts/mvc/history.js +++ b/static/scripts/mvc/history.js @@ -1,4 +1,8 @@ -/* +//define([ +// "../mvc/base-mvc" +// +//], function(){ +/* ============================================================================= Backbone.js implementation of history panel TODO: @@ -10,6 +14,8 @@ _render_displayApps _render_downloadButton widget building (popupmenu, etc.) + history.mako js: updater, etc. + have info bodies prev. opened, redisplay on refresh don't draw body until it's first unhide event all history.mako js -> this @@ -30,26 +36,7 @@ move inline styles into base.less add classes, ids on empty divs watch the magic strings -*/ - -//============================================================================== - -//============================================================================== -//TODO: move to Galaxy obj./namespace, decorate for current page (as GalaxyPaths) -/* -var Localizable = { - localizedStrings : {}, - setLocalizedString : function( str, localizedString ){ - this.localizedStrings[ str ] = localizedString; - }, - localize : function( str ){ - if( str in this.localizedStrings ){ return this.localizedStrings[ str ]; } - return str; - } -}; -var LocalizableView = LoggingView.extend( Localizable ); -*/ -//TODO: wire up to views +============================================================================= */ //============================================================================== // jq plugin? @@ -204,12 +191,8 @@ // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.) itemWrapper.find( '.tooltip' ).tooltip({ placement : 'bottom' }); - //TODO: broken - var popupmenus = itemWrapper.find( '[popupmenu]' ); - popupmenus.each( function( i, menu ){ - menu = $( menu ); - make_popupmenu( menu ); - }); + // we can potentially skip this step and call popupmenu directly on the download button + make_popup_menus( itemWrapper ); //TODO: better transition/method than this... this.$el.children().remove(); @@ -343,54 +326,25 @@ // ................................................................................ primary actions _render_primaryActionButtons : function( buttonRenderingFuncs ){ - var primaryActionButtons = $( '<div/>' ), + var primaryActionButtons = $( '<div/>' ).attr( 'id', 'primary-actions-' + this.model.get( 'id' ) ), view = this; _.each( buttonRenderingFuncs, function( fn ){ - primaryActionButtons.append( fn.call( view ) ); + var render_return = fn.call( view ); + primaryActionButtons.append( render_return ); }); return primaryActionButtons; }, _render_downloadButton : function(){ - // return either: a single download icon-button (if there are no meta files) - // or a popupmenu with links to download assoc. meta files (if there are meta files) - // don't show anything if the data's been purged if( this.model.get( 'purged' ) ){ return null; } - var downloadLink = linkHTMLTemplate({ - title : 'Download', - href : this.model.get( 'download_url' ), - classes : [ 'icon-button', 'tooltip', 'disk' ] - }); + // return either: a single download icon-button (if there are no meta files) + // or a popupmenu with links to download assoc. meta files (if there are meta files) + var downloadLinkHTML = HistoryItemView.templates.downloadLinks( this.model.toJSON() ); + this.log( '_render_downloadButton, downloadLinkHTML:', downloadLinkHTML ); - // if no metafiles, return only the main download link - var download_meta_urls = this.model.get( 'download_meta_urls' ); - if( !download_meta_urls ){ - return downloadLink; - } - - // build the popupmenu for downloading main, meta files - var popupmenu = $( '<div popupmenu="dataset-' + this.model.get( 'id' ) + '-popup"></div>' ); - popupmenu.append( linkHTMLTemplate({ - text : 'Download Dataset', - title : 'Download', - href : this.model.get( 'download_url' ), - classes : [ 'icon-button', 'tooltip', 'disk' ] - })); - popupmenu.append( '<a>Additional Files</a>' ); - for( file_type in download_meta_urls ){ - popupmenu.append( linkHTMLTemplate({ - text : 'Download ' + file_type, - href : download_meta_urls[ file_type ], - classes : [ 'action-button' ] - })); - } - var menuButton = $( ( '<div style="float:left;" class="menubutton split popup"' - + ' id="dataset-${dataset_id}-popup"></div>' ) ); - menuButton.append( downloadLink ); - popupmenu.append( menuButton ); - return popupmenu; + return $( downloadLinkHTML ); }, //NOTE: button renderers have the side effect of caching their IconButtonViews to this view @@ -451,8 +405,12 @@ // ................................................................................ secondary actions _render_secondaryActionButtons : function( buttonRenderingFuncs ){ // move to the right (same level as primary) - var secondaryActionButtons = $( '<div style="float: right;"></div>' ), + var secondaryActionButtons = $( '<div/>' ), view = this; + secondaryActionButtons + .attr( 'style', 'float: right;' ) + .attr( 'id', 'secondary-actions-' + this.model.get( 'id' ) ); + _.each( buttonRenderingFuncs, function( fn ){ secondaryActionButtons.append( fn.call( view ) ); }); @@ -501,54 +459,23 @@ }, _render_displayApps : function(){ - if( !this.model.get( 'display_apps' ) ){ return null; } - var displayApps = this.model.get( 'displayApps' ), - displayAppsDiv = $( '<div/>' ), - displayAppSpan = $( '<span/>' ); - - this.log( this + 'displayApps:', displayApps ); - ////TODO: grrr...somethings not in the right scope here - //for( app_name in displayApps ){ - // //TODO: to template - // var display_app = displayApps[ app_name ], - // display_app_HTML = app_name + ' '; - // for( location_name in display_app ){ - // display_app_HTML += linkHTMLTemplate({ - // text : location_name, - // href : display_app[ location_name ].url, - // target : display_app[ location_name ].target - // }) + ' '; - // } - // display_app_span.append( display_app_HTML ); - //} - //displayAppsDiv.append( display_app_span ); + // render links to external genome display applications (igb, gbrowse, etc.) + if( !this.model.hasData() ){ return null; } - //displayAppsDiv.append( '<br />' ); - - //var display_appsDiv = $( '<div/>' ); - //if( this.model.get( 'display_apps' ) ){ - // - // var display_apps = this.model.get( 'display_apps' ), - // display_app_span = $( '<span/>' ); - // - // //TODO: grrr...somethings not in the right scope here - // for( app_name in display_apps ){ - // //TODO: to template - // var display_app = display_apps[ app_name ], - // display_app_HTML = app_name + ' '; - // for( location_name in display_app ){ - // display_app_HTML += linkHTMLTemplate({ - // text : location_name, - // href : display_app[ location_name ].url, - // target : display_app[ location_name ].target - // }) + ' '; - // } - // display_app_span.append( display_app_HTML ); - // } - // display_appsDiv.append( display_app_span ); - //} - ////display_appsDiv.append( '<br />' ); - //parent.append( display_appsDiv ); + var displayAppsDiv = $( '<div/>' ).addClass( 'display-apps' ); + if( !_.isEmpty( this.model.get( 'display_types' ) ) ){ + this.log( this + 'display_types:', this.model.get( 'display_types' ) ); + //TODO:?? does this ever get used? + displayAppsDiv.append( + HistoryItemView.templates.displayApps({ displayApps : this.model.toJSON().display_types }) + ); + } + if( !_.isEmpty( this.model.get( 'display_apps' ) ) ){ + this.log( this + 'display_apps:', this.model.get( 'display_apps' ) ); + displayAppsDiv.append( + HistoryItemView.templates.displayApps({ displayApps : this.model.toJSON().display_apps }) + ); + } return displayAppsDiv; }, @@ -815,9 +742,11 @@ messages : 'template-history-warning-messages', titleLink : 'template-history-titleLink', hdaSummary : 'template-history-hdaSummary', + downloadLinks : 'template-history-downloadLinks', failedMetadata : 'template-history-failedMetaData', tagArea : 'template-history-tagArea', - annotationArea : 'template-history-annotationArea' + annotationArea : 'template-history-annotationArea', + displayApps : 'template-history-displayApps' } }); @@ -967,163 +896,10 @@ //============================================================================== -function createMockHistoryData(){ - mockHistory = {}; - mockHistory.data = { - - template : { - id : 'a799d38679e985db', - name : 'template', - data_type : 'fastq', - file_size : 226297533, - genome_build : '?', - metadata_data_lines : 0, - metadata_dbkey : '?', - metadata_sequences : 0, - misc_blurb : '215.8 MB', - misc_info : 'uploaded fastq file (misc_info)', - model_class : 'HistoryDatasetAssociation', - download_url : '', - state : 'ok', - visible : true, - deleted : false, - purged : false, - - hid : 0, - //TODO: move to history - for_editing : true, - //for_editing : false, - - //?? not needed - //can_edit : true, - //can_edit : false, - - accessible : true, - - //TODO: move into model functions (build there (and cache?)) - //!! be careful with adding these accrd. to permissions - //!! IOW, don't send them via template/API if the user doesn't have perms to use - //!! (even if they don't show up) - undelete_url : '', - purge_url : '', - unhide_url : '', - - display_url : 'example.com/display', - edit_url : 'example.com/edit', - delete_url : 'example.com/delete', - - show_params_url : 'example.com/show_params', - rerun_url : 'example.com/rerun', - - retag_url : 'example.com/retag', - annotate_url : 'example.com/annotate', - - peek : [ - '<table cellspacing="0" cellpadding="3"><tr><th>1.QNAME</th><th>2.FLAG</th><th>3.RNAME</th><th>4.POS</th><th>5.MAPQ</th><th>6.CIGAR</th><th>7.MRNM</th><th>8.MPOS</th><th>9.ISIZE</th><th>10.SEQ</th><th>11.QUAL</th><th>12.OPT</th></tr>', - '<tr><td colspan="100%">@SQ SN:gi|87159884|ref|NC_007793.1| LN:2872769</td></tr>', - '<tr><td colspan="100%">@PG ID:bwa PN:bwa VN:0.5.9-r16</td></tr>', - '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 73 gi|87159884|ref|NC_007793.1| 2720169 37 101M = 2720169 0 NAATATGACATTATTTTCAAAACAGCTGAAAATTTAGACGTACCGATTTATCTACATCCCGCGCCAGTTAACAGTGACATTTATCAATCATACTATAAAGG !!!!!!!!!!$!!!$!!!!!$!!!!!!$!$!$$$!!$!!$!!!!!!!!!!!$!</td></tr>', - '<tr><td colspan="100%">!!!$!$!$$!!$$!!$!!!!!!!!!!!!!!!!!!!!!!!!!!$!!$!! XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 X1:i:0 XM:i:1 XO:i:0 XG:i:0 MD:Z:0A100</td></tr>', - '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 133 gi|87159884|ref|NC_007793.1| 2720169 0 * = 2720169 0 NAAACTGTGGCTTCGTTNNNNNNNNNNNNNNNGTGANNNNNNNNNNNNNNNNNNNGNNNNNNNNNNNNNNNNNNNNCNAANNNNNNNNNNNNNNNNNNNNN !!!!!!!!!!!!$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>', - '<tr><td colspan="100%">!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>', - '</table>' - ].join( '' ) - } - - }; - _.extend( mockHistory.data, { - - notAccessible : - _.extend( _.clone( mockHistory.data.template ), - { accessible : false }), - - //deleted, purged, visible - deleted : - _.extend( _.clone( mockHistory.data.template ), - { deleted : true, - delete_url : '', - purge_url : 'example.com/purge', - undelete_url : 'example.com/undelete' }), - purgedNotDeleted : - _.extend( _.clone( mockHistory.data.template ), - { purged : true, - delete_url : '' }), - notvisible : - _.extend( _.clone( mockHistory.data.template ), - { visible : false, - unhide_url : 'example.com/unhide' }), - - hasDisplayApps : - _.extend( _.clone( mockHistory.data.template ), - { display_apps : { - 'display in IGB' : { - Web: "/display_application/63cd3858d057a6d1/igb_bam/Web", - Local: "/display_application/63cd3858d057a6d1/igb_bam/Local" - } - } - } - ), - canTrackster : - _.extend( _.clone( mockHistory.data.template ), - { trackster_urls : { - 'data-url' : "example.com/trackster-data", - 'action-url' : "example.com/trackster-action", - 'new-url' : "example.com/trackster-new" - } - } - ), - zeroSize : - _.extend( _.clone( mockHistory.data.template ), - { file_size : 0 }), - - hasMetafiles : - _.extend( _.clone( mockHistory.data.template ), { - download_meta_urls : { - 'bam_index' : "example.com/bam-index" - } - }), - - //states - upload : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.UPLOAD }), - queued : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.QUEUED }), - running : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.RUNNING }), - empty : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.EMPTY }), - error : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.ERROR, - report_error_url: 'example.com/report_err' }), - discarded : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.DISCARDED }), - setting_metadata : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.SETTING_METADATA }), - failed_metadata : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.FAILED_METADATA }) -/* -*/ - }); - - $( document ).ready( function(){ - //mockHistory.views.deleted.logger = console; - mockHistory.items = {}; - mockHistory.views = {}; - for( key in mockHistory.data ){ - mockHistory.items[ key ] = new HistoryItem( mockHistory.data[ key ] ); - mockHistory.items[ key ].set( 'name', key ); - mockHistory.views[ key ] = new HistoryItemView({ model : mockHistory.items[ key ] }); - //console.debug( 'view: ', mockHistory.views[ key ] ); - $( 'body' ).append( mockHistory.views[ key ].render() ); - } - }); -} - +//return { +// HistoryItem : HistoryItem, +// HitoryItemView : HistoryItemView, +// HistoryCollection : HistoryCollection, +// History : History, +// HistoryView : HistoryView +//};}); diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/galaxy.base.js --- a/static/scripts/packed/galaxy.base.js +++ b/static/scripts/packed/galaxy.base.js @@ -1,1 +1,1 @@ -(function(){var b=0;var c=["ms","moz","webkit","o"];for(var a=0;a<c.length&&!window.requestAnimationFrame;++a){window.requestAnimationFrame=window[c[a]+"RequestAnimationFrame"];window.cancelRequestAnimationFrame=window[c[a]+"CancelRequestAnimationFrame"]}if(!window.requestAnimationFrame){window.requestAnimationFrame=function(h,e){var d=new Date().getTime();var f=Math.max(0,16-(d-b));var g=window.setTimeout(function(){h(d+f)},f);b=d+f;return g}}if(!window.cancelAnimationFrame){window.cancelAnimationFrame=function(d){clearTimeout(d)}}}());if(!Array.indexOf){Array.prototype.indexOf=function(c){for(var b=0,a=this.length;b<a;b++){if(this[b]==c){return b}}return -1}}function obj_length(c){if(c.length!==undefined){return c.length}var b=0;for(var a in c){b++}return b}$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function make_popupmenu(b,c){var a=(b.data("menu_options"));b.data("menu_options",c);if(a){return}b.bind("click.show_popup",function(d){$(".popmenu-wrapper").remove();setTimeout(function(){var g=$("<ul class='dropdown-menu' id='"+b.attr("id")+"-menu'></ul>");var f=b.data("menu_options");if(obj_length(f)<=0){$("<li>No Options.</li>").appendTo(g)}$.each(f,function(j,i){if(i){g.append($("<li></li>").append($("<a href='#'></a>").html(j).click(i)))}else{g.append($("<li></li>").addClass("head").append($("<a href='#'></a>").html(j)))}});var h=$("<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>").append(g).appendTo("body");var e=d.pageX-h.width()/2;e=Math.min(e,$(document).scrollLeft()+$(window).width()-$(h).width()-5);e=Math.max(e,$(document).scrollLeft()+5);h.css({top:d.pageY,left:e})},10);setTimeout(function(){var f=function(h){$(h).bind("click.close_popup",function(){$(".popmenu-wrapper").remove();h.unbind("click.close_popup")})};f($(window.document));f($(window.top.document));for(var e=window.top.frames.length;e--;){var g=$(window.top.frames[e].document);f(g)}},50);return false})}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var a={};var c=$(this);c.find("a").each(function(){var f=$(this),h=f.get(0);var d=h.getAttribute("confirm"),e=h.getAttribute("href"),g=h.getAttribute("target");if(!e){a[f.text()]=null}else{a[f.text()]=function(){if(!d||confirm(d)){var i;if(g=="_parent"){window.parent.location=e}else{if(g=="_top"){window.top.location=e}else{if(g=="demo"){if(i===undefined||i.closed){i=window.open(e,g);i.creator=self}}else{window.location=e}}}}}}});var b=$("#"+c.attr("popupmenu"));b.find("a").bind("click",function(d){d.stopPropagation();return true});make_popupmenu(b,a);b.addClass("popup");c.remove()})}function naturalSort(j,h){var p=/(-?[0-9\.]+)/g,k=j.toString().toLowerCase()||"",g=h.toString().toLowerCase()||"",l=String.fromCharCode(0),n=k.replace(p,l+"$1"+l).split(l),e=g.replace(p,l+"$1"+l).split(l),d=(new Date(k)).getTime(),o=d?(new Date(g)).getTime():null;if(o){if(d<o){return -1}else{if(d>o){return 1}}}var m,f;for(var i=0,c=Math.max(n.length,e.length);i<c;i++){m=parseFloat(n[i])||n[i];f=parseFloat(e[i])||e[i];if(m<f){return -1}else{if(m>f){return 1}}}return 0}function replace_big_select_inputs(a,c,b){if(!jQuery().autocomplete){return}if(a===undefined){a=20}if(c===undefined){c=3000}var b=b||$("select");b.each(function(){var e=$(this);var h=e.find("option").length;if((h<a)||(h>c)){return}if(e.attr("multiple")==="multiple"){return}if(e.hasClass("no-autocomplete")){return}var n=e.attr("value");var d=$("<input type='text' class='text-and-autocomplete-select'></input>");d.attr("size",40);d.attr("name",e.attr("name"));d.attr("id",e.attr("id"));d.click(function(){var o=$(this).val();$(this).val("Loading...");$(this).showAllInCache();$(this).val(o);$(this).select()});var f=[];var j={};e.children("option").each(function(){var p=$(this).text();var o=$(this).attr("value");f.push(p);j[p]=o;j[o]=o;if(o==n){d.attr("value",p)}});if(n===""||n==="?"){d.attr("value","Click to Search or Select")}if(e.attr("name")=="dbkey"){f=f.sort(naturalSort)}var g={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:c,minChars:0,hideForLessThanMinChars:false};d.autocomplete(f,g);e.replaceWith(d);var l=function(){var p=d.attr("value");var o=j[p];if(o!==null&&o!==undefined){d.attr("value",o)}else{if(n!==""){d.attr("value",n)}else{d.attr("value","?")}}};d.parents("form").submit(function(){l()});$(document).bind("convert_to_values",function(){l()});if(e.attr("refresh_on_change")=="true"){var i=e.attr("refresh_on_change_values"),m=e.attr("last_selected_value");if(i!==undefined){i=i.split(",")}var k=function(){var o=j[d.attr("value")];if(m!==o&&o!==null&&o!==undefined){if(i!==undefined&&$.inArray(o,i)===-1&&$.inArray(m,i)===-1){return}d.attr("value",o);$(window).trigger("refresh_on_change");d.parents("form").submit()}};d.bind("result",k);d.keyup(function(o){if(o.keyCode===13){k()}});d.keydown(function(o){if(o.keyCode===13){return false}})}})}$.fn.make_text_editable=function(g){var d=("num_cols" in g?g.num_cols:30),c=("num_rows" in g?g.num_rows:4),e=("use_textarea" in g?g.use_textarea:false),b=("on_finish" in g?g.on_finish:null),f=("help_text" in g?g.help_text:null);var a=$(this);a.addClass("editable-text").click(function(l){if($(this).children(":input").length>0){return}a.removeClass("editable-text");var i=function(m){a.find(":input").remove();if(m!==""){a.text(m)}else{a.html("<br>")}a.addClass("editable-text");if(b){b(m)}};var h=a.text(),k,j;if(e){k=$("<textarea/>").attr({rows:c,cols:d}).text($.trim(h)).keyup(function(m){if(m.keyCode===27){i(h)}});j=$("<button/>").text("Done").click(function(){i(k.val());return false})}else{k=$("<input type='text'/>").attr({value:$.trim(h),size:d}).blur(function(){i(h)}).keyup(function(m){if(m.keyCode===27){$(this).trigger("blur")}else{if(m.keyCode===13){i($(this).val())}}})}a.text("");a.append(k);if(j){a.append(j)}k.focus();k.select();l.stopPropagation()});if(f){a.attr("title",f).tooltip()}return a};function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text($.trim(k))}else{j=$("<input type='text'></input>").attr({value:$.trim(k),size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){if(o!==""){l.text(o)}else{l.html("<em>None</em>")}if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(d,a,c){var b=function(){try{var e=$.jStorage.get("history_expand_state");if(e){for(var g in e){$("#"+g+" div.historyItemBody").show()}}}catch(f){$.jStorage.deleteKey("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}d.each(function(){var j=this.id,h=$(this).children("div.historyItemBody"),i=h.find("pre.peek");$(this).find(".historyItemTitleBar > .historyItemTitle").wrap("<a href='javascript:void(0);'></a>").click(function(){var k;if(h.is(":visible")){if($.browser.mozilla){i.css("overflow","hidden")}h.slideUp("fast");if(!c){k=$.jStorage.get("history_expand_state");if(k){delete k[j];$.jStorage.set("history_expand_state",k)}}}else{h.slideDown("fast",function(){if($.browser.mozilla){i.css("overflow","auto")}});if(!c){k=$.jStorage.get("history_expand_state");if(!k){k={}}k[j]=true;$.jStorage.set("history_expand_state",k)}}return false})});$("#top-links > a.toggle").click(function(){var h=$.jStorage.get("history_expand_state");if(!h){h={}}$("div.historyItemBody:visible").each(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(h){delete h[$(this).parent().attr("id")]}});$.jStorage.set("history_expand_state",h)}).show()};b()}function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}function reset_tool_search(a){var c=$("#galaxy_tools").contents();if(c.length===0){c=$(document)}$(this).removeClass("search_active");c.find(".toolTitle").removeClass("search_match");c.find(".toolSectionBody").hide();c.find(".toolTitle").show();c.find(".toolPanelLabel").show();c.find(".toolSectionWrapper").each(function(){if($(this).attr("id")!="recently_used_wrapper"){$(this).show()}else{if($(this).hasClass("user_pref_visible")){$(this).show()}}});c.find("#search-no-results").hide();c.find("#search-spinner").hide();if(a){var b=c.find("#tool-search-query");b.val("search tools")}}var GalaxyAsync=function(a){this.url_dict={};this.log_action=(a===undefined?false:a)};GalaxyAsync.prototype.set_func_url=function(a,b){this.url_dict[a]=b};GalaxyAsync.prototype.set_user_pref=function(a,b){var c=this.url_dict[arguments.callee];if(c===undefined){return false}$.ajax({url:c,data:{pref_name:a,pref_value:b},error:function(){return false},success:function(){return true}})};GalaxyAsync.prototype.log_user_action=function(c,b,d){if(!this.log_action){return}var a=this.url_dict[arguments.callee];if(a===undefined){return false}$.ajax({url:a,data:{action:c,context:b,params:d},error:function(){return false},success:function(){return true}})};$(document).ready(function(){$("select[refresh_on_change='true']").change(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_value");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");$(document).trigger("convert_to_values");a.get(0).form.submit()});$(":checkbox[refresh_on_change='true']").click(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_value");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");a.get(0).form.submit()});$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tooltip){$(".tooltip").tooltip({placement:"top"})}make_popup_menus();replace_big_select_inputs(20,1500);$("a").click(function(){var b=$(this);var c=(parent.frames&&parent.frames.galaxy_main);if((b.attr("target")=="galaxy_main")&&(!c)){var a=b.attr("href");if(a.indexOf("?")==-1){a+="?"}else{a+="&"}a+="use_panels=True";b.attr("href",a);b.attr("target","_self")}return b})}); \ No newline at end of file +(function(){var b=0;var c=["ms","moz","webkit","o"];for(var a=0;a<c.length&&!window.requestAnimationFrame;++a){window.requestAnimationFrame=window[c[a]+"RequestAnimationFrame"];window.cancelRequestAnimationFrame=window[c[a]+"CancelRequestAnimationFrame"]}if(!window.requestAnimationFrame){window.requestAnimationFrame=function(h,e){var d=new Date().getTime();var f=Math.max(0,16-(d-b));var g=window.setTimeout(function(){h(d+f)},f);b=d+f;return g}}if(!window.cancelAnimationFrame){window.cancelAnimationFrame=function(d){clearTimeout(d)}}}());if(!Array.indexOf){Array.prototype.indexOf=function(c){for(var b=0,a=this.length;b<a;b++){if(this[b]==c){return b}}return -1}}function obj_length(c){if(c.length!==undefined){return c.length}var b=0;for(var a in c){b++}return b}$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function make_popupmenu(b,c){var a=(b.data("menu_options"));b.data("menu_options",c);if(a){return}b.bind("click.show_popup",function(d){$(".popmenu-wrapper").remove();setTimeout(function(){var g=$("<ul class='dropdown-menu' id='"+b.attr("id")+"-menu'></ul>");var f=b.data("menu_options");if(obj_length(f)<=0){$("<li>No Options.</li>").appendTo(g)}$.each(f,function(j,i){if(i){g.append($("<li></li>").append($("<a href='#'></a>").html(j).click(i)))}else{g.append($("<li></li>").addClass("head").append($("<a href='#'></a>").html(j)))}});var h=$("<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>").append(g).appendTo("body");var e=d.pageX-h.width()/2;e=Math.min(e,$(document).scrollLeft()+$(window).width()-$(h).width()-5);e=Math.max(e,$(document).scrollLeft()+5);h.css({top:d.pageY,left:e})},10);setTimeout(function(){var f=function(h){$(h).bind("click.close_popup",function(){$(".popmenu-wrapper").remove();h.unbind("click.close_popup")})};f($(window.document));f($(window.top.document));for(var e=window.top.frames.length;e--;){var g=$(window.top.frames[e].document);f(g)}},50);return false})}function make_popup_menus(a){a=a||document;$(a).find("div[popupmenu]").each(function(){var b={};var d=$(this);d.find("a").each(function(){var g=$(this),i=g.get(0),e=i.getAttribute("confirm"),f=i.getAttribute("href"),h=i.getAttribute("target");if(!f){b[g.text()]=null}else{b[g.text()]=function(){if(!e||confirm(e)){var j;if(h=="_parent"){window.parent.location=f}else{if(h=="_top"){window.top.location=f}else{if(h=="demo"){if(j===undefined||j.closed){j=window.open(f,h);j.creator=self}}else{window.location=f}}}}}}});var c=$("#"+d.attr("popupmenu"));c.find("a").bind("click",function(f){f.stopPropagation();return true});make_popupmenu(c,b);c.addClass("popup");d.remove()})}function naturalSort(j,h){var p=/(-?[0-9\.]+)/g,k=j.toString().toLowerCase()||"",g=h.toString().toLowerCase()||"",l=String.fromCharCode(0),n=k.replace(p,l+"$1"+l).split(l),e=g.replace(p,l+"$1"+l).split(l),d=(new Date(k)).getTime(),o=d?(new Date(g)).getTime():null;if(o){if(d<o){return -1}else{if(d>o){return 1}}}var m,f;for(var i=0,c=Math.max(n.length,e.length);i<c;i++){m=parseFloat(n[i])||n[i];f=parseFloat(e[i])||e[i];if(m<f){return -1}else{if(m>f){return 1}}}return 0}function replace_big_select_inputs(a,c,b){if(!jQuery().autocomplete){return}if(a===undefined){a=20}if(c===undefined){c=3000}var b=b||$("select");b.each(function(){var e=$(this);var h=e.find("option").length;if((h<a)||(h>c)){return}if(e.attr("multiple")==="multiple"){return}if(e.hasClass("no-autocomplete")){return}var n=e.attr("value");var d=$("<input type='text' class='text-and-autocomplete-select'></input>");d.attr("size",40);d.attr("name",e.attr("name"));d.attr("id",e.attr("id"));d.click(function(){var o=$(this).val();$(this).val("Loading...");$(this).showAllInCache();$(this).val(o);$(this).select()});var f=[];var j={};e.children("option").each(function(){var p=$(this).text();var o=$(this).attr("value");f.push(p);j[p]=o;j[o]=o;if(o==n){d.attr("value",p)}});if(n===""||n==="?"){d.attr("value","Click to Search or Select")}if(e.attr("name")=="dbkey"){f=f.sort(naturalSort)}var g={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:c,minChars:0,hideForLessThanMinChars:false};d.autocomplete(f,g);e.replaceWith(d);var l=function(){var p=d.attr("value");var o=j[p];if(o!==null&&o!==undefined){d.attr("value",o)}else{if(n!==""){d.attr("value",n)}else{d.attr("value","?")}}};d.parents("form").submit(function(){l()});$(document).bind("convert_to_values",function(){l()});if(e.attr("refresh_on_change")=="true"){var i=e.attr("refresh_on_change_values"),m=e.attr("last_selected_value");if(i!==undefined){i=i.split(",")}var k=function(){var o=j[d.attr("value")];if(m!==o&&o!==null&&o!==undefined){if(i!==undefined&&$.inArray(o,i)===-1&&$.inArray(m,i)===-1){return}d.attr("value",o);$(window).trigger("refresh_on_change");d.parents("form").submit()}};d.bind("result",k);d.keyup(function(o){if(o.keyCode===13){k()}});d.keydown(function(o){if(o.keyCode===13){return false}})}})}$.fn.make_text_editable=function(g){var d=("num_cols" in g?g.num_cols:30),c=("num_rows" in g?g.num_rows:4),e=("use_textarea" in g?g.use_textarea:false),b=("on_finish" in g?g.on_finish:null),f=("help_text" in g?g.help_text:null);var a=$(this);a.addClass("editable-text").click(function(l){if($(this).children(":input").length>0){return}a.removeClass("editable-text");var i=function(m){a.find(":input").remove();if(m!==""){a.text(m)}else{a.html("<br>")}a.addClass("editable-text");if(b){b(m)}};var h=a.text(),k,j;if(e){k=$("<textarea/>").attr({rows:c,cols:d}).text($.trim(h)).keyup(function(m){if(m.keyCode===27){i(h)}});j=$("<button/>").text("Done").click(function(){i(k.val());return false})}else{k=$("<input type='text'/>").attr({value:$.trim(h),size:d}).blur(function(){i(h)}).keyup(function(m){if(m.keyCode===27){$(this).trigger("blur")}else{if(m.keyCode===13){i($(this).val())}}})}a.text("");a.append(k);if(j){a.append(j)}k.focus();k.select();l.stopPropagation()});if(f){a.attr("title",f).tooltip()}return a};function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text($.trim(k))}else{j=$("<input type='text'></input>").attr({value:$.trim(k),size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){if(o!==""){l.text(o)}else{l.html("<em>None</em>")}if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(d,a,c){var b=function(){try{var e=$.jStorage.get("history_expand_state");if(e){for(var g in e){$("#"+g+" div.historyItemBody").show()}}}catch(f){$.jStorage.deleteKey("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}d.each(function(){var j=this.id,h=$(this).children("div.historyItemBody"),i=h.find("pre.peek");$(this).find(".historyItemTitleBar > .historyItemTitle").wrap("<a href='javascript:void(0);'></a>").click(function(){var k;if(h.is(":visible")){if($.browser.mozilla){i.css("overflow","hidden")}h.slideUp("fast");if(!c){k=$.jStorage.get("history_expand_state");if(k){delete k[j];$.jStorage.set("history_expand_state",k)}}}else{h.slideDown("fast",function(){if($.browser.mozilla){i.css("overflow","auto")}});if(!c){k=$.jStorage.get("history_expand_state");if(!k){k={}}k[j]=true;$.jStorage.set("history_expand_state",k)}}return false})});$("#top-links > a.toggle").click(function(){var h=$.jStorage.get("history_expand_state");if(!h){h={}}$("div.historyItemBody:visible").each(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(h){delete h[$(this).parent().attr("id")]}});$.jStorage.set("history_expand_state",h)}).show()};b()}function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}function reset_tool_search(a){var c=$("#galaxy_tools").contents();if(c.length===0){c=$(document)}$(this).removeClass("search_active");c.find(".toolTitle").removeClass("search_match");c.find(".toolSectionBody").hide();c.find(".toolTitle").show();c.find(".toolPanelLabel").show();c.find(".toolSectionWrapper").each(function(){if($(this).attr("id")!="recently_used_wrapper"){$(this).show()}else{if($(this).hasClass("user_pref_visible")){$(this).show()}}});c.find("#search-no-results").hide();c.find("#search-spinner").hide();if(a){var b=c.find("#tool-search-query");b.val("search tools")}}var GalaxyAsync=function(a){this.url_dict={};this.log_action=(a===undefined?false:a)};GalaxyAsync.prototype.set_func_url=function(a,b){this.url_dict[a]=b};GalaxyAsync.prototype.set_user_pref=function(a,b){var c=this.url_dict[arguments.callee];if(c===undefined){return false}$.ajax({url:c,data:{pref_name:a,pref_value:b},error:function(){return false},success:function(){return true}})};GalaxyAsync.prototype.log_user_action=function(c,b,d){if(!this.log_action){return}var a=this.url_dict[arguments.callee];if(a===undefined){return false}$.ajax({url:a,data:{action:c,context:b,params:d},error:function(){return false},success:function(){return true}})};$(document).ready(function(){$("select[refresh_on_change='true']").change(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_value");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");$(document).trigger("convert_to_values");a.get(0).form.submit()});$(":checkbox[refresh_on_change='true']").click(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_value");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");a.get(0).form.submit()});$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tooltip){$(".tooltip").tooltip({placement:"top"})}make_popup_menus();replace_big_select_inputs(20,1500);$("a").click(function(){var b=$(this);var c=(parent.frames&&parent.frames.galaxy_main);if((b.attr("target")=="galaxy_main")&&(!c)){var a=b.attr("href");if(a.indexOf("?")==-1){a+="?"}else{a+="&"}a+="use_panels=True";b.attr("href",a);b.attr("target","_self")}return b})}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/libs/underscore.js --- a/static/scripts/packed/libs/underscore.js +++ b/static/scripts/packed/libs/underscore.js @@ -1,1 +1,1 @@ -(function(){var x=this;var t=x._;var b={};var j=Array.prototype,D=Object.prototype,G=Function.prototype;var v=j.slice,z=j.unshift,y=D.toString,p=D.hasOwnProperty;var n=j.forEach,i=j.map,B=j.reduce,e=j.reduceRight,m=j.filter,a=j.every,A=j.some,w=j.indexOf,f=j.lastIndexOf,c=Array.isArray,C=Object.keys,k=G.bind;var F=function(I){return new g(I)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports){exports=module.exports=F}exports._=F}else{x._=F}F.VERSION="1.3.1";var d=F.each=F.forEach=function(N,M,L){if(N==null){return}if(n&&N.forEach===n){N.forEach(M,L)}else{if(N.length===+N.length){for(var K=0,I=N.length;K<I;K++){if(K in N&&M.call(L,N[K],K,N)===b){return}}}else{for(var J in N){if(F.has(N,J)){if(M.call(L,N[J],J,N)===b){return}}}}}};F.map=F.collect=function(L,K,J){var I=[];if(L==null){return I}if(i&&L.map===i){return L.map(K,J)}d(L,function(O,M,N){I[I.length]=K.call(J,O,M,N)});if(L.length===+L.length){I.length=L.length}return I};F.reduce=F.foldl=F.inject=function(M,L,I,K){var J=arguments.length>2;if(M==null){M=[]}if(B&&M.reduce===B){if(K){L=F.bind(L,K)}return J?M.reduce(L,I):M.reduce(L)}d(M,function(P,N,O){if(!J){I=P;J=true}else{I=L.call(K,I,P,N,O)}});if(!J){throw new TypeError("Reduce of empty array with no initial value")}return I};F.reduceRight=F.foldr=function(M,L,I,K){var J=arguments.length>2;if(M==null){M=[]}if(e&&M.reduceRight===e){if(K){L=F.bind(L,K)}return J?M.reduceRight(L,I):M.reduceRight(L)}var N=F.toArray(M).reverse();if(K&&!J){L=F.bind(L,K)}return J?F.reduce(N,L,I,K):F.reduce(N,L)};F.find=F.detect=function(L,K,J){var I;r(L,function(O,M,N){if(K.call(J,O,M,N)){I=O;return true}});return I};F.filter=F.select=function(L,K,J){var I=[];if(L==null){return I}if(m&&L.filter===m){return L.filter(K,J)}d(L,function(O,M,N){if(K.call(J,O,M,N)){I[I.length]=O}});return I};F.reject=function(L,K,J){var I=[];if(L==null){return I}d(L,function(O,M,N){if(!K.call(J,O,M,N)){I[I.length]=O}});return I};F.every=F.all=function(L,K,J){var I=true;if(L==null){return I}if(a&&L.every===a){return L.every(K,J)}d(L,function(O,M,N){if(!(I=I&&K.call(J,O,M,N))){return b}});return I};var r=F.some=F.any=function(L,K,J){K||(K=F.identity);var I=false;if(L==null){return I}if(A&&L.some===A){return L.some(K,J)}d(L,function(O,M,N){if(I||(I=K.call(J,O,M,N))){return b}});return !!I};F.include=F.contains=function(K,J){var I=false;if(K==null){return I}if(w&&K.indexOf===w){return K.indexOf(J)!=-1}I=r(K,function(L){return L===J});return I};F.invoke=function(J,K){var I=v.call(arguments,2);return F.map(J,function(L){return(F.isFunction(K)?K||L:L[K]).apply(L,I)})};F.pluck=function(J,I){return F.map(J,function(K){return K[I]})};F.max=function(L,K,J){if(!K&&F.isArray(L)){return Math.max.apply(Math,L)}if(!K&&F.isEmpty(L)){return -Infinity}var I={computed:-Infinity};d(L,function(P,M,O){var N=K?K.call(J,P,M,O):P;N>=I.computed&&(I={value:P,computed:N})});return I.value};F.min=function(L,K,J){if(!K&&F.isArray(L)){return Math.min.apply(Math,L)}if(!K&&F.isEmpty(L)){return Infinity}var I={computed:Infinity};d(L,function(P,M,O){var N=K?K.call(J,P,M,O):P;N<I.computed&&(I={value:P,computed:N})});return I.value};F.shuffle=function(K){var I=[],J;d(K,function(N,L,M){if(L==0){I[0]=N}else{J=Math.floor(Math.random()*(L+1));I[L]=I[J];I[J]=N}});return I};F.sortBy=function(K,J,I){return F.pluck(F.map(K,function(N,L,M){return{value:N,criteria:J.call(I,N,L,M)}}).sort(function(O,N){var M=O.criteria,L=N.criteria;return M<L?-1:M>L?1:0}),"value")};F.groupBy=function(K,L){var I={};var J=F.isFunction(L)?L:function(M){return M[L]};d(K,function(O,M){var N=J(O,M);(I[N]||(I[N]=[])).push(O)});return I};F.sortedIndex=function(N,M,K){K||(K=F.identity);var I=0,L=N.length;while(I<L){var J=(I+L)>>1;K(N[J])<K(M)?I=J+1:L=J}return I};F.toArray=function(I){if(!I){return[]}if(I.toArray){return I.toArray()}if(F.isArray(I)){return v.call(I)}if(F.isArguments(I)){return v.call(I)}return F.values(I)};F.size=function(I){return F.toArray(I).length};F.first=F.head=function(K,J,I){return(J!=null)&&!I?v.call(K,0,J):K[0]};F.initial=function(K,J,I){return v.call(K,0,K.length-((J==null)||I?1:J))};F.last=function(K,J,I){if((J!=null)&&!I){return v.call(K,Math.max(K.length-J,0))}else{return K[K.length-1]}};F.rest=F.tail=function(K,I,J){return v.call(K,(I==null)||J?1:I)};F.compact=function(I){return F.filter(I,function(J){return !!J})};F.flatten=function(J,I){return F.reduce(J,function(K,L){if(F.isArray(L)){return K.concat(I?L:F.flatten(L))}K[K.length]=L;return K},[])};F.without=function(I){return F.difference(I,v.call(arguments,1))};F.uniq=F.unique=function(M,L,K){var J=K?F.map(M,K):M;var I=[];F.reduce(J,function(N,P,O){if(0==O||(L===true?F.last(N)!=P:!F.include(N,P))){N[N.length]=P;I[I.length]=M[O]}return N},[]);return I};F.union=function(){return F.uniq(F.flatten(arguments,true))};F.intersection=F.intersect=function(J){var I=v.call(arguments,1);return F.filter(F.uniq(J),function(K){return F.every(I,function(L){return F.indexOf(L,K)>=0})})};F.difference=function(J){var I=F.flatten(v.call(arguments,1));return F.filter(J,function(K){return !F.include(I,K)})};F.zip=function(){var I=v.call(arguments);var L=F.max(F.pluck(I,"length"));var K=new Array(L);for(var J=0;J<L;J++){K[J]=F.pluck(I,""+J)}return K};F.indexOf=function(M,K,L){if(M==null){return -1}var J,I;if(L){J=F.sortedIndex(M,K);return M[J]===K?J:-1}if(w&&M.indexOf===w){return M.indexOf(K)}for(J=0,I=M.length;J<I;J++){if(J in M&&M[J]===K){return J}}return -1};F.lastIndexOf=function(K,J){if(K==null){return -1}if(f&&K.lastIndexOf===f){return K.lastIndexOf(J)}var I=K.length;while(I--){if(I in K&&K[I]===J){return I}}return -1};F.range=function(N,L,M){if(arguments.length<=1){L=N||0;N=0}M=arguments[2]||1;var J=Math.max(Math.ceil((L-N)/M),0);var I=0;var K=new Array(J);while(I<J){K[I++]=N;N+=M}return K};var h=function(){};F.bind=function H(L,J){var K,I;if(L.bind===k&&k){return k.apply(L,v.call(arguments,1))}if(!F.isFunction(L)){throw new TypeError}I=v.call(arguments,2);return K=function(){if(!(this instanceof K)){return L.apply(J,I.concat(v.call(arguments)))}h.prototype=L.prototype;var N=new h;var M=L.apply(N,I.concat(v.call(arguments)));if(Object(M)===M){return M}return N}};F.bindAll=function(J){var I=v.call(arguments,1);if(I.length==0){I=F.functions(J)}d(I,function(K){J[K]=F.bind(J[K],J)});return J};F.memoize=function(K,J){var I={};J||(J=F.identity);return function(){var L=J.apply(this,arguments);return F.has(I,L)?I[L]:(I[L]=K.apply(this,arguments))}};F.delay=function(J,K){var I=v.call(arguments,2);return setTimeout(function(){return J.apply(J,I)},K)};F.defer=function(I){return F.delay.apply(F,[I,1].concat(v.call(arguments,1)))};F.throttle=function(N,P){var L,I,O,M,K;var J=F.debounce(function(){K=M=false},P);return function(){L=this;I=arguments;var Q=function(){O=null;if(K){N.apply(L,I)}J()};if(!O){O=setTimeout(Q,P)}if(M){K=true}else{N.apply(L,I)}J();M=true}};F.debounce=function(I,K){var J;return function(){var N=this,M=arguments;var L=function(){J=null;I.apply(N,M)};clearTimeout(J);J=setTimeout(L,K)}};F.once=function(K){var I=false,J;return function(){if(I){return J}I=true;return J=K.apply(this,arguments)}};F.wrap=function(I,J){return function(){var K=[I].concat(v.call(arguments,0));return J.apply(this,K)}};F.compose=function(){var I=arguments;return function(){var J=arguments;for(var K=I.length-1;K>=0;K--){J=[I[K].apply(this,J)]}return J[0]}};F.after=function(J,I){if(J<=0){return I()}return function(){if(--J<1){return I.apply(this,arguments)}}};F.keys=C||function(K){if(K!==Object(K)){throw new TypeError("Invalid object")}var J=[];for(var I in K){if(F.has(K,I)){J[J.length]=I}}return J};F.values=function(I){return F.map(I,F.identity)};F.functions=F.methods=function(K){var J=[];for(var I in K){if(F.isFunction(K[I])){J.push(I)}}return J.sort()};F.extend=function(I){d(v.call(arguments,1),function(J){for(var K in J){I[K]=J[K]}});return I};F.defaults=function(I){d(v.call(arguments,1),function(J){for(var K in J){if(I[K]==null){I[K]=J[K]}}});return I};F.clone=function(I){if(!F.isObject(I)){return I}return F.isArray(I)?I.slice():F.extend({},I)};F.tap=function(J,I){I(J);return J};function E(L,K,J){if(L===K){return L!==0||1/L==1/K}if(L==null||K==null){return L===K}if(L._chain){L=L._wrapped}if(K._chain){K=K._wrapped}if(L.isEqual&&F.isFunction(L.isEqual)){return L.isEqual(K)}if(K.isEqual&&F.isFunction(K.isEqual)){return K.isEqual(L)}var O=y.call(L);if(O!=y.call(K)){return false}switch(O){case"[object String]":return L==String(K);case"[object Number]":return L!=+L?K!=+K:(L==0?1/L==1/K:L==+K);case"[object Date]":case"[object Boolean]":return +L==+K;case"[object RegExp]":return L.source==K.source&&L.global==K.global&&L.multiline==K.multiline&&L.ignoreCase==K.ignoreCase}if(typeof L!="object"||typeof K!="object"){return false}var P=J.length;while(P--){if(J[P]==L){return true}}J.push(L);var N=0,I=true;if(O=="[object Array]"){N=L.length;I=N==K.length;if(I){while(N--){if(!(I=N in L==N in K&&E(L[N],K[N],J))){break}}}}else{if("constructor" in L!="constructor" in K||L.constructor!=K.constructor){return false}for(var M in L){if(F.has(L,M)){N++;if(!(I=F.has(K,M)&&E(L[M],K[M],J))){break}}}if(I){for(M in K){if(F.has(K,M)&&!(N--)){break}}I=!N}}J.pop();return I}F.isEqual=function(J,I){return E(J,I,[])};F.isEmpty=function(J){if(F.isArray(J)||F.isString(J)){return J.length===0}for(var I in J){if(F.has(J,I)){return false}}return true};F.isElement=function(I){return !!(I&&I.nodeType==1)};F.isArray=c||function(I){return y.call(I)=="[object Array]"};F.isObject=function(I){return I===Object(I)};F.isArguments=function(I){return y.call(I)=="[object Arguments]"};if(!F.isArguments(arguments)){F.isArguments=function(I){return !!(I&&F.has(I,"callee"))}}F.isFunction=function(I){return y.call(I)=="[object Function]"};F.isString=function(I){return y.call(I)=="[object String]"};F.isNumber=function(I){return y.call(I)=="[object Number]"};F.isNaN=function(I){return I!==I};F.isBoolean=function(I){return I===true||I===false||y.call(I)=="[object Boolean]"};F.isDate=function(I){return y.call(I)=="[object Date]"};F.isRegExp=function(I){return y.call(I)=="[object RegExp]"};F.isNull=function(I){return I===null};F.isUndefined=function(I){return I===void 0};F.has=function(J,I){return p.call(J,I)};F.noConflict=function(){x._=t;return this};F.identity=function(I){return I};F.times=function(L,K,J){for(var I=0;I<L;I++){K.call(J,I)}};F.escape=function(I){return(""+I).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};F.mixin=function(I){d(F.functions(I),function(J){s(J,F[J]=I[J])})};var l=0;F.uniqueId=function(I){var J=l++;return I?I+J:J};F.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/;var q=function(I){return I.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};F.template=function(L,K){var M=F.templateSettings;var I="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+L.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(M.escape||u,function(N,O){return"',_.escape("+q(O)+"),'"}).replace(M.interpolate||u,function(N,O){return"',"+q(O)+",'"}).replace(M.evaluate||u,function(N,O){return"');"+q(O).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";var J=new Function("obj","_",I);if(K){return J(K,F)}return function(N){return J.call(this,N,F)}};F.chain=function(I){return F(I).chain()};var g=function(I){this._wrapped=I};F.prototype=g.prototype;var o=function(J,I){return I?F(J).chain():J};var s=function(I,J){g.prototype[I]=function(){var K=v.call(arguments);z.call(K,this._wrapped);return o(J.apply(F,K),this._chain)}};F.mixin(F);d(["pop","push","reverse","shift","sort","splice","unshift"],function(I){var J=j[I];g.prototype[I]=function(){var K=this._wrapped;J.apply(K,arguments);var L=K.length;if((I=="shift"||I=="splice")&&L===0){delete K[0]}return o(K,this._chain)}});d(["concat","join","slice"],function(I){var J=j[I];g.prototype[I]=function(){return o(J.apply(this._wrapped,arguments),this._chain)}});g.prototype.chain=function(){this._chain=true;return this};g.prototype.value=function(){return this._wrapped}}).call(this); \ No newline at end of file +(function(){var w=this;var k=w._;var E={};var D=Array.prototype,g=Object.prototype,r=Function.prototype;var I=D.push,o=D.slice,y=D.concat,B=D.unshift,d=g.toString,j=g.hasOwnProperty;var M=D.forEach,q=D.map,F=D.reduce,c=D.reduceRight,b=D.filter,C=D.every,p=D.some,n=D.indexOf,l=D.lastIndexOf,u=Array.isArray,f=Object.keys,G=r.bind;var N=function(O){if(O instanceof N){return O}if(!(this instanceof N)){return new N(O)}this._wrapped=O};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports){exports=module.exports=N}exports._=N}else{w._=N}N.VERSION="1.4.0";var J=N.each=N.forEach=function(T,S,R){if(M&&T.forEach===M){T.forEach(S,R)}else{if(T.length===+T.length){for(var Q=0,O=T.length;Q<O;Q++){if(S.call(R,T[Q],Q,T)===E){return}}}else{for(var P in T){if(N.has(T,P)){if(S.call(R,T[P],P,T)===E){return}}}}}};N.map=N.collect=function(R,Q,P){var O=[];if(q&&R.map===q){return R.map(Q,P)}J(R,function(U,S,T){O[O.length]=Q.call(P,U,S,T)});return O};N.reduce=N.foldl=N.inject=function(S,R,O,Q){var P=arguments.length>2;if(F&&S.reduce===F){if(Q){R=N.bind(R,Q)}return P?S.reduce(R,O):S.reduce(R)}J(S,function(V,T,U){if(!P){O=V;P=true}else{O=R.call(Q,O,V,T,U)}});if(!P){throw new TypeError("Reduce of empty array with no initial value")}return O};N.reduceRight=N.foldr=function(U,R,O,Q){var P=arguments.length>2;if(c&&U.reduceRight===c){if(Q){R=N.bind(R,Q)}return arguments.length>2?U.reduceRight(R,O):U.reduceRight(R)}var T=U.length;if(T!==+T){var S=N.keys(U);T=S.length}J(U,function(X,V,W){V=S?S[--T]:--T;if(!P){O=U[V];P=true}else{O=R.call(Q,O,U[V],V,W)}});if(!P){throw new TypeError("Reduce of empty array with no initial value")}return O};N.find=N.detect=function(R,Q,P){var O;A(R,function(U,S,T){if(Q.call(P,U,S,T)){O=U;return true}});return O};N.filter=N.select=function(R,Q,P){var O=[];if(b&&R.filter===b){return R.filter(Q,P)}J(R,function(U,S,T){if(Q.call(P,U,S,T)){O[O.length]=U}});return O};N.reject=function(R,Q,P){var O=[];J(R,function(U,S,T){if(!Q.call(P,U,S,T)){O[O.length]=U}});return O};N.every=N.all=function(R,Q,P){Q||(Q=N.identity);var O=true;if(C&&R.every===C){return R.every(Q,P)}J(R,function(U,S,T){if(!(O=O&&Q.call(P,U,S,T))){return E}});return !!O};var A=N.some=N.any=function(R,Q,P){Q||(Q=N.identity);var O=false;if(p&&R.some===p){return R.some(Q,P)}J(R,function(U,S,T){if(O||(O=Q.call(P,U,S,T))){return E}});return !!O};N.contains=N.include=function(Q,P){var O=false;if(n&&Q.indexOf===n){return Q.indexOf(P)!=-1}O=A(Q,function(R){return R===P});return O};N.invoke=function(P,Q){var O=o.call(arguments,2);return N.map(P,function(R){return(N.isFunction(Q)?Q:R[Q]).apply(R,O)})};N.pluck=function(P,O){return N.map(P,function(Q){return Q[O]})};N.where=function(P,O){if(N.isEmpty(O)){return[]}return N.filter(P,function(R){for(var Q in O){if(O[Q]!==R[Q]){return false}}return true})};N.max=function(R,Q,P){if(!Q&&N.isArray(R)&&R[0]===+R[0]&&R.length<65535){return Math.max.apply(Math,R)}if(!Q&&N.isEmpty(R)){return -Infinity}var O={computed:-Infinity};J(R,function(V,S,U){var T=Q?Q.call(P,V,S,U):V;T>=O.computed&&(O={value:V,computed:T})});return O.value};N.min=function(R,Q,P){if(!Q&&N.isArray(R)&&R[0]===+R[0]&&R.length<65535){return Math.min.apply(Math,R)}if(!Q&&N.isEmpty(R)){return Infinity}var O={computed:Infinity};J(R,function(V,S,U){var T=Q?Q.call(P,V,S,U):V;T<O.computed&&(O={value:V,computed:T})});return O.value};N.shuffle=function(R){var Q;var P=0;var O=[];J(R,function(S){Q=N.random(P++);O[P-1]=O[Q];O[Q]=S});return O};var a=function(O){return N.isFunction(O)?O:function(P){return P[O]}};N.sortBy=function(R,Q,O){var P=a(Q);return N.pluck(N.map(R,function(U,S,T){return{value:U,index:S,criteria:P.call(O,U,S,T)}}).sort(function(V,U){var T=V.criteria;var S=U.criteria;if(T!==S){if(T>S||T===void 0){return 1}if(T<S||S===void 0){return -1}}return V.index<U.index?-1:1}),"value")};var t=function(T,S,P,R){var O={};var Q=a(S);J(T,function(W,U){var V=Q.call(P,W,U,T);R(O,V,W)});return O};N.groupBy=function(Q,P,O){return t(Q,P,O,function(R,S,T){(N.has(R,S)?R[S]:(R[S]=[])).push(T)})};N.countBy=function(Q,P,O){return t(Q,P,O,function(R,S,T){if(!N.has(R,S)){R[S]=0}R[S]++})};N.sortedIndex=function(V,U,R,Q){R=R==null?N.identity:a(R);var T=R.call(Q,U);var O=0,S=V.length;while(O<S){var P=(O+S)>>>1;R.call(Q,V[P])<T?O=P+1:S=P}return O};N.toArray=function(O){if(!O){return[]}if(O.length===+O.length){return o.call(O)}return N.values(O)};N.size=function(O){return(O.length===+O.length)?O.length:N.keys(O).length};N.first=N.head=N.take=function(Q,P,O){return(P!=null)&&!O?o.call(Q,0,P):Q[0]};N.initial=function(Q,P,O){return o.call(Q,0,Q.length-((P==null)||O?1:P))};N.last=function(Q,P,O){if((P!=null)&&!O){return o.call(Q,Math.max(Q.length-P,0))}else{return Q[Q.length-1]}};N.rest=N.tail=N.drop=function(Q,P,O){return o.call(Q,(P==null)||O?1:P)};N.compact=function(O){return N.filter(O,function(P){return !!P})};var x=function(P,Q,O){J(P,function(R){if(N.isArray(R)){Q?I.apply(O,R):x(R,Q,O)}else{O.push(R)}});return O};N.flatten=function(P,O){return x(P,O,[])};N.without=function(O){return N.difference(O,o.call(arguments,1))};N.uniq=N.unique=function(U,T,S,R){var P=S?N.map(U,S,R):U;var Q=[];var O=[];J(P,function(W,V){if(T?(!V||O[O.length-1]!==W):!N.contains(O,W)){O.push(W);Q.push(U[V])}});return Q};N.union=function(){return N.uniq(y.apply(D,arguments))};N.intersection=function(P){var O=o.call(arguments,1);return N.filter(N.uniq(P),function(Q){return N.every(O,function(R){return N.indexOf(R,Q)>=0})})};N.difference=function(P){var O=y.apply(D,o.call(arguments,1));return N.filter(P,function(Q){return !N.contains(O,Q)})};N.zip=function(){var O=o.call(arguments);var R=N.max(N.pluck(O,"length"));var Q=new Array(R);for(var P=0;P<R;P++){Q[P]=N.pluck(O,""+P)}return Q};N.object=function(S,Q){var O={};for(var R=0,P=S.length;R<P;R++){if(Q){O[S[R]]=Q[R]}else{O[S[R][0]]=S[R][1]}}return O};N.indexOf=function(S,Q,R){var P=0,O=S.length;if(R){if(typeof R=="number"){P=(R<0?Math.max(0,O+R):R)}else{P=N.sortedIndex(S,Q);return S[P]===Q?P:-1}}if(n&&S.indexOf===n){return S.indexOf(Q,R)}for(;P<O;P++){if(S[P]===Q){return P}}return -1};N.lastIndexOf=function(R,Q,P){if(l&&R.lastIndexOf===l){return R.lastIndexOf(Q,P)}var O=(P!=null?P:R.length);while(O--){if(R[O]===Q){return O}}return -1};N.range=function(T,R,S){if(arguments.length<=1){R=T||0;T=0}S=arguments[2]||1;var P=Math.max(Math.ceil((R-T)/S),0);var O=0;var Q=new Array(P);while(O<P){Q[O++]=T;T+=S}return Q};var H=function(){};N.bind=function e(R,P){var Q,O;if(R.bind===G&&G){return G.apply(R,o.call(arguments,1))}if(!N.isFunction(R)){throw new TypeError}O=o.call(arguments,2);return Q=function(){if(!(this instanceof Q)){return R.apply(P,O.concat(o.call(arguments)))}H.prototype=R.prototype;var T=new H;var S=R.apply(T,O.concat(o.call(arguments)));if(Object(S)===S){return S}return T}};N.bindAll=function(P){var O=o.call(arguments,1);if(O.length==0){O=N.functions(P)}J(O,function(Q){P[Q]=N.bind(P[Q],P)});return P};N.memoize=function(Q,P){var O={};P||(P=N.identity);return function(){var R=P.apply(this,arguments);return N.has(O,R)?O[R]:(O[R]=Q.apply(this,arguments))}};N.delay=function(P,Q){var O=o.call(arguments,2);return setTimeout(function(){return P.apply(null,O)},Q)};N.defer=function(O){return N.delay.apply(N,[O,1].concat(o.call(arguments,1)))};N.throttle=function(Q,R){var P,T,U,V,S,W;var O=N.debounce(function(){S=V=false},R);return function(){P=this;T=arguments;var X=function(){U=null;if(S){W=Q.apply(P,T)}O()};if(!U){U=setTimeout(X,R)}if(V){S=true}else{V=true;W=Q.apply(P,T)}O();return W}};N.debounce=function(Q,S,P){var R,O;return function(){var W=this,V=arguments;var U=function(){R=null;if(!P){O=Q.apply(W,V)}};var T=P&&!R;clearTimeout(R);R=setTimeout(U,S);if(T){O=Q.apply(W,V)}return O}};N.once=function(Q){var O=false,P;return function(){if(O){return P}O=true;P=Q.apply(this,arguments);Q=null;return P}};N.wrap=function(O,P){return function(){var Q=[O];I.apply(Q,arguments);return P.apply(this,Q)}};N.compose=function(){var O=arguments;return function(){var P=arguments;for(var Q=O.length-1;Q>=0;Q--){P=[O[Q].apply(this,P)]}return P[0]}};N.after=function(P,O){if(P<=0){return O()}return function(){if(--P<1){return O.apply(this,arguments)}}};N.keys=f||function(Q){if(Q!==Object(Q)){throw new TypeError("Invalid object")}var P=[];for(var O in Q){if(N.has(Q,O)){P[P.length]=O}}return P};N.values=function(Q){var O=[];for(var P in Q){if(N.has(Q,P)){O.push(Q[P])}}return O};N.pairs=function(Q){var P=[];for(var O in Q){if(N.has(Q,O)){P.push([O,Q[O]])}}return P};N.invert=function(Q){var O={};for(var P in Q){if(N.has(Q,P)){O[Q[P]]=P}}return O};N.functions=N.methods=function(Q){var P=[];for(var O in Q){if(N.isFunction(Q[O])){P.push(O)}}return P.sort()};N.extend=function(O){J(o.call(arguments,1),function(P){for(var Q in P){O[Q]=P[Q]}});return O};N.pick=function(P){var Q={};var O=y.apply(D,o.call(arguments,1));J(O,function(R){if(R in P){Q[R]=P[R]}});return Q};N.omit=function(Q){var R={};var P=y.apply(D,o.call(arguments,1));for(var O in Q){if(!N.contains(P,O)){R[O]=Q[O]}}return R};N.defaults=function(O){J(o.call(arguments,1),function(P){for(var Q in P){if(O[Q]==null){O[Q]=P[Q]}}});return O};N.clone=function(O){if(!N.isObject(O)){return O}return N.isArray(O)?O.slice():N.extend({},O)};N.tap=function(P,O){O(P);return P};var K=function(V,U,P,Q){if(V===U){return V!==0||1/V==1/U}if(V==null||U==null){return V===U}if(V instanceof N){V=V._wrapped}if(U instanceof N){U=U._wrapped}var S=d.call(V);if(S!=d.call(U)){return false}switch(S){case"[object String]":return V==String(U);case"[object Number]":return V!=+V?U!=+U:(V==0?1/V==1/U:V==+U);case"[object Date]":case"[object Boolean]":return +V==+U;case"[object RegExp]":return V.source==U.source&&V.global==U.global&&V.multiline==U.multiline&&V.ignoreCase==U.ignoreCase}if(typeof V!="object"||typeof U!="object"){return false}var O=P.length;while(O--){if(P[O]==V){return Q[O]==U}}P.push(V);Q.push(U);var X=0,Y=true;if(S=="[object Array]"){X=V.length;Y=X==U.length;if(Y){while(X--){if(!(Y=K(V[X],U[X],P,Q))){break}}}}else{var T=V.constructor,R=U.constructor;if(T!==R&&!(N.isFunction(T)&&(T instanceof T)&&N.isFunction(R)&&(R instanceof R))){return false}for(var W in V){if(N.has(V,W)){X++;if(!(Y=N.has(U,W)&&K(V[W],U[W],P,Q))){break}}}if(Y){for(W in U){if(N.has(U,W)&&!(X--)){break}}Y=!X}}P.pop();Q.pop();return Y};N.isEqual=function(P,O){return K(P,O,[],[])};N.isEmpty=function(P){if(P==null){return true}if(N.isArray(P)||N.isString(P)){return P.length===0}for(var O in P){if(N.has(P,O)){return false}}return true};N.isElement=function(O){return !!(O&&O.nodeType===1)};N.isArray=u||function(O){return d.call(O)=="[object Array]"};N.isObject=function(O){return O===Object(O)};J(["Arguments","Function","String","Number","Date","RegExp"],function(O){N["is"+O]=function(P){return d.call(P)=="[object "+O+"]"}});if(!N.isArguments(arguments)){N.isArguments=function(O){return !!(O&&N.has(O,"callee"))}}if(typeof(/./)!=="function"){N.isFunction=function(O){return typeof O==="function"}}N.isFinite=function(O){return N.isNumber(O)&&isFinite(O)};N.isNaN=function(O){return N.isNumber(O)&&O!=+O};N.isBoolean=function(O){return O===true||O===false||d.call(O)=="[object Boolean]"};N.isNull=function(O){return O===null};N.isUndefined=function(O){return O===void 0};N.has=function(P,O){return j.call(P,O)};N.noConflict=function(){w._=k;return this};N.identity=function(O){return O};N.times=function(R,Q,P){for(var O=0;O<R;O++){Q.call(P,O)}};N.random=function(P,O){if(O==null){O=P;P=0}return P+(0|Math.random()*(O-P+1))};var m={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};m.unescape=N.invert(m.escape);var L={escape:new RegExp("["+N.keys(m.escape).join("")+"]","g"),unescape:new RegExp("("+N.keys(m.unescape).join("|")+")","g")};N.each(["escape","unescape"],function(O){N[O]=function(P){if(P==null){return""}return(""+P).replace(L[O],function(Q){return m[O][Q]})}});N.result=function(O,Q){if(O==null){return null}var P=O[Q];return N.isFunction(P)?P.call(O):P};N.mixin=function(O){J(N.functions(O),function(P){var Q=N[P]=O[P];N.prototype[P]=function(){var R=[this._wrapped];I.apply(R,arguments);return s.call(this,Q.apply(N,R))}})};var z=0;N.uniqueId=function(O){var P=z++;return O?O+P:P};N.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var v=/(.)^/;var h={"'":"'","\\":"\\","\r":"r","\n":"n","\t":"t","\u2028":"u2028","\u2029":"u2029"};var i=/\\|'|\r|\n|\t|\u2028|\u2029/g;N.template=function(W,R,Q){Q=N.defaults({},Q,N.templateSettings);var S=new RegExp([(Q.escape||v).source,(Q.interpolate||v).source,(Q.evaluate||v).source].join("|")+"|$","g");var T=0;var O="__p+='";W.replace(S,function(Y,Z,X,ab,aa){O+=W.slice(T,aa).replace(i,function(ac){return"\\"+h[ac]});O+=Z?"'+\n((__t=("+Z+"))==null?'':_.escape(__t))+\n'":X?"'+\n((__t=("+X+"))==null?'':__t)+\n'":ab?"';\n"+ab+"\n__p+='":"";T=aa+Y.length});O+="';\n";if(!Q.variable){O="with(obj||{}){\n"+O+"}\n"}O="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+O+"return __p;\n";try{var P=new Function(Q.variable||"obj","_",O)}catch(U){U.source=O;throw U}if(R){return P(R,N)}var V=function(X){return P.call(this,X,N)};V.source="function("+(Q.variable||"obj")+"){\n"+O+"}";return V};N.chain=function(O){return N(O).chain()};var s=function(O){return this._chain?N(O).chain():O};N.mixin(N);J(["pop","push","reverse","shift","sort","splice","unshift"],function(O){var P=D[O];N.prototype[O]=function(){var Q=this._wrapped;P.apply(Q,arguments);if((O=="shift"||O=="splice")&&Q.length===0){delete Q[0]}return s.call(this,Q)}});J(["concat","join","slice"],function(O){var P=D[O];N.prototype[O]=function(){return s.call(this,P.apply(this._wrapped,arguments))}});N.extend(N.prototype,{chain:function(){this._chain=true;return this},value:function(){return this._wrapped}})}).call(this); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/mvc/data.js --- a/static/scripts/packed/mvc/data.js +++ b/static/scripts/packed/mvc/data.js @@ -1,1 +1,1 @@ -var Dataset=Backbone.RelationalModel.extend({defaults:{id:"",type:"",name:"",hda_ldda:"hda"},urlRoot:galaxy_paths.get("datasets_url")});var DatasetCollection=Backbone.Collection.extend({model:Dataset}); \ No newline at end of file +define(["libs/backbone/backbone-relational"],function(){var a=Backbone.RelationalModel.extend({defaults:{id:"",type:"",name:"",hda_ldda:"hda"},urlRoot:galaxy_paths.get("datasets_url")});var b=Backbone.Collection.extend({model:a});return{Dataset:a,DatasetCollection:b}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/mvc/history.js --- a/static/scripts/packed/mvc/history.js +++ b/static/scripts/packed/mvc/history.js @@ -1,1 +1,1 @@ -function linkHTMLTemplate(b,a){if(!b){return"<a></a>"}a=a||"a";var c=["<"+a];for(key in b){var d=b[key];if(d===""){continue}switch(key){case"text":continue;case"classes":key="class";d=(b.classes.join)?(b.classes.join(" ")):(b.classes);default:c.push([" ",key,'="',d,'"'].join(""))}}c.push(">");if("text" in b){c.push(b.text)}c.push("</"+a+">");return c.join("")}var HistoryItem=BaseModel.extend(LoggableMixin).extend({defaults:{id:null,name:"",data_type:null,file_size:0,genome_build:null,metadata_data_lines:0,metadata_dbkey:null,metadata_sequences:0,misc_blurb:"",misc_info:"",model_class:"",state:"",deleted:false,purged:false,visible:true,for_editing:true,bodyIsShown:false},initialize:function(){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",HistoryItem.STATES.NOT_VIEWABLE)}},isEditable:function(){return(!(this.get("deleted")||this.get("purged")))},hasData:function(){return(this.get("file_size")>0)},toString:function(){var a=this.get("id")||"";if(this.get("name")){a+=':"'+this.get("name")+'"'}return"HistoryItem("+a+")"}});HistoryItem.STATES={NOT_VIEWABLE:"not_viewable",NEW:"new",UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",OK:"ok",EMPTY:"empty",ERROR:"error",DISCARDED:"discarded",SETTING_METADATA:"setting_metadata",FAILED_METADATA:"failed_metadata"};var HistoryItemView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(){this.log(this+".initialize:",this,this.model)},render:function(){var d=this.model.get("id"),c=this.model.get("state");this.clearReferences();this.$el.attr("id","historyItemContainer-"+d);var a=$("<div/>").attr("id","historyItem-"+d).addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this.body=$(this._render_body());a.append(this.body);a.find(".tooltip").tooltip({placement:"bottom"});var b=a.find("[popupmenu]");b.each(function(e,f){f=$(f);make_popupmenu(f)});this.$el.children().remove();return this.$el.append(a)},clearReferences:function(){this.displayButton=null;this.editButton=null;this.deleteButton=null;this.errButton=null},_render_warnings:function(){return $(jQuery.trim(HistoryItemView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_displayButton:function(){if(this.model.get("state")===HistoryItem.STATES.UPLOAD){return null}displayBtnData=(this.model.get("purged"))?({title:"Cannot display datasets removed from disk",enabled:false,icon_class:"display"}):({title:"Display data in browser",href:this.model.get("display_url"),target:(this.model.get("for_editing"))?("galaxy_main"):(null),icon_class:"display"});this.displayButton=new IconButtonView({model:new IconButton(displayBtnData)});return this.displayButton.render().$el},_render_editButton:function(){if((this.model.get("state")===HistoryItem.STATES.UPLOAD)||(!this.model.get("for_editing"))){return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:"Edit attributes",href:this.model.get("edit_url"),target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false}if(a){b.title="Undelete dataset to edit attributes"}else{if(c){b.title="Cannot edit attributes of datasets removed from disk"}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if(!this.model.get("for_editing")){return null}var a={title:"Delete",href:this.model.get("delete_url"),target:"galaxy_main",id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete"};if((this.model.get("deleted")||this.model.get("purged"))&&(!this.model.get("delete_url"))){a={title:"Dataset is already deleted",icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HistoryItemView.templates.titleLink(this.model.toJSON())))},_render_hdaSummary:function(){var a=this.model.toJSON();if(this.model.get("metadata_dbkey")==="?"&&this.model.isEditable()){_.extend(a,{dbkey_unknown_and_editable:true})}return HistoryItemView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var b=$("<div/>"),a=this;_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")){return null}var a=linkHTMLTemplate({title:"Download",href:this.model.get("download_url"),classes:["icon-button","tooltip","disk"]});var d=this.model.get("download_meta_urls");if(!d){return a}var c=$('<div popupmenu="dataset-'+this.model.get("id")+'-popup"></div>');c.append(linkHTMLTemplate({text:"Download Dataset",title:"Download",href:this.model.get("download_url"),classes:["icon-button","tooltip","disk"]}));c.append("<a>Additional Files</a>");for(file_type in d){c.append(linkHTMLTemplate({text:"Download "+file_type,href:d[file_type],classes:["action-button"]}))}var b=$(('<div style="float:left;" class="menubutton split popup" id="dataset-${dataset_id}-popup"></div>'));b.append(a);c.append(b);return c},_render_errButton:function(){if((this.model.get("state")!==HistoryItem.STATES.ERROR)||(!this.model.get("for_editing"))){return null}this.errButton=new IconButtonView({model:new IconButton({title:"View or report this error",href:this.model.get("report_error_url"),target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:"View details",href:this.model.get("show_params_url"),target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_rerunButton:function(){if(!this.model.get("for_editing")){return null}this.rerunButton=new IconButtonView({model:new IconButton({title:"Run this job again",href:this.model.get("rerun_url"),target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_tracksterButton:function(){var a=this.model.get("trackster_urls");if(!(this.model.hasData())||!(this.model.get("for_editing"))||!(a)){return null}this.tracksterButton=new IconButtonView({model:new IconButton({title:"View in Trackster",icon_class:"chart_curve"})});this.errButton.render();this.errButton.$el.addClass("trackster-add").attr({"data-url":a["data-url"],"action-url":a["action-url"],"new-url":a["new-url"]});return this.errButton.$el},_render_secondaryActionButtons:function(b){var c=$('<div style="float: right;"></div>'),a=this;_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||!(this.model.get("for_editing"))||(!this.model.get("retag_url"))){return null}this.tagButton=new IconButtonView({model:new IconButton({title:"Edit dataset tags",target:"galaxy_main",href:this.model.get("retag_url"),icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||!(this.model.get("for_editing"))||(!this.model.get("annotate_url"))){return null}this.annotateButton=new IconButtonView({model:new IconButton({title:"Edit dataset annotation",target:"galaxy_main",href:this.model.get("annotate_url"),icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(this.model.get("retag_url")){return null}return $(HistoryItemView.templates.tagArea(this.model.toJSON()))},_render_annotationArea:function(){if(!this.model.get("annotate_url")){return null}return $(HistoryItemView.templates.annotationArea(this.model.toJSON()))},_render_displayApps:function(){if(!this.model.get("display_apps")){return null}var a=this.model.get("displayApps"),c=$("<div/>"),b=$("<span/>");this.log(this+"displayApps:",a);return c},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body_not_viewable:function(a){a.append($("<div>You do not have permission to view dataset.</div>"))},_render_body_uploading:function(a){a.append($("<div>Dataset is uploading</div>"))},_render_body_queued:function(a){a.append($("<div>Job is waiting to run.</div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_running:function(a){a.append("<div>Job is currently running.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append(("An error occurred running this job: <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]))},_render_body_discarded:function(a){a.append("<div>The job creating this dataset was cancelled before completion.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_setting_metadata:function(a){a.append($("<div>Metadata is being auto-detected.</div>"))},_render_body_empty:function(a){a.append($("<div>No data: <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_failed_metadata:function(a){a.append($(HistoryItemView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayApps());a.append(this._render_peek())},_render_body:function(){var b=this.model.get("state");var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: block");switch(b){case HistoryItem.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryItem.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryItem.STATES.QUEUED:this._render_body_queued(a);break;case HistoryItem.STATES.RUNNING:this._render_body_running(a);break;case HistoryItem.STATES.ERROR:this._render_body_error(a);break;case HistoryItem.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryItem.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryItem.STATES.EMPTY:this._render_body_empty(a);break;case HistoryItem.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryItem.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+b+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.model.get("bodyIsShown")===false){a.hide()}return a},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(b){this.log(this+".loadAndDisplayTags",b);var c=this.$el.find(".tag-area"),a=c.find(".tag-elt");if(c.is(":hidden")){if(!a.html()){$.ajax({url:this.model.get("ajax_get_tag_url"),error:function(){alert("Tagging failed")},success:function(d){a.html(d);a.find(".tooltip").tooltip();c.slideDown("fast")}})}else{c.slideDown("fast")}}else{c.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.model.get("ajax_set_annotation_url");if(d.is(":hidden")){if(!c.html()){$.ajax({url:this.model.get("ajax_get_annotation_url"),error:function(){alert("Annotations failed")},success:function(e){if(e===""){e="<em>Describe or add notes to dataset</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toggleBodyVisibility:function(){this.log(this+".toggleBodyVisibility");this.$el.find(".historyItemBody").toggle()},toString:function(){var a=(this.model)?(this.model+""):("");return"HistoryItemView("+a+")"}});HistoryItemView.templates=CompiledTemplateLoader.getTemplates({"common-templates.html":{warningMsg:"template-warningmessagesmall"},"history-templates.html":{messages:"template-history-warning-messages",titleLink:"template-history-titleLink",hdaSummary:"template-history-hdaSummary",failedMetadata:"template-history-failedMetaData",tagArea:"template-history-tagArea",annotationArea:"template-history-annotationArea"}});var HistoryCollection=Backbone.Collection.extend({model:HistoryItem,toString:function(){return("HistoryCollection()")}});var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",state_details:{discarded:0,empty:0,error:0,failed_metadata:0,ok:0,queued:0,running:0,setting_metadata:0,upload:0}},initialize:function(b,a){this.log(this+".initialize",b,a);this.items=new HistoryCollection()},loadDatasetsAsHistoryItems:function(c){var a=this,b=this.get("id"),d=this.get("state_details");_.each(c,function(f,e){a.log("loading dataset: ",f,e);var h=new HistoryItem(_.extend(f,{history_id:b}));a.log("as History:",h);a.items.add(h);var g=f.state;d[g]+=1});this.set("state_details",d);this._stateFromStateDetails();return this},_stateFromStateDetails:function(){this.set("state","");var a=this.get("state_details");if((a.error>0)||(a.failed_metadata>0)){this.set("state",HistoryItem.STATES.ERROR)}else{if((a.running>0)||(a.setting_metadata>0)){this.set("state",HistoryItem.STATES.RUNNING)}else{if(a.queued>0){this.set("state",HistoryItem.STATES.QUEUED)}else{if(a.ok===this.items.length){this.set("state",HistoryItem.STATES.OK)}else{throw ("_stateFromStateDetails: unable to determine history state from state details: "+this.state_details)}}}}return this},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});var HistoryView=BaseView.extend(LoggableMixin).extend({el:"body.historyPage",initialize:function(){this.log(this+".initialize");this.itemViews=[];var a=this;this.model.items.each(function(c){var b=new HistoryItemView({model:c});a.itemViews.push(b)})},render:function(){this.log(this+".render");var a=$("<div/>");_.each(this.itemViews,function(b){a.prepend(b.render())});this.$el.append(a.children());a.remove()},toString:function(){var a=this.model.get("name")||"";return"HistoryView("+a+")"}});function createMockHistoryData(){mockHistory={};mockHistory.data={template:{id:"a799d38679e985db",name:"template",data_type:"fastq",file_size:226297533,genome_build:"?",metadata_data_lines:0,metadata_dbkey:"?",metadata_sequences:0,misc_blurb:"215.8 MB",misc_info:"uploaded fastq file (misc_info)",model_class:"HistoryDatasetAssociation",download_url:"",state:"ok",visible:true,deleted:false,purged:false,hid:0,for_editing:true,accessible:true,undelete_url:"",purge_url:"",unhide_url:"",display_url:"example.com/display",edit_url:"example.com/edit",delete_url:"example.com/delete",show_params_url:"example.com/show_params",rerun_url:"example.com/rerun",retag_url:"example.com/retag",annotate_url:"example.com/annotate",peek:['<table cellspacing="0" cellpadding="3"><tr><th>1.QNAME</th><th>2.FLAG</th><th>3.RNAME</th><th>4.POS</th><th>5.MAPQ</th><th>6.CIGAR</th><th>7.MRNM</th><th>8.MPOS</th><th>9.ISIZE</th><th>10.SEQ</th><th>11.QUAL</th><th>12.OPT</th></tr>','<tr><td colspan="100%">@SQ SN:gi|87159884|ref|NC_007793.1| LN:2872769</td></tr>','<tr><td colspan="100%">@PG ID:bwa PN:bwa VN:0.5.9-r16</td></tr>','<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 73 gi|87159884|ref|NC_007793.1| 2720169 37 101M = 2720169 0 NAATATGACATTATTTTCAAAACAGCTGAAAATTTAGACGTACCGATTTATCTACATCCCGCGCCAGTTAACAGTGACATTTATCAATCATACTATAAAGG !!!!!!!!!!$!!!$!!!!!$!!!!!!$!$!$$$!!$!!$!!!!!!!!!!!$!</td></tr>','<tr><td colspan="100%">!!!$!$!$$!!$$!!$!!!!!!!!!!!!!!!!!!!!!!!!!!$!!$!! XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 X1:i:0 XM:i:1 XO:i:0 XG:i:0 MD:Z:0A100</td></tr>','<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 133 gi|87159884|ref|NC_007793.1| 2720169 0 * = 2720169 0 NAAACTGTGGCTTCGTTNNNNNNNNNNNNNNNGTGANNNNNNNNNNNNNNNNNNNGNNNNNNNNNNNNNNNNNNNNCNAANNNNNNNNNNNNNNNNNNNNN !!!!!!!!!!!!$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>','<tr><td colspan="100%">!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>',"</table>"].join("")}};_.extend(mockHistory.data,{notAccessible:_.extend(_.clone(mockHistory.data.template),{accessible:false}),deleted:_.extend(_.clone(mockHistory.data.template),{deleted:true,delete_url:"",purge_url:"example.com/purge",undelete_url:"example.com/undelete"}),purgedNotDeleted:_.extend(_.clone(mockHistory.data.template),{purged:true,delete_url:""}),notvisible:_.extend(_.clone(mockHistory.data.template),{visible:false,unhide_url:"example.com/unhide"}),hasDisplayApps:_.extend(_.clone(mockHistory.data.template),{display_apps:{"display in IGB":{Web:"/display_application/63cd3858d057a6d1/igb_bam/Web",Local:"/display_application/63cd3858d057a6d1/igb_bam/Local"}}}),canTrackster:_.extend(_.clone(mockHistory.data.template),{trackster_urls:{"data-url":"example.com/trackster-data","action-url":"example.com/trackster-action","new-url":"example.com/trackster-new"}}),zeroSize:_.extend(_.clone(mockHistory.data.template),{file_size:0}),hasMetafiles:_.extend(_.clone(mockHistory.data.template),{download_meta_urls:{bam_index:"example.com/bam-index"}}),upload:_.extend(_.clone(mockHistory.data.template),{state:HistoryItem.STATES.UPLOAD}),queued:_.extend(_.clone(mockHistory.data.template),{state:HistoryItem.STATES.QUEUED}),running:_.extend(_.clone(mockHistory.data.template),{state:HistoryItem.STATES.RUNNING}),empty:_.extend(_.clone(mockHistory.data.template),{state:HistoryItem.STATES.EMPTY}),error:_.extend(_.clone(mockHistory.data.template),{state:HistoryItem.STATES.ERROR,report_error_url:"example.com/report_err"}),discarded:_.extend(_.clone(mockHistory.data.template),{state:HistoryItem.STATES.DISCARDED}),setting_metadata:_.extend(_.clone(mockHistory.data.template),{state:HistoryItem.STATES.SETTING_METADATA}),failed_metadata:_.extend(_.clone(mockHistory.data.template),{state:HistoryItem.STATES.FAILED_METADATA})});$(document).ready(function(){mockHistory.items={};mockHistory.views={};for(key in mockHistory.data){mockHistory.items[key]=new HistoryItem(mockHistory.data[key]);mockHistory.items[key].set("name",key);mockHistory.views[key]=new HistoryItemView({model:mockHistory.items[key]});$("body").append(mockHistory.views[key].render())}})}; \ No newline at end of file +function linkHTMLTemplate(b,a){if(!b){return"<a></a>"}a=a||"a";var c=["<"+a];for(key in b){var d=b[key];if(d===""){continue}switch(key){case"text":continue;case"classes":key="class";d=(b.classes.join)?(b.classes.join(" ")):(b.classes);default:c.push([" ",key,'="',d,'"'].join(""))}}c.push(">");if("text" in b){c.push(b.text)}c.push("</"+a+">");return c.join("")}var HistoryItem=BaseModel.extend(LoggableMixin).extend({defaults:{id:null,name:"",data_type:null,file_size:0,genome_build:null,metadata_data_lines:0,metadata_dbkey:null,metadata_sequences:0,misc_blurb:"",misc_info:"",model_class:"",state:"",deleted:false,purged:false,visible:true,for_editing:true,bodyIsShown:false},initialize:function(){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",HistoryItem.STATES.NOT_VIEWABLE)}},isEditable:function(){return(!(this.get("deleted")||this.get("purged")))},hasData:function(){return(this.get("file_size")>0)},toString:function(){var a=this.get("id")||"";if(this.get("name")){a+=':"'+this.get("name")+'"'}return"HistoryItem("+a+")"}});HistoryItem.STATES={NOT_VIEWABLE:"not_viewable",NEW:"new",UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",OK:"ok",EMPTY:"empty",ERROR:"error",DISCARDED:"discarded",SETTING_METADATA:"setting_metadata",FAILED_METADATA:"failed_metadata"};var HistoryItemView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(){this.log(this+".initialize:",this,this.model)},render:function(){var c=this.model.get("id"),b=this.model.get("state");this.clearReferences();this.$el.attr("id","historyItemContainer-"+c);var a=$("<div/>").attr("id","historyItem-"+c).addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+b);a.append(this._render_warnings());a.append(this._render_titleBar());this.body=$(this._render_body());a.append(this.body);a.find(".tooltip").tooltip({placement:"bottom"});make_popup_menus(a);this.$el.children().remove();return this.$el.append(a)},clearReferences:function(){this.displayButton=null;this.editButton=null;this.deleteButton=null;this.errButton=null},_render_warnings:function(){return $(jQuery.trim(HistoryItemView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_displayButton:function(){if(this.model.get("state")===HistoryItem.STATES.UPLOAD){return null}displayBtnData=(this.model.get("purged"))?({title:"Cannot display datasets removed from disk",enabled:false,icon_class:"display"}):({title:"Display data in browser",href:this.model.get("display_url"),target:(this.model.get("for_editing"))?("galaxy_main"):(null),icon_class:"display"});this.displayButton=new IconButtonView({model:new IconButton(displayBtnData)});return this.displayButton.render().$el},_render_editButton:function(){if((this.model.get("state")===HistoryItem.STATES.UPLOAD)||(!this.model.get("for_editing"))){return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:"Edit attributes",href:this.model.get("edit_url"),target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false}if(a){b.title="Undelete dataset to edit attributes"}else{if(c){b.title="Cannot edit attributes of datasets removed from disk"}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if(!this.model.get("for_editing")){return null}var a={title:"Delete",href:this.model.get("delete_url"),target:"galaxy_main",id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete"};if((this.model.get("deleted")||this.model.get("purged"))&&(!this.model.get("delete_url"))){a={title:"Dataset is already deleted",icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HistoryItemView.templates.titleLink(this.model.toJSON())))},_render_hdaSummary:function(){var a=this.model.toJSON();if(this.model.get("metadata_dbkey")==="?"&&this.model.isEditable()){_.extend(a,{dbkey_unknown_and_editable:true})}return HistoryItemView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var b=$("<div/>").attr("id","primary-actions-"+this.model.get("id")),a=this;_.each(c,function(d){var e=d.call(a);b.append(e)});return b},_render_downloadButton:function(){if(this.model.get("purged")){return null}var a=HistoryItemView.templates.downloadLinks(this.model.toJSON());this.log("_render_downloadButton, downloadLinkHTML:",a);return $(a)},_render_errButton:function(){if((this.model.get("state")!==HistoryItem.STATES.ERROR)||(!this.model.get("for_editing"))){return null}this.errButton=new IconButtonView({model:new IconButton({title:"View or report this error",href:this.model.get("report_error_url"),target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:"View details",href:this.model.get("show_params_url"),target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_rerunButton:function(){if(!this.model.get("for_editing")){return null}this.rerunButton=new IconButtonView({model:new IconButton({title:"Run this job again",href:this.model.get("rerun_url"),target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_tracksterButton:function(){var a=this.model.get("trackster_urls");if(!(this.model.hasData())||!(this.model.get("for_editing"))||!(a)){return null}this.tracksterButton=new IconButtonView({model:new IconButton({title:"View in Trackster",icon_class:"chart_curve"})});this.errButton.render();this.errButton.$el.addClass("trackster-add").attr({"data-url":a["data-url"],"action-url":a["action-url"],"new-url":a["new-url"]});return this.errButton.$el},_render_secondaryActionButtons:function(b){var c=$("<div/>"),a=this;c.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||!(this.model.get("for_editing"))||(!this.model.get("retag_url"))){return null}this.tagButton=new IconButtonView({model:new IconButton({title:"Edit dataset tags",target:"galaxy_main",href:this.model.get("retag_url"),icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||!(this.model.get("for_editing"))||(!this.model.get("annotate_url"))){return null}this.annotateButton=new IconButtonView({model:new IconButton({title:"Edit dataset annotation",target:"galaxy_main",href:this.model.get("annotate_url"),icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(this.model.get("retag_url")){return null}return $(HistoryItemView.templates.tagArea(this.model.toJSON()))},_render_annotationArea:function(){if(!this.model.get("annotate_url")){return null}return $(HistoryItemView.templates.annotationArea(this.model.toJSON()))},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){this.log(this+"display_types:",this.model.get("display_types"));a.append(HistoryItemView.templates.displayApps({displayApps:this.model.toJSON().display_types}))}if(!_.isEmpty(this.model.get("display_apps"))){this.log(this+"display_apps:",this.model.get("display_apps"));a.append(HistoryItemView.templates.displayApps({displayApps:this.model.toJSON().display_apps}))}return a},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body_not_viewable:function(a){a.append($("<div>You do not have permission to view dataset.</div>"))},_render_body_uploading:function(a){a.append($("<div>Dataset is uploading</div>"))},_render_body_queued:function(a){a.append($("<div>Job is waiting to run.</div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_running:function(a){a.append("<div>Job is currently running.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append(("An error occurred running this job: <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]))},_render_body_discarded:function(a){a.append("<div>The job creating this dataset was cancelled before completion.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_setting_metadata:function(a){a.append($("<div>Metadata is being auto-detected.</div>"))},_render_body_empty:function(a){a.append($("<div>No data: <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_failed_metadata:function(a){a.append($(HistoryItemView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayApps());a.append(this._render_peek())},_render_body:function(){var b=this.model.get("state");var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: block");switch(b){case HistoryItem.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryItem.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryItem.STATES.QUEUED:this._render_body_queued(a);break;case HistoryItem.STATES.RUNNING:this._render_body_running(a);break;case HistoryItem.STATES.ERROR:this._render_body_error(a);break;case HistoryItem.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryItem.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryItem.STATES.EMPTY:this._render_body_empty(a);break;case HistoryItem.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryItem.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+b+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.model.get("bodyIsShown")===false){a.hide()}return a},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(b){this.log(this+".loadAndDisplayTags",b);var c=this.$el.find(".tag-area"),a=c.find(".tag-elt");if(c.is(":hidden")){if(!a.html()){$.ajax({url:this.model.get("ajax_get_tag_url"),error:function(){alert("Tagging failed")},success:function(d){a.html(d);a.find(".tooltip").tooltip();c.slideDown("fast")}})}else{c.slideDown("fast")}}else{c.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.model.get("ajax_set_annotation_url");if(d.is(":hidden")){if(!c.html()){$.ajax({url:this.model.get("ajax_get_annotation_url"),error:function(){alert("Annotations failed")},success:function(e){if(e===""){e="<em>Describe or add notes to dataset</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toggleBodyVisibility:function(){this.log(this+".toggleBodyVisibility");this.$el.find(".historyItemBody").toggle()},toString:function(){var a=(this.model)?(this.model+""):("");return"HistoryItemView("+a+")"}});HistoryItemView.templates=CompiledTemplateLoader.getTemplates({"common-templates.html":{warningMsg:"template-warningmessagesmall"},"history-templates.html":{messages:"template-history-warning-messages",titleLink:"template-history-titleLink",hdaSummary:"template-history-hdaSummary",downloadLinks:"template-history-downloadLinks",failedMetadata:"template-history-failedMetaData",tagArea:"template-history-tagArea",annotationArea:"template-history-annotationArea",displayApps:"template-history-displayApps"}});var HistoryCollection=Backbone.Collection.extend({model:HistoryItem,toString:function(){return("HistoryCollection()")}});var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",state_details:{discarded:0,empty:0,error:0,failed_metadata:0,ok:0,queued:0,running:0,setting_metadata:0,upload:0}},initialize:function(b,a){this.log(this+".initialize",b,a);this.items=new HistoryCollection()},loadDatasetsAsHistoryItems:function(c){var a=this,b=this.get("id"),d=this.get("state_details");_.each(c,function(f,e){a.log("loading dataset: ",f,e);var h=new HistoryItem(_.extend(f,{history_id:b}));a.log("as History:",h);a.items.add(h);var g=f.state;d[g]+=1});this.set("state_details",d);this._stateFromStateDetails();return this},_stateFromStateDetails:function(){this.set("state","");var a=this.get("state_details");if((a.error>0)||(a.failed_metadata>0)){this.set("state",HistoryItem.STATES.ERROR)}else{if((a.running>0)||(a.setting_metadata>0)){this.set("state",HistoryItem.STATES.RUNNING)}else{if(a.queued>0){this.set("state",HistoryItem.STATES.QUEUED)}else{if(a.ok===this.items.length){this.set("state",HistoryItem.STATES.OK)}else{throw ("_stateFromStateDetails: unable to determine history state from state details: "+this.state_details)}}}}return this},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});var HistoryView=BaseView.extend(LoggableMixin).extend({el:"body.historyPage",initialize:function(){this.log(this+".initialize");this.itemViews=[];var a=this;this.model.items.each(function(c){var b=new HistoryItemView({model:c});a.itemViews.push(b)})},render:function(){this.log(this+".render");var a=$("<div/>");_.each(this.itemViews,function(b){a.prepend(b.render())});this.$el.append(a.children());a.remove()},toString:function(){var a=this.model.get("name")||"";return"HistoryView("+a+")"}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/mvc/tools.js --- a/static/scripts/packed/mvc/tools.js +++ b/static/scripts/packed/mvc/tools.js @@ -1,1 +1,1 @@ -var ServerStateDeferred=Backbone.Model.extend({defaults:{ajax_settings:{},interval:1000,success_fn:function(a){return true}},go:function(){var d=$.Deferred(),c=this,f=c.get("ajax_settings"),e=c.get("success_fn"),b=c.get("interval"),a=function(){$.ajax(f).success(function(g){if(e(g)){d.resolve(g)}else{setTimeout(a,b)}})};a();return d}});var BaseModel=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var Tool=BaseModel.extend({defaults:{description:null,target:null,inputs:[]},relations:[{type:Backbone.HasMany,key:"inputs",relatedModel:"ToolInput",reverseRelation:{key:"tool",includeInJSON:false}}],urlRoot:galaxy_paths.get("tool_url"),copy:function(b){var c=new Tool(this.toJSON());if(b){var a=new Backbone.Collection();c.get("inputs").each(function(d){if(d.get_samples()){a.push(d)}});c.set("inputs",a)}return c},apply_search_results:function(a){(_.indexOf(a,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(a,b){this.get("inputs").find(function(c){return c.get("name")===a}).set("value",b)},set_input_values:function(b){var a=this;_.each(_.keys(b),function(c){a.set_input_value(c,b[c])})},run:function(){return this._run()},rerun:function(b,a){return this._run({action:"rerun",target_dataset_id:b.id,regions:a})},get_inputs_dict:function(){var a={};this.get("inputs").each(function(b){a[b.get("name")]=b.get("value")});return a},_run:function(c){var d=_.extend({tool_id:this.id,inputs:this.get_inputs_dict()},c);var b=$.Deferred(),a=new ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(d),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(e){return e!=="pending"}});$.when(a.go()).then(function(e){b.resolve(new DatasetCollection().reset(e))});return b}});var ToolInput=Backbone.RelationalModel.extend({defaults:{name:null,label:null,type:null,value:null,num_samples:5},initialize:function(){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new ToolInput(this.toJSON())},get_samples:function(){var b=this.get("type"),a=null;if(b==="number"){a=d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}else{if(b==="select"){a=_.map(this.get("options"),function(c){return c[0]})}}return a}});var ToolCollection=Backbone.Collection.extend({model:Tool});var ToolPanelLabel=BaseModel.extend({});var ToolPanelSection=BaseModel.extend({defaults:{elems:[],open:false},clear_search_results:function(){_.each(this.attributes.elems,function(a){a.show()});this.show();this.set("open",false)},apply_search_results:function(b){var c=true,a;_.each(this.attributes.elems,function(d){if(d instanceof ToolPanelLabel){a=d;a.hide()}else{if(d instanceof Tool){if(d.apply_search_results(b)){c=false;if(a){a.show()}}}}});if(c){this.hide()}else{this.show();this.set("open",true)}}});var ToolSearch=BaseModel.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var c=this.attributes.query;if(c.length<this.attributes.min_chars_for_search){this.set("results",null);return}var b=c+"*";if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var a=this;this.timer=setTimeout(function(){$.get(a.attributes.search_url,{query:b},function(d){a.set("results",d);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});var ToolPanel=Backbone.Collection.extend({url:"/tools",tools:new ToolCollection(),parse:function(a){var b=function(e){var d=e.type;if(d==="tool"){return new Tool(e)}else{if(d==="section"){var c=_.map(e.elems,b);e.elems=c;return new ToolPanelSection(e)}else{if(d==="label"){return new ToolPanelLabel(e)}}}};return _.map(a,b)},initialize:function(a){this.tool_search=a.tool_search;this.tool_search.on("change:results",this.apply_search_results,this);this.on("reset",this.populate_tools,this)},populate_tools:function(){var a=this;a.tools=new ToolCollection();this.each(function(b){if(b instanceof ToolPanelSection){_.each(b.attributes.elems,function(c){if(c instanceof Tool){a.tools.push(c)}})}else{if(b instanceof Tool){a.tools.push(b)}}})},clear_search_results:function(){this.each(function(a){if(a instanceof ToolPanelSection){a.clear_search_results()}else{a.show()}})},apply_search_results:function(){var b=this.tool_search.attributes.results;if(b===null){this.clear_search_results();return}var a=null;this.each(function(c){if(c instanceof ToolPanelLabel){a=c;a.hide()}else{if(c instanceof Tool){if(c.apply_search_results(b)){if(a){a.show()}}}else{a=null;c.apply_search_results(b)}}})}});var BaseView=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var ToolLinkView=BaseView.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var ToolPanelLabelView=BaseView.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.name));return this}});var ToolPanelSectionView=BaseView.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){BaseView.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var a=this.$el.find(".toolSectionBody");_.each(this.model.attributes.elems,function(b){if(b instanceof Tool){var c=new ToolLinkView({model:b,className:"toolTitle"});c.render();a.append(c.$el)}else{if(b instanceof ToolPanelLabel){var d=new ToolPanelLabelView({model:b});d.render();a.append(d.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var ToolSearchView=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(a){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===a.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var ToolPanelView=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.collection.tool_search.on("change:results",this.handle_search_results,this)},render:function(){var a=this;var b=new ToolSearchView({model:this.collection.tool_search});b.render();a.$el.append(b.$el);this.collection.each(function(d){if(d instanceof ToolPanelSection){var c=new ToolPanelSectionView({model:d});c.render();a.$el.append(c.$el)}else{if(d instanceof Tool){var e=new ToolLinkView({model:d,className:"toolTitleNoSection"});e.render();a.$el.append(e.$el)}else{if(d instanceof ToolPanelLabel){var f=new ToolPanelLabelView({model:d});f.render();a.$el.append(f.$el)}}}});a.$el.find("a.tool-link").click(function(f){var d=$(this).attr("class").split(/\s+/)[0],c=a.collection.tools.get(d);a.trigger("tool_link_click",f,c)});return this},handle_search_results:function(){var a=this.collection.tool_search.attributes.results;if(a&&a.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var ToolFormView=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var IntegratedToolMenuAndView=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new ToolPanelView({collection:this.collection});this.tool_form_view=new ToolFormView()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var a=this;this.tool_panel_view.on("tool_link_click",function(c,b){c.preventDefault();a.show_tool(b)})},show_tool:function(b){var a=this;b.fetch().done(function(){a.tool_form_view.model=b;a.tool_form_view.render();a.tool_form_view.$el.show();$("#left").width("650px")})}}); \ No newline at end of file +define(["libs/underscore","viz/trackster/util","mvc/data","libs/backbone/backbone-relational"],function(q,a,r){var f=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var k=Backbone.RelationalModel.extend({defaults:{name:null,label:null,type:null,value:null,num_samples:5},initialize:function(){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new k(this.toJSON())},get_samples:function(){var u=this.get("type"),t=null;if(u==="number"){t=d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}else{if(u==="select"){t=q.map(this.get("options"),function(v){return v[0]})}}return t}});var e=f.extend({defaults:{description:null,target:null,inputs:[]},relations:[{type:Backbone.HasMany,key:"inputs",relatedModel:k,reverseRelation:{key:"tool",includeInJSON:false}}],urlRoot:galaxy_paths.get("tool_url"),copy:function(u){var v=new e(this.toJSON());if(u){var t=new Backbone.Collection();v.get("inputs").each(function(w){if(w.get_samples()){t.push(w)}});v.set("inputs",t)}return v},apply_search_results:function(t){(q.indexOf(t,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(t,u){this.get("inputs").find(function(v){return v.get("name")===t}).set("value",u)},set_input_values:function(u){var t=this;q.each(q.keys(u),function(v){t.set_input_value(v,u[v])})},run:function(){return this._run()},rerun:function(u,t){return this._run({action:"rerun",target_dataset_id:u.id,regions:t})},get_inputs_dict:function(){var t={};this.get("inputs").each(function(u){t[u.get("name")]=u.get("value")});return t},_run:function(v){var w=q.extend({tool_id:this.id,inputs:this.get_inputs_dict()},v);var u=$.Deferred(),t=new a.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(w),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(x){return x!=="pending"}});$.when(t.go()).then(function(x){u.resolve(new r.DatasetCollection().reset(x))});return u}});var i=Backbone.Collection.extend({model:e});var m=f.extend({});var p=f.extend({defaults:{elems:[],open:false},clear_search_results:function(){q.each(this.attributes.elems,function(t){t.show()});this.show();this.set("open",false)},apply_search_results:function(u){var v=true,t;q.each(this.attributes.elems,function(w){if(w instanceof m){t=w;t.hide()}else{if(w instanceof e){if(w.apply_search_results(u)){v=false;if(t){t.show()}}}}});if(v){this.hide()}else{this.show();this.set("open",true)}}});var b=f.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:true,query:"",results:null,clear_key:27},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var v=this.attributes.query;if(v.length<this.attributes.min_chars_for_search){this.set("results",null);return}var u=v+"*";if(this.timer){clearTimeout(this.timer)}$("#search-clear-btn").hide();$("#search-spinner").show();var t=this;this.timer=setTimeout(function(){$.get(t.attributes.search_url,{query:u},function(w){t.set("results",w);$("#search-spinner").hide();$("#search-clear-btn").show()},"json")},200)},clear_search:function(){this.set("query","");this.set("results",null)}});var j=Backbone.Collection.extend({url:"/tools",tools:new i(),parse:function(t){var u=function(x){var w=x.type;if(w==="tool"){return new e(x)}else{if(w==="section"){var v=q.map(x.elems,u);x.elems=v;return new p(x)}else{if(w==="label"){return new m(x)}}}};return q.map(t,u)},initialize:function(t){this.tool_search=t.tool_search;this.tool_search.on("change:results",this.apply_search_results,this);this.on("reset",this.populate_tools,this)},populate_tools:function(){var t=this;t.tools=new i();this.each(function(u){if(u instanceof p){q.each(u.attributes.elems,function(v){if(v instanceof e){t.tools.push(v)}})}else{if(u instanceof e){t.tools.push(u)}}})},clear_search_results:function(){this.each(function(t){if(t instanceof p){t.clear_search_results()}else{t.show()}})},apply_search_results:function(){var u=this.tool_search.attributes.results;if(u===null){this.clear_search_results();return}var t=null;this.each(function(v){if(v instanceof m){t=v;t.hide()}else{if(v instanceof e){if(v.apply_search_results(u)){if(t){t.show()}}}else{t=null;v.apply_search_results(u)}}})}});var n=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var h=n.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var c=n.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.name));return this}});var g=n.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){n.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var t=this.$el.find(".toolSectionBody");q.each(this.model.attributes.elems,function(u){if(u instanceof e){var v=new h({model:u,className:"toolTitle"});v.render();t.append(v.$el)}else{if(u instanceof m){var w=new c({model:u});w.render();t.append(w.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var l=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}return this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){this.model.clear_search();this.$el.find(":input").val(this.model.attributes.search_hint_string);this.focus_and_select();return false},query_changed:function(t){if((this.model.attributes.clear_key)&&(this.model.attributes.clear_key===t.which)){this.clear();return false}this.model.set("query",this.$el.find(":input").val())}});var s=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.collection.tool_search.on("change:results",this.handle_search_results,this)},render:function(){var t=this;var u=new l({model:this.collection.tool_search});u.render();t.$el.append(u.$el);this.collection.each(function(w){if(w instanceof p){var v=new g({model:w});v.render();t.$el.append(v.$el)}else{if(w instanceof e){var x=new h({model:w,className:"toolTitleNoSection"});x.render();t.$el.append(x.$el)}else{if(w instanceof m){var y=new c({model:w});y.render();t.$el.append(y.$el)}}}});t.$el.find("a.tool-link").click(function(x){var w=$(this).attr("class").split(/\s+/)[0],v=t.collection.tools.get(w);t.trigger("tool_link_click",x,v)});return this},handle_search_results:function(){var t=this.collection.tool_search.attributes.results;if(t&&t.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var o=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var d=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new s({collection:this.collection});this.tool_form_view=new o()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var t=this;this.tool_panel_view.on("tool_link_click",function(v,u){v.preventDefault();t.show_tool(u)})},show_tool:function(u){var t=this;u.fetch().done(function(){t.tool_form_view.model=u;t.tool_form_view.render();t.tool_form_view.$el.show();$("#left").width("650px")})}});return{Tool:e,ToolSearch:b,ToolPanel:j,ToolPanelView:s,ToolFormView:o}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/templates/compiled/helpers-common-templates.js --- a/static/scripts/packed/templates/compiled/helpers-common-templates.js +++ b/static/scripts/packed/templates/compiled/helpers-common-templates.js @@ -1,1 +1,1 @@ -Handlebars.registerPartial("clearFloatDiv",function(a){return'<div class="clear"></div>'});Handlebars.registerPartial("iconButton",function(c,b){var a="";a+=(c.enabled)?("<a"):("<span");if(c.title){a+=' title="'+c.title+'"'}a+=' class="icon-button';if(c.isMenuButton){a+=" menu-button"}if(c.title){a+=" tooltip"}a+=" "+c.icon_class;if(!c.enabled){a+="_disabled"}a+='"';if(c.id){a+=' id="'+c.id+'"'}a+=' href="'+((c.href)?(c.href):("javascript:void(0);"))+'"';if(c.target){a+=' target="'+c.target+'"'}if(!c.visible){a+=' style="display: none;"'}a+=">"+((c.enabled)?("</a>"):("</span>"));return a});Handlebars.registerHelper("warningmessagesmall",function(a){return'<div class="warningmessagesmall"><strong>'+a.fn(this)+"</strong></div>"}); \ No newline at end of file +Handlebars.registerPartial("clearFloatDiv",function(a){return'<div class="clear"></div>'});Handlebars.registerHelper("warningmessagesmall",function(a){return'<div class="warningmessagesmall"><strong>'+a.fn(this)+"</strong></div>"});Handlebars.registerPartial("iconButton",function(c,b){var a="";a+=(c.enabled)?("<a"):("<span");if(c.title){a+=' title="'+c.title+'"'}a+=' class="icon-button';if(c.isMenuButton){a+=" menu-button"}if(c.title){a+=" tooltip"}a+=" "+c.icon_class;if(!c.enabled){a+="_disabled"}a+='"';if(c.id){a+=' id="'+c.id+'"'}a+=' href="'+((c.href)?(c.href):("javascript:void(0);"))+'"';if(c.target){a+=' target="'+c.target+'"'}if(!c.visible){a+=' style="display: none;"'}a+=">"+((c.enabled)?("</a>"):("</span>"));return a}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/templates/compiled/template-history-displayApps.js --- /dev/null +++ b/static/scripts/packed/templates/compiled/template-history-displayApps.js @@ -0,0 +1,1 @@ +(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-displayApps"]=b(function(g,l,f,k,j){f=f||g.helpers;var c,h="function",i=this.escapeExpression,m=this;function e(r,q){var o="",p,n;o+="\n ";n=f.label;if(n){p=n.call(r,{hash:{}})}else{p=r.label;p=typeof p===h?p():p}o+=i(p)+"\n ";p=r.links;p=f.each.call(r,p,{hash:{},inverse:m.noop,fn:m.program(2,d,q)});if(p||p===0){o+=p}o+="\n <br />\n";return o}function d(r,q){var o="",p,n;o+='\n <a target="';n=f.target;if(n){p=n.call(r,{hash:{}})}else{p=r.target;p=typeof p===h?p():p}o+=i(p)+'" href="';n=f.href;if(n){p=n.call(r,{hash:{}})}else{p=r.href;p=typeof p===h?p():p}o+=i(p)+'">';n=f.text;if(n){p=n.call(r,{hash:{}})}else{p=r.text;p=typeof p===h?p():p}o+=i(p)+"</a>\n ";return o}c=l.displayApps;c=f.each.call(l,c,{hash:{},inverse:m.noop,fn:m.program(1,e,j)});if(c||c===0){return c}else{return""}})})(); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/templates/compiled/template-history-downloadLinks.js --- /dev/null +++ b/static/scripts/packed/templates/compiled/template-history-downloadLinks.js @@ -0,0 +1,1 @@ +(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-downloadLinks"]=b(function(g,l,f,k,j){f=f||g.helpers;var c,h="function",i=this.escapeExpression,m=this;function e(s,r){var p="",q,o;p+='\n<div popupmenu="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a class="action-button" href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'">Download Dataset</a>\n <a>Additional Files</a>\n ';q=s.meta_files;q=f.each.call(s,q,{hash:{},inverse:m.noop,fn:m.program(2,d,r)});if(q||q===0){p+=q}p+='\n</div>\n<div style="float:left;" class="menubutton split popup" id="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'" title="Download" class="icon-button disk tooltip"></a>\n</div>\n';return p}function d(s,r){var p="",q,o;p+='\n <a class="action-button" href="';o=f.meta_download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.meta_download_url;q=typeof q===h?q():q}p+=i(q)+'">Download ';o=f.meta_file_type;if(o){q=o.call(s,{hash:{}})}else{q=s.meta_file_type;q=typeof q===h?q():q}p+=i(q)+"</a>\n ";return p}function n(p,o){return'\n<a href="" title="Download" class="icon-button disk tooltip"></a>\n'}c=l.meta_files;c=f["if"].call(l,c,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j)});if(c||c===0){return c}else{return""}})})(); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/viz/circster.js --- a/static/scripts/packed/viz/circster.js +++ b/static/scripts/packed/viz/circster.js @@ -1,1 +1,1 @@ -define(["libs/d3","viz/visualization"],function(e,f){var d=function(){this.initialize&&this.initialize.apply(this,arguments)};d.extend=Backbone.Model.extend;var c=Backbone.View.extend({className:"circster",initialize:function(h){this.total_gap=h.total_gap;this.genome=h.genome;this.dataset_arc_height=h.dataset_arc_height;this.track_gap=5},render:function(){var j=this,l=this.dataset_arc_height,m=j.$el.width(),h=j.$el.height(),k=(Math.min(m,h)/2-this.model.get("tracks").length*(this.dataset_arc_height+this.track_gap));var i=e.select(j.$el[0]).append("svg").attr("width",m).attr("height",h).attr("pointer-events","all").append("svg:g").call(e.behavior.zoom().on("zoom",function(){i.attr("transform","translate("+e.event.translate+") scale("+e.event.scale+")")})).attr("transform","translate("+m/2+","+h/2+")").append("svg:g");this.model.get("tracks").each(function(n,p){var q=n.get("genome_wide_data"),s=k+p*(l+j.track_gap),o=(q instanceof f.GenomeWideBigWigData?g:a);var r=new o({track:n,radius_start:s,radius_end:s+l,genome:j.genome,total_gap:j.total_gap});r.render(i)})}});var b=d.extend({initialize:function(h){this.options=h},render:function(m){var h=this.chroms_layout(),k=this.genome_data_layout();var n=this.options.radius_start,j=this.options.radius_end,p=m.append("g").attr("id","inner-arc"),o=e.svg.arc().innerRadius(n).outerRadius(j),i=p.selectAll("#inner-arc>path").data(h).enter().append("path").attr("d",o).style("stroke","#ccc").style("fill","#ccc").append("title").text(function(r){return r.data.chrom});var q=this.options.track.get("prefs"),l=q.block_color;_.each(k,function(r){if(!r){return}var u=m.append("g"),t=e.svg.arc().innerRadius(n),s=u.selectAll("path").data(r).enter();s.append("path").attr("d",t).style("stroke",l)})},chroms_layout:function(){var i=this.options.genome.get_chroms_info(),k=e.layout.pie().value(function(m){return m.len}).sort(null),l=k(i),h=this.options.total_gap/i.length,j=_.map(l,function(o,n){var m=o.endAngle-h;o.endAngle=(m>o.startAngle?m:o.startAngle);return o});return j},chrom_data_layout:function(k,j,i,l,h){},genome_data_layout:function(){var i=this,h=this.chroms_layout(),m=this.options.track.get("genome_wide_data"),l=this.options.radius_start,j=this.options.radius_end,k=_.zip(h,m.get("data")),n=_.map(k,function(p){var q=p[0],o=p[1];return i.chrom_data_layout(q,o,l,j,m.get("min"),m.get("max"))});return n}});var a=b.extend({chrom_data_layout:function(r,i,o,n,k,p){if(!i||typeof i==="string"){return null}var l=i[0],q=i[3],j=e.scale.linear().domain([k,p]).range([o,n]),m=e.layout.pie().value(function(s){return q}).startAngle(r.startAngle).endAngle(r.endAngle),h=m(l);_.each(l,function(s,t){h[t].outerRadius=j(s[1])});return h}});var g=b.extend({chrom_data_layout:function(q,i,o,n,k,p){var l=i.data;if(l.length===0){return}var j=e.scale.linear().domain([k,p]).range([o,n]),m=e.layout.pie().value(function(s,r){if(r+1===l.length){return 0}return l[r+1][0]-l[r][0]}).startAngle(q.startAngle).endAngle(q.endAngle),h=m(l);_.each(l,function(r,s){h[s].outerRadius=j(r[1])});return h}});return{CircsterView:c}}); \ No newline at end of file +define(["libs/underscore","libs/d3","viz/visualization"],function(i,k,j){var e=function(){this.initialize&&this.initialize.apply(this,arguments)};e.extend=Backbone.Model.extend;var l=Backbone.Model.extend({is_visible:function(p,m){var n=p.getBoundingClientRect(),o=$("svg")[0].getBoundingClientRect();if(n.right<0||n.left>o.right||n.bottom<0||n.top>o.bottom){return false}return true}});var f=Backbone.Model.extend({defaults:{prefs:{color:"#ccc"}}});var b=Backbone.View.extend({className:"circster",initialize:function(m){this.total_gap=m.total_gap;this.genome=m.genome;this.dataset_arc_height=m.dataset_arc_height;this.track_gap=5;this.label_arc_height=20},render:function(){var u=this,r=this.dataset_arc_height,m=u.$el.width(),t=u.$el.height(),n=Math.min(m,t)/2-this.model.get("tracks").length*(this.dataset_arc_height+this.track_gap)-(this.label_arc_height+this.track_gap),s=this.model.get("tracks");var p=k.select(u.$el[0]).append("svg").attr("width",m).attr("height",t).attr("pointer-events","all").append("svg:g").call(k.behavior.zoom().on("zoom",function(){p.attr("transform","translate("+k.event.translate+") scale("+k.event.scale+")");var v=new l(),w={};s.each(function(x){w[x.id]=[]});k.selectAll("path.chrom-data").filter(function(y,x){return v.is_visible(this,p)}).each(function(z,x){var y=$.data(this,"chrom_data");w[y.track.id].push(y.chrom)})})).attr("transform","translate("+m/2+","+t/2+")").append("svg:g");s.each(function(v,x){var z=n+x*(r+u.track_gap),w=(v.get("track_type")==="LineTrack"?g:h);var y=new w({track:v,track_index:x,radius_start:z,radius_end:z+r,genome:u.genome,total_gap:u.total_gap});y.render(p)});var q=n+s.length*(r+u.track_gap)+u.track_gap;var o=new a({track:new f(),track_index:s.length,radius_start:q,radius_end:q,genome:u.genome,total_gap:u.total_gap});o.render(p)}});var c=e.extend({initialize:function(m){this.options=m;this.options.bg_stroke="ccc";this.options.bg_fill="ccc"},render:function(r){var o=r.append("g").attr("id","parent-"+this.options.track_index);var m=this._chroms_layout(),s=this.options.radius_start,p=this.options.radius_end,t=k.svg.arc().innerRadius(s).outerRadius(p),n=o.selectAll("g").data(m).enter().append("svg:g");n.append("path").attr("d",t).style("stroke",this.options.bg_stroke).style("fill",this.options.bg_fill).append("title").text(function(v){return v.data.chrom});this.render_data(o);var u=this.options.track.get("prefs"),q=u.block_color;if(!q){q=u.color}o.selectAll("path.chrom-data").style("stroke",q).style("fill",q)},_chroms_layout:function(){var n=this.options.genome.get_chroms_info(),p=k.layout.pie().value(function(r){return r.len}).sort(null),q=p(n),m=this.options.total_gap/n.length,o=i.map(q,function(t,s){var r=t.endAngle-m;t.endAngle=(r>t.startAngle?r:t.startAngle);return t});return o},render_chrom_data:function(o,p,q,n,r,m){},render_data:function(q){var v=this,u=this._chroms_layout(),o=this.options.track,n=this.options.radius_start,s=this.options.radius_end,t=o.get_genome_wide_data(this.options.genome),r=i.zip(u,t),m=this.get_bounds(t),p=i.map(r,function(w){var x=w[0],y=w[1];return v.render_chrom_data(q,x,y,n,s,m.min,m.max)});return p}});var a=c.extend({initialize:function(m){this.options=m;this.options.bg_stroke="fff";this.options.bg_fill="fff"},render_data:function(n){var m=n.selectAll("g");m.selectAll("path").attr("id",function(o){return"label-"+o.data.chrom});m.append("svg:text").filter(function(o){return o.endAngle-o.startAngle>0.08}).attr("text-anchor","middle").append("svg:textPath").attr("xlink:href",function(o){return"#label-"+o.data.chrom}).attr("startOffset","25%").text(function(o){return o.data.chrom})}});var d=c.extend({render_quantitative_data:function(q,w,p,t,s,o,u){var r=k.scale.linear().domain([o,u]).range([t,s]);var n=k.scale.linear().domain([0,p.length]).range([w.startAngle,w.endAngle]);var y=k.svg.line.radial().interpolate("linear").radius(function(z){return r(z[1])}).angle(function(A,z){return n(z)});var m=k.svg.area.radial().interpolate(y.interpolate()).innerRadius(r(0)).outerRadius(y.radius()).angle(y.angle());var v=q.datum(p),x=v.append("path").attr("class","chrom-data").attr("d",m);$.data(x[0][0],"chrom_data",{track:this.options.track,chrom:w.data.chrom})},get_bounds:function(){}});var h=d.extend({render_chrom_data:function(o,r,p,n,s,q,m){if(!p||typeof p==="string"){return null}return this.render_quantitative_data(o,r,p.data,n,s,q,m)},get_bounds:function(n){var m=i.map(n,function(o){if(!o||typeof o==="string"){return 0}return o.max});return{min:0,max:(m&&typeof m!=="string"?i.max(m):0)}}});var g=d.extend({render_chrom_data:function(o,r,p,n,t,q,m){var s=p.data;if(s.length===0){return}return this.render_quantitative_data(o,r,s,n,t,q,m)},get_bounds:function(n){var m=i.flatten(i.map(n,function(o){if(o){return i.map(o.data,function(q){return q[1]})}else{return 0}}));return{min:i.min(m),max:i.max(m)}}});return{CircsterView:b}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/viz/scatterplot.js --- /dev/null +++ b/static/scripts/packed/viz/scatterplot.js @@ -0,0 +1,1 @@ +define(["../libs/underscore","../libs/d3","../mvc/base-mvc"],function(){function b(e){var h=this,g=10,f=12,d=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(null,i)}};this.log("new TwoVarScatterplot:",e);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,bubbleRadius: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,e);this.updateConfig=function(i){_.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").style("display","none");this.content=this.svg.append("svg:g").attr("class","content");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.log("built svg:",d3.selectAll("svg"));this.adjustChartDimensions=function(){this.svg.attr("width",this.config.width+(this.config.marginRight+this.config.marginLeft)).attr("height",this.config.height+(this.config.marginTop+this.config.marginBottom)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft,this.config.marginTop))};this.preprocessData=function(i){return i.slice(0,this.config.maxDataPoints)};this.setUpDomains=function(i,j){this.xMin=this.config.xMin||d3.min(i);this.xMax=this.config.xMax||d3.max(i);this.yMin=this.config.yMin||d3.min(j);this.yMax=this.config.yMax||d3.max(j)};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.log("xAxis:",this.xAxis);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));this.log("xLongestLabel:",this.xLongestLabel);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.log("xAxisLabel:",this.xAxisLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);this.log("yAxis:",this.yAxis);this.yLongestLabel=d3.max(_.map([this.yMin,this.yMax],function(j){return(String(j)).length}));this.log("yLongestLabel:",this.yLongestLabel);var i=this.yLongestLabel*g+(d);if(this.config.yAxisLabelBumpX>-(i)){this.config.yAxisLabelBumpX=-(i)}if(this.config.marginLeft<i){this.config.marginLeft=i+f;this.adjustChartDimensions()}this.log("this.config.yAxisLableBumpx, this.config.marginLeft:",this.config.yAxisLabelBumpX,this.config.marginLeft);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.log("yAxisLabel:",this.yAxisLabel)};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.log("vGridLines:",this.vGridLines);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.log("hGridLines:",this.hGridLines)};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l){var k=function(n,m){return h.xScale(i[m])};var j=function(n,m){return h.yScale(l[m])};this.datapoints=this.content.selectAll(".glyph").data(i);this.datapoints.enter().append("svg:circle").attr("class","glyph").attr("cx",k).attr("cy",0).attr("r",0);this.datapoints.transition().duration(this.config.entryAnimDuration).attr("cx",k).attr("cy",j).attr("r",this.config.bubbleRadius);this.datapoints.exit().transition().duration(this.config.entryAnimDuration).attr("cy",this.config.height).attr("r",0).style("fill-opacity",0).remove();this.log(this.datapoints,"glyphs rendered")};this.render=function(i,j){this.log("renderScatterplot",i.length,j.length,this.config);i=this.preprocessData(i);j=this.preprocessData(j);this.log("xCol len",i.length,"yCol len",j.length);this.setUpDomains(i,j);this.log("xMin, xMax, yMin, yMax:",this.xMin,this.xMax,this.yMin,this.yMax);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,j)}}var a=BaseView.extend(LoggableMixin).extend({tagName:"form",className:"scatterplot-settings-form",events:{"click #render-button":"renderScatterplot"},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("this.chartConfig:",this.chartConfig);this.plot=new b(this.chartConfig)},render:function(){var c=this,e="",d="";this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(", ");_.each(this.dataset.metadata_column_types,function(h,g){if(h==="int"||h==="float"){var f="column "+g;if(c.dataset.metadata_column_names){f=c.dataset.metadata_column_names[g]}d+='<option value="'+g+'">'+f+"</column>"}});e+='<div id="x-column-input">';e+='<label for="">Data column for X: </label><select name="x-column">'+d+"</select>";e+="</div>";e+='<div id="y-column-input">';e+='<label for="">Data column for Y: </label><select name="y-column">'+d+"</select>";e+="</div>";e+='<input id="render-button" type="button" value="Draw" />';e+='<div class="clear"></div>';this.$el.append(e);this.$el.find("#render-button");return this},renderScatterplot:function(){var d=this,e=this.apiDatasetsURL+"/"+this.dataset.id+"?data_type=raw_data&",i=this.$el.find('[name="x-column"]'),j=i.val(),g=i.children('[value="'+j+'"]').text(),h=this.$el.find('[name="y-column"]'),f=h.val(),c=h.children('[value="'+f+'"]').text();this.log(g,c);this.chartConfig.xLabel=g;this.chartConfig.yLabel=c;d.plot.updateConfig(this.chartConfig);e+=jQuery.param({columns:"["+[j,f]+"]"});this.log("url:",e);jQuery.ajax({url:e,dataType:"json",success:function(k){d.endpoint=k.endpoint;d.plot.render(_.map(k.data,function(l){return l[0]}),_.map(k.data,function(l){return l[1]}))},error:function(m,k,l){alert("ERROR:"+k+"\n"+l)}})}});return{ScatterplotView:a}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/viz/sweepster.js --- a/static/scripts/packed/viz/sweepster.js +++ b/static/scripts/packed/viz/sweepster.js @@ -1,1 +1,1 @@ -define(["libs/d3","viz/trackster/util","viz/visualization","viz/trackster/tracks"],function(m,e,l,f){var k=Backbone.Model.extend({defaults:{inputs:null,values:null}});var n=Backbone.RelationalModel.extend({defaults:{tool:null,tree_data:null},initialize:function(p){var o=this;this.get("tool").get("inputs").each(function(q){if(!q.get_samples()){return}q.on("change:min change:max change:num_samples",function(r){if(r.get("in_ptree")){o.set_tree_data()}},o);q.on("change:in_ptree",function(r){if(r.get("in_ptree")){o.add_param(r)}else{o.remove_param(r)}o.set_tree_data()},o)});if(p.config){_.each(p.config,function(r){var q=o.get("tool").get("inputs").find(function(s){return s.get("name")===r.name});o.add_param(q);q.set(r)})}},add_param:function(o){if(o.get("ptree_index")){return}o.set("in_ptree",true);o.set("ptree_index",this.get_tree_params().length)},remove_param:function(o){o.set("in_ptree",false);o.set("ptree_index",null);_(this.get_tree_params()).each(function(p,q){p.set("ptree_index",q+1)})},set_tree_data:function(){var p=_.map(this.get_tree_params(),function(r){return{param:r,samples:r.get_samples()}});var o=0,q=function(u,r){var w=u[r],v=w.param,t=v.get("label"),s=w.samples;if(u.length-1===r){return _.map(s,function(x){return{id:o++,name:x,param:v,value:x}})}return _.map(s,function(x){return{id:o++,name:x,param:v,value:x,children:q(u,r+1)}})};this.set("tree_data",{name:"Root",id:o++,children:(p.length!==0?q(p,0):null)})},get_tree_params:function(){return _(this.get("tool").get("inputs").where({in_ptree:true})).sortBy(function(o){return o.get("ptree_index")})},get_num_leaves:function(){return this.get_tree_params().reduce(function(o,p){return o*p.get_samples().length},1)},get_node_settings:function(s){var q=this.get("tool").get_inputs_dict();var t=s.parent;if(t){while(t.depth!==0){q[t.param.get("name")]=t.value;t=t.parent}}var o=this,p=function(v,u){if(v.param){u[v.param.get("name")]=v.value}if(!v.children){return new k({inputs:o.get("tool").get("inputs"),values:u})}else{return _.flatten(_.map(v.children,function(w){return p(w,_.clone(u))}))}},r=p(s,q);if(!_.isArray(r)){r=[r]}return r},get_connected_nodes:function(q){var r=function(s){if(!s.children){return s}else{return _.flatten([s,_.map(s.children,function(t){return r(t)})])}};var p=[],o=q.parent;while(o){p.push(o);o=o.parent}return _.flatten([p,r(q)])},get_leaf:function(p){var q=this.get("tree_data"),o=function(r){return _.find(r,function(s){return p[s.param.get("name")]===s.value})};while(q.children){q=o(q.children)}return q},toJSON:function(){return this.get_tree_params().map(function(o){return{name:o.get("name"),min:o.get("min"),max:o.get("max"),num_samples:o.get("num_samples")}})}});var c=Backbone.RelationalModel.extend({defaults:{track:null,mode:"Pack",settings:null,regions:null},relations:[{type:Backbone.HasMany,key:"regions",relatedModel:l.GenomeRegion}],initialize:function(o){if(o.track){var p=_.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},o.track);this.set("track",f.object_from_template(p,{},null))}},same_settings:function(o){var p=this.get("settings"),q=o.get("settings");for(var r in p){if(!q[r]||p[r]!==q[r]){return false}}return true},toJSON:function(){return{track:this.get("track").to_dict(),settings:this.get("settings"),regions:this.get("regions")}}});var a=Backbone.Collection.extend({model:c});var g=l.Visualization.extend({defaults:_.extend({},l.Visualization.prototype.defaults,{dataset:null,tool:null,parameter_tree:null,regions:null,tracks:null,default_mode:"Pack"}),relations:[{type:Backbone.HasOne,key:"dataset",relatedModel:Dataset},{type:Backbone.HasOne,key:"tool",relatedModel:Tool},{type:Backbone.HasMany,key:"regions",relatedModel:l.GenomeRegion},{type:Backbone.HasMany,key:"tracks",relatedModel:c}],initialize:function(o){var p=this.get("tool").copy(true);this.set("tool_with_samplable_inputs",p);this.set("parameter_tree",new n({tool:p,config:o.tree_config}))},add_track:function(o){this.get("tracks").add(o)},toJSON:function(){return{id:this.get("id"),title:"Parameter exploration for dataset '"+this.get("dataset").get("name")+"'",type:"sweepster",dataset_id:this.get("dataset").id,tool_id:this.get("tool").id,regions:this.get("regions").toJSON(),tree_config:this.get("parameter_tree").toJSON(),tracks:this.get("tracks").toJSON()}}});var j=Backbone.View.extend({tagName:"tr",TILE_LEN:250,initialize:function(o){this.canvas_manager=o.canvas_manager;this.render();this.model.on("change:track change:mode",this.draw_tiles,this)},render:function(){var t=this.model.get("settings"),p=t.get("values"),r=$("<td/>").addClass("settings").appendTo(this.$el),q=$("<div/>").addClass("track-info").hide().appendTo(r);q.append($("<div/>").css("font-weight","bold").text("Track Settings"));t.get("inputs").each(function(v){q.append(v.get("label")+": "+p[v.get("name")]+"<br/>")});var o=this,u=$("<button/>").appendTo(q).text("Run on complete dataset").click(function(){q.toggle();o.trigger("run_on_dataset",t)});var s=create_icon_buttons_menu([{title:"Settings",icon_class:"gear track-settings",on_click:function(){q.toggle()}},{title:"Remove",icon_class:"cross-circle",on_click:function(){o.$el.remove();$(".bs-tooltip").remove()}}]);r.prepend(s.$el);this.model.get("regions").each(function(){o.$el.append($("<td/>").addClass("tile").html($("<img/>").attr("src",galaxy_paths.get("image_path")+"/loading_large_white_bg.gif")))});if(this.model.get("track")){this.draw_tiles()}},draw_tiles:function(){var p=this,o=this.model.get("track"),r=this.model.get("regions"),q=this.$el.find("td.tile");if(!o){return}$.when(o.data_manager.data_is_ready()).then(function(s){r.each(function(v,u){var t=v.length()/p.TILE_LEN,x=1/t,w=p.model.get("mode");$.when(o.data_manager.get_data(v,w,t,{})).then(function(z){var y=p.canvas_manager.new_canvas();y.width=p.TILE_LEN;y.height=o.get_canvas_height(z,w,x,y.width);o.draw_tile(z,y.getContext("2d"),w,t,v,x);$(q[u]).empty().append(y)})})})}});var b=Backbone.View.extend({number_input_template:'<div class="form-row-input sweep"><input class="min" type="text" size="6" value="<%= min %>"> - <input class="max" type="text" size="6" value="<%= max %>"> samples: <input class="num_samples" type="text" size="1" value="<%= num_samples %>"></div>',select_input_template:'<div class="form-row-input sweep"><%= options %></div>',initialize:function(o){this.$el=o.tool_row;this.render()},render:function(){var p=this.model,t=p.get("type"),v=this.$el.find(".form-row-input"),r=null;v.find(":input").change(function(){p.set("value",$(this).val())});if(t==="number"){r=$(_.template(this.number_input_template,this.model.toJSON()))}else{if(t==="select"){var q=_.map(this.$el.find("select option"),function(w){return $(w).val()}),s=q.join(", ");r=$(_.template(this.select_input_template,{options:s}))}}r.insertAfter(v);var o=this,u=create_icon_buttons_menu([{title:"Add parameter to tree",icon_class:"plus-button",on_click:function(){p.set("in_ptree",true);v.hide();r.show();$(this).hide();o.$el.find(".icon-button.toggle").show()}},{title:"Remove parameter from tree",icon_class:"toggle",on_click:function(){p.set("in_ptree",false);r.hide();v.show();$(this).hide();o.$el.find(".icon-button.plus-button").show()}}],{});this.$el.prepend(u.$el);if(p.get("in_ptree")){v.hide();o.$el.find(".icon-button.plus-button").hide()}else{o.$el.find(".icon-button.toggle").hide();r.hide()}_.each(["min","max","num_samples"],function(w){r.find("."+w).change(function(){p.set(w,parseFloat($(this).val()))})})}});var i=Backbone.View.extend({className:"tree-design",initialize:function(o){this.render()},render:function(){var q=new ToolFormView({model:this.model.get("tool")});q.render();this.$el.append(q.$el);var p=this,o=p.model.get("tool").get("inputs");this.$el.find(".form-row").not(".form-actions").each(function(r){var s=new b({model:o.at(r),tool_row:$(this)})})}});var h=Backbone.View.extend({className:"tool-parameter-tree",initialize:function(o){this.model.on("change:tree_data",this.render,this)},render:function(){this.$el.children().remove();var w=this.model.get_tree_params();if(!w.length){return}this.width=100*(2+w.length);this.height=15*this.model.get_num_leaves();var v=this;var u=m.layout.cluster().size([this.height,this.width-160]);var q=m.svg.diagonal().projection(function(x){return[x.y,x.x]});var o=u.nodes(this.model.get("tree_data"));var r=_.uniq(_.pluck(o,"y"));_.each(w,function(A,z){var y=r[z+1],B=$("#center").position().left;v.$el.append($("<div>").addClass("label").text(A.get("label")).css("left",y+B))});var p=m.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height+30).append("g").attr("transform","translate(40, 20)");var t=p.selectAll("path.link").data(u.links(o)).enter().append("path").attr("class","link").attr("d",q);var s=p.selectAll("g.node").data(o).enter().append("g").attr("class","node").attr("transform",function(x){return"translate("+x.y+","+x.x+")"}).on("mouseover",function(y){var x=_.pluck(v.model.get_connected_nodes(y),"id");s.filter(function(z){return _.find(x,function(A){return A===z.id})!==undefined}).style("fill","#f00")}).on("mouseout",function(){s.style("fill","#000")});s.append("circle").attr("r",9);s.append("text").attr("dx",function(x){return x.children?-12:12}).attr("dy",3).attr("text-anchor",function(x){return x.children?"end":"start"}).text(function(x){return x.name})}});var d=Backbone.View.extend({className:"Sweepster",helpText:"<div><h4>Getting Started</h4><ol><li>Create a parameter tree by using the icons next to the tool's parameter names to add or remove parameters.<li>Adjust the tree by using parameter inputs to select min, max, and number of samples<li>Run the tool with different settings by clicking on tree nodes</ol></div>",initialize:function(p){this.canvas_manager=new l.CanvasManager(this.$el.parents("body"));this.tool_param_tree_view=new h({model:this.model.get("parameter_tree")});this.track_collection_container=$("<table/>").addClass("tracks");this.model.get("parameter_tree").on("change:tree_data",this.handle_node_clicks,this);var o=this;this.model.get("tracks").each(function(q){q.get("track").view=o});this.block_color=e.get_random_color();this.reverse_strand_color=e.get_random_color([this.block_color,"#ffffff"])},render:function(){var u=new i({model:this.model.get("parameter_tree")});$("#left").append(u.$el);var x=this,r=x.model.get("regions"),v=$("<tr/>").appendTo(this.track_collection_container);r.each(function(y){v.append($("<th>").text(y.toString()))});v.children().first().attr("colspan",2);var s=$("<div>").addClass("tiles");$("#right").append(s.append(this.track_collection_container));x.model.get("tracks").each(function(y){x.add_track(y)});var w=$(this.helpText).addClass("help"),t=create_icon_buttons_menu([{title:"Close",icon_class:"cross-circle",on_click:function(){$(".bs-tooltip").remove();w.remove()}}]);w.prepend(t.$el.css("float","right"));$("#center").append(w);this.tool_param_tree_view.render();$("#center").append(this.tool_param_tree_view.$el);this.handle_node_clicks();var q=create_icon_buttons_menu([{icon_class:"chevron-expand",title:"Set display mode"},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location="${h.url_for( controller='visualization', action='list' )}"}}],{tooltip_config:{placement:"bottom"}});var p=["Squish","Pack"],o={};_.each(p,function(y){o[y]=function(){x.model.set("default_mode",y);x.model.get("tracks").each(function(z){z.set("mode",y)})}});make_popupmenu(q.$el.find(".chevron-expand"),o);q.$el.attr("style","float: right");$("#right .unified-panel-header-inner").append(q.$el)},run_tool_on_dataset:function(p){var o=this.model.get("tool"),r=o.get("name"),q=this.model.get("dataset");o.set_input_values(p.get("values"));$.when(o.rerun(q)).then(function(s){});show_modal("Running "+r+" on complete dataset",r+" is running on dataset '"+q.get("name")+"'. Outputs are in the dataset's history.",{Ok:function(){hide_modal()}})},add_track:function(r){var p=this,q=this.model.get("parameter_tree");p.model.add_track(r);var o=new j({model:r,canvas_manager:p.canvas_manager});o.on("run_on_dataset",p.run_tool_on_dataset,p);p.track_collection_container.append(o.$el);o.$el.hover(function(){var t=q.get_leaf(r.get("settings").get("values"));var s=_.pluck(q.get_connected_nodes(t),"id");m.select(p.tool_param_tree_view.$el[0]).selectAll("g.node").filter(function(u){return _.find(s,function(v){return v===u.id})!==undefined}).style("fill","#f00")},function(){m.select(p.tool_param_tree_view.$el[0]).selectAll("g.node").style("fill","#000")});return r},handle_node_clicks:function(){var o=this,p=this.model.get("parameter_tree"),r=this.model.get("regions"),q=m.select(this.tool_param_tree_view.$el[0]).selectAll("g.node");q.on("click",function(x,u){var t=o.model.get("tool"),w=o.model.get("dataset"),v=p.get_node_settings(x),s=$.Deferred();if(v.length>=10){show_modal("Whoa there cowboy!","You clicked on a node to try "+o.model.get("tool").get("name")+" with "+v.length+" different combinations of settings. You can only run 10 jobs at a time.",{Ok:function(){hide_modal();s.resolve(false)}})}else{s.resolve(true)}$.when(s).then(function(y){if(!y){return}var z=_.map(v,function(A){var B=new c({settings:A,regions:r,mode:o.model.get("default_mode")});o.add_track(B);return B});_.each(z,function(B,A){setTimeout(function(){t.set_input_values(B.get("settings").get("values"));$.when(t.rerun(w,r)).then(function(D){var E=_.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},D.first().get("track_config")),C=f.object_from_template(E,o,null);C.data_manager.set("data_type","raw_data");C.prefs.block_color=o.block_color;C.prefs.reverse_strand_color=o.reverse_strand_color;B.set("track",C)})},A*10000)})})})}});return{SweepsterVisualization:g,SweepsterVisualizationView:d}}); \ No newline at end of file +define(["libs/d3","viz/trackster/util","viz/visualization","viz/trackster/tracks","mvc/tools","mvc/data"],function(o,f,n,h,g,d){var m=Backbone.Model.extend({defaults:{inputs:null,values:null}});var p=Backbone.RelationalModel.extend({defaults:{tool:null,tree_data:null},initialize:function(r){var q=this;this.get("tool").get("inputs").each(function(s){if(!s.get_samples()){return}s.on("change:min change:max change:num_samples",function(t){if(t.get("in_ptree")){q.set_tree_data()}},q);s.on("change:in_ptree",function(t){if(t.get("in_ptree")){q.add_param(t)}else{q.remove_param(t)}q.set_tree_data()},q)});if(r.config){_.each(r.config,function(t){var s=q.get("tool").get("inputs").find(function(u){return u.get("name")===t.name});q.add_param(s);s.set(t)})}},add_param:function(q){if(q.get("ptree_index")){return}q.set("in_ptree",true);q.set("ptree_index",this.get_tree_params().length)},remove_param:function(q){q.set("in_ptree",false);q.set("ptree_index",null);_(this.get_tree_params()).each(function(r,s){r.set("ptree_index",s+1)})},set_tree_data:function(){var r=_.map(this.get_tree_params(),function(t){return{param:t,samples:t.get_samples()}});var q=0,s=function(w,t){var y=w[t],x=y.param,v=x.get("label"),u=y.samples;if(w.length-1===t){return _.map(u,function(z){return{id:q++,name:z,param:x,value:z}})}return _.map(u,function(z){return{id:q++,name:z,param:x,value:z,children:s(w,t+1)}})};this.set("tree_data",{name:"Root",id:q++,children:(r.length!==0?s(r,0):null)})},get_tree_params:function(){return _(this.get("tool").get("inputs").where({in_ptree:true})).sortBy(function(q){return q.get("ptree_index")})},get_num_leaves:function(){return this.get_tree_params().reduce(function(q,r){return q*r.get_samples().length},1)},get_node_settings:function(u){var s=this.get("tool").get_inputs_dict();var v=u.parent;if(v){while(v.depth!==0){s[v.param.get("name")]=v.value;v=v.parent}}var q=this,r=function(x,w){if(x.param){w[x.param.get("name")]=x.value}if(!x.children){return new m({inputs:q.get("tool").get("inputs"),values:w})}else{return _.flatten(_.map(x.children,function(y){return r(y,_.clone(w))}))}},t=r(u,s);if(!_.isArray(t)){t=[t]}return t},get_connected_nodes:function(s){var t=function(u){if(!u.children){return u}else{return _.flatten([u,_.map(u.children,function(v){return t(v)})])}};var r=[],q=s.parent;while(q){r.push(q);q=q.parent}return _.flatten([r,t(s)])},get_leaf:function(r){var s=this.get("tree_data"),q=function(t){return _.find(t,function(u){return r[u.param.get("name")]===u.value})};while(s.children){s=q(s.children)}return s},toJSON:function(){return this.get_tree_params().map(function(q){return{name:q.get("name"),min:q.get("min"),max:q.get("max"),num_samples:q.get("num_samples")}})}});var c=Backbone.RelationalModel.extend({defaults:{track:null,mode:"Pack",settings:null,regions:null},relations:[{type:Backbone.HasMany,key:"regions",relatedModel:n.GenomeRegion}],initialize:function(q){if(q.track){var r=_.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},q.track);this.set("track",h.object_from_template(r,{},null))}},same_settings:function(q){var r=this.get("settings"),s=q.get("settings");for(var t in r){if(!s[t]||r[t]!==s[t]){return false}}return true},toJSON:function(){return{track:this.get("track").to_dict(),settings:this.get("settings"),regions:this.get("regions")}}});var a=Backbone.Collection.extend({model:c});var i=n.Visualization.extend({defaults:_.extend({},n.Visualization.prototype.defaults,{dataset:null,tool:null,parameter_tree:null,regions:null,tracks:null,default_mode:"Pack"}),relations:[{type:Backbone.HasOne,key:"dataset",relatedModel:d.Dataset},{type:Backbone.HasOne,key:"tool",relatedModel:g.Tool},{type:Backbone.HasMany,key:"regions",relatedModel:n.GenomeRegion},{type:Backbone.HasMany,key:"tracks",relatedModel:c}],initialize:function(q){var r=this.get("tool").copy(true);this.set("tool_with_samplable_inputs",r);this.set("parameter_tree",new p({tool:r,config:q.tree_config}))},add_track:function(q){this.get("tracks").add(q)},toJSON:function(){return{id:this.get("id"),title:"Parameter exploration for dataset '"+this.get("dataset").get("name")+"'",type:"sweepster",dataset_id:this.get("dataset").id,tool_id:this.get("tool").id,regions:this.get("regions").toJSON(),tree_config:this.get("parameter_tree").toJSON(),tracks:this.get("tracks").toJSON()}}});var l=Backbone.View.extend({tagName:"tr",TILE_LEN:250,initialize:function(q){this.canvas_manager=q.canvas_manager;this.render();this.model.on("change:track change:mode",this.draw_tiles,this)},render:function(){var v=this.model.get("settings"),r=v.get("values"),t=$("<td/>").addClass("settings").appendTo(this.$el),s=$("<div/>").addClass("track-info").hide().appendTo(t);s.append($("<div/>").css("font-weight","bold").text("Track Settings"));v.get("inputs").each(function(x){s.append(x.get("label")+": "+r[x.get("name")]+"<br/>")});var q=this,w=$("<button/>").appendTo(s).text("Run on complete dataset").click(function(){s.toggle();q.trigger("run_on_dataset",v)});var u=create_icon_buttons_menu([{title:"Settings",icon_class:"gear track-settings",on_click:function(){s.toggle()}},{title:"Remove",icon_class:"cross-circle",on_click:function(){q.$el.remove();$(".bs-tooltip").remove()}}]);t.prepend(u.$el);this.model.get("regions").each(function(){q.$el.append($("<td/>").addClass("tile").html($("<img/>").attr("src",galaxy_paths.get("image_path")+"/loading_large_white_bg.gif")))});if(this.model.get("track")){this.draw_tiles()}},draw_tiles:function(){var r=this,q=this.model.get("track"),t=this.model.get("regions"),s=this.$el.find("td.tile");if(!q){return}$.when(q.data_manager.data_is_ready()).then(function(u){t.each(function(x,w){var v=x.length()/r.TILE_LEN,z=1/v,y=r.model.get("mode");$.when(q.data_manager.get_data(x,y,v,{})).then(function(B){var A=r.canvas_manager.new_canvas();A.width=r.TILE_LEN;A.height=q.get_canvas_height(B,y,z,A.width);q.draw_tile(B,A.getContext("2d"),y,v,x,z);$(s[w]).empty().append(A)})})})}});var b=Backbone.View.extend({number_input_template:'<div class="form-row-input sweep"><input class="min" type="text" size="6" value="<%= min %>"> - <input class="max" type="text" size="6" value="<%= max %>"> samples: <input class="num_samples" type="text" size="1" value="<%= num_samples %>"></div>',select_input_template:'<div class="form-row-input sweep"><%= options %></div>',initialize:function(q){this.$el=q.tool_row;this.render()},render:function(){var r=this.model,v=r.get("type"),x=this.$el.find(".form-row-input"),t=null;x.find(":input").change(function(){r.set("value",$(this).val())});if(v==="number"){t=$(_.template(this.number_input_template,this.model.toJSON()))}else{if(v==="select"){var s=_.map(this.$el.find("select option"),function(y){return $(y).val()}),u=s.join(", ");t=$(_.template(this.select_input_template,{options:u}))}}t.insertAfter(x);var q=this,w=create_icon_buttons_menu([{title:"Add parameter to tree",icon_class:"plus-button",on_click:function(){r.set("in_ptree",true);x.hide();t.show();$(this).hide();q.$el.find(".icon-button.toggle").show()}},{title:"Remove parameter from tree",icon_class:"toggle",on_click:function(){r.set("in_ptree",false);t.hide();x.show();$(this).hide();q.$el.find(".icon-button.plus-button").show()}}],{});this.$el.prepend(w.$el);if(r.get("in_ptree")){x.hide();q.$el.find(".icon-button.plus-button").hide()}else{q.$el.find(".icon-button.toggle").hide();t.hide()}_.each(["min","max","num_samples"],function(y){t.find("."+y).change(function(){r.set(y,parseFloat($(this).val()))})})}});var k=Backbone.View.extend({className:"tree-design",initialize:function(q){this.render()},render:function(){var s=new g.ToolFormView({model:this.model.get("tool")});s.render();this.$el.append(s.$el);var r=this,q=r.model.get("tool").get("inputs");this.$el.find(".form-row").not(".form-actions").each(function(t){var u=new b({model:q.at(t),tool_row:$(this)})})}});var j=Backbone.View.extend({className:"tool-parameter-tree",initialize:function(q){this.model.on("change:tree_data",this.render,this)},render:function(){this.$el.children().remove();var y=this.model.get_tree_params();if(!y.length){return}this.width=100*(2+y.length);this.height=15*this.model.get_num_leaves();var x=this;var w=o.layout.cluster().size([this.height,this.width-160]);var s=o.svg.diagonal().projection(function(z){return[z.y,z.x]});var q=w.nodes(this.model.get("tree_data"));var t=_.uniq(_.pluck(q,"y"));_.each(y,function(B,A){var z=t[A+1],C=$("#center").position().left;x.$el.append($("<div>").addClass("label").text(B.get("label")).css("left",z+C))});var r=o.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height+30).append("g").attr("transform","translate(40, 20)");var v=r.selectAll("path.link").data(w.links(q)).enter().append("path").attr("class","link").attr("d",s);var u=r.selectAll("g.node").data(q).enter().append("g").attr("class","node").attr("transform",function(z){return"translate("+z.y+","+z.x+")"}).on("mouseover",function(A){var z=_.pluck(x.model.get_connected_nodes(A),"id");u.filter(function(B){return _.find(z,function(C){return C===B.id})!==undefined}).style("fill","#f00")}).on("mouseout",function(){u.style("fill","#000")});u.append("circle").attr("r",9);u.append("text").attr("dx",function(z){return z.children?-12:12}).attr("dy",3).attr("text-anchor",function(z){return z.children?"end":"start"}).text(function(z){return z.name})}});var e=Backbone.View.extend({className:"Sweepster",helpText:"<div><h4>Getting Started</h4><ol><li>Create a parameter tree by using the icons next to the tool's parameter names to add or remove parameters.<li>Adjust the tree by using parameter inputs to select min, max, and number of samples<li>Run the tool with different settings by clicking on tree nodes</ol></div>",initialize:function(r){this.canvas_manager=new n.CanvasManager(this.$el.parents("body"));this.tool_param_tree_view=new j({model:this.model.get("parameter_tree")});this.track_collection_container=$("<table/>").addClass("tracks");this.model.get("parameter_tree").on("change:tree_data",this.handle_node_clicks,this);var q=this;this.model.get("tracks").each(function(s){s.get("track").view=q});this.block_color=f.get_random_color();this.reverse_strand_color=f.get_random_color([this.block_color,"#ffffff"])},render:function(){var w=new k({model:this.model.get("parameter_tree")});$("#left").append(w.$el);var z=this,t=z.model.get("regions"),x=$("<tr/>").appendTo(this.track_collection_container);t.each(function(A){x.append($("<th>").text(A.toString()))});x.children().first().attr("colspan",2);var u=$("<div>").addClass("tiles");$("#right").append(u.append(this.track_collection_container));z.model.get("tracks").each(function(A){z.add_track(A)});var y=$(this.helpText).addClass("help"),v=create_icon_buttons_menu([{title:"Close",icon_class:"cross-circle",on_click:function(){$(".bs-tooltip").remove();y.remove()}}]);y.prepend(v.$el.css("float","right"));$("#center").append(y);this.tool_param_tree_view.render();$("#center").append(this.tool_param_tree_view.$el);this.handle_node_clicks();var s=create_icon_buttons_menu([{icon_class:"chevron-expand",title:"Set display mode"},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location="${h.url_for( controller='visualization', action='list' )}"}}],{tooltip_config:{placement:"bottom"}});var r=["Squish","Pack"],q={};_.each(r,function(A){q[A]=function(){z.model.set("default_mode",A);z.model.get("tracks").each(function(B){B.set("mode",A)})}});make_popupmenu(s.$el.find(".chevron-expand"),q);s.$el.attr("style","float: right");$("#right .unified-panel-header-inner").append(s.$el)},run_tool_on_dataset:function(r){var q=this.model.get("tool"),t=q.get("name"),s=this.model.get("dataset");q.set_input_values(r.get("values"));$.when(q.rerun(s)).then(function(u){});show_modal("Running "+t+" on complete dataset",t+" is running on dataset '"+s.get("name")+"'. Outputs are in the dataset's history.",{Ok:function(){hide_modal()}})},add_track:function(t){var r=this,s=this.model.get("parameter_tree");r.model.add_track(t);var q=new l({model:t,canvas_manager:r.canvas_manager});q.on("run_on_dataset",r.run_tool_on_dataset,r);r.track_collection_container.append(q.$el);q.$el.hover(function(){var v=s.get_leaf(t.get("settings").get("values"));var u=_.pluck(s.get_connected_nodes(v),"id");o.select(r.tool_param_tree_view.$el[0]).selectAll("g.node").filter(function(w){return _.find(u,function(x){return x===w.id})!==undefined}).style("fill","#f00")},function(){o.select(r.tool_param_tree_view.$el[0]).selectAll("g.node").style("fill","#000")});return t},handle_node_clicks:function(){var q=this,r=this.model.get("parameter_tree"),t=this.model.get("regions"),s=o.select(this.tool_param_tree_view.$el[0]).selectAll("g.node");s.on("click",function(z,w){var v=q.model.get("tool"),y=q.model.get("dataset"),x=r.get_node_settings(z),u=$.Deferred();if(x.length>=10){show_modal("Whoa there cowboy!","You clicked on a node to try "+q.model.get("tool").get("name")+" with "+x.length+" different combinations of settings. You can only run 10 jobs at a time.",{Ok:function(){hide_modal();u.resolve(false)}})}else{u.resolve(true)}$.when(u).then(function(A){if(!A){return}var B=_.map(x,function(C){var D=new c({settings:C,regions:t,mode:q.model.get("default_mode")});q.add_track(D);return D});_.each(B,function(D,C){setTimeout(function(){v.set_input_values(D.get("settings").get("values"));$.when(v.rerun(y,t)).then(function(F){var G=_.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},F.first().get("track_config")),E=h.object_from_template(G,q,null);E.data_manager.set("data_type","raw_data");E.prefs.block_color=q.block_color;E.prefs.reverse_strand_color=q.reverse_strand_color;D.set("track",E)})},C*10000)})})})}});return{SweepsterVisualization:i,SweepsterVisualizationView:e}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/viz/trackster/filters.js --- /dev/null +++ b/static/scripts/packed/viz/trackster/filters.js @@ -0,0 +1,1 @@ +define(["libs/underscore"],function(c){var f=c.extend;var a=function(g){this.manager=null;this.name=g.name;this.index=g.index;this.tool_id=g.tool_id;this.tool_exp_name=g.tool_exp_name};f(a.prototype,{to_dict:function(){return{name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name}}});var d=function(i,h,g){return $("<a/>").attr("href","javascript:void(0);").attr("title",i).addClass("icon-button").addClass(h).tooltip().click(g)};var e=function(o){a.call(this,o);this.low=("low" in o?o.low:-Number.MAX_VALUE);this.high=("high" in o?o.high:Number.MAX_VALUE);this.min=("min" in o?o.min:Number.MAX_VALUE);this.max=("max" in o?o.max:-Number.MAX_VALUE);this.container=null;this.slider=null;this.slider_label=null;var k=function(p,q,r){p.click(function(){var w=q.text(),u=parseFloat(r.slider("option","max")),t=(u<=1?4:u<=1000000?u.toString().length:6),v=false,s=$(this).parents(".slider-row");s.addClass("input");if(r.slider("option","values")){t=2*t+1;v=true}q.text("");$("<input type='text'/>").attr("size",t).attr("maxlength",t).attr("value",w).appendTo(q).focus().select().click(function(x){x.stopPropagation()}).blur(function(){$(this).remove();q.text(w);s.removeClass("input")}).keyup(function(B){if(B.keyCode===27){$(this).trigger("blur")}else{if(B.keyCode===13){var z=r.slider("option","min"),x=r.slider("option","max"),A=function(C){return(isNaN(C)||C>x||C<z)},y=$(this).val();if(!v){y=parseFloat(y);if(A(y)){alert("Parameter value must be in the range ["+z+"-"+x+"]");return $(this)}}else{y=y.split("-");y=[parseFloat(y[0]),parseFloat(y[1])];if(A(y[0])||A(y[1])){alert("Parameter value must be in the range ["+z+"-"+x+"]");return $(this)}}r.slider((v?"values":"value"),y);s.removeClass("input")}}})})};var h=this;h.parent_div=$("<div/>").addClass("filter-row slider-row");var g=$("<div/>").addClass("elt-label").appendTo(h.parent_div),m=$("<span/>").addClass("slider-name").text(h.name+" ").appendTo(g),i=$("<span/>").text(this.low+"-"+this.high),j=$("<span/>").addClass("slider-value").appendTo(g).append("[").append(i).append("]");h.values_span=i;var l=$("<div/>").addClass("slider").appendTo(h.parent_div);h.control_element=$("<div/>").attr("id",h.name+"-filter-control").appendTo(l);h.control_element.slider({range:true,min:this.min,max:this.max,step:this.get_slider_step(this.min,this.max),values:[this.low,this.high],slide:function(p,q){h.slide(p,q)},change:function(p,q){h.control_element.slider("option","slide").call(h.control_element,p,q)}});h.slider=h.control_element;h.slider_label=i;k(j,i,h.control_element);var n=$("<div/>").addClass("display-controls").appendTo(h.parent_div);this.transparency_icon=d("Use filter for data transparency","layer-transparent",function(){if(h.manager.alpha_filter!==h){h.manager.alpha_filter=h;h.manager.parent_div.find(".layer-transparent").removeClass("active").hide();h.transparency_icon.addClass("active").show()}else{h.manager.alpha_filter=null;h.transparency_icon.removeClass("active")}h.manager.track.request_draw(true,true)}).appendTo(n).hide();this.height_icon=d("Use filter for data height","arrow-resize-090",function(){if(h.manager.height_filter!==h){h.manager.height_filter=h;h.manager.parent_div.find(".arrow-resize-090").removeClass("active").hide();h.height_icon.addClass("active").show()}else{h.manager.height_filter=null;h.height_icon.removeClass("active")}h.manager.track.request_draw(true,true)}).appendTo(n).hide();h.parent_div.hover(function(){h.transparency_icon.show();h.height_icon.show()},function(){if(h.manager.alpha_filter!==h){h.transparency_icon.hide()}if(h.manager.height_filter!==h){h.height_icon.hide()}});$("<div style='clear: both;'/>").appendTo(h.parent_div)};f(e.prototype,{to_dict:function(){var g=a.prototype.to_dict.call(this);return f(g,{type:"number",min:this.min,max:this.max,low:this.low,high:this.high})},copy:function(){return new e({name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name})},get_slider_step:function(i,g){var h=g-i;return(h<=2?0.01:1)},slide:function(i,j){var h=j.values;this.values_span.text(h[0]+"-"+h[1]);this.low=h[0];this.high=h[1];var g=this;setTimeout(function(){if(h[0]===g.low&&h[1]===g.high){g.manager.track.request_draw(true,true)}},25)},applies_to:function(g){if(g.length>this.index){return true}return false},_keep_val:function(g){return(isNaN(g)||(g>=this.low&&g<=this.high))},keep:function(h){if(!this.applies_to(h)){return true}var k=this;var l=h[this.index];if(l instanceof Array){var j=true;for(var g=0;g<l.length;g++){if(!this._keep_val(l[g])){j=false;break}}return j}else{return this._keep_val(h[this.index])}},update_attrs:function(k){var g=false;if(!this.applies_to(k)){return g}var h=k[this.index];if(!(h instanceof Array)){h=[h]}for(var j=0;j<h.length;j++){var l=h[j];if(l<this.min){this.min=Math.floor(l);g=true}if(l>this.max){this.max=Math.ceil(l);g=true}}return g},update_ui_elt:function(){if(this.min<this.max){this.parent_div.show()}else{this.parent_div.hide()}var h=this.slider.slider("option","min"),g=this.slider.slider("option","max");if(this.min<h||this.max>g){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",this.get_slider_step(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var b=function(j,p){this.track=j;this.alpha_filter=null;this.height_filter=null;this.filters=[];this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(i){i.stopPropagation()}).click(function(i){i.stopPropagation()}).bind("dblclick",function(i){i.stopPropagation()}).bind("keydown",function(i){i.stopPropagation()});if(p&&"filters" in p){var g=("alpha_filter" in p?p.alpha_filter:null),k=("height_filter" in p?p.height_filter:null),m=p.filters,h;for(var n=0;n<m.length;n++){if(m[n].type==="number"){h=new e(m[n]);this.add_filter(h);if(h.name===g){this.alpha_filter=h;h.transparency_icon.addClass("active").show()}if(h.name===k){this.height_filter=h;h.height_icon.addClass("active").show()}}else{console.log("ERROR: unsupported filter: ",name,type)}}if("visible" in p&&p.visible){this.parent_div.show()}}if(this.filters.length!==0){var q=$("<div/>").addClass("param-row").appendTo(this.parent_div);var o=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(q);var l=this;o.click(function(){l.run_on_dataset()})}};f(b.prototype,{show:function(){this.parent_div.show()},hide:function(){this.parent_div.hide()},toggle:function(){this.parent_div.toggle()},visible:function(){return this.parent_div.is(":visible")},to_dict:function(){var k={},j=[],h;for(var g=0;g<this.filters.length;g++){h=this.filters[g];j.push(h.to_dict())}k.filters=j;k.alpha_filter=(this.alpha_filter?this.alpha_filter.name:null);k.height_filter=(this.height_filter?this.height_filter.name:null);k.visible=this.parent_div.is(":visible");return k},copy:function(h){var j=new b(h);for(var g=0;g<this.filters.length;g++){j.add_filter(this.filters[g].copy())}return j},add_filter:function(g){g.manager=this;this.parent_div.append(g.parent_div);this.filters.push(g)},remove_all:function(){this.filters=[];this.parent_div.children().remove()},init_filters:function(){for(var g=0;g<this.filters.length;g++){var h=this.filters[g];h.update_ui_elt()}},clear_filters:function(){for(var g=0;g<this.filters.length;g++){var h=this.filters[g];h.slider.slider("option","values",[h.min,h.max])}this.alpha_filter=null;this.height_filter=null;this.parent_div.find(".icon-button").hide()},run_on_dataset:function(){var n=function(q,i,p){if(!(i in q)){q[i]=p}return q[i]};var m={},o,g;for(var l=0;l<this.filters.length;l++){o=this.filters[l];if(o.tool_id){if(o.min!==o.low){g=n(m,o.tool_id,[]);g[g.length]=o.tool_exp_name+" >= "+o.low}if(o.max!==o.high){g=n(m,o.tool_id,[]);g[g.length]=o.tool_exp_name+" <= "+o.high}}}var h=[];for(var k in m){h[h.length]=[k,m[k]]}(function j(u,r){var p=r[0],q=p[0],t=p[1],s="("+t.join(") and (")+")",i={cond:s,input:u,target_dataset_id:u,tool_id:q};r=r.slice(1);$.getJSON(run_tool_url,i,function(v){if(v.error){show_modal("Filter Dataset","Error running tool "+q,{Close:hide_modal})}else{if(r.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{j(v.dataset_id,r)}}})})(this.track.dataset_id,h)}});return{FiltersManager:b,NumberFilter:e}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/viz/trackster/painters.js --- a/static/scripts/packed/viz/trackster/painters.js +++ b/static/scripts/packed/viz/trackster/painters.js @@ -1,1 +1,1 @@ -define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height;delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start-1)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2]-1,feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-1-tile_low)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null)};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,orig_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=0,char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color);var draw_last=[];if((mode==="Pack"||this.mode==="Auto")&&orig_seq!==undefined&&w_scale>char_width_px){gap=Math.round(w_scale/2)}if(!cigar){cigar=[[0,orig_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];if(cig_op==="H"||cig_op==="S"){base_offset-=cig_len}var seq_start=(feature_start-1)+base_offset,s_start=Math.floor(Math.max(0,(seq_start-tile_low)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":case"M":case"=":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=orig_seq.slice(seq_offset,seq_offset+cig_len);if(gap>0){ctx.fillStyle=block_color;ctx.fillRect(s_start-gap,y_center+1,s_end-s_start,9);ctx.fillStyle=CONNECTOR_COLOR;for(var c=0,str_len=seq.length;c<str_len;c++){if(this.prefs.show_differences){if(this.ref_seq){var ref_char=this.ref_seq[seq_start-tile_low+c];if(!ref_char||ref_char.toLowerCase()===seq[c].toLowerCase()){continue}}else{continue}}if(seq_start+c>=tile_low&&seq_start+c<=tile_high){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start,y_center+9)}}}else{ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+4,s_end-s_start,SQUISH_FEATURE_HEIGHT)}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start-gap,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="red";ctx.fillRect(s_start-gap,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=orig_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&orig_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&orig_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break;case"X":seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color,gap=0;if((mode==="Pack"||this.mode==="Auto")&&w_scale>ctx.canvas.manager.char_width_px){var gap=Math.round(w_scale/2)}if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end-gap,y_center+5,b2_start-gap,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;var tile_index=1;if(tile_index===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING-gap,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING-gap,y_center+8)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"4169E1",neg_color:"FF8C00"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter}}); \ No newline at end of file +define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height;delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start-1)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2]-1,feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-1-tile_low)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null)};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,ref_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=0,char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color);var draw_last=[];if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){gap=Math.round(w_scale/2)}if(!cigar){cigar=[[0,ref_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];if(cig_op==="H"||cig_op==="S"){base_offset-=cig_len}var seq_start=(feature_start-1)+base_offset,s_start=Math.floor(Math.max(0,(seq_start-tile_low)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":case"M":case"=":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=ref_seq.slice(seq_offset-1,seq_offset+cig_len);if(gap>0){ctx.fillStyle=block_color;ctx.fillRect(s_start-gap,y_center+1,s_end-s_start,9);ctx.fillStyle=CONNECTOR_COLOR;for(var c=0,str_len=seq.length;c<str_len;c++){if(this.prefs.show_differences){if(this.ref_seq){var ref_char=this.ref_seq[seq_start-tile_low+c];if(!ref_char||ref_char.toLowerCase()===seq[c].toLowerCase()){continue}}else{continue}}if(seq_start+c>=tile_low&&seq_start+c<=tile_high){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start,y_center+9)}}}else{ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+4,s_end-s_start,SQUISH_FEATURE_HEIGHT)}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start-gap,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="red";ctx.fillRect(s_start-gap,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=ref_seq.slice(seq_offset-1,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break;case"X":seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(0,(feature_start-tile_low)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color,gap=0;if((mode==="Pack"||this.mode==="Auto")&&w_scale>ctx.canvas.manager.char_width_px){var gap=Math.round(w_scale/2)}if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end-gap,y_center+5,b2_start-gap,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;var tile_index=1;if(tile_index===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING-gap,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING-gap,y_center+8)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"4169E1",neg_color:"FF8C00"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 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"],function(ae,y,m,v,M){var r=ae.extend;var R=m.get_random_color;var Y=function(af){return("isResolved" in af)};var o={};var l=function(af,ag){o[af.attr("id")]=ag};var n=function(af,ah,aj,ai){aj=".group";var ag={};o[af.attr("id")]=ai;af.bind("drag",{handle:"."+ah,relative:true},function(ar,at){var aq=$(this),aw=$(this).parent(),an=aw.children(),ap=o[$(this).attr("id")],am,al,au,ak,ao;al=$(this).parents(aj);if(al.length!==0){au=al.position().top;ak=au+al.outerHeight();if(at.offsetY<au){$(this).insertBefore(al);var av=o[al.attr("id")];av.remove_drawable(ap);av.container.add_drawable_before(ap,av);return}else{if(at.offsetY>ak){$(this).insertAfter(al);var av=o[al.attr("id")];av.remove_drawable(ap);av.container.add_drawable(ap);return}}}al=null;for(ao=0;ao<an.length;ao++){am=$(an.get(ao));au=am.position().top;ak=au+am.outerHeight();if(am.is(aj)&&this!==am.get(0)&&at.offsetY>=au&&at.offsetY<=ak){if(at.offsetY-au<ak-at.offsetY){am.find(".content-div").prepend(this)}else{am.find(".content-div").append(this)}if(ap.container){ap.container.remove_drawable(ap)}o[am.attr("id")].add_drawable(ap);return}}for(ao=0;ao<an.length;ao++){am=$(an.get(ao));if(at.offsetY<am.position().top&&!(am.hasClass("reference-track")||am.hasClass("intro"))){break}}if(ao===an.length){if(this!==an.get(ao-1)){aw.append(this);o[aw.attr("id")].move_drawable(ap,ao)}}else{if(this!==an.get(ao)){$(this).insertBefore(an.get(ao));o[aw.attr("id")].move_drawable(ap,(at.deltaY>0?ao-1:ao))}}}).bind("dragstart",function(){ag["border-top"]=af.css("border-top");ag["border-bottom"]=af.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ag)})};exports.moveable=n;var ad=16,H=9,E=20,B=100,J=12000,U=400,L=5000,x=100,p="There was an error in indexing this dataset. ",K="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",F="No data for this chrom/contig.",w="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",z="Tool cannot be rerun: ",a="Loading data...",X="Ready for display",S=10,I=20;function Z(ag,af){if(!af){af=0}var ah=Math.pow(10,af);return Math.round(ag*ah)/ah}var s=function(ag,af,ai){if(!s.id_counter){s.id_counter=0}this.id=s.id_counter++;this.name=ai.name;this.view=ag;this.container=af;this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ai.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ai.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(aj){aj.stopPropagation()});var ah=this;this.container_div.hover(function(){ah.icons_div.show()},function(){ah.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};s.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(af){if(af.content_visible){af.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");af.hide_contents();af.content_visible=false}else{af.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");af.content_visible=true;af.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ag){var ai=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},af=function(){ag.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ah=function(aj){if((aj.keyCode||aj.which)===27){ai()}else{if((aj.keyCode||aj.which)===13){af()}}};$(window).bind("keypress.check_enter_esc",ah);show_modal("Configure",ag.config.build_form(),{Cancel:ai,OK:af})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(af){$(".bs-tooltip").remove();af.remove()}}];r(s.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(af){this.old_name=this.name;this.name=af;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 af=this.view;this.container_div.hide(0,function(){$(this).remove();af.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ag,al,ak,aj,af,ai){var ah=this;this.action_icons[ag]=$("<a/>").attr("href","javascript:void(0);").attr("title",al).addClass("icon-button").addClass(ak).tooltip().click(function(){aj(ah)}).appendTo(this.icons_div);if(ai){this.action_icons[ag].hide()}},build_action_icons:function(af){var ah;for(var ag=0;ag<af.length;ag++){ah=af[ag];this.add_action_icon(ah.name,ah.title,ah.css_class,ah.on_click_fn,ah.prepend,ah.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var A=function(ag,af,ah){s.call(this,ag,af,ah);this.obj_type=ah.obj_type;this.drawables=[]};r(A.prototype,s.prototype,{unpack_drawables:function(ah){this.drawables=[];var ag;for(var af=0;af<ah.length;af++){ag=q(ah[af],this.view,this);this.add_drawable(ag)}},init:function(){for(var af=0;af<this.drawables.length;af++){this.drawables[af].init()}},_draw:function(){for(var af=0;af<this.drawables.length;af++){this.drawables[af]._draw()}},to_dict:function(){var ag=[];for(var af=0;af<this.drawables.length;af++){ag.push(this.drawables[af].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ag}},add_drawable:function(af){this.drawables.push(af);af.container=this;this.changed()},add_drawable_before:function(ah,af){this.changed();var ag=this.drawables.indexOf(af);if(ag!==-1){this.drawables.splice(ag,0,ah);return true}return false},replace_drawable:function(ah,af,ag){var ai=this.drawables.indexOf(ah);if(ai!==-1){this.drawables[ai]=af;if(ag){ah.container_div.replaceWith(af.container_div)}this.changed()}return ai},remove_drawable:function(ag){var af=this.drawables.indexOf(ag);if(af!==-1){this.drawables.splice(af,1);ag.container=null;this.changed();return true}return false},move_drawable:function(ag,ah){var af=this.drawables.indexOf(ag);if(af!==-1){this.drawables.splice(af,1);this.drawables.splice(ah,0,ag);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var Q=function(ag,af,ai){r(ai,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});A.call(this,ag,af,ai);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);l(this.container_div,this);l(this.content_div,this);n(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new aa(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ai){this.unpack_drawables(ai.drawables)}if("filters" in ai){var ah=this.filters_manager;this.filters_manager=new aa(this,ai.filters);ah.parent_div.replaceWith(this.filters_manager.parent_div);if(ai.filters.visible){this.setup_multitrack_filtering()}}};r(Q.prototype,s.prototype,A.prototype,{action_icons_def:[s.prototype.action_icons_def[0],s.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(af){$(".bs-tooltip").remove();af.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(af){if(af.filters_manager.visible()){af.filters_manager.clear_filters();af._restore_filter_managers()}else{af.setup_multitrack_filtering();af.request_draw(true)}af.filters_manager.toggle()}},s.prototype.action_icons_def[2]],build_container_div:function(){var af=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(af)}return af},build_header_div:function(){var af=$("<div/>").addClass("track-header");af.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(af);return af},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ah=this.drawables.length;if(ah===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ah===1){if(this.drawables[0] instanceof h){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var ao,an,al,ar=true,aj=this.drawables[0].get_type(),af=0;for(ao=0;ao<ah;ao++){al=this.drawables[ao];if(al.get_type()!==aj){can_composite=false;break}if(al instanceof d){af++}}if(ar||af===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(af>1&&af===this.drawables.length){var at={},ag;al=this.drawables[0];for(an=0;an<al.filters_manager.filters.length;an++){ag=al.filters_manager.filters[an];at[ag.name]=[ag]}for(ao=1;ao<this.drawables.length;ao++){al=this.drawables[ao];for(an=0;an<al.filters_manager.filters.length;an++){ag=al.filters_manager.filters[an];if(ag.name in at){at[ag.name].push(ag)}}}this.filters_manager.remove_all();var ai,ak,am,ap;for(var aq in at){ai=at[aq];if(ai.length===af){ak=new V({name:ai[0].name,index:ai[0].index});this.filters_manager.add_filter(ak)}}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 af=0;af<this.drawables.length;af++){this.drawables[af].filters_manager=this.saved_filters_managers[af]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var af=0;af<this.drawables.length;af++){drawable=this.drawables[af];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var aj=[];for(var ag=0;ag<this.drawables.length;ag++){aj.push(this.drawables[ag].name)}var ah="Composite Track of "+this.drawables.length+" tracks ("+aj.join(", ")+")";var ai=new h(this.view,this.view,{name:ah,drawables:this.drawables});var af=this.container.replace_drawable(this,ai,true);ai.request_draw()},add_drawable:function(af){A.prototype.add_drawable.call(this,af);this.update_icons()},remove_drawable:function(af){A.prototype.remove_drawable.call(this,af);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var af=r(A.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return af},request_draw:function(af,ah){for(var ag=0;ag<this.drawables.length;ag++){this.drawables[ag].request_draw(af,ah)}}});var ac=function(af){r(af,{obj_type:"View"});A.call(this,"View",af.container,af);this.chrom=null;this.vis_id=af.vis_id;this.dbkey=af.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 CanvasManager(this.container.get(0).ownerDocument);this.reset()};ae.extend(ac.prototype,Backbone.Events);r(ac.prototype,A.prototype,{init:function(){this.requested_redraw=false;var ah=this.container,af=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ah);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ah);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ah);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;l(this.viewport_container,af);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ai=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_datasets(add_datasets_url,add_track_async_url,function(aj){ae.each(aj,function(ak){af.add_drawable(q(ak,af,af))})})});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 ag=function(aj){if(aj.type==="focusout"||(aj.keyCode||aj.which)===13||(aj.keyCode||aj.which)===27){if((aj.keyCode||aj.which)!==27){af.go_to($(this).val())}$(this).hide();$(this).val("");af.location_span.show();af.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ag).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(){af.location_span.hide();af.chrom_select.hide();af.nav_input.val(af.chrom+":"+af.low+"-"+af.high);af.nav_input.css("display","inline-block");af.nav_input.select();af.nav_input.focus();af.nav_input.autocomplete({source:function(al,aj){var am=[],ak=$.map(af.get_drawables(),function(an){return an.data_manager.search_features(al.term).success(function(ao){am=am.concat(ao)})});$.when.apply($,ak).done(function(){aj($.map(am,function(an){return{label:an[0],value:an[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(){af.zoom_out();af.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){af.zoom_in();af.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){af.change_chrom(af.chrom_select.val())});this.browser_content_div.click(function(aj){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(aj){af.zoom_in(aj.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(aj,ak){this.current_x=ak.offsetX}).bind("drag",function(aj,al){var am=al.offsetX-this.current_x;this.current_x=al.offsetX;var ak=Math.round(am/af.viewport_container.width()*(af.max_high-af.max_low));af.move_delta(-ak)});this.overview_close.click(function(){af.reset_overview()});this.viewport_container.bind("draginit",function(aj,ak){if(aj.clientX>af.viewport_container.width()-16){return false}}).bind("dragstart",function(aj,ak){ak.original_low=af.low;ak.current_height=aj.clientY;ak.current_x=ak.offsetX}).bind("drag",function(al,an){var aj=$(this);var ao=an.offsetX-an.current_x;var ak=aj.scrollTop()-(al.clientY-an.current_height);aj.scrollTop(ak);an.current_height=al.clientY;an.current_x=an.offsetX;var am=Math.round(ao/af.viewport_container.width()*(af.high-af.low));af.move_delta(am)}).bind("mousewheel",function(al,an,ak,aj){if(ak){ak*=50;var am=Math.round(-ak/af.viewport_container.width()*(af.high-af.low));af.move_delta(am)}});this.top_labeltrack.bind("dragstart",function(aj,ak){return $("<div />").css({height:af.browser_content_div.height()+af.top_labeltrack.height()+af.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(an,ao){$(ao.proxy).css({left:Math.min(an.pageX,ao.startX)-af.container.offset().left,width:Math.abs(an.pageX-ao.startX)});var ak=Math.min(an.pageX,ao.startX)-af.container.offset().left,aj=Math.max(an.pageX,ao.startX)-af.container.offset().left,am=(af.high-af.low),al=af.viewport_container.width();af.update_location(Math.round(ak/al*am)+af.low,Math.round(aj/al*am)+af.low)}).bind("dragend",function(ao,ap){var ak=Math.min(ao.pageX,ap.startX),aj=Math.max(ao.pageX,ap.startX),am=(af.high-af.low),al=af.viewport_container.width(),an=af.low;af.low=Math.round(ak/al*am)+an;af.high=Math.round(aj/al*am)+an;$(ap.proxy).remove();af.request_redraw()});this.add_label_track(new ab(this,{content_div:this.top_labeltrack}));this.add_label_track(new ab(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){af.resize_window()},500)});$(document).bind("redraw",function(){af.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(ag,ai,af,aj){if(this.timer){clearTimeout(this.timer)}if(aj){var ah=this;this.timer=setTimeout(function(){ah.trigger("navigate",ag+":"+ai+"-"+af)},500)}else{view.trigger("navigate",ag+":"+ai+"-"+af)}},update_location:function(af,ah){this.location_span.text(commatize(af)+" - "+commatize(ah));this.nav_input.val(this.chrom+":"+commatize(af)+"-"+commatize(ah));var ag=view.chrom_select.val();if(ag!==""){this.trigger_navigate(ag,view.low,view.high,true)}},load_chroms:function(ah){ah.num=x;var af=this,ag=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ah,dataType:"json",success:function(aj){if(aj.chrom_info.length===0){return}if(aj.reference){af.add_label_track(new C(af))}af.chrom_data=aj.chrom_info;var am='<option value="">Select Chrom/Contig</option>';for(var al=0,ai=af.chrom_data.length;al<ai;al++){var ak=af.chrom_data[al].chrom;am+='<option value="'+ak+'">'+ak+"</option>"}if(aj.prev_chroms){am+='<option value="previous">Previous '+x+"</option>"}if(aj.next_chroms){am+='<option value="next">Next '+x+"</option>"}af.chrom_select.html(am);af.chrom_start_index=aj.start_index;ag.resolve(aj)},error:function(){alert("Could not load chroms for this dbkey:",af.dbkey)}});return ag},change_chrom:function(ak,ag,am){var ah=this;if(!ah.chrom_data){ah.load_chroms_deferred.then(function(){ah.change_chrom(ak,ag,am)});return}if(!ak||ak==="None"){return}if(ak==="previous"){ah.load_chroms({low:this.chrom_start_index-x});return}if(ak==="next"){ah.load_chroms({low:this.chrom_start_index+x});return}var al=$.grep(ah.chrom_data,function(an,ao){return an.chrom===ak})[0];if(al===undefined){ah.load_chroms({chrom:ak},function(){ah.change_chrom(ak,ag,am)});return}else{if(ak!==ah.chrom){ah.chrom=ak;ah.chrom_select.val(ah.chrom);ah.max_high=al.len-1;ah.reset();ah.request_redraw(true);for(var aj=0,af=ah.drawables.length;aj<af;aj++){var ai=ah.drawables[aj];if(ai.init){ai.init()}}if(ah.reference_track){ah.reference_track.init()}}if(ag!==undefined&&am!==undefined){ah.low=Math.max(ag,0);ah.high=Math.min(am,ah.max_high)}else{ah.low=0;ah.high=ah.max_high}ah.reset_overview();ah.request_redraw()}},go_to:function(aj){aj=aj.replace(/ |,/g,"");var an=this,af,ai,ag=aj.split(":"),al=ag[0],am=ag[1];if(am!==undefined){try{var ak=am.split("-");af=parseInt(ak[0],10);ai=parseInt(ak[1],10)}catch(ah){return false}}an.change_chrom(al,af,ai)},move_fraction:function(ah){var af=this;var ag=af.high-af.low;this.move_delta(ah*ag)},move_delta:function(ai){var af=this;var ah=af.high-af.low;if(af.low-ai<af.max_low){af.low=af.max_low;af.high=af.max_low+ah}else{if(af.high-ai>af.max_high){af.high=af.max_high;af.low=af.max_high-ah}else{af.high-=ai;af.low-=ai}}af.request_redraw();var ag=af.chrom_select.val();this.trigger_navigate(ag,af.low,af.high,true)},add_drawable:function(af){A.prototype.add_drawable.call(this,af);af.init();this.changed();this.update_intro_div()},add_label_track:function(af){af.view=this;af.init();this.label_tracks.push(af)},remove_drawable:function(ah,ag){A.prototype.remove_drawable.call(this,ah);if(ag){var af=this;ah.container_div.hide(0,function(){$(this).remove();af.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(an,af,am,ao){var al=this,ak=(ao?[ao]:al.drawables),ah;var ag;for(var aj=0;aj<ak.length;aj++){ag=ak[aj];ah=-1;for(var ai=0;ai<al.tracks_to_be_redrawn.length;ai++){if(al.tracks_to_be_redrawn[ai][0]===ag){ah=ai;break}}if(ah<0){al.tracks_to_be_redrawn.push([ag,af,am])}else{al.tracks_to_be_redrawn[aj][1]=af;al.tracks_to_be_redrawn[aj][2]=am}}if(!this.requested_redraw){requestAnimationFrame(function(){al._redraw(an)});this.requested_redraw=true}},_redraw:function(ap){this.requested_redraw=false;var am=this.low,ai=this.high;if(am<this.max_low){am=this.max_low}if(ai>this.max_high){ai=this.max_high}var ao=this.high-this.low;if(this.high!==0&&ao<this.min_separation){ai=am+this.min_separation}this.low=Math.floor(am);this.high=Math.ceil(ai);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 af=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var al=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var aq=13;this.overview_box.css({left:af,width:Math.max(aq,al)}).show();if(al<aq){this.overview_box.css("left",af-(aq-al)/2)}if(this.overview_highlight){this.overview_highlight.css({left:af,width:al})}if(!ap){var ah,ag,an;for(var aj=0,ak=this.tracks_to_be_redrawn.length;aj<ak;aj++){ah=this.tracks_to_be_redrawn[aj][0];ag=this.tracks_to_be_redrawn[aj][1];an=this.tracks_to_be_redrawn[aj][2];if(ah){ah._draw(ag,an)}}this.tracks_to_be_redrawn=[];for(aj=0,ak=this.label_tracks.length;aj<ak;aj++){this.label_tracks[aj]._draw()}}},zoom_in:function(ag,ah){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ai=this.high-this.low,aj=ai/2+this.low,af=(ai/this.zoom_factor)/2;if(ag){aj=ag/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(aj-af);this.high=Math.round(aj+af);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ag=this.high-this.low,ah=ag/2+this.low,af=(ag*this.zoom_factor)/2;this.low=Math.round(ah-af);this.high=Math.round(ah+af);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(ah){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ah.dataset_id){return}this.overview_viewport.find(".track").remove()}var ag=ah.copy({content_div:this.overview_viewport}),af=this;ag.header_div.hide();ag.is_overview=true;af.overview_drawable=ag;this.overview_drawable.postdraw_actions=function(){af.overview_highlight.show().height(af.overview_drawable.content_div.height());af.overview_viewport.height(af.overview_drawable.content_div.height()+af.overview_box.outerHeight());af.overview_close.show();af.resize_window()};af.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 t=function(ah,am,ai){this.track=ah;this.name=am.name;this.params=[];var au=am.params;for(var aj=0;aj<au.length;aj++){var ao=au[aj],ag=ao.name,at=ao.label,ak=unescape(ao.html),av=ao.value,aq=ao.type;if(aq==="number"){this.params.push(new f(ag,at,ak,(ag in ai?ai[ag]:av),ao.min,ao.max))}else{if(aq==="select"){this.params.push(new O(ag,at,ak,(ag in ai?ai[ag]:av)))}else{console.log("WARNING: unrecognized tool parameter type:",ag,aq)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ax){ax.stopPropagation()}).click(function(ax){ax.stopPropagation()}).bind("dblclick",function(ax){ax.stopPropagation()});var ar=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var ap=this.params;var an=this;$.each(this.params,function(ay,aB){var aA=$("<div>").addClass("param-row").appendTo(an.parent_div);var ax=$("<div>").addClass("param-label").text(aB.label).appendTo(aA);var az=$("<div/>").addClass("param-input").html(aB.html).appendTo(aA);az.find(":input").val(aB.value);$("<div style='clear: both;'/>").appendTo(aA)});this.parent_div.find("input").click(function(){$(this).select()});var aw=$("<div>").addClass("param-row").appendTo(this.parent_div);var al=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(aw);var af=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(aw);af.click(function(){an.run_on_region()});al.click(function(){an.run_on_dataset()});if("visible" in ai&&ai.visible){this.parent_div.show()}};r(t.prototype,{update_params:function(){for(var af=0;af<this.params.length;af++){this.params[af].update_value()}},state_dict:function(){var ag={};for(var af=0;af<this.params.length;af++){ag[this.params[af].name]=this.params[af].value}ag.visible=this.parent_div.is(":visible");return ag},get_param_values_dict:function(){var af={};this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();af[ag]=ah});return af},get_param_values:function(){var af=[];this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();if(ag){af[af.length]=ah}});return af},run_on_dataset:function(){var af=this;af.run({target_dataset_id:this.track.original_dataset_id,tool_id:af.name},null,function(ag){show_modal(af.name+" is Running",af.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ag={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}]},ak=this.track,ah=ag.tool_id+ak.tool_region_and_parameters_str(ag.chrom,ag.low,ag.high),af;if(ak.container===view){var aj=new Q(view,view,{name:this.name});var ai=ak.container.replace_drawable(ak,aj,false);aj.container_div.insertBefore(ak.view.content_div.children()[ai]);aj.add_drawable(ak);ak.container_div.appendTo(aj.content_div);af=aj}else{af=ak.container}var al=new ak.constructor(view,af,{name:ah,hda_ldda:"hda"});al.init_for_tool_data();al.change_mode(ak.mode);al.set_filters_manager(ak.filters_manager.copy(al));al.update_icons();af.add_drawable(al);al.tiles_div.text("Starting job.");this.update_params();this.run(ag,al,function(am){al.set_dataset(new Dataset(am));al.tiles_div.text("Running job.");al.init()})},run:function(af,ah,ai){af.inputs=this.get_param_values_dict();var ag=new ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(af),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(aj){return aj!=="pending"}});$.when(ag.go()).then(function(aj){if(aj==="no converter"){ah.container_div.addClass("error");ah.content_div.text(K)}else{if(aj.error){ah.container_div.addClass("error");ah.content_div.text(z+aj.message)}else{ai(aj)}}})}});var O=function(ag,af,ah,ai){this.name=ag;this.label=af;this.html=$(ah);this.value=ai};r(O.prototype,{update_value:function(){this.value=$(this.html).val()}});var f=function(ah,ag,aj,ak,ai,af){O.call(this,ah,ag,aj,ak);this.min=ai;this.max=af};r(f.prototype,O.prototype,{update_value:function(){O.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var g=function(af){this.manager=null;this.name=af.name;this.index=af.index;this.tool_id=af.tool_id;this.tool_exp_name=af.tool_exp_name};r(g.prototype,{to_dict:function(){return{name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name}}});var c=function(ah,ag,af){return $("<a/>").attr("href","javascript:void(0);").attr("title",ah).addClass("icon-button").addClass(ag).tooltip().click(af)};var V=function(an){g.call(this,an);this.low=("low" in an?an.low:-Number.MAX_VALUE);this.high=("high" in an?an.high:Number.MAX_VALUE);this.min=("min" in an?an.min:Number.MAX_VALUE);this.max=("max" in an?an.max:-Number.MAX_VALUE);this.container=null;this.slider=null;this.slider_label=null;var aj=function(ao,ap,aq){ao.click(function(){var aw=ap.text(),au=parseFloat(aq.slider("option","max")),at=(au<=1?4:au<=1000000?au.toString().length:6),av=false,ar=$(this).parents(".slider-row");ar.addClass("input");if(aq.slider("option","values")){at=2*at+1;av=true}ap.text("");$("<input type='text'/>").attr("size",at).attr("maxlength",at).attr("value",aw).appendTo(ap).focus().select().click(function(ax){ax.stopPropagation()}).blur(function(){$(this).remove();ap.text(aw);ar.removeClass("input")}).keyup(function(aB){if(aB.keyCode===27){$(this).trigger("blur")}else{if(aB.keyCode===13){var az=aq.slider("option","min"),ax=aq.slider("option","max"),aA=function(aC){return(isNaN(aC)||aC>ax||aC<az)},ay=$(this).val();if(!av){ay=parseFloat(ay);if(aA(ay)){alert("Parameter value must be in the range ["+az+"-"+ax+"]");return $(this)}}else{ay=ay.split("-");ay=[parseFloat(ay[0]),parseFloat(ay[1])];if(aA(ay[0])||aA(ay[1])){alert("Parameter value must be in the range ["+az+"-"+ax+"]");return $(this)}}aq.slider((av?"values":"value"),ay);ar.removeClass("input")}}})})};var ag=this;ag.parent_div=$("<div/>").addClass("filter-row slider-row");var af=$("<div/>").addClass("elt-label").appendTo(ag.parent_div),al=$("<span/>").addClass("slider-name").text(ag.name+" ").appendTo(af),ah=$("<span/>").text(this.low+"-"+this.high),ai=$("<span/>").addClass("slider-value").appendTo(af).append("[").append(ah).append("]");ag.values_span=ah;var ak=$("<div/>").addClass("slider").appendTo(ag.parent_div);ag.control_element=$("<div/>").attr("id",ag.name+"-filter-control").appendTo(ak);ag.control_element.slider({range:true,min:this.min,max:this.max,step:this.get_slider_step(this.min,this.max),values:[this.low,this.high],slide:function(ao,ap){ag.slide(ao,ap)},change:function(ao,ap){ag.control_element.slider("option","slide").call(ag.control_element,ao,ap)}});ag.slider=ag.control_element;ag.slider_label=ah;aj(ai,ah,ag.control_element);var am=$("<div/>").addClass("display-controls").appendTo(ag.parent_div);this.transparency_icon=c("Use filter for data transparency","layer-transparent",function(){if(ag.manager.alpha_filter!==ag){ag.manager.alpha_filter=ag;ag.manager.parent_div.find(".layer-transparent").removeClass("active").hide();ag.transparency_icon.addClass("active").show()}else{ag.manager.alpha_filter=null;ag.transparency_icon.removeClass("active")}ag.manager.track.request_draw(true,true)}).appendTo(am).hide();this.height_icon=c("Use filter for data height","arrow-resize-090",function(){if(ag.manager.height_filter!==ag){ag.manager.height_filter=ag;ag.manager.parent_div.find(".arrow-resize-090").removeClass("active").hide();ag.height_icon.addClass("active").show()}else{ag.manager.height_filter=null;ag.height_icon.removeClass("active")}ag.manager.track.request_draw(true,true)}).appendTo(am).hide();ag.parent_div.hover(function(){ag.transparency_icon.show();ag.height_icon.show()},function(){if(ag.manager.alpha_filter!==ag){ag.transparency_icon.hide()}if(ag.manager.height_filter!==ag){ag.height_icon.hide()}});$("<div style='clear: both;'/>").appendTo(ag.parent_div)};r(V.prototype,{to_dict:function(){var af=g.prototype.to_dict.call(this);return r(af,{type:"number",min:this.min,max:this.max,low:this.low,high:this.high})},copy:function(){return new V({name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name})},get_slider_step:function(ah,af){var ag=af-ah;return(ag<=2?0.01:1)},slide:function(ah,ai){var ag=ai.values;this.values_span.text(ag[0]+"-"+ag[1]);this.low=ag[0];this.high=ag[1];var af=this;setTimeout(function(){if(ag[0]===af.low&&ag[1]===af.high){af.manager.track.request_draw(true,true)}},25)},applies_to:function(af){if(af.length>this.index){return true}return false},_keep_val:function(af){return(isNaN(af)||(af>=this.low&&af<=this.high))},keep:function(ag){if(!this.applies_to(ag)){return true}var ai=this;var aj=ag[this.index];if(aj instanceof Array){var ah=true;for(var af=0;af<aj.length;af++){if(!this._keep_val(aj[af])){ah=false;break}}return ah}else{return this._keep_val(ag[this.index])}},update_attrs:function(ai){var af=false;if(!this.applies_to(ai)){return af}var ag=ai[this.index];if(!(ag instanceof Array)){ag=[ag]}for(var ah=0;ah<ag.length;ah++){var aj=ag[ah];if(aj<this.min){this.min=Math.floor(aj);af=true}if(aj>this.max){this.max=Math.ceil(aj);af=true}}return af},update_ui_elt:function(){if(this.min<this.max){this.parent_div.show()}else{this.parent_div.hide()}var ag=this.slider.slider("option","min"),af=this.slider.slider("option","max");if(this.min<ag||this.max>af){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",this.get_slider_step(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var aa=function(ah,an){this.track=ah;this.alpha_filter=null;this.height_filter=null;this.filters=[];this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ap){ap.stopPropagation()}).click(function(ap){ap.stopPropagation()}).bind("dblclick",function(ap){ap.stopPropagation()}).bind("keydown",function(ap){ap.stopPropagation()});if(an&&"filters" in an){var af=("alpha_filter" in an?an.alpha_filter:null),ai=("height_filter" in an?an.height_filter:null),ak=an.filters,ag;for(var al=0;al<ak.length;al++){if(ak[al].type==="number"){ag=new V(ak[al]);this.add_filter(ag);if(ag.name===af){this.alpha_filter=ag;ag.transparency_icon.addClass("active").show()}if(ag.name===ai){this.height_filter=ag;ag.height_icon.addClass("active").show()}}else{console.log("ERROR: unsupported filter: ",name,type)}}if("visible" in an&&an.visible){this.parent_div.show()}}if(this.filters.length!==0){var ao=$("<div/>").addClass("param-row").appendTo(this.parent_div);var am=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(ao);var aj=this;am.click(function(){aj.run_on_dataset()})}};r(aa.prototype,{show:function(){this.parent_div.show()},hide:function(){this.parent_div.hide()},toggle:function(){this.parent_div.toggle()},visible:function(){return this.parent_div.is(":visible")},to_dict:function(){var ai={},ah=[],ag;for(var af=0;af<this.filters.length;af++){ag=this.filters[af];ah.push(ag.to_dict())}ai.filters=ah;ai.alpha_filter=(this.alpha_filter?this.alpha_filter.name:null);ai.height_filter=(this.height_filter?this.height_filter.name:null);ai.visible=this.parent_div.is(":visible");return ai},copy:function(ag){var ah=new aa(ag);for(var af=0;af<this.filters.length;af++){ah.add_filter(this.filters[af].copy())}return ah},add_filter:function(af){af.manager=this;this.parent_div.append(af.parent_div);this.filters.push(af)},remove_all:function(){this.filters=[];this.parent_div.children().remove()},init_filters:function(){for(var af=0;af<this.filters.length;af++){var ag=this.filters[af];ag.update_ui_elt()}},clear_filters:function(){for(var af=0;af<this.filters.length;af++){var ag=this.filters[af];ag.slider.slider("option","values",[ag.min,ag.max])}this.alpha_filter=null;this.height_filter=null;this.parent_div.find(".icon-button").hide()},run_on_dataset:function(){var al=function(ap,an,ao){if(!(an in ap)){ap[an]=ao}return ap[an]};var ak={},am,af;for(var aj=0;aj<this.filters.length;aj++){am=this.filters[aj];if(am.tool_id){if(am.min!==am.low){af=al(ak,am.tool_id,[]);af[af.length]=am.tool_exp_name+" >= "+am.low}if(am.max!==am.high){af=al(ak,am.tool_id,[]);af[af.length]=am.tool_exp_name+" <= "+am.high}}}var ag=[];for(var ai in ak){ag[ag.length]=[ai,ak[ai]]}(function ah(au,aq){var ao=aq[0],ap=ao[0],at=ao[1],ar="("+at.join(") and (")+")",an={cond:ar,input:au,target_dataset_id:au,tool_id:ap},aq=aq.slice(1);$.getJSON(run_tool_url,an,function(av){if(av.error){show_modal("Filter Dataset","Error running tool "+ap,{Close:hide_modal})}else{if(aq.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{ah(av.dataset_id,aq)}}})})(this.track.dataset_id,ag)}});var D=function(af,ag){M.Scaler.call(this,ag);this.filter=af};D.prototype.gen_val=function(af){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(af[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var G=function(af){this.track=af.track;this.params=af.params;this.values={};this.restore_values((af.saved_values?af.saved_values:{}));this.onchange=af.onchange};r(G.prototype,{restore_values:function(af){var ag=this;$.each(this.params,function(ah,ai){if(af[ai.key]!==undefined){ag.values[ai.key]=af[ai.key]}else{ag.values[ai.key]=ai.default_value}})},build_form:function(){var ai=this;var af=$("<div />");var ah;function ag(an,aj){for(var ar=0;ar<an.length;ar++){ah=an[ar];if(ah.hidden){continue}var al="param_"+ar;var aw=ai.values[ah.key];var ay=$("<div class='form-row' />").appendTo(aj);ay.append($("<label />").attr("for",al).text(ah.label+":"));if(ah.type==="bool"){ay.append($('<input type="checkbox" />').attr("id",al).attr("name",al).attr("checked",aw))}else{if(ah.type==="text"){ay.append($('<input type="text"/>').attr("id",al).val(aw).click(function(){$(this).select()}))}else{if(ah.type==="select"){var au=$("<select />").attr("id",al);for(var ap=0;ap<ah.options.length;ap++){$("<option/>").text(ah.options[ap].label).attr("value",ah.options[ap].value).appendTo(au)}au.val(aw);ay.append(au)}else{if(ah.type==="color"){var ax=$("<div/>").appendTo(ay),at=$("<input />").attr("id",al).attr("name",al).val(aw).css("float","left").appendTo(ax).click(function(aA){$(".bs-tooltip").removeClass("in");var az=$(this).siblings(".bs-tooltip").addClass("in");az.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(az).height()/2)+($(this).height()/2)}).show();az.click(function(aB){aB.stopPropagation()});$(document).bind("click.color-picker",function(){az.hide();$(document).unbind("click.color-picker")});aA.stopPropagation()}),aq=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(ax).attr("title","Set new random color").tooltip(),av=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(ax).hide(),am=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(av),ak=$("<div class='tooltip-arrow'></div>").appendTo(av),ao=$.farbtastic(am,{width:100,height:100,callback:at,color:aw});ax.append($("<div/>").css("clear","both"));(function(az){aq.click(function(){az.setColor(R())})})(ao)}else{ay.append($("<input />").attr("id",al).attr("name",al).val(aw))}}}}if(ah.help){ay.append($("<div class='help'/>").text(ah.help))}}}ag(this.params,af);return af},update_from_form:function(af){var ah=this;var ag=false;$.each(this.params,function(ai,ak){if(!ak.hidden){var al="param_"+ai;var aj=af.find("#"+al).val();if(ak.type==="float"){aj=parseFloat(aj)}else{if(ak.type==="int"){aj=parseInt(aj)}else{if(ak.type==="bool"){aj=af.find("#"+al).is(":checked")}}}if(aj!==ah.values[ak.key]){ah.values[ak.key]=aj;ag=true}}});if(ag){this.onchange();this.track.changed()}}});var b=function(af,aj,ah,ag,ai){this.track=af;this.region=aj;this.low=aj.get("start");this.high=aj.get("end");this.resolution=ah;this.html_elt=$("<div class='track-tile'/>").append(ag).height($(ag).attr("height"));this.data=ai;this.stale=false};b.prototype.predisplay_actions=function(){};var k=function(af,ak,ah,ag,ai,aj){b.call(this,af,ak,ah,ag,ai);this.max_val=aj};r(k.prototype,b.prototype);var P=function(ai,aq,aj,ah,al,at,am,au,ag,ap){b.call(this,ai,aq,aj,ah,al);this.mode=am;this.all_slotted=ag;this.feature_mapper=ap;this.has_icons=false;if(au){this.has_icons=true;var an=this;ah=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:E-1,width:ah.width}).prependTo(this.html_elt);var ao=new GenomeRegion({chrom:ai.view.chrom,start:this.low,end:this.high}),ar=al.length,ak=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ar+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),af=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ar+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ak.click(function(){an.stale=true;ai.data_manager.get_more_data(ao,ai.mode,an.resolution,{},ai.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();ai.request_draw(true)}).dblclick(function(av){av.stopPropagation()});af.click(function(){an.stale=true;ai.data_manager.get_more_data(ao,ai.mode,an.resolution,{},ai.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();ai.request_draw(true)}).dblclick(function(av){av.stopPropagation()})}};r(P.prototype,b.prototype);P.prototype.predisplay_actions=function(){var ag=this,af={};if(ag.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(ar){if(!this.hovered){return}var am=$(this).offset(),aq=ar.pageX-am.left,ap=ar.pageY-am.top,aw=ag.feature_mapper.get_feature_data(aq,ap),an=(aw?aw[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!an||$(this).attr("id")!==an.toString()){$(this).remove()}});if(aw){var ai=af[an];if(!ai){var an=aw[0],at={name:aw[3],start:aw[1],end:aw[2],strand:aw[4]},al=ag.track.filters_manager.filters,ak;for(var ao=0;ao<al.length;ao++){ak=al[ao];at[ak.name]=aw[ak.index]}var ai=$("<div/>").attr("id",an).addClass("feature-popup"),ax=$("<table/>"),av,au,ay;for(av in at){au=at[av];ay=$("<tr/>").appendTo(ax);$("<th/>").appendTo(ay).text(av);$("<td/>").attr("align","left").appendTo(ay).text(typeof(au)==="number"?Z(au,2):au)}ai.append($("<div class='feature-popup-inner'>").append(ax));af[an]=ai}ai.appendTo($(this).parents(".track-content").children(".overlay"));var aj=aq+parseInt(ag.html_elt.css("left"))-ai.width()/2,ah=ap+parseInt(ag.html_elt.css("top"))+7;ai.css("left",aj+"px").css("top",ah+"px")}else{if(!ar.isPropagationStopped()){ar.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ar)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var i=function(ag,af,ah){r(ah,{drag_handle_class:"draghandle"});s.call(this,ag,af,ah);this.dataset=new Dataset({id:ah.dataset_id,hda_ldda:ah.hda_ldda});this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ah?ah.data_query_wait:L);this.data_manager=("data_manager" in ah?ah.data_manager:new y.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 ah)||ah.resize){this.add_resize_handle()}}};r(i.prototype,s.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},s.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(af){af.view.set_overview(af)}},s.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(af){if(af.filters_manager.visible()){af.filters_manager.clear_filters()}else{af.filters_manager.init_filters()}af.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(af){af.dynamic_tool_div.toggle();if(af.dynamic_tool_div.is(":visible")){af.set_name(af.name+af.tool_region_and_parameters_str())}else{af.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(af){var ai='<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>',ah=ae.template(ai,{track:af});var ak=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ag=function(){var am=$('select[name="regions"] option:selected').val(),ao,al=new GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),an=ae.map($(".bookmark"),function(ap){return new GenomeRegion({from_str:$(ap).children(".position").text()})});if(am==="cur"){ao=[al]}else{if(am==="bookmarks"){ao=an}else{ao=[al].concat(an)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:af.dataset_id,hda_ldda:af.hda_ldda,regions:JSON.stringify(new Backbone.Collection(ao).toJSON())})},aj=function(al){if((al.keyCode||al.which)===27){ak()}else{if((al.keyCode||al.which)===13){ag()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ah,{No:ak,Yes:ag})}},s.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&s.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 af=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(af)}this.name_div=$("<div/>").addClass("track-name").appendTo(af).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return af},on_resize:function(){},add_resize_handle:function(){var af=this;var ai=false;var ah=false;var ag=$("<div class='track-resize'>");$(af.container_div).hover(function(){if(af.content_visible){ai=true;ag.show()}},function(){ai=false;if(!ah){ag.hide()}});ag.hide().bind("dragstart",function(aj,ak){ah=true;ak.original_height=$(af.content_div).height()}).bind("drag",function(ak,al){var aj=Math.min(Math.max(al.original_height+al.deltaY,af.min_height_px),af.max_height_px);$(af.tiles_div).css("height",aj);af.visible_height_px=(af.max_height_px===aj?0:aj);af.on_resize()}).bind("dragend",function(aj,ak){af.tile_cache.clear();ah=false;if(!ai){ag.hide()}af.config.values.height=af.visible_height_px;af.changed()}).appendTo(af.container_div)},set_display_modes:function(ai,al){this.display_modes=ai;this.mode=(al?al:(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 ag=this,aj={};for(var ah=0,af=ag.display_modes.length;ah<af;ah++){var ak=ag.display_modes[ah];aj[ak]=function(am){return function(){ag.change_mode(am);ag.icons_div.show();ag.container_div.mouseleave(function(){ag.icons_div.hide()})}}(ak)}make_popupmenu(this.action_icons.mode_icon,aj)},build_action_icons:function(){s.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 ab){return"LabelTrack"}else{if(this instanceof C){return"ReferenceTrack"}else{if(this instanceof j){return"LineTrack"}else{if(this instanceof W){return"ReadTrack"}else{if(this instanceof T){return"VcfTrack"}else{if(this instanceof h){return"CompositeTrack"}else{if(this instanceof d){return"FeatureTrack"}}}}}}}return""},init:function(){var ag=this;ag.enabled=false;ag.tile_cache.clear();ag.data_manager.clear();ag.content_div.css("height","auto");ag.tiles_div.children().remove();ag.container_div.removeClass("nodata error pending");if(!ag.dataset_id){return}var af=$.Deferred(),ah={hda_ldda:ag.hda_ldda,data_type:this.dataset_check_type,chrom:ag.view.chrom};$.getJSON(this.dataset.url(),ah,function(ai){if(!ai||ai==="error"||ai.kind==="error"){ag.container_div.addClass("error");ag.tiles_div.text(p);if(ai.message){var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ag.tiles_div.append(aj)}}else{if(ai==="no converter"){ag.container_div.addClass("error");ag.tiles_div.text(K)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ag.container_div.addClass("nodata");ag.tiles_div.text(F)}else{if(ai==="pending"){ag.container_div.addClass("pending");ag.tiles_div.html(w);setTimeout(function(){ag.init()},ag.data_query_wait)}else{if(ai==="data"||ai.status==="data"){if(ai.valid_chroms){ag.valid_chroms=ai.valid_chroms;ag.update_icons()}ag.tiles_div.text(X);if(ag.view.chrom){ag.tiles_div.text("");ag.tiles_div.css("height",ag.visible_height_px+"px");ag.enabled=true;$.when(ag.predraw_init()).done(function(){af.resolve();ag.container_div.removeClass("nodata error pending");ag.request_draw()})}else{af.resolve()}}}}}}});this.update_icons();return af},predraw_init:function(){},get_drawables:function(){return this}});var N=function(ah,ag,ai){i.call(this,ah,ag,ai);var af=this;n(af.container_div,af.drag_handle_class,".group",af);this.filters_manager=new aa(this,("filters" in ai?ai.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in ai&&ai.tool?new t(this,ai.tool,ai.tool_state):null);this.tile_cache=new y.Cache(S);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(ai.mode){this.change_mode(ai.mode)}};r(N.prototype,s.prototype,i.prototype,{action_icons_def:i.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(af){$(".bs-tooltip").remove();af.slotters[af.view.resolution_px_b].max_rows*=2;af.request_draw(true)},hide:true}]),copy:function(af){var ag=this.to_dict();r(ag,{data_manager:this.data_manager});var ah=new this.constructor(this.view,af,ag);ah.change_mode(this.mode);ah.enabled=this.enabled;return ah},set_filters_manager:function(af){this.filters_manager=af;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(ag){var af=this;af.mode=ag;af.config.values.mode=ag;af.tile_cache.clear();af.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+af.mode+")");return af},update_icons:function(){var af=this;if(af.filters_available){af.action_icons.filters_icon.show()}else{af.action_icons.filters_icon.hide()}if(af.tool){af.action_icons.tools_icon.show();af.action_icons.param_space_viz_icon.show()}else{af.action_icons.tools_icon.hide();af.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ag,ah,af){return ag+"_"+ah+"_"+af},request_draw:function(ag,af){this.view.request_redraw(false,ag,af,this)},before_draw:function(){},_draw:function(ag,aq){if(!this.can_draw()){return}var ao=this.view.low,ak=this.view.high,am=ak-ao,ah=this.view.container.width(),at=this.view.resolution_px_b,aj=this.view.resolution_b_px;if(this.is_overview){ao=this.view.max_low;ak=this.view.max_high;aj=(view.max_high-view.max_low)/ah;at=1/aj}this.before_draw();this.tiles_div.children().addClass("remove");var af=Math.floor(ao/(aj*U)),an=true,ar=[],al=function(au){return(au&&"track" in au)};while((af*U*aj)<ak){var ap=this.draw_helper(ag,ah,af,aj,this.tiles_div,at);if(al(ap)){ar.push(ap)}else{an=false}af+=1}if(!aq){this.tiles_div.children(".remove").removeClass("remove").remove()}var ai=this;if(an){this.tiles_div.children(".remove").remove();ai.postdraw_actions(ar,ah,at,aq)}},postdraw_actions:function(ah,ai,ak,af){var aj=false;for(var ag=0;ag<ah.length;ag++){if(ah[ag].has_icons){aj=true;break}}if(aj){for(var ag=0;ag<ah.length;ag++){tile=ah[ag];if(!tile.has_icons){tile.html_elt.css("padding-top",E)}}}},draw_helper:function(af,ar,ax,av,ak,al,at){var aq=this,aA=this._gen_tile_cache_key(ar,al,ax),ai=this._get_tile_bounds(ax,av);if(!at){at={}}var az=(af?undefined:aq.tile_cache.get_elt(aA));if(az){aq.show_tile(az,ak,al);return az}var ao=true;var aw=aq.data_manager.get_data(ai,aq.mode,av,aq.data_url_extra_params);if(Y(aw)){ao=false}var am;if(view.reference_track&&al>view.canvas_manager.char_width_px){am=view.reference_track.data_manager.get_data(ai,aq.mode,av,view.reference_track.data_url_extra_params);if(Y(am)){ao=false}}if(ao){r(aw,at.more_tile_data);var an=aq.mode;if(an==="Auto"){an=aq.get_mode(aw);aq.update_auto_mode(an)}var ah=aq.view.canvas_manager.new_canvas(),ay=ai.get("start"),ag=ai.get("end"),ar=Math.ceil((ag-ay)*al)+aq.left_offset,ap=aq.get_canvas_height(aw,an,al,ar);ah.width=ar;ah.height=ap;var au=ah.getContext("2d");au.translate(this.left_offset,0);var az=aq.draw_tile(aw,au,an,av,ai,al,am);if(az!==undefined){aq.tile_cache.set_elt(aA,az);aq.show_tile(az,ak,al)}return az}var aj=$.Deferred();$.when(aw,am).then(function(){view.request_redraw(false,false,false,aq);aj.resolve()});return aj},get_canvas_height:function(af,ah,ai,ag){return this.visible_height_px},draw_tile:function(af,ag,ak,ai,aj,al,ah){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ah,aj,ak){var ag=this,af=ah.html_elt;ah.predisplay_actions();var ai=(ah.low-(this.is_overview?this.view.max_low:this.view.low))*ak;if(this.left_offset){ai-=this.left_offset}af.css({position:"absolute",top:0,left:ai});if(af.hasClass("remove")){af.removeClass("remove")}else{aj.append(af)}ag.after_show_tile(ah)},after_show_tile:function(af){this.max_height_px=Math.max(this.max_height_px,af.html_elt.height());af.html_elt.parent().children().css("height",this.max_height_px+"px");var ag=this.max_height_px;if(this.visible_height_px!==0){ag=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",ag+"px")},_get_tile_bounds:function(af,ag){var ai=Math.floor(af*U*ag),aj=Math.ceil(U*ag),ah=(ai+aj<=this.view.max_high?ai+aj:this.view.max_high);return new GenomeRegion({chrom:this.view.chrom,start:ai,end:ah})},tool_region_and_parameters_str:function(ah,af,ai){var ag=this,aj=(ah!==undefined&&af!==undefined&&ai!==undefined?ah+":"+af+"-"+ai:"all");return" - region=["+aj+"], parameters=["+ag.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(af,ag){return true},can_subset:function(af){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(ah,ai,ak,af){var ag=this;ag.normal_postdraw_actions(ah,ai,ak,af);ag.dataset_check_type="converted_datasets_state";ag.data_query_wait=L;var aj=new ServerStateDeferred({url:ag.dataset_state_url,url_params:{dataset_id:ag.dataset_id,hda_ldda:ag.hda_ldda},interval:ag.data_query_wait,success_fn:function(al){return al!=="pending"}});$.when(aj.go()).then(function(){ag.data_manager.set("data_type","data")});ag.postdraw_actions=ag.normal_postdraw_actions}}});var ab=function(ag,af){var ah={resize:false};i.call(this,ag,af,ah);this.container_div.addClass("label-track")};r(ab.prototype,i.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ah=this.view,ai=ah.high-ah.low,al=Math.floor(Math.pow(10,Math.floor(Math.log(ai)/Math.log(10)))),af=Math.floor(ah.low/al)*al,aj=this.view.container.width(),ag=$("<div style='position: relative; height: 1.3em;'></div>");while(af<ah.high){var ak=(af-ah.low)/ai*aj;ag.append($("<div class='label'>"+commatize(af)+"</div>").css({position:"absolute",left:ak-1}));af+=al}this.content_div.children(":first").remove();this.content_div.append(ag)}});var h=function(ag,af,aj){N.call(this,ag,af,aj);this.drawables=[];this.left_offset=0;if("drawables" in aj){var ai;for(var ah=0;ah<aj.drawables.length;ah++){ai=aj.drawables[ah];this.drawables[ah]=q(ai,ag,null);if(ai.left_offset>this.left_offset){this.left_offset=ai.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"};r(h.prototype,N.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(af){$(".bs-tooltip").remove();af.show_group()}}].concat(N.prototype.action_icons_def),to_dict:A.prototype.to_dict,add_drawable:A.prototype.add_drawable,unpack_drawables:A.prototype.unpack_drawables,change_mode:function(af){N.prototype.change_mode.call(this,af);for(var ag=0;ag<this.drawables.length;ag++){this.drawables[ag].change_mode(af)}},init:function(){var ah=[];for(var ag=0;ag<this.drawables.length;ag++){ah.push(this.drawables[ag].init())}var af=this;$.when.apply($,ah).then(function(){af.enabled=true;af.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:s.prototype.can_draw,draw_helper:function(ag,aw,aC,az,an,ap,ax){var av=this,aG=this._gen_tile_cache_key(aw,ap,aC),ak=this._get_tile_bounds(aC,az);if(!ax){ax={}}var aF=(ag?undefined:av.tile_cache.get_elt(aG));if(aF){av.show_tile(aF,an,ap);return aF}var ao=[],av,at=true,aA,aq;for(var aB=0;aB<this.drawables.length;aB++){av=this.drawables[aB];aA=av.data_manager.get_data(ak,av.mode,az,av.data_url_extra_params);if(Y(aA)){at=false}ao.push(aA);aq=null;if(view.reference_track&&ap>view.canvas_manager.char_width_px){aq=view.reference_track.data_manager.get_data(ak,av.mode,az,view.reference_track.data_url_extra_params);if(Y(aq)){at=false}}ao.push(aq)}if(at){r(aA,ax.more_tile_data);this.tile_predraw_init();var aj=av.view.canvas_manager.new_canvas(),al=av._get_tile_bounds(aC,az),aD=ak.get("start"),ah=ak.get("end"),aE=0,aw=Math.ceil((ah-aD)*ap)+this.left_offset,au=0,ai=[],aB;var af=0;for(aB=0;aB<this.drawables.length;aB++,aE+=2){av=this.drawables[aB];aA=ao[aE];var ar=av.mode;if(ar==="Auto"){ar=av.get_mode(aA);av.update_auto_mode(ar)}ai.push(ar);af=av.get_canvas_height(aA,ar,ap,aw);if(af>au){au=af}}aj.width=aw;aj.height=(ax.height?ax.height:au);aE=0;var ay=aj.getContext("2d");ay.translate(this.left_offset,0);ay.globalAlpha=0.5;ay.globalCompositeOperation="source-over";for(aB=0;aB<this.drawables.length;aB++,aE+=2){av=this.drawables[aB];aA=ao[aE];aq=ao[aE+1];aF=av.draw_tile(aA,ay,ai[aB],az,ak,ap,aq)}this.tile_cache.set_elt(aG,aF);this.show_tile(aF,an,ap);return aF}var am=$.Deferred(),av=this;$.when.apply($,ao).then(function(){view.request_redraw(false,false,false,av);am.resolve()});return am},show_group:function(){var ai=new Q(this.view,this.container,{name:this.name}),af;for(var ah=0;ah<this.drawables.length;ah++){af=this.drawables[ah];af.update_icons();ai.add_drawable(af);af.container=ai;ai.content_div.append(af.container_div)}var ag=this.container.replace_drawable(this,ai,true);ai.request_draw()},tile_predraw_init:function(){var ai=Number.MAX_VALUE,af=-ai,ag;for(var ah=0;ah<this.drawables.length;ah++){ag=this.drawables[ah];if(ag instanceof j){if(ag.prefs.min_value<ai){ai=ag.prefs.min_value}if(ag.prefs.max_value>af){af=ag.prefs.max_value}}}for(var ah=0;ah<this.drawables.length;ah++){ag=this.drawables[ah];ag.prefs.min_value=ai;ag.prefs.max_value=af}},postdraw_actions:function(ah,ak,am,ag){N.prototype.postdraw_actions.call(this,ah,ak,am,ag);var aj=-1;for(var ai=0;ai<ah.length;ai++){var af=ah[ai].html_elt.find("canvas").height();if(af>aj){aj=af}}for(var ai=0;ai<ah.length;ai++){var al=ah[ai];if(al.html_elt.find("canvas").height()!==aj){this.draw_helper(true,ak,al.index,al.resolution,al.html_elt.parent(),am,{height:aj});al.html_elt.remove()}}}});var C=function(af){N.call(this,af,{content_div:af.top_labeltrack},{resize:false});af.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 ReferenceTrackDataManager({data_url:this.data_url});this.hide_contents()};r(C.prototype,s.prototype,N.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:s.prototype.can_draw,draw_helper:function(aj,ah,af,ag,ak,al,ai){if(al>this.view.canvas_manager.char_width_px){return N.prototype.draw_helper.call(this,aj,ah,af,ag,ak,al,ai)}else{this.hide_contents();return null}},draw_tile:function(an,ao,aj,ai,al,ap){var ah=this;if(ap>this.view.canvas_manager.char_width_px){if(an.data===null){this.hide_contents();return}var ag=ao.canvas;ao.font=ao.canvas.manager.default_font;ao.textAlign="center";an=an.data;for(var ak=0,am=an.length;ak<am;ak++){var af=Math.floor(ak*ap);ao.fillText(an[ak],af,10)}this.show_contents();return new b(ah,al,ai,ag,an)}this.hide_contents()}});var j=function(ah,ag,ai){var af=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";N.call(this,ah,ag,ai);this.hda_ldda=ai.hda_ldda;this.dataset_id=ai.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:R()},{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:ai.prefs,onchange:function(){af.set_name(af.prefs.name);af.vertical_range=af.prefs.max_value-af.prefs.min_value;af.set_min_value(af.prefs.min_value);af.set_max_value(af.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};r(j.prototype,s.prototype,N.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(af){this.prefs.min_value=af;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(af){this.prefs.max_value=af;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var af=this;af.vertical_range=undefined;return $.getJSON(af.dataset.url(),{data_type:"data",stats:true,chrom:af.view.chrom,low:0,high:af.view.max_high,hda_ldda:af.hda_ldda,dataset_id:af.dataset_id},function(ag){af.container_div.addClass("line-track");var aj=ag.data;if(isNaN(parseFloat(af.prefs.min_value))||isNaN(parseFloat(af.prefs.max_value))){var ah=aj.min,al=aj.max;ah=Math.floor(Math.min(0,Math.max(ah,aj.mean-2*aj.sd)));al=Math.ceil(Math.max(0,Math.min(al,aj.mean+2*aj.sd)));af.prefs.min_value=ah;af.prefs.max_value=al;$("#track_"+af.dataset_id+"_minval").val(af.prefs.min_value);$("#track_"+af.dataset_id+"_maxval").val(af.prefs.max_value)}af.vertical_range=af.prefs.max_value-af.prefs.min_value;af.total_frequency=aj.total_frequency;af.container_div.find(".yaxislabel").remove();var ak=$("<div/>").text(Z(af.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(am){$(".bs-tooltip").remove();var am=parseFloat(am);if(!isNaN(am)){af.set_min_value(am)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+af.dataset_id+"_minval").prependTo(af.container_div),ai=$("<div/>").text(Z(af.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(am){$(".bs-tooltip").remove();var am=parseFloat(am);if(!isNaN(am)){af.set_max_value(am)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+af.dataset_id+"_maxval").prependTo(af.container_div)})},draw_tile:function(ao,am,ah,ag,aj,an){var af=am.canvas,ai=aj.get("start"),al=aj.get("end"),ak=new M.LinePainter(ao.data,ai,al,this.prefs,ah);ak.draw(am,af.width,af.height,an);return new b(this,aj,ag,af,ao.data)},can_subset:function(af){return false}});var u=function(ah,ag,ai){var af=this;this.display_modes=["Heatmap"];this.mode="Heatmap";N.call(this,ah,ag,ai);this.hda_ldda=ai.hda_ldda;this.dataset_id=ai.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new G({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:ai.prefs,onchange:function(){af.set_name(af.prefs.name);af.vertical_range=af.prefs.max_value-af.prefs.min_value;af.set_min_value(af.prefs.min_value);af.set_max_value(af.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};r(u.prototype,s.prototype,N.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(af){this.prefs.min_value=af;this.tile_cache.clear();this.request_draw()},set_max_value:function(af){this.prefs.max_value=af;this.tile_cache.clear();this.request_draw()},draw_tile:function(ap,an,ak,ai,ag,ao){var ah=an.canvas,af=this._get_tile_bounds(ag,ai),aj=af[0],am=af[1],al=new M.DiagonalHeatmapPainter(ap.data,aj,am,this.prefs,ak);al.draw(an,ah.width,ah.height,ao);return new b(this,ag,ai,ah,ap.data)}});var d=function(ai,ah,ak){var ag=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ai,ah,ak);var aj=R(),af=R([aj,"#ffffff"]);this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:aj},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:af},{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:ak.prefs,onchange:function(){ag.set_name(ag.prefs.name);ag.tile_cache.clear();ag.set_painter_from_config();ag.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ak.hda_ldda;this.dataset_id=ak.dataset_id;this.original_dataset_id=ak.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()};r(d.prototype,s.prototype,N.prototype,{set_dataset:function(af){this.dataset_id=af.get("id");this.hda_ldda=af.get("hda_ldda");this.dataset=af;this.data_manager.set("dataset",af)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=M.ArcLinkedFeaturePainter}else{this.painter=M.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(av,ap,ak,aj){N.prototype.postdraw_actions.call(this,av,aj);var ao=this,ar;if(ao.mode==="Coverage"){var ag=-1;for(ar=0;ar<av.length;ar++){var aq=av[ar].max_val;if(aq>ag){ag=aq}}for(ar=0;ar<av.length;ar++){var ax=av[ar];if(ax.max_val!==ag){ax.html_elt.remove();ao.draw_helper(true,ap,ax.index,ax.resolution,ax.html_elt.parent(),ak,{more_tile_data:{max:ag}})}}}if(ao.filters_manager){var al=ao.filters_manager.filters;for(var au=0;au<al.length;au++){al[au].update_ui_elt()}var aw=false,af,am;for(ar=0;ar<av.length;ar++){if(av[ar].data.length){af=av[ar].data[0];for(var au=0;au<al.length;au++){am=al[au];if(am.applies_to(af)&&am.min!==am.max){aw=true;break}}}}if(ao.filters_available!==aw){ao.filters_available=aw;if(!ao.filters_available){ao.filters_manager.hide()}ao.update_icons()}}this.container_div.find(".yaxislabel").remove();var ai=av[0];if(ai instanceof k){var an=(this.prefs.histogram_max?this.prefs.histogram_max:ai.max_val),ah=$("<div/>").text(an).make_text_editable({num_cols:12,on_finish:function(ay){$(".bs-tooltip").remove();var ay=parseFloat(ay);ao.prefs.histogram_max=(!isNaN(ay)?ay:null);ao.tile_cache.clear();ao.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(ah)}if(ai instanceof P){var at=true;for(ar=0;ar<av.length;ar++){if(!av[ar].all_slotted){at=false;break}}if(!at){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(af){var af;if(this.mode==="Auto"){if(af==="no_detail"){af="feature spans"}else{if(af==="summary_tree"){af="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+af+")")}},incremental_slots:function(aj,af,ai){var ag=this.view.canvas_manager.dummy_context,ah=this.slotters[aj];if(!ah||(ah.mode!==ai)){ah=new (v.FeatureSlotter)(aj,ai,B,function(ak){return ag.measureText(ak)});this.slotters[aj]=ah}return ah.slot_features(af)},get_mode:function(af){if(af.dataset_type==="summary_tree"){mode="summary_tree"}else{if(af.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>J){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(af,aj,ak,ag){if(aj==="summary_tree"||aj==="Coverage"){return this.summary_draw_height}else{var ai=this.incremental_slots(ak,af.data,aj);var ah=new (this.painter)(null,null,null,this.prefs,aj);return Math.max(ad,ah.get_required_height(ai,ag))}},draw_tile:function(ap,au,ar,av,ai,am,ah){var at=this,ag=au.canvas,aB=ai.get("start"),af=ai.get("end"),aj=this.left_offset;if(ar==="summary_tree"||ar==="Coverage"){var aD=new M.SummaryTreePainter(ap,aB,af,this.prefs);aD.draw(au,ag.width,ag.height,am);return new k(at,ai,av,ag,ap.data,ap.max)}var al=[],aq=this.slotters[am].slots;all_slotted=true;if(ap.data){var an=this.filters_manager.filters;for(var aw=0,ay=ap.data.length;aw<ay;aw++){var ak=ap.data[aw];var ax=false;var ao;for(var aA=0,aF=an.length;aA<aF;aA++){ao=an[aA];ao.update_attrs(ak);if(!ao.keep(ak)){ax=true;break}}if(!ax){al.push(ak);if(!(ak[0] in aq)){all_slotted=false}}}}var aE=(this.filters_manager.alpha_filter?new D(this.filters_manager.alpha_filter):null);var aC=(this.filters_manager.height_filter?new D(this.filters_manager.height_filter):null);var aD=new (this.painter)(al,aB,af,this.prefs,ar,aE,aC,ah);var az=null;au.fillStyle=this.prefs.block_color;au.font=au.canvas.manager.default_font;au.textAlign="right";if(ap.data){az=aD.draw(au,ag.width,ag.height,am,aq);az.translation=-aj}return new P(at,ai,av,ag,ap.data,am,ar,ap.message,all_slotted,az)},data_and_mode_compatible:function(af,ag){if(ag==="Auto"){return true}else{if(ag==="Coverage"){return af.dataset_type==="summary_tree"}else{if(af.extra_info==="no_detail"||af.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(af){if(af.dataset_type==="summary_tree"||af.message||af.extra_info==="no_detail"){return false}return true}});var T=function(ag,af,ah){d.call(this,ag,af,ah);this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:R()},{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:ah.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=M.ReadPainter};r(T.prototype,s.prototype,N.prototype,d.prototype);var W=function(ah,ag,aj){d.call(this,ah,ag,aj);var ai=R(),af=R([ai,"#ffffff"]);this.config=new G({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:ai},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:af},{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:aj.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=M.ReadPainter;this.update_icons()};r(W.prototype,s.prototype,N.prototype,d.prototype);var e={LineTrack:j,FeatureTrack:d,VcfTrack:T,ReadTrack:W,CompositeTrack:h,DrawableGroup:Q};var q=function(ah,ag,af){if("copy" in ah){return ah.copy(af)}else{var ai=ah.obj_type;if(!ai){ai=ah.track_type}return new e[ai](ag,af,ah)}};return{View:ac,DrawableGroup:Q,LineTrack:j,FeatureTrack:d,DiagonalHeatmapTrack:u,ReadTrack:W,VcfTrack:T,CompositeTrack:h,object_from_template:q}}); \ 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","viz/trackster_ui"],function(ad,y,l,v,M,ab,i,q){var r=ad.extend;var R=l.get_random_color;var ae=function(af,ah,ag){$.ajax({url:af,data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(ai){show_modal("Select datasets for new tracks",ai,{Cancel:function(){hide_modal()},Add:function(){var aj=[];$("input[name=id]:checked,input[name=ldda_ids]:checked").each(function(){var ak={data_type:"track_config",hda_ldda:"hda"},al=$(this).val();if($(this).attr("name")!=="id"){ak.hda_ldda="ldda"}aj[aj.length]=$.ajax({url:ah+"/"+al,data:ak,dataType:"json"})});$.when.apply($,aj).then(function(){var ak=(arguments[0] instanceof Array?$.map(arguments,function(al){return al[0]}):[arguments[0]]);ag(ak)});hide_modal()}})}})};var X=function(af){return("isResolved" in af)};var n={};var k=function(af,ag){n[af.attr("id")]=ag};var m=function(af,ah,aj,ai){aj=".group";var ag={};n[af.attr("id")]=ai;af.bind("drag",{handle:"."+ah,relative:true},function(ar,at){var aq=$(this),aw=$(this).parent(),an=aw.children(),ap=n[$(this).attr("id")],am,al,au,ak,ao;al=$(this).parents(aj);if(al.length!==0){au=al.position().top;ak=au+al.outerHeight();if(at.offsetY<au){$(this).insertBefore(al);var av=n[al.attr("id")];av.remove_drawable(ap);av.container.add_drawable_before(ap,av);return}else{if(at.offsetY>ak){$(this).insertAfter(al);var av=n[al.attr("id")];av.remove_drawable(ap);av.container.add_drawable(ap);return}}}al=null;for(ao=0;ao<an.length;ao++){am=$(an.get(ao));au=am.position().top;ak=au+am.outerHeight();if(am.is(aj)&&this!==am.get(0)&&at.offsetY>=au&&at.offsetY<=ak){if(at.offsetY-au<ak-at.offsetY){am.find(".content-div").prepend(this)}else{am.find(".content-div").append(this)}if(ap.container){ap.container.remove_drawable(ap)}n[am.attr("id")].add_drawable(ap);return}}for(ao=0;ao<an.length;ao++){am=$(an.get(ao));if(at.offsetY<am.position().top&&!(am.hasClass("reference-track")||am.hasClass("intro"))){break}}if(ao===an.length){if(this!==an.get(ao-1)){aw.append(this);n[aw.attr("id")].move_drawable(ap,ao)}}else{if(this!==an.get(ao)){$(this).insertBefore(an.get(ao));n[aw.attr("id")].move_drawable(ap,(at.deltaY>0?ao-1:ao))}}}).bind("dragstart",function(){ag["border-top"]=af.css("border-top");ag["border-bottom"]=af.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ag)})};exports.moveable=m;var ac=16,H=9,E=20,B=100,J=12000,U=400,L=5000,x=100,o="There was an error in indexing this dataset. ",K="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",F="No data for this chrom/contig.",w="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",z="Tool cannot be rerun: ",a="Loading data...",W="Ready for display",S=10,I=20;function Y(ag,af){if(!af){af=0}var ah=Math.pow(10,af);return Math.round(ag*ah)/ah}var s=function(ag,af,ai){if(!s.id_counter){s.id_counter=0}this.id=s.id_counter++;this.name=ai.name;this.view=ag;this.container=af;this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ai.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ai.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(aj){aj.stopPropagation()});var ah=this;this.container_div.hover(function(){ah.icons_div.show()},function(){ah.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};s.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(af){if(af.content_visible){af.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");af.hide_contents();af.content_visible=false}else{af.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");af.content_visible=true;af.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ag){var ai=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},af=function(){ag.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ah=function(aj){if((aj.keyCode||aj.which)===27){ai()}else{if((aj.keyCode||aj.which)===13){af()}}};$(window).bind("keypress.check_enter_esc",ah);show_modal("Configure",ag.config.build_form(),{Cancel:ai,OK:af})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(af){$(".bs-tooltip").remove();af.remove()}}];r(s.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(af){this.old_name=this.name;this.name=af;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 af=this.view;this.container_div.hide(0,function(){$(this).remove();af.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ag,al,ak,aj,af,ai){var ah=this;this.action_icons[ag]=$("<a/>").attr("href","javascript:void(0);").attr("title",al).addClass("icon-button").addClass(ak).tooltip().click(function(){aj(ah)}).appendTo(this.icons_div);if(ai){this.action_icons[ag].hide()}},build_action_icons:function(af){var ah;for(var ag=0;ag<af.length;ag++){ah=af[ag];this.add_action_icon(ah.name,ah.title,ah.css_class,ah.on_click_fn,ah.prepend,ah.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var A=function(ag,af,ah){s.call(this,ag,af,ah);this.obj_type=ah.obj_type;this.drawables=[]};r(A.prototype,s.prototype,{unpack_drawables:function(ah){this.drawables=[];var ag;for(var af=0;af<ah.length;af++){ag=p(ah[af],this.view,this);this.add_drawable(ag)}},init:function(){for(var af=0;af<this.drawables.length;af++){this.drawables[af].init()}},_draw:function(){for(var af=0;af<this.drawables.length;af++){this.drawables[af]._draw()}},to_dict:function(){var ag=[];for(var af=0;af<this.drawables.length;af++){ag.push(this.drawables[af].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ag}},add_drawable:function(af){this.drawables.push(af);af.container=this;this.changed()},add_drawable_before:function(ah,af){this.changed();var ag=this.drawables.indexOf(af);if(ag!==-1){this.drawables.splice(ag,0,ah);return true}return false},replace_drawable:function(ah,af,ag){var ai=this.drawables.indexOf(ah);if(ai!==-1){this.drawables[ai]=af;if(ag){ah.container_div.replaceWith(af.container_div)}this.changed()}return ai},remove_drawable:function(ag){var af=this.drawables.indexOf(ag);if(af!==-1){this.drawables.splice(af,1);ag.container=null;this.changed();return true}return false},move_drawable:function(ag,ah){var af=this.drawables.indexOf(ag);if(af!==-1){this.drawables.splice(af,1);this.drawables.splice(ah,0,ag);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var Q=function(ag,af,ai){r(ai,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});A.call(this,ag,af,ai);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 ai){this.unpack_drawables(ai.drawables)}if("filters" in ai){var ah=this.filters_manager;this.filters_manager=new i.FiltersManager(this,ai.filters);ah.parent_div.replaceWith(this.filters_manager.parent_div);if(ai.filters.visible){this.setup_multitrack_filtering()}}};r(Q.prototype,s.prototype,A.prototype,{action_icons_def:[s.prototype.action_icons_def[0],s.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(af){$(".bs-tooltip").remove();af.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(af){if(af.filters_manager.visible()){af.filters_manager.clear_filters();af._restore_filter_managers()}else{af.setup_multitrack_filtering();af.request_draw(true)}af.filters_manager.toggle()}},s.prototype.action_icons_def[2]],build_container_div:function(){var af=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(af)}return af},build_header_div:function(){var af=$("<div/>").addClass("track-header");af.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(af);return af},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ah=this.drawables.length;if(ah===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ah===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var ao,an,al,ar=true,aj=this.drawables[0].get_type(),af=0;for(ao=0;ao<ah;ao++){al=this.drawables[ao];if(al.get_type()!==aj){can_composite=false;break}if(al instanceof c){af++}}if(ar||af===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(af>1&&af===this.drawables.length){var at={},ag;al=this.drawables[0];for(an=0;an<al.filters_manager.filters.length;an++){ag=al.filters_manager.filters[an];at[ag.name]=[ag]}for(ao=1;ao<this.drawables.length;ao++){al=this.drawables[ao];for(an=0;an<al.filters_manager.filters.length;an++){ag=al.filters_manager.filters[an];if(ag.name in at){at[ag.name].push(ag)}}}this.filters_manager.remove_all();var ai,ak,am,ap;for(var aq in at){ai=at[aq];if(ai.length===af){ak=new i.NumberFilter({name:ai[0].name,index:ai[0].index});this.filters_manager.add_filter(ak)}}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 af=0;af<this.drawables.length;af++){this.drawables[af].filters_manager=this.saved_filters_managers[af]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var af=0;af<this.drawables.length;af++){drawable=this.drawables[af];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var aj=[];for(var ag=0;ag<this.drawables.length;ag++){aj.push(this.drawables[ag].name)}var ah="Composite Track of "+this.drawables.length+" tracks ("+aj.join(", ")+")";var ai=new f(this.view,this.view,{name:ah,drawables:this.drawables});var af=this.container.replace_drawable(this,ai,true);ai.request_draw()},add_drawable:function(af){A.prototype.add_drawable.call(this,af);this.update_icons()},remove_drawable:function(af){A.prototype.remove_drawable.call(this,af);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var af=r(A.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return af},request_draw:function(af,ah){for(var ag=0;ag<this.drawables.length;ag++){this.drawables[ag].request_draw(af,ah)}}});var aa=function(af){r(af,{obj_type:"View"});A.call(this,"View",af.container,af);this.chrom=null;this.vis_id=af.vis_id;this.dbkey=af.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 y.CanvasManager(this.container.get(0).ownerDocument);this.reset()};ad.extend(aa.prototype,Backbone.Events);r(aa.prototype,A.prototype,{init:function(){this.requested_redraw=false;var ah=this.container,af=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ah);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ah);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ah);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,af);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ai=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){ae(add_datasets_url,add_track_async_url,function(aj){ad.each(aj,function(ak){af.add_drawable(p(ak,af,af))})})});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 ag=function(aj){if(aj.type==="focusout"||(aj.keyCode||aj.which)===13||(aj.keyCode||aj.which)===27){if((aj.keyCode||aj.which)!==27){af.go_to($(this).val())}$(this).hide();$(this).val("");af.location_span.show();af.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ag).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(){af.location_span.hide();af.chrom_select.hide();af.nav_input.val(af.chrom+":"+af.low+"-"+af.high);af.nav_input.css("display","inline-block");af.nav_input.select();af.nav_input.focus();af.nav_input.autocomplete({source:function(al,aj){var am=[],ak=$.map(af.get_drawables(),function(an){return an.data_manager.search_features(al.term).success(function(ao){am=am.concat(ao)})});$.when.apply($,ak).done(function(){aj($.map(am,function(an){return{label:an[0],value:an[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(){af.zoom_out();af.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){af.zoom_in();af.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){af.change_chrom(af.chrom_select.val())});this.browser_content_div.click(function(aj){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(aj){af.zoom_in(aj.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(aj,ak){this.current_x=ak.offsetX}).bind("drag",function(aj,al){var am=al.offsetX-this.current_x;this.current_x=al.offsetX;var ak=Math.round(am/af.viewport_container.width()*(af.max_high-af.max_low));af.move_delta(-ak)});this.overview_close.click(function(){af.reset_overview()});this.viewport_container.bind("draginit",function(aj,ak){if(aj.clientX>af.viewport_container.width()-16){return false}}).bind("dragstart",function(aj,ak){ak.original_low=af.low;ak.current_height=aj.clientY;ak.current_x=ak.offsetX}).bind("drag",function(al,an){var aj=$(this);var ao=an.offsetX-an.current_x;var ak=aj.scrollTop()-(al.clientY-an.current_height);aj.scrollTop(ak);an.current_height=al.clientY;an.current_x=an.offsetX;var am=Math.round(ao/af.viewport_container.width()*(af.high-af.low));af.move_delta(am)}).bind("mousewheel",function(al,an,ak,aj){if(ak){ak*=50;var am=Math.round(-ak/af.viewport_container.width()*(af.high-af.low));af.move_delta(am)}});this.top_labeltrack.bind("dragstart",function(aj,ak){return $("<div />").css({height:af.browser_content_div.height()+af.top_labeltrack.height()+af.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(an,ao){$(ao.proxy).css({left:Math.min(an.pageX,ao.startX)-af.container.offset().left,width:Math.abs(an.pageX-ao.startX)});var ak=Math.min(an.pageX,ao.startX)-af.container.offset().left,aj=Math.max(an.pageX,ao.startX)-af.container.offset().left,am=(af.high-af.low),al=af.viewport_container.width();af.update_location(Math.round(ak/al*am)+af.low,Math.round(aj/al*am)+af.low)}).bind("dragend",function(ao,ap){var ak=Math.min(ao.pageX,ap.startX),aj=Math.max(ao.pageX,ap.startX),am=(af.high-af.low),al=af.viewport_container.width(),an=af.low;af.low=Math.round(ak/al*am)+an;af.high=Math.round(aj/al*am)+an;$(ap.proxy).remove();af.request_redraw()});this.add_label_track(new Z(this,{content_div:this.top_labeltrack}));this.add_label_track(new Z(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){af.resize_window()},500)});$(document).bind("redraw",function(){af.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(ag,ai,af,aj){if(this.timer){clearTimeout(this.timer)}if(aj){var ah=this;this.timer=setTimeout(function(){ah.trigger("navigate",ag+":"+ai+"-"+af)},500)}else{view.trigger("navigate",ag+":"+ai+"-"+af)}},update_location:function(af,ah){this.location_span.text(commatize(af)+" - "+commatize(ah));this.nav_input.val(this.chrom+":"+commatize(af)+"-"+commatize(ah));var ag=view.chrom_select.val();if(ag!==""){this.trigger_navigate(ag,view.low,view.high,true)}},load_chroms:function(ah){ah.num=x;var af=this,ag=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ah,dataType:"json",success:function(aj){if(aj.chrom_info.length===0){return}if(aj.reference){af.add_label_track(new C(af))}af.chrom_data=aj.chrom_info;var am='<option value="">Select Chrom/Contig</option>';for(var al=0,ai=af.chrom_data.length;al<ai;al++){var ak=af.chrom_data[al].chrom;am+='<option value="'+ak+'">'+ak+"</option>"}if(aj.prev_chroms){am+='<option value="previous">Previous '+x+"</option>"}if(aj.next_chroms){am+='<option value="next">Next '+x+"</option>"}af.chrom_select.html(am);af.chrom_start_index=aj.start_index;ag.resolve(aj)},error:function(){alert("Could not load chroms for this dbkey:",af.dbkey)}});return ag},change_chrom:function(ak,ag,am){var ah=this;if(!ah.chrom_data){ah.load_chroms_deferred.then(function(){ah.change_chrom(ak,ag,am)});return}if(!ak||ak==="None"){return}if(ak==="previous"){ah.load_chroms({low:this.chrom_start_index-x});return}if(ak==="next"){ah.load_chroms({low:this.chrom_start_index+x});return}var al=$.grep(ah.chrom_data,function(an,ao){return an.chrom===ak})[0];if(al===undefined){ah.load_chroms({chrom:ak},function(){ah.change_chrom(ak,ag,am)});return}else{if(ak!==ah.chrom){ah.chrom=ak;ah.chrom_select.val(ah.chrom);ah.max_high=al.len-1;ah.reset();ah.request_redraw(true);for(var aj=0,af=ah.drawables.length;aj<af;aj++){var ai=ah.drawables[aj];if(ai.init){ai.init()}}if(ah.reference_track){ah.reference_track.init()}}if(ag!==undefined&&am!==undefined){ah.low=Math.max(ag,0);ah.high=Math.min(am,ah.max_high)}else{ah.low=0;ah.high=ah.max_high}ah.reset_overview();ah.request_redraw()}},go_to:function(aj){aj=aj.replace(/ |,/g,"");var an=this,af,ai,ag=aj.split(":"),al=ag[0],am=ag[1];if(am!==undefined){try{var ak=am.split("-");af=parseInt(ak[0],10);ai=parseInt(ak[1],10)}catch(ah){return false}}an.change_chrom(al,af,ai)},move_fraction:function(ah){var af=this;var ag=af.high-af.low;this.move_delta(ah*ag)},move_delta:function(ai){var af=this;var ah=af.high-af.low;if(af.low-ai<af.max_low){af.low=af.max_low;af.high=af.max_low+ah}else{if(af.high-ai>af.max_high){af.high=af.max_high;af.low=af.max_high-ah}else{af.high-=ai;af.low-=ai}}af.request_redraw();var ag=af.chrom_select.val();this.trigger_navigate(ag,af.low,af.high,true)},add_drawable:function(af){A.prototype.add_drawable.call(this,af);af.init();this.changed();this.update_intro_div()},add_label_track:function(af){af.view=this;af.init();this.label_tracks.push(af)},remove_drawable:function(ah,ag){A.prototype.remove_drawable.call(this,ah);if(ag){var af=this;ah.container_div.hide(0,function(){$(this).remove();af.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(an,af,am,ao){var al=this,ak=(ao?[ao]:al.drawables),ah;var ag;for(var aj=0;aj<ak.length;aj++){ag=ak[aj];ah=-1;for(var ai=0;ai<al.tracks_to_be_redrawn.length;ai++){if(al.tracks_to_be_redrawn[ai][0]===ag){ah=ai;break}}if(ah<0){al.tracks_to_be_redrawn.push([ag,af,am])}else{al.tracks_to_be_redrawn[aj][1]=af;al.tracks_to_be_redrawn[aj][2]=am}}if(!this.requested_redraw){requestAnimationFrame(function(){al._redraw(an)});this.requested_redraw=true}},_redraw:function(ap){this.requested_redraw=false;var am=this.low,ai=this.high;if(am<this.max_low){am=this.max_low}if(ai>this.max_high){ai=this.max_high}var ao=this.high-this.low;if(this.high!==0&&ao<this.min_separation){ai=am+this.min_separation}this.low=Math.floor(am);this.high=Math.ceil(ai);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 af=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var al=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var aq=13;this.overview_box.css({left:af,width:Math.max(aq,al)}).show();if(al<aq){this.overview_box.css("left",af-(aq-al)/2)}if(this.overview_highlight){this.overview_highlight.css({left:af,width:al})}if(!ap){var ah,ag,an;for(var aj=0,ak=this.tracks_to_be_redrawn.length;aj<ak;aj++){ah=this.tracks_to_be_redrawn[aj][0];ag=this.tracks_to_be_redrawn[aj][1];an=this.tracks_to_be_redrawn[aj][2];if(ah){ah._draw(ag,an)}}this.tracks_to_be_redrawn=[];for(aj=0,ak=this.label_tracks.length;aj<ak;aj++){this.label_tracks[aj]._draw()}}},zoom_in:function(ag,ah){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ai=this.high-this.low,aj=ai/2+this.low,af=(ai/this.zoom_factor)/2;if(ag){aj=ag/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(aj-af);this.high=Math.round(aj+af);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ag=this.high-this.low,ah=ag/2+this.low,af=(ag*this.zoom_factor)/2;this.low=Math.round(ah-af);this.high=Math.round(ah+af);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(ah){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ah.dataset_id){return}this.overview_viewport.find(".track").remove()}var ag=ah.copy({content_div:this.overview_viewport}),af=this;ag.header_div.hide();ag.is_overview=true;af.overview_drawable=ag;this.overview_drawable.postdraw_actions=function(){af.overview_highlight.show().height(af.overview_drawable.content_div.height());af.overview_viewport.height(af.overview_drawable.content_div.height()+af.overview_box.outerHeight());af.overview_close.show();af.resize_window()};af.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 t=function(ah,am,ai){this.track=ah;this.name=am.name;this.params=[];var au=am.params;for(var aj=0;aj<au.length;aj++){var ao=au[aj],ag=ao.name,at=ao.label,ak=unescape(ao.html),av=ao.value,aq=ao.type;if(aq==="number"){this.params.push(new e(ag,at,ak,(ag in ai?ai[ag]:av),ao.min,ao.max))}else{if(aq==="select"){this.params.push(new O(ag,at,ak,(ag in ai?ai[ag]:av)))}else{console.log("WARNING: unrecognized tool parameter type:",ag,aq)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ax){ax.stopPropagation()}).click(function(ax){ax.stopPropagation()}).bind("dblclick",function(ax){ax.stopPropagation()});var ar=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var ap=this.params;var an=this;$.each(this.params,function(ay,aB){var aA=$("<div>").addClass("param-row").appendTo(an.parent_div);var ax=$("<div>").addClass("param-label").text(aB.label).appendTo(aA);var az=$("<div/>").addClass("param-input").html(aB.html).appendTo(aA);az.find(":input").val(aB.value);$("<div style='clear: both;'/>").appendTo(aA)});this.parent_div.find("input").click(function(){$(this).select()});var aw=$("<div>").addClass("param-row").appendTo(this.parent_div);var al=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(aw);var af=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(aw);af.click(function(){an.run_on_region()});al.click(function(){an.run_on_dataset()});if("visible" in ai&&ai.visible){this.parent_div.show()}};r(t.prototype,{update_params:function(){for(var af=0;af<this.params.length;af++){this.params[af].update_value()}},state_dict:function(){var ag={};for(var af=0;af<this.params.length;af++){ag[this.params[af].name]=this.params[af].value}ag.visible=this.parent_div.is(":visible");return ag},get_param_values_dict:function(){var af={};this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();af[ag]=ah});return af},get_param_values:function(){var af=[];this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();if(ag){af[af.length]=ah}});return af},run_on_dataset:function(){var af=this;af.run({target_dataset_id:this.track.original_dataset_id,tool_id:af.name},null,function(ag){show_modal(af.name+" is Running",af.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ag={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}]},ak=this.track,ah=ag.tool_id+ak.tool_region_and_parameters_str(ag.chrom,ag.low,ag.high),af;if(ak.container===view){var aj=new Q(view,view,{name:this.name});var ai=ak.container.replace_drawable(ak,aj,false);aj.container_div.insertBefore(ak.view.content_div.children()[ai]);aj.add_drawable(ak);ak.container_div.appendTo(aj.content_div);af=aj}else{af=ak.container}var al=new ak.constructor(view,af,{name:ah,hda_ldda:"hda"});al.init_for_tool_data();al.change_mode(ak.mode);al.set_filters_manager(ak.filters_manager.copy(al));al.update_icons();af.add_drawable(al);al.tiles_div.text("Starting job.");this.update_params();this.run(ag,al,function(am){al.set_dataset(new ab.Dataset(am));al.tiles_div.text("Running job.");al.init()})},run:function(af,ah,ai){af.inputs=this.get_param_values_dict();var ag=new l.ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(af),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(aj){return aj!=="pending"}});$.when(ag.go()).then(function(aj){if(aj==="no converter"){ah.container_div.addClass("error");ah.content_div.text(K)}else{if(aj.error){ah.container_div.addClass("error");ah.content_div.text(z+aj.message)}else{ai(aj)}}})}});var O=function(ag,af,ah,ai){this.name=ag;this.label=af;this.html=$(ah);this.value=ai};r(O.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ah,ag,aj,ak,ai,af){O.call(this,ah,ag,aj,ak);this.min=ai;this.max=af};r(e.prototype,O.prototype,{update_value:function(){O.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var D=function(af,ag){M.Scaler.call(this,ag);this.filter=af};D.prototype.gen_val=function(af){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(af[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var G=function(af){this.track=af.track;this.params=af.params;this.values={};this.restore_values((af.saved_values?af.saved_values:{}));this.onchange=af.onchange};r(G.prototype,{restore_values:function(af){var ag=this;$.each(this.params,function(ah,ai){if(af[ai.key]!==undefined){ag.values[ai.key]=af[ai.key]}else{ag.values[ai.key]=ai.default_value}})},build_form:function(){var ai=this;var af=$("<div />");var ah;function ag(an,aj){for(var ar=0;ar<an.length;ar++){ah=an[ar];if(ah.hidden){continue}var al="param_"+ar;var aw=ai.values[ah.key];var ay=$("<div class='form-row' />").appendTo(aj);ay.append($("<label />").attr("for",al).text(ah.label+":"));if(ah.type==="bool"){ay.append($('<input type="checkbox" />').attr("id",al).attr("name",al).attr("checked",aw))}else{if(ah.type==="text"){ay.append($('<input type="text"/>').attr("id",al).val(aw).click(function(){$(this).select()}))}else{if(ah.type==="select"){var au=$("<select />").attr("id",al);for(var ap=0;ap<ah.options.length;ap++){$("<option/>").text(ah.options[ap].label).attr("value",ah.options[ap].value).appendTo(au)}au.val(aw);ay.append(au)}else{if(ah.type==="color"){var ax=$("<div/>").appendTo(ay),at=$("<input />").attr("id",al).attr("name",al).val(aw).css("float","left").appendTo(ax).click(function(aA){$(".bs-tooltip").removeClass("in");var az=$(this).siblings(".bs-tooltip").addClass("in");az.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(az).height()/2)+($(this).height()/2)}).show();az.click(function(aB){aB.stopPropagation()});$(document).bind("click.color-picker",function(){az.hide();$(document).unbind("click.color-picker")});aA.stopPropagation()}),aq=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(ax).attr("title","Set new random color").tooltip(),av=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(ax).hide(),am=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(av),ak=$("<div class='tooltip-arrow'></div>").appendTo(av),ao=$.farbtastic(am,{width:100,height:100,callback:at,color:aw});ax.append($("<div/>").css("clear","both"));(function(az){aq.click(function(){az.setColor(R())})})(ao)}else{ay.append($("<input />").attr("id",al).attr("name",al).val(aw))}}}}if(ah.help){ay.append($("<div class='help'/>").text(ah.help))}}}ag(this.params,af);return af},update_from_form:function(af){var ah=this;var ag=false;$.each(this.params,function(ai,ak){if(!ak.hidden){var al="param_"+ai;var aj=af.find("#"+al).val();if(ak.type==="float"){aj=parseFloat(aj)}else{if(ak.type==="int"){aj=parseInt(aj)}else{if(ak.type==="bool"){aj=af.find("#"+al).is(":checked")}}}if(aj!==ah.values[ak.key]){ah.values[ak.key]=aj;ag=true}}});if(ag){this.onchange();this.track.changed()}}});var b=function(af,aj,ah,ag,ai){this.track=af;this.region=aj;this.low=aj.get("start");this.high=aj.get("end");this.resolution=ah;this.html_elt=$("<div class='track-tile'/>").append(ag).height($(ag).attr("height"));this.data=ai;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(af,ak,ah,ag,ai,aj){b.call(this,af,ak,ah,ag,ai);this.max_val=aj};r(j.prototype,b.prototype);var P=function(ai,aq,aj,ah,al,at,am,au,ag,ap){b.call(this,ai,aq,aj,ah,al);this.mode=am;this.all_slotted=ag;this.feature_mapper=ap;this.has_icons=false;if(au){this.has_icons=true;var an=this;ah=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:E-1,width:ah.width}).prependTo(this.html_elt);var ao=new y.GenomeRegion({chrom:ai.view.chrom,start:this.low,end:this.high}),ar=al.length,ak=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ar+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),af=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ar+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ak.click(function(){an.stale=true;ai.data_manager.get_more_data(ao,ai.mode,an.resolution,{},ai.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();ai.request_draw(true)}).dblclick(function(av){av.stopPropagation()});af.click(function(){an.stale=true;ai.data_manager.get_more_data(ao,ai.mode,an.resolution,{},ai.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();ai.request_draw(true)}).dblclick(function(av){av.stopPropagation()})}};r(P.prototype,b.prototype);P.prototype.predisplay_actions=function(){var ag=this,af={};if(ag.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(ar){if(!this.hovered){return}var am=$(this).offset(),aq=ar.pageX-am.left,ap=ar.pageY-am.top,aw=ag.feature_mapper.get_feature_data(aq,ap),an=(aw?aw[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!an||$(this).attr("id")!==an.toString()){$(this).remove()}});if(aw){var ai=af[an];if(!ai){var an=aw[0],at={name:aw[3],start:aw[1],end:aw[2],strand:aw[4]},al=ag.track.filters_manager.filters,ak;for(var ao=0;ao<al.length;ao++){ak=al[ao];at[ak.name]=aw[ak.index]}var ai=$("<div/>").attr("id",an).addClass("feature-popup"),ax=$("<table/>"),av,au,ay;for(av in at){au=at[av];ay=$("<tr/>").appendTo(ax);$("<th/>").appendTo(ay).text(av);$("<td/>").attr("align","left").appendTo(ay).text(typeof(au)==="number"?Y(au,2):au)}ai.append($("<div class='feature-popup-inner'>").append(ax));af[an]=ai}ai.appendTo($(this).parents(".track-content").children(".overlay"));var aj=aq+parseInt(ag.html_elt.css("left"))-ai.width()/2,ah=ap+parseInt(ag.html_elt.css("top"))+7;ai.css("left",aj+"px").css("top",ah+"px")}else{if(!ar.isPropagationStopped()){ar.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ar)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ag,af,ah){r(ah,{drag_handle_class:"draghandle"});s.call(this,ag,af,ah);this.dataset=new ab.Dataset({id:ah.dataset_id,hda_ldda:ah.hda_ldda});this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ah?ah.data_query_wait:L);this.data_manager=("data_manager" in ah?ah.data_manager:new y.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 ah)||ah.resize){this.add_resize_handle()}}};r(g.prototype,s.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},s.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(af){af.view.set_overview(af)}},s.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(af){if(af.filters_manager.visible()){af.filters_manager.clear_filters()}else{af.filters_manager.init_filters()}af.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(af){af.dynamic_tool_div.toggle();if(af.dynamic_tool_div.is(":visible")){af.set_name(af.name+af.tool_region_and_parameters_str())}else{af.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(af){var ai='<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>',ah=ad.template(ai,{track:af});var ak=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ag=function(){var am=$('select[name="regions"] option:selected').val(),ao,al=new y.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),an=ad.map($(".bookmark"),function(ap){return new y.GenomeRegion({from_str:$(ap).children(".position").text()})});if(am==="cur"){ao=[al]}else{if(am==="bookmarks"){ao=an}else{ao=[al].concat(an)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:af.dataset_id,hda_ldda:af.hda_ldda,regions:JSON.stringify(new Backbone.Collection(ao).toJSON())})},aj=function(al){if((al.keyCode||al.which)===27){ak()}else{if((al.keyCode||al.which)===13){ag()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ah,{No:ak,Yes:ag})}},s.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&s.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 af=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(af)}this.name_div=$("<div/>").addClass("track-name").appendTo(af).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return af},on_resize:function(){},add_resize_handle:function(){var af=this;var ai=false;var ah=false;var ag=$("<div class='track-resize'>");$(af.container_div).hover(function(){if(af.content_visible){ai=true;ag.show()}},function(){ai=false;if(!ah){ag.hide()}});ag.hide().bind("dragstart",function(aj,ak){ah=true;ak.original_height=$(af.content_div).height()}).bind("drag",function(ak,al){var aj=Math.min(Math.max(al.original_height+al.deltaY,af.min_height_px),af.max_height_px);$(af.tiles_div).css("height",aj);af.visible_height_px=(af.max_height_px===aj?0:aj);af.on_resize()}).bind("dragend",function(aj,ak){af.tile_cache.clear();ah=false;if(!ai){ag.hide()}af.config.values.height=af.visible_height_px;af.changed()}).appendTo(af.container_div)},set_display_modes:function(ai,al){this.display_modes=ai;this.mode=(al?al:(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 ag=this,aj={};for(var ah=0,af=ag.display_modes.length;ah<af;ah++){var ak=ag.display_modes[ah];aj[ak]=function(am){return function(){ag.change_mode(am);ag.icons_div.show();ag.container_div.mouseleave(function(){ag.icons_div.hide()})}}(ak)}make_popupmenu(this.action_icons.mode_icon,aj)},build_action_icons:function(){s.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 Z){return"LabelTrack"}else{if(this instanceof C){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof V){return"ReadTrack"}else{if(this instanceof T){return"VcfTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(){var ag=this;ag.enabled=false;ag.tile_cache.clear();ag.data_manager.clear();ag.content_div.css("height","auto");ag.tiles_div.children().remove();ag.container_div.removeClass("nodata error pending");if(!ag.dataset_id){return}var af=$.Deferred(),ah={hda_ldda:ag.hda_ldda,data_type:this.dataset_check_type,chrom:ag.view.chrom};$.getJSON(this.dataset.url(),ah,function(ai){if(!ai||ai==="error"||ai.kind==="error"){ag.container_div.addClass("error");ag.tiles_div.text(o);if(ai.message){var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ag.tiles_div.append(aj)}}else{if(ai==="no converter"){ag.container_div.addClass("error");ag.tiles_div.text(K)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ag.container_div.addClass("nodata");ag.tiles_div.text(F)}else{if(ai==="pending"){ag.container_div.addClass("pending");ag.tiles_div.html(w);setTimeout(function(){ag.init()},ag.data_query_wait)}else{if(ai==="data"||ai.status==="data"){if(ai.valid_chroms){ag.valid_chroms=ai.valid_chroms;ag.update_icons()}ag.tiles_div.text(W);if(ag.view.chrom){ag.tiles_div.text("");ag.tiles_div.css("height",ag.visible_height_px+"px");ag.enabled=true;$.when(ag.predraw_init()).done(function(){af.resolve();ag.container_div.removeClass("nodata error pending");ag.request_draw()})}else{af.resolve()}}}}}}});this.update_icons();return af},predraw_init:function(){},get_drawables:function(){return this}});var N=function(ah,ag,ai){g.call(this,ah,ag,ai);var af=this;m(af.container_div,af.drag_handle_class,".group",af);this.filters_manager=new i.FiltersManager(this,("filters" in ai?ai.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in ai&&ai.tool?new t(this,ai.tool,ai.tool_state):null);this.tile_cache=new y.Cache(S);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(ai.mode){this.change_mode(ai.mode)}};r(N.prototype,s.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(af){$(".bs-tooltip").remove();af.slotters[af.view.resolution_px_b].max_rows*=2;af.request_draw(true)},hide:true}]),copy:function(af){var ag=this.to_dict();r(ag,{data_manager:this.data_manager});var ah=new this.constructor(this.view,af,ag);ah.change_mode(this.mode);ah.enabled=this.enabled;return ah},set_filters_manager:function(af){this.filters_manager=af;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(ag){var af=this;af.mode=ag;af.config.values.mode=ag;af.tile_cache.clear();af.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+af.mode+")");return af},update_icons:function(){var af=this;if(af.filters_available){af.action_icons.filters_icon.show()}else{af.action_icons.filters_icon.hide()}if(af.tool){af.action_icons.tools_icon.show();af.action_icons.param_space_viz_icon.show()}else{af.action_icons.tools_icon.hide();af.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ag,ah,af){return ag+"_"+ah+"_"+af},request_draw:function(ag,af){this.view.request_redraw(false,ag,af,this)},before_draw:function(){},_draw:function(ag,aq){if(!this.can_draw()){return}var ao=this.view.low,ak=this.view.high,am=ak-ao,ah=this.view.container.width(),at=this.view.resolution_px_b,aj=this.view.resolution_b_px;if(this.is_overview){ao=this.view.max_low;ak=this.view.max_high;aj=(view.max_high-view.max_low)/ah;at=1/aj}this.before_draw();this.tiles_div.children().addClass("remove");var af=Math.floor(ao/(aj*U)),an=true,ar=[],al=function(au){return(au&&"track" in au)};while((af*U*aj)<ak){var ap=this.draw_helper(ag,ah,af,aj,this.tiles_div,at);if(al(ap)){ar.push(ap)}else{an=false}af+=1}if(!aq){this.tiles_div.children(".remove").removeClass("remove").remove()}var ai=this;if(an){this.tiles_div.children(".remove").remove();ai.postdraw_actions(ar,ah,at,aq)}},postdraw_actions:function(ah,ai,ak,af){var aj=false;for(var ag=0;ag<ah.length;ag++){if(ah[ag].has_icons){aj=true;break}}if(aj){for(var ag=0;ag<ah.length;ag++){tile=ah[ag];if(!tile.has_icons){tile.html_elt.css("padding-top",E)}}}},draw_helper:function(af,ar,ax,av,ak,al,at){var aq=this,aA=this._gen_tile_cache_key(ar,al,ax),ai=this._get_tile_bounds(ax,av);if(!at){at={}}var az=(af?undefined:aq.tile_cache.get_elt(aA));if(az){aq.show_tile(az,ak,al);return az}var ao=true;var aw=aq.data_manager.get_data(ai,aq.mode,av,aq.data_url_extra_params);if(X(aw)){ao=false}var am;if(view.reference_track&&al>view.canvas_manager.char_width_px){am=view.reference_track.data_manager.get_data(ai,aq.mode,av,view.reference_track.data_url_extra_params);if(X(am)){ao=false}}if(ao){r(aw,at.more_tile_data);var an=aq.mode;if(an==="Auto"){an=aq.get_mode(aw);aq.update_auto_mode(an)}var ah=aq.view.canvas_manager.new_canvas(),ay=ai.get("start"),ag=ai.get("end"),ar=Math.ceil((ag-ay)*al)+aq.left_offset,ap=aq.get_canvas_height(aw,an,al,ar);ah.width=ar;ah.height=ap;var au=ah.getContext("2d");au.translate(this.left_offset,0);var az=aq.draw_tile(aw,au,an,av,ai,al,am);if(az!==undefined){aq.tile_cache.set_elt(aA,az);aq.show_tile(az,ak,al)}return az}var aj=$.Deferred();$.when(aw,am).then(function(){view.request_redraw(false,false,false,aq);aj.resolve()});return aj},get_canvas_height:function(af,ah,ai,ag){return this.visible_height_px},draw_tile:function(af,ag,ak,ai,aj,al,ah){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ah,aj,ak){var ag=this,af=ah.html_elt;ah.predisplay_actions();var ai=(ah.low-(this.is_overview?this.view.max_low:this.view.low))*ak;if(this.left_offset){ai-=this.left_offset}af.css({position:"absolute",top:0,left:ai});if(af.hasClass("remove")){af.removeClass("remove")}else{aj.append(af)}ag.after_show_tile(ah)},after_show_tile:function(af){this.max_height_px=Math.max(this.max_height_px,af.html_elt.height());af.html_elt.parent().children().css("height",this.max_height_px+"px");var ag=this.max_height_px;if(this.visible_height_px!==0){ag=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",ag+"px")},_get_tile_bounds:function(af,ag){var ai=Math.floor(af*U*ag),aj=Math.ceil(U*ag),ah=(ai+aj<=this.view.max_high?ai+aj:this.view.max_high);return new y.GenomeRegion({chrom:this.view.chrom,start:ai,end:ah})},tool_region_and_parameters_str:function(ah,af,ai){var ag=this,aj=(ah!==undefined&&af!==undefined&&ai!==undefined?ah+":"+af+"-"+ai:"all");return" - region=["+aj+"], parameters=["+ag.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(af,ag){return true},can_subset:function(af){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(ah,ai,ak,af){var ag=this;ag.normal_postdraw_actions(ah,ai,ak,af);ag.dataset_check_type="converted_datasets_state";ag.data_query_wait=L;var aj=new l.ServerStateDeferred({url:ag.dataset_state_url,url_params:{dataset_id:ag.dataset_id,hda_ldda:ag.hda_ldda},interval:ag.data_query_wait,success_fn:function(al){return al!=="pending"}});$.when(aj.go()).then(function(){ag.data_manager.set("data_type","data")});ag.postdraw_actions=ag.normal_postdraw_actions}}});var Z=function(ag,af){var ah={resize:false};g.call(this,ag,af,ah);this.container_div.addClass("label-track")};r(Z.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ah=this.view,ai=ah.high-ah.low,al=Math.floor(Math.pow(10,Math.floor(Math.log(ai)/Math.log(10)))),af=Math.floor(ah.low/al)*al,aj=this.view.container.width(),ag=$("<div style='position: relative; height: 1.3em;'></div>");while(af<ah.high){var ak=(af-ah.low)/ai*aj;ag.append($("<div class='label'>"+commatize(af)+"</div>").css({position:"absolute",left:ak-1}));af+=al}this.content_div.children(":first").remove();this.content_div.append(ag)}});var f=function(ag,af,aj){N.call(this,ag,af,aj);this.drawables=[];this.left_offset=0;if("drawables" in aj){var ai;for(var ah=0;ah<aj.drawables.length;ah++){ai=aj.drawables[ah];this.drawables[ah]=p(ai,ag,null);if(ai.left_offset>this.left_offset){this.left_offset=ai.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"};r(f.prototype,N.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(af){$(".bs-tooltip").remove();af.show_group()}}].concat(N.prototype.action_icons_def),to_dict:A.prototype.to_dict,add_drawable:A.prototype.add_drawable,unpack_drawables:A.prototype.unpack_drawables,change_mode:function(af){N.prototype.change_mode.call(this,af);for(var ag=0;ag<this.drawables.length;ag++){this.drawables[ag].change_mode(af)}},init:function(){var ah=[];for(var ag=0;ag<this.drawables.length;ag++){ah.push(this.drawables[ag].init())}var af=this;$.when.apply($,ah).then(function(){af.enabled=true;af.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:s.prototype.can_draw,draw_helper:function(ag,aw,aC,az,an,ap,ax){var av=this,aG=this._gen_tile_cache_key(aw,ap,aC),ak=this._get_tile_bounds(aC,az);if(!ax){ax={}}var aF=(ag?undefined:av.tile_cache.get_elt(aG));if(aF){av.show_tile(aF,an,ap);return aF}var ao=[],av,at=true,aA,aq;for(var aB=0;aB<this.drawables.length;aB++){av=this.drawables[aB];aA=av.data_manager.get_data(ak,av.mode,az,av.data_url_extra_params);if(X(aA)){at=false}ao.push(aA);aq=null;if(view.reference_track&&ap>view.canvas_manager.char_width_px){aq=view.reference_track.data_manager.get_data(ak,av.mode,az,view.reference_track.data_url_extra_params);if(X(aq)){at=false}}ao.push(aq)}if(at){r(aA,ax.more_tile_data);this.tile_predraw_init();var aj=av.view.canvas_manager.new_canvas(),al=av._get_tile_bounds(aC,az),aD=ak.get("start"),ah=ak.get("end"),aE=0,aw=Math.ceil((ah-aD)*ap)+this.left_offset,au=0,ai=[],aB;var af=0;for(aB=0;aB<this.drawables.length;aB++,aE+=2){av=this.drawables[aB];aA=ao[aE];var ar=av.mode;if(ar==="Auto"){ar=av.get_mode(aA);av.update_auto_mode(ar)}ai.push(ar);af=av.get_canvas_height(aA,ar,ap,aw);if(af>au){au=af}}aj.width=aw;aj.height=(ax.height?ax.height:au);aE=0;var ay=aj.getContext("2d");ay.translate(this.left_offset,0);ay.globalAlpha=0.5;ay.globalCompositeOperation="source-over";for(aB=0;aB<this.drawables.length;aB++,aE+=2){av=this.drawables[aB];aA=ao[aE];aq=ao[aE+1];aF=av.draw_tile(aA,ay,ai[aB],az,ak,ap,aq)}this.tile_cache.set_elt(aG,aF);this.show_tile(aF,an,ap);return aF}var am=$.Deferred(),av=this;$.when.apply($,ao).then(function(){view.request_redraw(false,false,false,av);am.resolve()});return am},show_group:function(){var ai=new Q(this.view,this.container,{name:this.name}),af;for(var ah=0;ah<this.drawables.length;ah++){af=this.drawables[ah];af.update_icons();ai.add_drawable(af);af.container=ai;ai.content_div.append(af.container_div)}var ag=this.container.replace_drawable(this,ai,true);ai.request_draw()},tile_predraw_init:function(){var ai=Number.MAX_VALUE,af=-ai,ag;for(var ah=0;ah<this.drawables.length;ah++){ag=this.drawables[ah];if(ag instanceof h){if(ag.prefs.min_value<ai){ai=ag.prefs.min_value}if(ag.prefs.max_value>af){af=ag.prefs.max_value}}}for(var ah=0;ah<this.drawables.length;ah++){ag=this.drawables[ah];ag.prefs.min_value=ai;ag.prefs.max_value=af}},postdraw_actions:function(ah,ak,am,ag){N.prototype.postdraw_actions.call(this,ah,ak,am,ag);var aj=-1;for(var ai=0;ai<ah.length;ai++){var af=ah[ai].html_elt.find("canvas").height();if(af>aj){aj=af}}for(var ai=0;ai<ah.length;ai++){var al=ah[ai];if(al.html_elt.find("canvas").height()!==aj){this.draw_helper(true,ak,al.index,al.resolution,al.html_elt.parent(),am,{height:aj});al.html_elt.remove()}}}});var C=function(af){N.call(this,af,{content_div:af.top_labeltrack},{resize:false});af.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 y.ReferenceTrackDataManager({data_url:this.data_url});this.hide_contents()};r(C.prototype,s.prototype,N.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:s.prototype.can_draw,draw_helper:function(aj,ah,af,ag,ak,al,ai){if(al>this.view.canvas_manager.char_width_px){return N.prototype.draw_helper.call(this,aj,ah,af,ag,ak,al,ai)}else{this.hide_contents();return null}},draw_tile:function(an,ao,aj,ai,al,ap){var ah=this;if(ap>this.view.canvas_manager.char_width_px){if(an.data===null){this.hide_contents();return}var ag=ao.canvas;ao.font=ao.canvas.manager.default_font;ao.textAlign="center";an=an.data;for(var ak=0,am=an.length;ak<am;ak++){var af=Math.floor(ak*ap);ao.fillText(an[ak],af,10)}this.show_contents();return new b(ah,al,ai,ag,an)}this.hide_contents()}});var h=function(ah,ag,ai){var af=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";N.call(this,ah,ag,ai);this.hda_ldda=ai.hda_ldda;this.dataset_id=ai.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:R()},{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:ai.prefs,onchange:function(){af.set_name(af.prefs.name);af.vertical_range=af.prefs.max_value-af.prefs.min_value;af.set_min_value(af.prefs.min_value);af.set_max_value(af.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};r(h.prototype,s.prototype,N.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(af){this.prefs.min_value=af;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(af){this.prefs.max_value=af;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var af=this;af.vertical_range=undefined;return $.getJSON(af.dataset.url(),{data_type:"data",stats:true,chrom:af.view.chrom,low:0,high:af.view.max_high,hda_ldda:af.hda_ldda},function(ag){af.container_div.addClass("line-track");var aj=ag.data;if(isNaN(parseFloat(af.prefs.min_value))||isNaN(parseFloat(af.prefs.max_value))){var ah=aj.min,al=aj.max;ah=Math.floor(Math.min(0,Math.max(ah,aj.mean-2*aj.sd)));al=Math.ceil(Math.max(0,Math.min(al,aj.mean+2*aj.sd)));af.prefs.min_value=ah;af.prefs.max_value=al;$("#track_"+af.dataset_id+"_minval").val(af.prefs.min_value);$("#track_"+af.dataset_id+"_maxval").val(af.prefs.max_value)}af.vertical_range=af.prefs.max_value-af.prefs.min_value;af.total_frequency=aj.total_frequency;af.container_div.find(".yaxislabel").remove();var ak=$("<div/>").text(Y(af.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(am){$(".bs-tooltip").remove();var am=parseFloat(am);if(!isNaN(am)){af.set_min_value(am)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+af.dataset_id+"_minval").prependTo(af.container_div),ai=$("<div/>").text(Y(af.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(am){$(".bs-tooltip").remove();var am=parseFloat(am);if(!isNaN(am)){af.set_max_value(am)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+af.dataset_id+"_maxval").prependTo(af.container_div)})},draw_tile:function(ao,am,ah,ag,aj,an){var af=am.canvas,ai=aj.get("start"),al=aj.get("end"),ak=new M.LinePainter(ao.data,ai,al,this.prefs,ah);ak.draw(am,af.width,af.height,an);return new b(this,aj,ag,af,ao.data)},can_subset:function(af){return false}});var u=function(ah,ag,ai){var af=this;this.display_modes=["Heatmap"];this.mode="Heatmap";N.call(this,ah,ag,ai);this.hda_ldda=ai.hda_ldda;this.dataset_id=ai.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new G({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:ai.prefs,onchange:function(){af.set_name(af.prefs.name);af.vertical_range=af.prefs.max_value-af.prefs.min_value;af.set_min_value(af.prefs.min_value);af.set_max_value(af.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};r(u.prototype,s.prototype,N.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(af){this.prefs.min_value=af;this.tile_cache.clear();this.request_draw()},set_max_value:function(af){this.prefs.max_value=af;this.tile_cache.clear();this.request_draw()},draw_tile:function(ap,an,ak,ai,ag,ao){var ah=an.canvas,af=this._get_tile_bounds(ag,ai),aj=af[0],am=af[1],al=new M.DiagonalHeatmapPainter(ap.data,aj,am,this.prefs,ak);al.draw(an,ah.width,ah.height,ao);return new b(this,ag,ai,ah,ap.data)}});var c=function(ai,ah,ak){var ag=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];N.call(this,ai,ah,ak);var aj=R(),af=R([aj,"#ffffff"]);this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:aj},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:af},{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:ak.prefs,onchange:function(){ag.set_name(ag.prefs.name);ag.tile_cache.clear();ag.set_painter_from_config();ag.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ak.hda_ldda;this.dataset_id=ak.dataset_id;this.original_dataset_id=ak.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()};r(c.prototype,s.prototype,N.prototype,{set_dataset:function(af){this.dataset_id=af.get("id");this.hda_ldda=af.get("hda_ldda");this.dataset=af;this.data_manager.set("dataset",af)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=M.ArcLinkedFeaturePainter}else{this.painter=M.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(av,ap,ak,aj){N.prototype.postdraw_actions.call(this,av,aj);var ao=this,ar;if(ao.mode==="Coverage"){var ag=-1;for(ar=0;ar<av.length;ar++){var aq=av[ar].max_val;if(aq>ag){ag=aq}}for(ar=0;ar<av.length;ar++){var ax=av[ar];if(ax.max_val!==ag){ax.html_elt.remove();ao.draw_helper(true,ap,ax.index,ax.resolution,ax.html_elt.parent(),ak,{more_tile_data:{max:ag}})}}}if(ao.filters_manager){var al=ao.filters_manager.filters;for(var au=0;au<al.length;au++){al[au].update_ui_elt()}var aw=false,af,am;for(ar=0;ar<av.length;ar++){if(av[ar].data.length){af=av[ar].data[0];for(var au=0;au<al.length;au++){am=al[au];if(am.applies_to(af)&&am.min!==am.max){aw=true;break}}}}if(ao.filters_available!==aw){ao.filters_available=aw;if(!ao.filters_available){ao.filters_manager.hide()}ao.update_icons()}}this.container_div.find(".yaxislabel").remove();var ai=av[0];if(ai instanceof j){var an=(this.prefs.histogram_max?this.prefs.histogram_max:ai.max_val),ah=$("<div/>").text(an).make_text_editable({num_cols:12,on_finish:function(ay){$(".bs-tooltip").remove();var ay=parseFloat(ay);ao.prefs.histogram_max=(!isNaN(ay)?ay:null);ao.tile_cache.clear();ao.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(ah)}if(ai instanceof P){var at=true;for(ar=0;ar<av.length;ar++){if(!av[ar].all_slotted){at=false;break}}if(!at){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(af){var af;if(this.mode==="Auto"){if(af==="no_detail"){af="feature spans"}else{if(af==="summary_tree"){af="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+af+")")}},incremental_slots:function(aj,af,ai){var ag=this.view.canvas_manager.dummy_context,ah=this.slotters[aj];if(!ah||(ah.mode!==ai)){ah=new (v.FeatureSlotter)(aj,ai,B,function(ak){return ag.measureText(ak)});this.slotters[aj]=ah}return ah.slot_features(af)},get_mode:function(af){if(af.dataset_type==="summary_tree"){mode="summary_tree"}else{if(af.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>J){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(af,aj,ak,ag){if(aj==="summary_tree"||aj==="Coverage"){return this.summary_draw_height}else{var ai=this.incremental_slots(ak,af.data,aj);var ah=new (this.painter)(null,null,null,this.prefs,aj);return Math.max(ac,ah.get_required_height(ai,ag))}},draw_tile:function(ap,au,ar,av,ai,am,ah){var at=this,ag=au.canvas,aB=ai.get("start"),af=ai.get("end"),aj=this.left_offset;if(ar==="summary_tree"||ar==="Coverage"){var aD=new M.SummaryTreePainter(ap,aB,af,this.prefs);aD.draw(au,ag.width,ag.height,am);return new j(at,ai,av,ag,ap.data,ap.max)}var al=[],aq=this.slotters[am].slots;all_slotted=true;if(ap.data){var an=this.filters_manager.filters;for(var aw=0,ay=ap.data.length;aw<ay;aw++){var ak=ap.data[aw];var ax=false;var ao;for(var aA=0,aF=an.length;aA<aF;aA++){ao=an[aA];ao.update_attrs(ak);if(!ao.keep(ak)){ax=true;break}}if(!ax){al.push(ak);if(!(ak[0] in aq)){all_slotted=false}}}}var aE=(this.filters_manager.alpha_filter?new D(this.filters_manager.alpha_filter):null);var aC=(this.filters_manager.height_filter?new D(this.filters_manager.height_filter):null);var aD=new (this.painter)(al,aB,af,this.prefs,ar,aE,aC,ah);var az=null;au.fillStyle=this.prefs.block_color;au.font=au.canvas.manager.default_font;au.textAlign="right";if(ap.data){az=aD.draw(au,ag.width,ag.height,am,aq);az.translation=-aj}return new P(at,ai,av,ag,ap.data,am,ar,ap.message,all_slotted,az)},data_and_mode_compatible:function(af,ag){if(ag==="Auto"){return true}else{if(ag==="Coverage"){return af.dataset_type==="summary_tree"}else{if(af.extra_info==="no_detail"||af.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(af){if(af.dataset_type==="summary_tree"||af.message||af.extra_info==="no_detail"){return false}return true}});var T=function(ag,af,ah){c.call(this,ag,af,ah);this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:R()},{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:ah.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=M.ReadPainter};r(T.prototype,s.prototype,N.prototype,c.prototype);var V=function(ah,ag,aj){c.call(this,ah,ag,aj);var ai=R(),af=R([ai,"#ffffff"]);this.config=new G({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:ai},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:af},{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:aj.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=M.ReadPainter;this.update_icons()};r(V.prototype,s.prototype,N.prototype,c.prototype);var d={LineTrack:h,FeatureTrack:c,VcfTrack:T,ReadTrack:V,CompositeTrack:f,DrawableGroup:Q};var p=function(ah,ag,af){if("copy" in ah){return ah.copy(af)}else{var ai=ah.obj_type;if(!ai){ai=ah.track_type}return new d[ai](ag,af,ah)}};return{View:aa,DrawableGroup:Q,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:u,ReadTrack:V,VcfTrack:T,CompositeTrack:f,object_from_template:p,add_datasets:ae}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/viz/trackster/util.js --- a/static/scripts/packed/viz/trackster/util.js +++ b/static/scripts/packed/viz/trackster/util.js @@ -1,1 +1,1 @@ -define(function(){exports={};exports.get_random_color=function(a){if(!a){a="#ffffff"}if(typeof(a)==="string"){a=[a]}for(var j=0;j<a.length;j++){a[j]=parseInt(a[j].slice(1),16)}var n=function(t,s,i){return((t*299)+(s*587)+(i*114))/1000};var e=function(v,u,w,s,i,t){return(Math.max(v,s)-Math.min(v,s))+(Math.max(u,i)-Math.min(u,i))+(Math.max(w,t)-Math.min(w,t))};var g,o,f,k,q,h,r,c,d,b,p,m=false,l=0;do{g=Math.round(Math.random()*16777215);o=(g&16711680)>>16;f=(g&65280)>>8;k=g&255;d=n(o,f,k);m=true;for(j=0;j<a.length;j++){q=a[j];h=(q&16711680)>>16;r=(q&65280)>>8;c=q&255;b=n(h,r,c);p=e(o,f,k,h,r,c);if((Math.abs(d-b)<40)||(p<200)){m=false;break}}l++}while(!m&&l<=10);return"#"+(16777216+g).toString(16).substr(1,6)};return exports}); \ No newline at end of file +define(function(){exports={};exports.ServerStateDeferred=Backbone.Model.extend({defaults:{ajax_settings:{},interval:1000,success_fn:function(a){return true}},go:function(){var d=$.Deferred(),c=this,f=c.get("ajax_settings"),e=c.get("success_fn"),b=c.get("interval"),a=function(){$.ajax(f).success(function(g){if(e(g)){d.resolve(g)}else{setTimeout(a,b)}})};a();return d}});exports.get_random_color=function(a){if(!a){a="#ffffff"}if(typeof(a)==="string"){a=[a]}for(var j=0;j<a.length;j++){a[j]=parseInt(a[j].slice(1),16)}var n=function(t,s,i){return((t*299)+(s*587)+(i*114))/1000};var e=function(v,u,w,s,i,t){return(Math.max(v,s)-Math.min(v,s))+(Math.max(u,i)-Math.min(u,i))+(Math.max(w,t)-Math.min(w,t))};var g,o,f,k,q,h,r,c,d,b,p,m=false,l=0;do{g=Math.round(Math.random()*16777215);o=(g&16711680)>>16;f=(g&65280)>>8;k=g&255;d=n(o,f,k);m=true;for(j=0;j<a.length;j++){q=a[j];h=(q&16711680)>>16;r=(q&65280)>>8;c=q&255;b=n(h,r,c);p=e(o,f,k,h,r,c);if((Math.abs(d-b)<40)||(p<200)){m=false;break}}l++}while(!m&&l<=10);return"#"+(16777216+g).toString(16).substr(1,6)};return exports}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/viz/trackster_ui.js --- a/static/scripts/packed/viz/trackster_ui.js +++ b/static/scripts/packed/viz/trackster_ui.js @@ -1,1 +1,1 @@ -define(["base","libs/underscore","viz/trackster/slotting","viz/trackster/painters","viz/trackster/tracks"],function(f,c,g,d,b){var a=b.object_from_template;var e=f.Base.extend({initialize:function(h){this.baseURL=h},createButtonMenu:function(){var h=this,j=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){add_datasets(add_datasets_url,add_track_async_url,function(k){c.each(k,function(l){view.add_drawable(trackster_ui.object_from_template(l,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new b.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){parent.force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=h.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){show_modal("Saving...","progress");var k=[];$(".bookmark").each(function(){k.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var l=(view.overview_drawable?view.overview_drawable.name:null),m={id:view.vis_id,title:view.name,dbkey:view.dbkey,type:"trackster",datasets:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:l},bookmarks:k};$.ajax({url:galaxy_paths.get("visualization_url"),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(m)}}).success(function(n){hide_modal();view.vis_id=n.vis_id;view.has_changes=false;window.history.pushState({},"",n.url+window.location.hash)}).error(function(){show_modal("Could Not Save","Could not save visualization. Please try again later.",{Close:hide_modal})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=h.baseURL+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=j;return j},add_bookmarks:function(){var h=this.baseURL;show_modal("Select dataset for new bookmarks","progress");$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(j){show_modal("Select dataset for new bookmarks",j,{Cancel:function(){hide_modal()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var k,l=$(this).val();if($(this).attr("name")==="id"){k={hda_id:l}}else{k={ldda_id:l}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:k,dataType:"json"}).then(function(m){for(i=0;i<m.data.length;i++){var n=m.data[i];add_bookmark(n[0],n[1])}})});hide_modal()}})}})},add_bookmark:function(m,k,h){var o=$("#bookmarks-container"),q=$("<div/>").addClass("bookmark").appendTo(o);var r=$("<div/>").addClass("position").appendTo(q),n=$("<a href=''/>").text(m).appendTo(r).click(function(){view.go_to(m);return false}),l=$("<div/>").text(k).appendTo(q);if(h){var p=$("<div/>").addClass("delete-icon-container").prependTo(q).click(function(){q.slideUp("fast");q.remove();view.has_changes=true;return false}),j=$("<a href=''/>").addClass("icon-button delete").appendTo(p);l.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return q},create_visualization:function(l,h,k,m,j){view=new b.View(l);view.editor=true;$.when(view.load_chroms_deferred).then(function(){if(h){var v=h.chrom,n=h.start,s=h.end,p=h.overview;if(v&&(n!==undefined)&&s){view.change_chrom(v,n,s)}}if(k){var q,o,r;for(var t=0;t<k.length;t++){view.add_drawable(a(k[t],view,view))}}view.update_intro_div();var w;for(var t=0;t<view.drawables.length;t++){if(view.drawables[t].name===p){view.set_overview(view.drawables[t]);break}}if(m){var u;for(var t=0;t<m.length;t++){u=m[t];add_bookmark(u.position,u.annotation,j)}}view.has_changes=false});return view},init_keyboard_nav:function(h){$(document).keydown(function(j){if($(j.srcElement).is(":input")){return}switch(j.which){case 37:h.move_fraction(0.25);break;case 38:var k=Math.round(h.viewport_container.height()/15);h.viewport_container.scrollTop(h.viewport_container.scrollTop()-20);break;case 39:h.move_fraction(-0.25);break;case 40:var k=Math.round(h.viewport_container.height()/15);h.viewport_container.scrollTop(h.viewport_container.scrollTop()+20);break}})}});return{object_from_template:a,TracksterUI:e}}); \ No newline at end of file +define(["base","libs/underscore","viz/trackster/slotting","viz/trackster/painters","viz/trackster/tracks"],function(f,c,g,d,b){var a=b.object_from_template;var e=f.Base.extend({initialize:function(h){this.baseURL=h},createButtonMenu:function(){var h=this,j=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){b.add_datasets(add_datasets_url,add_track_async_url,function(k){c.each(k,function(l){view.add_drawable(a(l,view,view))})})}},{icon_class:"block--plus",title:"Add group",on_click:function(){view.add_drawable(new b.DrawableGroup(view,view,{name:"New Group"}))}},{icon_class:"bookmarks",title:"Bookmarks",on_click:function(){parent.force_right_panel(($("div#right").css("right")=="0px"?"hide":"show"))}},{icon_class:"globe",title:"Circster",on_click:function(){window.location=h.baseURL+"visualization/circster?id="+view.vis_id}},{icon_class:"disk--arrow",title:"Save",on_click:function(){show_modal("Saving...","progress");var k=[];$(".bookmark").each(function(){k.push({position:$(this).children(".position").text(),annotation:$(this).children(".annotation").text()})});var l=(view.overview_drawable?view.overview_drawable.name:null),m={id:view.vis_id,title:view.name,dbkey:view.dbkey,type:"trackster",datasets:view.to_dict(),viewport:{chrom:view.chrom,start:view.low,end:view.high,overview:l},bookmarks:k};$.ajax({url:galaxy_paths.get("visualization_url"),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(m)}}).success(function(n){hide_modal();view.vis_id=n.vis_id;view.has_changes=false;window.history.pushState({},"",n.url+window.location.hash)}).error(function(){show_modal("Could Not Save","Could not save visualization. Please try again later.",{Close:hide_modal})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=h.baseURL+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});this.buttonMenu=j;return j},add_bookmarks:function(){var h=this,j=this.baseURL;show_modal("Select dataset for new bookmarks","progress");$.ajax({url:this.baseURL+"/visualization/list_histories",data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(k){show_modal("Select dataset for new bookmarks",k,{Cancel:function(){hide_modal()},Insert:function(){$("input[name=id]:checked,input[name=ldda_ids]:checked").first().each(function(){var l,m=$(this).val();if($(this).attr("name")==="id"){l={hda_id:m}}else{l={ldda_id:m}}$.ajax({url:this.baseURL+"/visualization/bookmarks_from_dataset",data:l,dataType:"json"}).then(function(n){for(i=0;i<n.data.length;i++){var o=n.data[i];h.add_bookmark(o[0],o[1])}})});hide_modal()}})}})},add_bookmark:function(m,k,h){var o=$("#bookmarks-container"),q=$("<div/>").addClass("bookmark").appendTo(o);var r=$("<div/>").addClass("position").appendTo(q),n=$("<a href=''/>").text(m).appendTo(r).click(function(){view.go_to(m);return false}),l=$("<div/>").text(k).appendTo(q);if(h){var p=$("<div/>").addClass("delete-icon-container").prependTo(q).click(function(){q.slideUp("fast");q.remove();view.has_changes=true;return false}),j=$("<a href=''/>").addClass("icon-button delete").appendTo(p);l.make_text_editable({num_rows:3,use_textarea:true,help_text:"Edit bookmark note"}).addClass("annotation")}view.has_changes=true;return q},create_visualization:function(n,h,m,o,l){var k=this,j=new b.View(n);j.editor=true;$.when(j.load_chroms_deferred).then(function(){if(h){var x=h.chrom,p=h.start,u=h.end,r=h.overview;if(x&&(p!==undefined)&&u){j.change_chrom(x,p,u)}}if(m){var s,q,t;for(var v=0;v<m.length;v++){j.add_drawable(a(m[v],j,j))}}j.update_intro_div();var y;for(var v=0;v<j.drawables.length;v++){if(j.drawables[v].name===r){j.set_overview(j.drawables[v]);break}}if(o){var w;for(var v=0;v<o.length;v++){w=o[v];k.add_bookmark(w.position,w.annotation,l)}}j.has_changes=false});return j},init_keyboard_nav:function(h){$(document).keydown(function(j){if($(j.srcElement).is(":input")){return}switch(j.which){case 37:h.move_fraction(0.25);break;case 38:var k=Math.round(h.viewport_container.height()/15);h.viewport_container.scrollTop(h.viewport_container.scrollTop()-20);break;case 39:h.move_fraction(-0.25);break;case 40:var k=Math.round(h.viewport_container.height()/15);h.viewport_container.scrollTop(h.viewport_container.scrollTop()+20);break}})}});return{object_from_template:a,TracksterUI:e}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/packed/viz/visualization.js --- a/static/scripts/packed/viz/visualization.js +++ b/static/scripts/packed/viz/visualization.js @@ -1,1 +1,1 @@ -(function(){var k=function(u){return("isResolved" in u)};var f=Backbone.Model.extend({defaults:{ajax_settings:{},interval:1000,success_fn:function(u){return true}},go:function(){var x=$.Deferred(),w=this,z=w.get("ajax_settings"),y=w.get("success_fn"),v=w.get("interval"),u=function(){$.ajax(z).success(function(A){if(y(A)){x.resolve(A)}else{setTimeout(u,v)}})};u();return x}});var g=function(u){this.default_font=u!==undefined?u:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};_.extend(g.prototype,{load_pattern:function(u,y){var v=this.patterns,w=this.dummy_context,x=new Image();x.src=galaxy_paths.attributes.image_path+y;x.onload=function(){v[u]=w.createPattern(x,"repeat")}},get_pattern:function(u){return this.patterns[u]},new_canvas:function(){var u=$("<canvas/>")[0];if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(u)}u.manager=this;return u}});var q=Backbone.Model.extend({defaults:{num_elements:20,obj_cache:null,key_ary:null},initialize:function(u){this.clear()},get_elt:function(v){var w=this.attributes.obj_cache,x=this.attributes.key_ary,u=x.indexOf(v);if(u!==-1){if(w[v].stale){x.splice(u,1);delete w[v]}else{this.move_key_to_end(v,u)}}return w[v]},set_elt:function(v,x){var y=this.attributes.obj_cache,z=this.attributes.key_ary,w=this.attributes.num_elements;if(!y[v]){if(z.length>=w){var u=z.shift();delete y[u]}z.push(v)}y[v]=x;return x},move_key_to_end:function(v,u){this.attributes.key_ary.splice(u,1);this.attributes.key_ary.push(v)},clear:function(){this.attributes.obj_cache={};this.attributes.key_ary=[]},size:function(){return this.attributes.key_ary.length}});var d=q.extend({defaults:_.extend({},q.prototype.defaults,{dataset:null,filters_manager:null,data_type:"data",genome_wide_summary_data:null,data_mode_compatible:function(u,v){return true},can_subset:function(u){return false}}),data_is_ready:function(){var w=this.get("dataset"),v=$.Deferred(),u=new f({ajax_settings:{url:this.get("dataset").url(),data:{hda_ldda:w.get("hda_ldda"),data_type:"state"},dataType:"json"},interval:5000,success_fn:function(x){return x!=="pending"}});$.when(u.go()).then(function(x){v.resolve(x==="ok"||x==="data")});return v},search_features:function(u){var v=this.get("dataset"),w={query:u,dataset_id:v.id,hda_ldda:v.get("hda_ldda"),data_type:"features"};return $.getJSON(v.url(),w)},load_data:function(C,B,v,A){var x={data_type:this.get("data_type"),chrom:C.get("chrom"),low:C.get("start"),high:C.get("end"),mode:B,resolution:v},y=this.get("dataset");if(y){x.dataset_id=y.id;x.hda_ldda=y.get("hda_ldda")}$.extend(x,A);var D=this.get("filters_manager");if(D){var E=[];var u=D.filters;for(var z=0;z<u.length;z++){E.push(u[z].name)}x.filter_cols=JSON.stringify(E)}var w=this;return $.getJSON(y.url(),x,function(F){w.set_data(C,F)})},get_data:function(A,z,w,y){var B=this.get_elt(A);if(B&&(k(B)||this.get("data_mode_compatible")(B,z))){return B}var C=this.get("key_ary"),v=this.get("obj_cache"),D,u;for(var x=0;x<C.length;x++){D=C[x];u=new h({from_str:D});if(u.contains(A)){B=v[D];if(k(B)||(this.get("data_mode_compatible")(B,z)&&this.get("can_subset")(B))){this.move_key_to_end(D,x);return B}}}B=this.load_data(A,z,w,y);this.set_data(A,B);return B},set_data:function(v,u){this.set_elt(v,u)},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(C,B,x,A,y){var E=this.get_elt(C);if(!(E&&this.get("data_mode_compatible")(E,B))){console.log("ERROR: no current data for: ",dataset,C.toString(),B,x,A);return}E.stale=true;var w=C.get("start");if(y===this.DEEP_DATA_REQ){$.extend(A,{start_val:E.data.length+1})}else{if(y===this.BROAD_DATA_REQ){w=(E.max_high?E.max_high:E.data[E.data.length-1][2])+1}}var D=C.copy().set("start",w);var v=this,z=this.load_data(D,B,x,A),u=$.Deferred();this.set_data(C,u);$.when(z).then(function(F){if(F.data){F.data=E.data.concat(F.data);if(F.max_low){F.max_low=E.max_low}if(F.message){F.message=F.message.replace(/[0-9]+/,F.data.length)}}v.set_data(C,F);u.resolve(F)});return u},get_elt:function(u){return q.prototype.get_elt.call(this,u.toString())},set_elt:function(v,u){return q.prototype.set_elt.call(this,v.toString(),u)}});var o=d.extend({load_data:function(u,x,y,v,w){if(v>1){return{data:null}}return d.prototype.load_data.call(this,u,x,y,v,w)}});var c=Backbone.Model.extend({defaults:{name:null,key:null,chroms_info:null},get_chroms_info:function(){return this.attributes.chroms_info.chrom_info}});var h=Backbone.RelationalModel.extend({defaults:{chrom:null,start:0,end:0,DIF_CHROMS:1000,BEFORE:1001,CONTAINS:1002,OVERLAP_START:1003,OVERLAP_END:1004,CONTAINED_BY:1005,AFTER:1006},initialize:function(v){if(v.from_str){var x=v.from_str.split(":"),w=x[0],u=x[1].split("-");this.set({chrom:w,start:parseInt(u[0],10),end:parseInt(u[1],10)})}},copy:function(){return new h({chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")})},length:function(){return this.get("end")-this.get("start")},toString:function(){return this.get("chrom")+":"+this.get("start")+"-"+this.get("end")},toJSON:function(){return{chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")}},compute_overlap:function(B){var v=this.get("chrom"),A=B.get("chrom"),z=this.get("start"),x=B.get("start"),y=this.get("end"),w=B.get("end"),u;if(v&&A&&v!==A){return this.get("DIF_CHROMS")}if(z<x){if(y<x){u=this.get("BEFORE")}else{if(y<=w){u=this.get("OVERLAP_START")}else{u=this.get("CONTAINS")}}}else{if(z>w){u=this.get("AFTER")}else{if(y<=w){u=this.get("CONTAINED_BY")}else{u=this.get("OVERLAP_END")}}}return u},contains:function(u){return this.compute_overlap(u)===this.get("CONTAINS")},overlaps:function(u){return _.intersection([this.compute_overlap(u)],[this.get("DIF_CHROMS"),this.get("BEFORE"),this.get("AFTER")]).length===0}});var m=Backbone.Collection.extend({model:h});var e=Backbone.RelationalModel.extend({defaults:{region:null,note:""},relations:[{type:Backbone.HasOne,key:"region",relatedModel:h}]});var r=Backbone.Collection.extend({model:e});var b=Backbone.Model.extend({defaults:{data:null,min:0,max:0},initialize:function(v){var u=_.flatten(_.map(this.get("data"),function(w){if(w.data.length!==0){return _.map(w.data,function(x){return x[1]})}else{return 0}}));this.set("max",_.max(u));this.set("min",_.min(u))}});var n=Backbone.RelationalModel.extend({defaults:{data:null,min:0,max:0},initialize:function(v){var u=_.max(this.get("data"),function(w){if(!w||typeof w==="string"){return 0}return w[1]});this.attributes.max=(u&&typeof u!=="string"?u[1]:0)}});var t=Dataset.extend({initialize:function(u){this.set("id",u.dataset_id);var w=this.get("genome_wide_data");if(w){var v=(this.get("track_type")==="LineTrack"?b:n);this.set("genome_wide_data",new v(w))}}});var p=Backbone.RelationalModel.extend({defaults:{id:"",title:"",type:"",dbkey:"",tracks:null},relations:[{type:Backbone.HasMany,key:"tracks",relatedModel:t}],url:function(){return galaxy_paths.get("visualization_url")},save:function(){return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(this)}})}});var l=p.extend({defaults:_.extend({},p.prototype.defaults,{bookmarks:null,viewport:null})});var a=Backbone.Model.extend({});var i=Backbone.Router.extend({initialize:function(v){this.view=v.view;this.route(/([\w]+)$/,"change_location");this.route(/([\w]+\:[\d,]+-[\d,]+)$/,"change_location");var u=this;u.view.on("navigate",function(w){u.navigate(w)})},change_location:function(u){this.view.go_to(u)}});var j=function(u,w,v){$.ajax({url:u,data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(x){show_modal("Select datasets for new tracks",x,{Cancel:function(){hide_modal()},Add:function(){var y=[];$("input[name=id]:checked,input[name=ldda_ids]:checked").each(function(){var z={data_type:"track_config",hda_ldda:"hda"},A=$(this).val();if($(this).attr("name")!=="id"){z.hda_ldda="ldda"}y[y.length]=$.ajax({url:w+"/"+A,data:z,dataType:"json"})});$.when.apply($,y).then(function(){var z=(arguments[0] instanceof Array?$.map(arguments,function(A){return A[0]}):[arguments[0]]);v(z)});hide_modal()}})}})};var s=(function(){if(typeof module!=="undefined"&&module.exports){return module.exports}else{if(typeof define==="function"&&define.amd){s={};define(function(){return s});return s}else{return window}}})();s.BrowserBookmark=e;s.BrowserBookmarkCollection=r;s.Cache=q;s.CanvasManager=g;s.Genome=c;s.GenomeDataManager=d;s.GenomeRegion=h;s.GenomeRegionCollection=m;s.GenomeVisualization=l;s.GenomeWideBigWigData=b;s.GenomeWideSummaryTreeData=n;s.ReferenceTrackDataManager=o;s.ServerStateDeferred=f;s.TrackBrowserRouter=i;s.TrackConfig=a;s.Visualization=p;s.add_datasets=j}).call(this); \ No newline at end of file +define(["libs/underscore","mvc/data","viz/trackster/util"],function(q,h,j){var i=function(s){return("isResolved" in s)};var e=function(s){this.default_font=s!==undefined?s:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};q.extend(e.prototype,{load_pattern:function(s,w){var t=this.patterns,u=this.dummy_context,v=new Image();v.src=galaxy_paths.attributes.image_path+w;v.onload=function(){t[s]=u.createPattern(v,"repeat")}},get_pattern:function(s){return this.patterns[s]},new_canvas:function(){var s=$("<canvas/>")[0];if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(s)}s.manager=this;return s}});var o=Backbone.Model.extend({defaults:{num_elements:20,obj_cache:null,key_ary:null},initialize:function(s){this.clear()},get_elt:function(t){var u=this.attributes.obj_cache,v=this.attributes.key_ary,s=v.indexOf(t);if(s!==-1){if(u[t].stale){v.splice(s,1);delete u[t]}else{this.move_key_to_end(t,s)}}return u[t]},set_elt:function(t,v){var w=this.attributes.obj_cache,x=this.attributes.key_ary,u=this.attributes.num_elements;if(!w[t]){if(x.length>=u){var s=x.shift();delete w[s]}x.push(t)}w[t]=v;return v},move_key_to_end:function(t,s){this.attributes.key_ary.splice(s,1);this.attributes.key_ary.push(t)},clear:function(){this.attributes.obj_cache={};this.attributes.key_ary=[]},size:function(){return this.attributes.key_ary.length}});var c=o.extend({defaults:q.extend({},o.prototype.defaults,{dataset:null,filters_manager:null,data_type:"data",data_mode_compatible:function(s,t){return true},can_subset:function(s){return false}}),data_is_ready:function(){var u=this.get("dataset"),t=$.Deferred(),s=new j.ServerStateDeferred({ajax_settings:{url:this.get("dataset").url(),data:{hda_ldda:u.get("hda_ldda"),data_type:"state"},dataType:"json"},interval:5000,success_fn:function(v){return v!=="pending"}});$.when(s.go()).then(function(v){t.resolve(v==="ok"||v==="data")});return t},search_features:function(s){var t=this.get("dataset"),u={query:s,hda_ldda:t.get("hda_ldda"),data_type:"features"};return $.getJSON(t.url(),u)},load_data:function(A,z,t,y){var w=this.get("dataset"),v={data_type:this.get("data_type"),chrom:A.get("chrom"),low:A.get("start"),high:A.get("end"),mode:z,resolution:t,hda_ldda:w.get("hda_ldda")};$.extend(v,y);var C=this.get("filters_manager");if(C){var D=[];var s=C.filters;for(var x=0;x<s.length;x++){D.push(s[x].name)}v.filter_cols=JSON.stringify(D)}var u=this,B=$.getJSON(w.url(),v,function(E){u.set_data(A,E)});this.set_data(A,B);return B},get_data:function(y,x,u,w){var z=this.get_elt(y);if(z&&(i(z)||this.get("data_mode_compatible")(z,x))){return z}var A=this.get("key_ary"),t=this.get("obj_cache"),B,s;for(var v=0;v<A.length;v++){B=A[v];s=new f({from_str:B});if(s.contains(y)){z=t[B];if(i(z)||(this.get("data_mode_compatible")(z,x)&&this.get("can_subset")(z))){this.move_key_to_end(B,v);return z}}}return this.load_data(y,x,u,w)},set_data:function(t,s){this.set_elt(t,s)},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(A,z,v,y,w){var C=this._mark_stale(A);if(!(C&&this.get("data_mode_compatible")(C,z))){console.log("ERROR: problem with getting more data: current data is not compatible");return}var u=A.get("start");if(w===this.DEEP_DATA_REQ){$.extend(y,{start_val:C.data.length+1})}else{if(w===this.BROAD_DATA_REQ){u=(C.max_high?C.max_high:C.data[C.data.length-1][2])+1}}var B=A.copy().set("start",u);var t=this,x=this.load_data(B,z,v,y),s=$.Deferred();this.set_data(A,s);$.when(x).then(function(D){if(D.data){D.data=C.data.concat(D.data);if(D.max_low){D.max_low=C.max_low}if(D.message){D.message=D.message.replace(/[0-9]+/,D.data.length)}}t.set_data(A,D);s.resolve(D)});return s},get_more_detailed_data:function(v,x,t,w,u){var s=this._mark_stale(v);if(!s){console.log("ERROR getting more detailed data: no current data");return}if(!u){u={}}var x;if(s.dataset_type==="bigwig"){u.num_samples=s.data.length*w}else{if(s.dataset_type==="summary_tree"){u.level=s.level+1}}return this.load_data(v,x,t,u)},_mark_stale:function(t){var s=this.get_elt(t);if(!s){console.log("ERROR: no data to mark as stale: ",this.get("dataset"),t.toString())}s.stale=true;return s},get_elt:function(s){return o.prototype.get_elt.call(this,s.toString())},set_elt:function(t,s){return o.prototype.set_elt.call(this,t.toString(),s)}});var m=c.extend({initialize:function(s){var t=new Backbone.Model();t.urlRoot=s.data_url;this.set("dataset",t)},load_data:function(u,v,s,t){console.log(u,v,s);if(s>1){return{data:null}}return c.prototype.load_data.call(this,u,v,s,t)}});var b=Backbone.Model.extend({defaults:{name:null,key:null,chroms_info:null},initialize:function(s){this.id=s.dbkey},get_chroms_info:function(){return this.attributes.chroms_info.chrom_info},get_chrom_region:function(s){var t=q.find(this.get_chroms_info(),function(u){return u.chrom==s});return new f({chrom:t.chrom,end:t.len})}});var f=Backbone.RelationalModel.extend({defaults:{chrom:null,start:0,end:0,DIF_CHROMS:1000,BEFORE:1001,CONTAINS:1002,OVERLAP_START:1003,OVERLAP_END:1004,CONTAINED_BY:1005,AFTER:1006},initialize:function(t){if(t.from_str){var v=t.from_str.split(":"),u=v[0],s=v[1].split("-");this.set({chrom:u,start:parseInt(s[0],10),end:parseInt(s[1],10)})}},copy:function(){return new f({chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")})},length:function(){return this.get("end")-this.get("start")},toString:function(){return this.get("chrom")+":"+this.get("start")+"-"+this.get("end")},toJSON:function(){return{chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")}},compute_overlap:function(z){var t=this.get("chrom"),y=z.get("chrom"),x=this.get("start"),v=z.get("start"),w=this.get("end"),u=z.get("end"),s;if(t&&y&&t!==y){return this.get("DIF_CHROMS")}if(x<v){if(w<v){s=this.get("BEFORE")}else{if(w<=u){s=this.get("OVERLAP_START")}else{s=this.get("CONTAINS")}}}else{if(x>u){s=this.get("AFTER")}else{if(w<=u){s=this.get("CONTAINED_BY")}else{s=this.get("OVERLAP_END")}}}return s},contains:function(s){return this.compute_overlap(s)===this.get("CONTAINS")},overlaps:function(s){return q.intersection([this.compute_overlap(s)],[this.get("DIF_CHROMS"),this.get("BEFORE"),this.get("AFTER")]).length===0}});var l=Backbone.Collection.extend({model:f});var d=Backbone.RelationalModel.extend({defaults:{region:null,note:""},relations:[{type:Backbone.HasOne,key:"region",relatedModel:f}]});var p=Backbone.Collection.extend({model:d});var r=h.Dataset.extend({initialize:function(s){this.set("id",s.dataset_id);var t=new c({dataset:this});this.set("data_manager",t);var u=this.get("preloaded_data");if(u){t.set("num_elements",u.data.length);q.each(u.data,function(v){t.set_data(v.region,v)})}},get_genome_wide_data:function(s){var t=this.get("data_manager");return q.map(s.get("chroms_info").chrom_info,function(u){return t.get_elt(new f({chrom:u.chrom,start:0,end:u.len}))})}});var n=Backbone.RelationalModel.extend({defaults:{id:"",title:"",type:"",dbkey:"",tracks:null},relations:[{type:Backbone.HasMany,key:"tracks",relatedModel:r}],url:function(){return galaxy_paths.get("visualization_url")},save:function(){return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(this)}})}});var k=n.extend({defaults:q.extend({},n.prototype.defaults,{bookmarks:null,viewport:null})});var a=Backbone.Model.extend({});var g=Backbone.Router.extend({initialize:function(t){this.view=t.view;this.route(/([\w]+)$/,"change_location");this.route(/([\w]+\:[\d,]+-[\d,]+)$/,"change_location");var s=this;s.view.on("navigate",function(u){s.navigate(u)})},change_location:function(s){this.view.go_to(s)}});return{BrowserBookmark:d,BrowserBookmarkCollection:p,Cache:o,CanvasManager:e,Genome:b,GenomeDataManager:c,GenomeRegion:f,GenomeRegionCollection:l,GenomeVisualization:k,ReferenceTrackDataManager:m,TrackBrowserRouter:g,TrackConfig:a,Visualization:n}}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/compile_templates.py --- a/static/scripts/templates/compile_templates.py +++ b/static/scripts/templates/compile_templates.py @@ -46,153 +46,99 @@ from glob import glob from subprocess import call -from shutil import copyfile -from os import path +import os from optparse import OptionParser -from HTMLParser import HTMLParser +import re -import logging -log = logging.getLogger( __name__ ) +import logging as log +log.basicConfig( + #level = log.DEBUG, + name = __name__ +) COMPILED_DIR = 'compiled' COMPILED_EXT = '.js' COMPILE_CMD_STR = "handlebars %s -f %s" COMPILE_MINIMIZE_SWITCH = ' -m' +TEMPLATE_TAG = 'script' +TEMPLATE_TYPE = 'text/template' +HELPER_TYPE = 'text/javascript' + # both of these are off by default for backward compat DEFAULT_MINIMIZATION = False DEFAULT_MULTI_EXT = None #'.html' # ------------------------------------------------------------------------------ -class HTMLMultiTemplateParser( HTMLParser ): - """Parses multiple templates from an HTML file, saving them to a map of: - { id : template_text, ... } +def parse_html_tag_attrs( string ): + attrs = {} + for match in re.finditer( r'(?P<key>\w+?)=[\'|\"](?P<val>.*?)[\'|\"]', string, re.DOTALL | re.MULTILINE ): + match = match.groupdict() + key = match[ 'key' ] + val = match[ 'val' ] + attrs[ key ] = val + return attrs + +def split_on_html_tag( string, tag ): + tag_pattern = r'<%s\s*(?P<attrs>.*?)>(?P<body>.*?)</%s>' % ( tag, tag ) + log.debug( tag_pattern ) + tag_pattern = re.compile( tag_pattern, re.MULTILINE | re.DOTALL ) + + found_list = re.findall( tag_pattern, string ) + for attrs, body in found_list: + yield ( parse_html_tag_attrs( attrs ), body ) + +def filter_on_tag_type( generator, type_attr_to_match ): + for attrs, body in generator: + log.debug( 'attrs: %s', str( attrs ) ) + if( ( 'type' in attrs ) + and ( attrs[ 'type' ] == type_attr_to_match ) ): + yield attrs, body + - Templates must: - * be within the TEMPLATE_TAG - * TEMPLATE_TAG must have a type attribute - * that attr must == TEMPLATE_TYPE - * TEMPLATE_TAG cannot be nested within one another - * TEMPLATE_TAG must have an id attribute - """ - TEMPLATE_TAG = 'script' - TEMPLATE_TYPES = [ 'text/template' ] - - HELPER_TAG = 'script' - HELPER_TYPES = [ 'text/javascript' ] - - def __init__( self ): - HTMLParser.__init__( self ) - self.templates = {} - self.curr_template_id = None - self.template_data = '' - - self.helpers = {} - self.curr_helper_id = None - self.helper_data = '' - - def is_template_tag( self, tag, attr_dict ): - # both tag and type attr must match - return ( ( tag == self.TEMPLATE_TAG ) - and ( 'type' in attr_dict ) - and ( attr_dict[ 'type' ] in self.TEMPLATE_TYPES ) ) - - def is_helper_tag( self, tag, attr_dict ): - # both tag and type attr must match - return ( ( tag == self.HELPER_TAG ) - and ( 'type' in attr_dict ) - and ( attr_dict[ 'type' ] in self.HELPER_TYPES ) ) - - def handle_starttag( self, tag, attrs ): - attr_dict = dict( attrs ) - if self.is_template_tag( tag, attr_dict ): - log.debug( "\t template tag: %s, %s", tag, str( attr_dict ) ); - - # as far as I know these tags can't/shouldn't nest/overlap - #pre: not already inside a template/helper tag - assert self.curr_template_id == None, "Found nested template tag: %s" % ( self.curr_template_id ) - assert self.curr_helper_id == None, "Found template tag inside helper: %s" % ( self.curr_helper_id ) - #pre: must have an id - assert 'id' in attr_dict, "No id attribute in template: " + str( attr_dict ) - - self.curr_template_id = attr_dict[ 'id' ] - - elif self.is_helper_tag( tag, attr_dict ): - log.debug( "\t helper tag: %s, %s", tag, str( attr_dict ) ); - - #pre: not already inside a template/helper tag - assert self.curr_helper_id == None, "Found nested helper tag: %s" % ( self.curr_helper_id ) - assert self.curr_template_id == None, "Found helper tag inside template: %s" % ( self.curr_template_id ) - #pre: must have an id - assert 'id' in attr_dict, "No id attribute in helper: " + str( attr_dict ) - - self.curr_helper_id = attr_dict[ 'id' ] - - def handle_endtag( self, tag ): - if( ( tag == self.TEMPLATE_TAG ) - and ( self.curr_template_id ) ): - log.debug( "\t ending template tag :", tag, self.curr_template_id ); - - # store the template data by the id - if self.template_data: - self.templates[ self.curr_template_id ] = self.template_data - - #! reset for next template - self.curr_template_id = None - self.template_data = '' - - elif( ( tag == self.HELPER_TAG ) - and ( self.curr_helper_id ) ): - log.debug( "\t ending helper tag :", tag, self.curr_template_id ); - - # store the template data by the id - if self.helper_data: - self.helpers[ self.curr_helper_id ] = self.helper_data - - #! reset for next template - self.curr_helper_id = None - self.helper_data = '' - - def handle_data(self, data): - data = data.strip() - if data: - if self.curr_template_id: - log.debug( "\t template text :", data ); - self.template_data += data - - elif self.curr_helper_id: - log.debug( "\t helper js fn :", data ); - self.helper_data += data - - # ------------------------------------------------------------------------------ def break_multi_template( multi_template_filename ): """parse the multi template, writing each template into a new handlebars tmpl and returning their names""" template_filenames = [] - parser = HTMLMultiTemplateParser() # parse the multi template print "\nBreaking multi-template file %s into individual templates and helpers:" % ( multi_template_filename ) with open( multi_template_filename, 'r' ) as multi_template_file: - # wish I could use a gen here - parser.feed( multi_template_file.read() ) + multi_template_file_text = multi_template_file.read() - # after breaking, write each indiv. template and save the names - for template_id, template_text in parser.templates.items(): + # write a template file for each template (name based on id in tag) + tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG ) + for attrs, template_text in filter_on_tag_type( tag_generator, TEMPLATE_TYPE ): + if( 'id' not in attrs ): + log.warning( 'Template has no "id". attrs: %s' %( str( attrs ) ) ) + continue + + template_id = attrs[ 'id' ] + template_text = template_text.strip() handlebar_template_filename = template_id + '.handlebars' with open( handlebar_template_filename, 'w' ) as handlebar_template_file: handlebar_template_file.write( template_text ) + log.debug( "%s\n%s\n", template_id, template_text ) template_filenames.append( handlebar_template_filename ) - # write all helpers to a 'helper-' prefixed js file in the compilation dir - if parser.helpers: - helper_filename = 'helpers-' + path.splitext( multi_template_filename )[0] + '.js' - helper_filename = path.join( COMPILED_DIR, helper_filename ) + ## write all helpers to a single 'helper-' prefixed js file in the compilation dir + helper_fns = [] + # same tag, different type + tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG ) + for attrs, helper_text in filter_on_tag_type( tag_generator, HELPER_TYPE ): + helper_text = helper_text.strip() + print '(helper):', ( attrs[ 'id' ] if 'id' in attrs else '(No id)' ) + + helper_fns.append( helper_text ) + + if helper_fns: + # prefix original filename (in compiled dir) and write all helper funcs to that file + helper_filename = 'helpers-' + os.path.splitext( multi_template_filename )[0] + '.js' + helper_filename = os.path.join( COMPILED_DIR, helper_filename ) with open( helper_filename, 'w' ) as helper_file: - for helper_fn_name, helper_fn in parser.helpers.items(): - print '(helper)', helper_fn_name - helper_file.write( helper_fn + '\n' ) + helper_file.write( '\n'.join( helper_fns ) ) + print '(helper functions written to %s)' % helper_filename print '\n'.join( template_filenames ) return template_filenames @@ -204,8 +150,8 @@ Use the basename of the template file for the outputed js. """ - template_basename = path.splitext( path.split( template_filename )[1] )[0] - compiled_filename = path.join( COMPILED_DIR, template_basename + COMPILED_EXT ) + template_basename = os.path.splitext( os.path.split( template_filename )[1] )[0] + compiled_filename = os.path.join( COMPILED_DIR, template_basename + COMPILED_EXT ) command_string = COMPILE_CMD_STR % ( template_filename, compiled_filename ) if minimize: @@ -233,6 +179,7 @@ # if desired, break up any passed-in or found multi template files # adding the names of the new single templates to those needing compilation + multi_template_template_filenames = [] if options.multi_ext: multi_templates = [] if len( args ) >= 1: @@ -241,10 +188,10 @@ multi_templates = glob( '*' + options.multi_ext ) for multi_template_filename in multi_templates: - handlebars_templates.extend( break_multi_template( multi_template_filename ) ) + multi_template_template_filenames.extend( break_multi_template( multi_template_filename ) ) # unique filenames only (Q&D) - handlebars_templates = list( set( handlebars_templates ) ) + handlebars_templates = list( set( handlebars_templates + multi_template_template_filenames ) ) # compile the templates print "\nCompiling templates:" @@ -260,6 +207,12 @@ print ',\n'.join( filenames_w_possible_errors ) print "\nCall this script with the '-h' for more help" + # delete multi template intermediate files + print "\nCleaning up intermediate multi-template template files:" + for filename in multi_template_template_filenames: + print 'removing', filename + os.remove( filename ) + # ------------------------------------------------------------------------------ if __name__ == '__main__': diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/compiled/helpers-common-templates.js --- a/static/scripts/templates/compiled/helpers-common-templates.js +++ b/static/scripts/templates/compiled/helpers-common-templates.js @@ -3,6 +3,11 @@ Handlebars.registerPartial( 'clearFloatDiv', function( options ){ return '<div class="clear"></div>'; }); +/** Renders a warning in a (mostly css) highlighted, iconned warning box + */ +Handlebars.registerHelper( 'warningmessagesmall', function( options ){ + return '<div class="warningmessagesmall"><strong>' + options.fn( this ) + '</strong></div>' +}); /** Renders a glx style icon-button (see IconButton in mvc/ui.js) * can be used in either of the following ways: * within a template: {{> iconButton buttonData}} @@ -29,9 +34,4 @@ buffer += '>' + ( ( buttonData.enabled )?( '</a>' ):( '</span>' ) ); return buffer; -}); -/** Renders a warning in a (mostly css) highlighted, iconned warning box - */ -Handlebars.registerHelper( 'warningmessagesmall', function( options ){ - return '<div class="warningmessagesmall"><strong>' + options.fn( this ) + '</strong></div>' -}); +}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/compiled/template-history-displayApps.js --- /dev/null +++ b/static/scripts/templates/compiled/template-history-displayApps.js @@ -0,0 +1,42 @@ +(function() { + var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; +templates['template-history-displayApps'] = template(function (Handlebars,depth0,helpers,partials,data) { + helpers = helpers || Handlebars.helpers; + var stack1, functionType="function", escapeExpression=this.escapeExpression, self=this; + +function program1(depth0,data) { + + var buffer = "", stack1, foundHelper; + buffer += "\n "; + foundHelper = helpers.label; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.label; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "\n "; + stack1 = depth0.links; + stack1 = helpers.each.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(2, program2, data)}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n <br />\n"; + return buffer;} +function program2(depth0,data) { + + var buffer = "", stack1, foundHelper; + buffer += "\n <a target=\""; + foundHelper = helpers.target; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.target; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "\" href=\""; + foundHelper = helpers.href; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.href; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "\">"; + foundHelper = helpers.text; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.text; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "</a>\n "; + return buffer;} + + stack1 = depth0.displayApps; + stack1 = helpers.each.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(1, program1, data)}); + if(stack1 || stack1 === 0) { return stack1; } + else { return ''; }}); +})(); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/compiled/template-history-downloadLinks.js --- /dev/null +++ b/static/scripts/templates/compiled/template-history-downloadLinks.js @@ -0,0 +1,55 @@ +(function() { + var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; +templates['template-history-downloadLinks'] = template(function (Handlebars,depth0,helpers,partials,data) { + helpers = helpers || Handlebars.helpers; + var stack1, functionType="function", escapeExpression=this.escapeExpression, self=this; + +function program1(depth0,data) { + + var buffer = "", stack1, foundHelper; + buffer += "\n<div popupmenu=\"dataset-"; + foundHelper = helpers.id; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "-popup\">\n <a class=\"action-button\" href=\""; + foundHelper = helpers.download_url; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "\">Download Dataset</a>\n <a>Additional Files</a>\n "; + stack1 = depth0.meta_files; + stack1 = helpers.each.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(2, program2, data)}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n</div>\n<div style=\"float:left;\" class=\"menubutton split popup\" id=\"dataset-"; + foundHelper = helpers.id; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "-popup\">\n <a href=\""; + foundHelper = helpers.download_url; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n</div>\n"; + return buffer;} +function program2(depth0,data) { + + var buffer = "", stack1, foundHelper; + buffer += "\n <a class=\"action-button\" href=\""; + foundHelper = helpers.meta_download_url; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.meta_download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "\">Download "; + foundHelper = helpers.meta_file_type; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.meta_file_type; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "</a>\n "; + return buffer;} + +function program4(depth0,data) { + + + return "\n<a href=\"\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n";} + + stack1 = depth0.meta_files; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(4, program4, data),fn:self.program(1, program1, data)}); + if(stack1 || stack1 === 0) { return stack1; } + else { return ''; }}); +})(); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/compiled/tool_search.js --- a/static/scripts/templates/compiled/tool_search.js +++ b/static/scripts/templates/compiled/tool_search.js @@ -9,7 +9,7 @@ foundHelper = helpers.search_hint_string; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } else { stack1 = depth0.search_hint_string; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - buffer += escapeExpression(stack1) + "\" id=\"tool-search-query\" autocomplete=\"off\" class=\"search-query parent-width\" />\n<a id=\"search-clear-btn\" class=\"icon-button cross-circle tooltip\" title=\"clear search (esc)\"></a>\n<img src=\""; + buffer += escapeExpression(stack1) + "\" id=\"tool-search-query\" autocomplete=\"off\" class=\"search-query parent-width\" />\n<a id=\"search-clear-btn\" class=\"tooltip\" title=\"clear search (esc)\"></a>\n<img src=\""; foundHelper = helpers.spinner_url; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } else { stack1 = depth0.spinner_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/history-templates.html --- a/static/scripts/templates/history-templates.html +++ b/static/scripts/templates/history-templates.html @@ -51,6 +51,23 @@ {{/warningmessagesmall}} </script> +<script type="text/template" class="template-history" id="template-history-downloadLinks"> +{{#if meta_files}} +<div popupmenu="dataset-{{id}}-popup"> + <a class="action-button" href="{{download_url}}">Download Dataset</a> + <a>Additional Files</a> + {{#each meta_files}} + <a class="action-button" href="{{meta_download_url}}">Download {{meta_file_type}}</a> + {{/each}} +</div> +<div style="float:left;" class="menubutton split popup" id="dataset-{{id}}-popup"> + <a href="{{download_url}}" title="Download" class="icon-button disk tooltip"></a> +</div> +{{else}} +<a href="" title="Download" class="icon-button disk tooltip"></a> +{{/if}} +</script> + <script type="text/template" class="template-history" id="template-history-tagArea"> {{! TODO: move to mvc/tag.js templates }} <div class="tag-area" style="display: none;"> @@ -70,3 +87,12 @@ </div></script> +<script type="text/template" class="template-history" id="template-history-displayApps"> +{{#each displayApps}} + {{label}} + {{#each links}} + <a target="{{target}}" href="{{href}}">{{text}}</a> + {{/each}} + <br /> +{{/each}} +</script> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/template-history-annotationArea.handlebars --- a/static/scripts/templates/template-history-annotationArea.handlebars +++ /dev/null @@ -1,7 +0,0 @@ -{{! TODO: move to mvc/annotations.js templates, editable-text }} -<div id="{{ id }}-annotation-area" class="annotation-area" style="display: none;"> - <strong>Annotation:</strong> - <div id="{{ id }}-anotation-elt" class="annotation-elt tooltip editable-text" - style="margin: 1px 0px 1px 0px" title="Edit dataset annotation"> - </div> -</div> \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/template-history-failedMetaData.handlebars --- a/static/scripts/templates/template-history-failedMetaData.handlebars +++ /dev/null @@ -1,4 +0,0 @@ -{{#warningmessagesmall}} -An error occurred setting the metadata for this dataset. -You may be able to <a href="{{ edit_url }}" target="galaxy_main">set it manually or retry auto-detection</a>. -{{/warningmessagesmall}} \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/template-history-hdaSummary.handlebars --- a/static/scripts/templates/template-history-hdaSummary.handlebars +++ /dev/null @@ -1,13 +0,0 @@ -<div class="hda-summary"> - {{ misc_blurb }}<br /> - format: <span class="{{ data_type }}">{{ data_type }}</span>, - database: - {{#if dbkey_unknown_and_editable }} - <a href="{{ edit_url }}" target="galaxy_main">{{ metadata_dbkey }}</a> - {{else}} - <span class="{{ metadata_dbkey }}">{{ metadata_dbkey }}</span> - {{/if}} -</div> -{{#if misc_info}} -<div class="hda-info">{{ misc_info }}</div> -{{/if}} \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/template-history-tagArea.handlebars --- a/static/scripts/templates/template-history-tagArea.handlebars +++ /dev/null @@ -1,6 +0,0 @@ -{{! TODO: move to mvc/tag.js templates }} -<div class="tag-area" style="display: none;"> - <strong>Tags:</strong> - <div class="tag-elt"> - </div> -</div> \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/template-history-titleLink.handlebars --- a/static/scripts/templates/template-history-titleLink.handlebars +++ /dev/null @@ -1,1 +0,0 @@ -<a href="javascript:void(0);"><span class="historyItemTitle">{{ hid }}: {{ name }}</span></a> \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/template-history-warning-messages.handlebars --- a/static/scripts/templates/template-history-warning-messages.handlebars +++ /dev/null @@ -1,23 +0,0 @@ -{{#if deleted}}{{#warningmessagesmall}} - This dataset has been deleted. - {{#if undelete_url}} - Click <a href="{{ undelete_url }}" class="historyItemUndelete" id="historyItemUndeleter-{{ id }}" - target="galaxy_history">here</a> to undelete it - {{#if purge_url}} - or <a href="{{ purge_url }}" class="historyItemPurge" id="historyItemPurger-{{ id }}" - target="galaxy_history">here</a> to immediately remove it from disk - {{/if}} - {{/if}} -{{/warningmessagesmall}}{{/if}} - -{{#if purged}}{{#warningmessagesmall}} - This dataset has been deleted and removed from disk. -{{/warningmessagesmall}}{{/if}} - -{{#unless visible}}{{#warningmessagesmall}} - This dataset has been hidden. - {{#if unhide_url}} - Click <a href="{{ unhide_url }}" class="historyItemUnhide" id="historyItemUnhider-{{ id }}" - target="galaxy_history">here</a> to unhide it - {{/if}} -{{/warningmessagesmall}}{{/unless}} \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/template-iconButton.handlebars --- a/static/scripts/templates/template-iconButton.handlebars +++ /dev/null @@ -1,2 +0,0 @@ -{{! alternate template-based icon-button }} -{{> iconButton this}} \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/template-warningmessagesmall.handlebars --- a/static/scripts/templates/template-warningmessagesmall.handlebars +++ /dev/null @@ -1,2 +0,0 @@ -{{! renders a warning in a (mostly css) highlighted, iconned warning box }} - <div class="warningmessagesmall"><strong>{{{ warning }}}</strong></div> \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/templates/tool_search.handlebars --- a/static/scripts/templates/tool_search.handlebars +++ b/static/scripts/templates/tool_search.handlebars @@ -1,3 +1,3 @@ <input type="text" name="query" value="{{search_hint_string}}" id="tool-search-query" autocomplete="off" class="search-query parent-width" /> -<a id="search-clear-btn" class="icon-button cross-circle tooltip" title="clear search (esc)"></a> +<a id="search-clear-btn" class="tooltip" title="clear search (esc)"></a><img src="{{spinner_url}}" id="search-spinner" class="search-spinner"/> \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/viz/circster.js --- a/static/scripts/viz/circster.js +++ b/static/scripts/viz/circster.js @@ -1,4 +1,4 @@ -define( ["libs/d3", "viz/visualization"], function( d3, visualization ) { +define(["libs/underscore", "libs/d3", "viz/visualization"], function(_, d3, visualization) { // General backbone style inheritence var Base = function() { this.initialize && this.initialize.apply(this, arguments); }; Base.extend = Backbone.Model.extend; @@ -28,6 +28,18 @@ }); /** + * A label track. + */ +// FIXME: merge with tracks.js LabelTrack +var LabelTrack = Backbone.Model.extend({ + defaults: { + prefs: { + color: '#ccc' + } + } +}); + +/** * Renders a full circster visualization. */ var CircsterView = Backbone.View.extend({ @@ -38,6 +50,7 @@ this.genome = options.genome; this.dataset_arc_height = options.dataset_arc_height; this.track_gap = 5; + this.label_arc_height = 20; }, render: function() { @@ -47,8 +60,10 @@ height = self.$el.height(), // Compute radius start based on model, will be centered // and fit entirely inside element by default. - init_radius_start = ( Math.min(width, height)/2 - - this.model.get('tracks').length * (this.dataset_arc_height + this.track_gap) ); + init_radius_start = Math.min(width, height) / 2 - + this.model.get('tracks').length * (this.dataset_arc_height + this.track_gap) - + (this.label_arc_height + this.track_gap), + tracks = this.model.get('tracks'); // Set up SVG element. var svg = d3.select(self.$el[0]) @@ -59,31 +74,61 @@ // Set up zooming, dragging. .append('svg:g') .call(d3.behavior.zoom().on('zoom', function() { + // Do zoom. svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); - var utils = new SVGUtils(); - var visible_elts = d3.selectAll('path').filter(function(d, i) { + + // Update visible elements with more data. + var utils = new SVGUtils(), + tracks_and_chroms_to_update = {}; + + tracks.each(function(t) { + tracks_and_chroms_to_update[t.id] = []; + }); + + d3.selectAll('path.chrom-data').filter(function(d, i) { return utils.is_visible(this, svg); + }).each(function(d, i) { + var elt_data = $.data(this, 'chrom_data'); + tracks_and_chroms_to_update[elt_data.track.id].push(elt_data.chrom); }); - visible_elts.each(function(d, i) { - // TODO: redraw visible elements. + + /* + _.each(_.pairs(tracks_and_chroms_to_update), function(track_and_chroms) { + var track = tracks.get(track_and_chroms[0]) + chroms = track_and_chroms[1]; + + _.each(chroms, function(chr_name) { + var chr_region = self.genome.get_chrom_region(chr_name), + data_deferred = track.get('data_manager').get_more_detailed_data(chr_region, 'Coverage', 0, d3.event.scale); + + $.when(data_deferred).then(function(data) { + console.log("got more detailed data", data); + }) + }) + + }); + + // TODO: update tracks and chroms. + console.log(tracks_and_chroms_to_update); + */ })) .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")") .append('svg:g'); // -- Render each dataset in the visualization. -- - this.model.get('tracks').each(function(track, index) { - var dataset = track.get('genome_wide_data'), - radius_start = init_radius_start + index * (dataset_arc_height + self.track_gap), - track_renderer_class = (dataset instanceof visualization.GenomeWideBigWigData ? + tracks.each(function(track, index) { + var radius_start = init_radius_start + index * (dataset_arc_height + self.track_gap), + track_renderer_class = (track.get('track_type') === 'LineTrack' ? CircsterBigWigTrackRenderer : CircsterSummaryTreeTrackRenderer ); var track_renderer = new track_renderer_class({ track: track, + track_index: index, radius_start: radius_start, radius_end: radius_start + dataset_arc_height, genome: self.genome, @@ -93,47 +138,67 @@ track_renderer.render(svg); }); + + // -- Render chromosome labels. -- + var radius_start = init_radius_start + tracks.length * (dataset_arc_height + self.track_gap) + self.track_gap; + var chrom_labels_track = new CircsterLabelTrackRenderer({ + track: new LabelTrack(), + track_index: tracks.length, + radius_start: radius_start, + radius_end: radius_start, + genome: self.genome, + total_gap: self.total_gap + }); + + chrom_labels_track.render(svg); } }); var CircsterTrackRenderer = Base.extend( { - initialize: function( options ) { + initialize: function(options) { this.options = options; + this.options.bg_stroke = 'ccc'; + this.options.bg_fill = 'ccc'; }, - render: function( svg ) { - // Draw background arcs for each chromosome. - var genome_arcs = this.chroms_layout(), + render: function(svg) { + // Create track group element. + var track_group_elt = svg.append("g").attr("id", "parent-" + this.options.track_index); + + // Render background arcs. + var genome_arcs = this._chroms_layout(), radius_start = this.options.radius_start, radius_end = this.options.radius_end, - track_parent_elt = svg.append("g").attr("id", "inner-arc"), arc_gen = d3.svg.arc() - .innerRadius(radius_start) - .outerRadius(radius_end), - // Draw arcs. - chroms_elts = track_parent_elt.selectAll("#inner-arc>path") - .data(genome_arcs).enter().append("path") - .attr("d", arc_gen) - .style("stroke", "#ccc") - .style("fill", "#ccc") - .append("title").text(function(d) { return d.data.chrom; }); + .innerRadius(radius_start) + .outerRadius(radius_end), - // Render data. - this.render_data(track_parent_elt); + chroms_elts = track_group_elt.selectAll('g') + .data(genome_arcs).enter().append('svg:g'); + + // Draw arcs. + chroms_elts.append("path") + .attr("d", arc_gen) + .style("stroke", this.options.bg_stroke) + .style("fill", this.options.bg_fill) + .append("title").text(function(d) { return d.data.chrom; }); + + // Render track data. + this.render_data(track_group_elt); // Apply prefs. var prefs = this.options.track.get('prefs'), block_color = prefs.block_color; if (!block_color) { block_color = prefs.color; } - track_parent_elt.selectAll('path.chrom-data').style('stroke', block_color).style('fill', block_color); + track_group_elt.selectAll('path.chrom-data').style('stroke', block_color).style('fill', block_color); }, /** * Returns arc layouts for genome's chromosomes/contigs. Arcs are arranged in a circle * separated by gaps. */ - chroms_layout: function() { + _chroms_layout: function() { // Setup chroms layout using pie. var chroms_info = this.options.genome.get_chroms_info(), pie_layout = d3.layout.pie().value(function(d) { return d.len; }).sort(null), @@ -159,13 +224,18 @@ */ render_data: function(svg) { var self = this, - chrom_arcs = this.chroms_layout(), - dataset = this.options.track.get('genome_wide_data'), + chrom_arcs = this._chroms_layout(), + track = this.options.track, r_start = this.options.radius_start, r_end = this.options.radius_end, + + genome_wide_data = track.get_genome_wide_data(this.options.genome), // Merge chroms layout with data. - layout_and_data = _.zip(chrom_arcs, dataset.get('data')), + layout_and_data = _.zip(chrom_arcs, genome_wide_data), + + // Get min, max in data. + bounds = this.get_bounds(genome_wide_data), // Do dataset layout for each chromosome's data using pie layout. chroms_data_layout = _.map(layout_and_data, function(chrom_info) { @@ -173,7 +243,7 @@ data = chrom_info[1]; return self.render_chrom_data(svg, chrom_arc, data, r_start, r_end, - dataset.get('min'), dataset.get('max')); + bounds.min, bounds.max); }); return chroms_data_layout; @@ -181,13 +251,49 @@ }); /** + * Render chromosome labels. + */ +var CircsterLabelTrackRenderer = CircsterTrackRenderer.extend({ + + initialize: function(options) { + this.options = options; + this.options.bg_stroke = 'fff'; + this.options.bg_fill = 'fff'; + }, + + /** + * Render labels. + */ + render_data: function(svg) { + // Add chromosome label where it will fit; an alternative labeling mechanism + // would be nice for small chromosomes. + var chrom_arcs = svg.selectAll('g'); + + chrom_arcs.selectAll('path') + .attr('id', function(d) { return 'label-' + d.data.chrom; }) + + chrom_arcs.append("svg:text") + .filter(function(d) { + return d.endAngle - d.startAngle > 0.08; + }) + .attr('text-anchor', 'middle') + .append("svg:textPath") + .attr("xlink:href", function(d) { return "#label-" + d.data.chrom; }) + .attr('startOffset', '25%') + .text(function(d) { + return d.data.chrom; + }); + } +}); + +/** * Rendered for quantitative data. */ var CircsterQuantitativeTrackRenderer = CircsterTrackRenderer.extend({ /** * Renders quantitative data with the form [x, value] and assumes data is equally spaced across - * chromosome. + * chromosome. Attachs a dict with track and chrom name information to DOM element. */ render_quantitative_data: function(svg, chrom_arc, data, inner_radius, outer_radius, min, max) { // Radius scaler. @@ -212,14 +318,25 @@ .angle(line.angle()); // Render data. - var parent = svg.datum(data); - - parent.append("path") - .attr("class", "chrom-data") - .attr("d", area); - } + var parent = svg.datum(data), + path = parent.append("path") + .attr("class", "chrom-data") + .attr("d", area); -}) + // Attach dict with track and chrom info for path. + $.data(path[0][0], "chrom_data", { + track: this.options.track, + chrom: chrom_arc.data.chrom + }); + }, + + /** + * Returns an object with min, max attributes denoting the minimum and maximum + * values for the track. + */ + get_bounds: function() {} + +}); /** * Layout for summary tree data in a circster visualization. @@ -235,7 +352,19 @@ return null; } - return this.render_quantitative_data(svg, chrom_arc, chrom_data[0], inner_radius, outer_radius, min, max); + return this.render_quantitative_data(svg, chrom_arc, chrom_data.data, inner_radius, outer_radius, min, max); + }, + + get_bounds: function(data) { + // Get max across data. + var max_data = _.map(data, function(d) { + if (!d || typeof d === 'string') { return 0; } + return d.max; + }); + return { + min: 0, + max: (max_data && typeof max_data !== 'string' ? _.max(max_data) : 0) + }; } }); @@ -252,6 +381,27 @@ if (data.length === 0) { return; } return this.render_quantitative_data(svg, chrom_arc, data, inner_radius, outer_radius, min, max); + }, + + get_bounds: function(data) { + // Set max across dataset by extracting all values, flattening them into a + // single array, and getting the min and max. + var values = _.flatten( _.map(data, function(d) { + if (d) { + // Each data point has the form [position, value], so return all values. + return _.map(d.data, function(p) { + return p[1]; + }); + } + else { + return 0; + } + }) ); + + return { + min: _.min(values), + max: _.max(values) + }; } }); diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/viz/scatterplot.js --- a/static/scripts/viz/scatterplot.js +++ b/static/scripts/viz/scatterplot.js @@ -1,3 +1,9 @@ +define([ + "../libs/underscore", + "../libs/d3", + "../mvc/base-mvc" + +], function(){ /* ============================================================================= todo: outside this: @@ -355,11 +361,11 @@ }; } -//// ugh...this seems like the wrong way to use models -//var ScatterplotModel = BaseModel.extend( LoggableMixin ).extend({ -// logger : console -//}); - +//============================================================================== +/** + * Scatterplot control UI as a backbone view + * + */ var ScatterplotView = BaseView.extend( LoggableMixin ).extend({ //logger : console, tagName : 'form', @@ -370,15 +376,19 @@ }, initialize : function( attributes ){ - if( !attributes.dataset ){ + if( !attributes || !attributes.dataset ){ throw( "ScatterplotView requires a dataset" ); } else { this.dataset = attributes.dataset; } + + // passed from mako helper + //TODO: integrate to galaxyPaths this.apiDatasetsURL = attributes.apiDatasetsURL; + + // set up the basic chart infrastructure with config (if any) this.chartConfig = attributes.chartConfig || {}; this.log( 'this.chartConfig:', this.chartConfig ); - this.plot = new TwoVarScatterplot( this.chartConfig ); }, @@ -422,18 +432,23 @@ }, renderScatterplot : function(){ + // parse the column values for both + // indeces (for the data fetch) and names (for the graph) var view = this, - url = this.apiDatasetsURL + '/' + this.dataset.id + '?data_type=raw_data&'; + url = this.apiDatasetsURL + '/' + this.dataset.id + '?data_type=raw_data&', + xSelector = this.$el.find( '[name="x-column"]' ), xVal = xSelector.val(), xName = xSelector.children( '[value="' + xVal + '"]' ).text(), + ySelector = this.$el.find( '[name="y-column"]' ), yVal = ySelector.val(), yName = ySelector.children( '[value="' + yVal + '"]' ).text(); - //TODO this.log( xName, yName ); + this.chartConfig.xLabel = xName; this.chartConfig.yLabel = yName; + //TODO: alter directly view.plot.updateConfig( this.chartConfig ); @@ -441,6 +456,7 @@ //TODO: other vals: max, start, page //TODO: chart config + // fetch the data, sending chosen columns to the server url += jQuery.param({ columns : '[' + [ xVal, yVal ] + ']' }); @@ -450,6 +466,7 @@ url : url, dataType : 'json', success : function( response ){ + //TODO: server sends back an endpoint, cache for next pagination request view.endpoint = response.endpoint; view.plot.render( // pull apart first two regardless of number of columns @@ -464,3 +481,8 @@ } }); +//============================================================================== +return { + //TwoVarScatterplot : TwoVarScatterplot, + ScatterplotView : ScatterplotView +};}); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/viz/trackster/painters.js --- a/static/scripts/viz/trackster/painters.js +++ b/static/scripts/viz/trackster/painters.js @@ -729,7 +729,7 @@ /** * Draw a single read. */ - draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, orig_seq) { + draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, ref_seq) { ctx.textAlign = "center"; var tile_region = [tile_low, tile_high], base_offset = 0, @@ -743,12 +743,12 @@ // Gap is needed so that read is offset and hence first base can be drawn on read. // TODO-FIX: using this gap offsets reads so that their start is not visually in sync with other tracks. - if ((mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > char_width_px) { + if ((mode === "Pack" || this.mode === "Auto") && ref_seq !== undefined && w_scale > char_width_px) { gap = Math.round(w_scale/2); } if (!cigar) { // If no cigar string, then assume all matches - cigar = [ [0, orig_seq.length] ]; + cigar = [ [0, ref_seq.length] ]; } for (var cig_id = 0, len = cigar.length; cig_id < len; cig_id++) { var cig = cigar[cig_id], @@ -782,7 +782,8 @@ case "=": // Equals. if (is_overlap([seq_start, seq_start + cig_len], tile_region)) { // Draw. - var seq = orig_seq.slice(seq_offset, seq_offset + cig_len); + // -1 b/c sequence data is 1-based but painter is 0-based. + var seq = ref_seq.slice(seq_offset - 1, seq_offset + cig_len); if (gap > 0) { ctx.fillStyle = block_color; ctx.fillRect(s_start - gap, y_center + 1, s_end - s_start, 9); @@ -838,7 +839,8 @@ var insert_x_coord = s_start - gap; if (is_overlap([seq_start, seq_start + cig_len], tile_region)) { - var seq = orig_seq.slice(seq_offset, seq_offset + cig_len); + // -1 b/c sequence data is 1-based but painter is 0-based. + var seq = ref_seq.slice(seq_offset - 1, seq_offset + cig_len); // Insertion point is between the sequence start and the previous base: (-gap) moves // back from sequence start to insertion point. if (this.prefs.show_insertions) { @@ -849,7 +851,7 @@ // Draw sequence. // X center is offset + start - <half_sequence_length> var x_center = s_start - (s_end - s_start)/2; - if ( (mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > char_width_px) { + if ( (mode === "Pack" || this.mode === "Auto") && ref_seq !== undefined && w_scale > char_width_px) { // Draw sequence container. ctx.fillStyle = "yellow"; ctx.fillRect(x_center - gap, y_center - 9, s_end - s_start, 9); @@ -885,7 +887,7 @@ } } else { - if ( (mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > char_width_px) { + if ( (mode === "Pack" || this.mode === "Auto") && ref_seq !== undefined && w_scale > char_width_px) { // Show insertions with a single number at the insertion point. draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_center + 9] } ); } diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/viz/trackster/tracks.js --- a/static/scripts/viz/trackster/tracks.js +++ b/static/scripts/viz/trackster/tracks.js @@ -1,11 +1,63 @@ define( ["libs/underscore", "viz/visualization", "viz/trackster/util", "viz/trackster/slotting", "viz/trackster/painters", "mvc/data", - "viz/trackster/filters" ], - function( _, visualization, util, slotting, painters, data, filters_mod ) { + "viz/trackster/filters", "viz/trackster_ui" ], + function( _, visualization, util, slotting, painters, data, filters_mod, trackster_ui_mod ) { var extend = _.extend; var get_random_color = util.get_random_color; +/** + * Use a popup grid to add more datasets. + */ +var add_datasets = function(dataset_url, add_track_async_url, success_fn) { + $.ajax({ + url: dataset_url, + data: { "f-dbkey": view.dbkey }, + error: function() { alert( "Grid failed" ); }, + success: function(table_html) { + show_modal( + "Select datasets for new tracks", + table_html, { + "Cancel": function() { + hide_modal(); + }, + "Add": function() { + var requests = []; + $('input[name=id]:checked,input[name=ldda_ids]:checked').each(function() { + var data = { + data_type: 'track_config', + 'hda_ldda': 'hda' + }, + id = $(this).val(); + if ($(this).attr("name") !== "id") { + data.hda_ldda = 'ldda'; + } + requests[requests.length] = $.ajax({ + url: add_track_async_url + "/" + id, + data: data, + dataType: "json" + }); + }); + // To preserve order, wait until there are definitions for all tracks and then add + // them sequentially. + $.when.apply($, requests).then(function() { + // jQuery always returns an Array for arguments, so need to look at first element + // to determine whether multiple requests were made and consequently how to + // map arguments to track definitions. + var track_defs = (arguments[0] instanceof Array ? + $.map(arguments, function(arg) { return arg[0]; }) : + [ arguments[0] ] + ); + success_fn(track_defs); + }); + hide_modal(); + } + } + ); + } + }); +}; + /** * Helper to determine if object is jQuery deferred. @@ -3427,7 +3479,7 @@ 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 ReferenceTrackDataManager({ + this.data_manager = new visualization.ReferenceTrackDataManager({ data_url: this.data_url }); this.hide_contents(); @@ -3550,8 +3602,7 @@ track.vertical_range = undefined; return $.getJSON( track.dataset.url(), { data_type: 'data', stats: true, chrom: track.view.chrom, low: 0, - high: track.view.max_high, hda_ldda: track.hda_ldda, dataset_id: - track.dataset_id }, function(result) { + high: track.view.max_high, hda_ldda: track.hda_ldda }, function(result) { track.container_div.addClass( "line-track" ); var data = result.data; if ( isNaN(parseFloat(track.prefs.min_value)) || isNaN(parseFloat(track.prefs.max_value)) ) { @@ -4197,7 +4248,8 @@ ReadTrack: ReadTrack, VcfTrack: VcfTrack, CompositeTrack: CompositeTrack, - object_from_template: object_from_template + object_from_template: object_from_template, + add_datasets: add_datasets }; // End trackster_module encapsulation diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/viz/trackster_ui.js --- a/static/scripts/viz/trackster_ui.js +++ b/static/scripts/viz/trackster_ui.js @@ -1,4 +1,4 @@ -define( ["base","libs/underscore","viz/trackster/slotting", "viz/trackster/painters","viz/trackster/tracks"], function( base, _, slotting, painters, tracks ) { +define( ["base","libs/underscore","viz/trackster/slotting", "viz/trackster/painters", "viz/trackster/tracks" ], function( base, _, slotting, painters, tracks ) { /************************************************************************ * Functions used for creating and managing the Trackster user interface. @@ -19,9 +19,9 @@ var self = this, menu = create_icon_buttons_menu([ { icon_class: 'plus-button', title: 'Add tracks', on_click: function() { - add_datasets(add_datasets_url, add_track_async_url, function(tracks) { + tracks.add_datasets(add_datasets_url, add_track_async_url, function(tracks) { _.each(tracks, function(track) { - view.add_drawable( trackster_ui.object_from_template(track, view, view) ); + view.add_drawable( object_from_template(track, view, view) ); }); }); } }, @@ -99,7 +99,8 @@ * Use a popup to select a dataset of create bookmarks from */ add_bookmarks: function() { - var baseURL = this.baseURL; + var self = this, + baseURL = this.baseURL; show_modal( "Select dataset for new bookmarks", "progress" ); $.ajax({ url: this.baseURL + "/visualization/list_histories", @@ -129,7 +130,7 @@ }).then( function(data) { for( i = 0; i < data.data.length; i++ ) { var row = data.data[i]; - add_bookmark( row[0], row[1] ); + self.add_bookmark( row[0], row[1] ); } }); }); @@ -183,7 +184,8 @@ create_visualization: function(view_config, viewport_config, drawables_config, bookmarks_config, editable) { // Create view. - view = new tracks.View(view_config); + var self = this, + view = new tracks.View(view_config); view.editor = true; $.when( view.load_chroms_deferred ).then(function() { // Viewport config. @@ -227,7 +229,7 @@ var bookmark; for (var i = 0; i < bookmarks_config.length; i++) { bookmark = bookmarks_config[i]; - add_bookmark(bookmark['position'], bookmark['annotation'], editable); + self.add_bookmark(bookmark['position'], bookmark['annotation'], editable); } } diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 static/scripts/viz/visualization.js --- a/static/scripts/viz/visualization.js +++ b/static/scripts/viz/visualization.js @@ -1,4 +1,4 @@ -define( ["mvc/data", "viz/trackster/util" ], function(data, util) { +define( ["libs/underscore", "mvc/data", "viz/trackster/util" ], function(_, data_mod, util_mod) { /** * Model, view, and controller objects for Galaxy visualization framework. @@ -138,7 +138,6 @@ dataset: null, filters_manager: null, data_type: "data", - genome_wide_summary_data: null, data_mode_compatible: function(entry, mode) { return true; }, can_subset: function(entry) { return false; } }), @@ -150,7 +149,7 @@ data_is_ready: function() { var dataset = this.get('dataset'), ready_deferred = $.Deferred(), - ss_deferred = new util.ServerStateDeferred({ + ss_deferred = new util_mod.ServerStateDeferred({ ajax_settings: { url: this.get('dataset').url(), data: { @@ -176,7 +175,6 @@ var dataset = this.get('dataset'), params = { query: query, - dataset_id: dataset.id, hda_ldda: dataset.get('hda_ldda'), data_type: 'features' }; @@ -184,26 +182,23 @@ }, /** - * Load data from server; returns Deferred object that resolves when data is available. + * Load data from server and manages data entries. Adds a Deferred to manager + * for region; when data becomes available, replaces Deferred with data. + * Returns the Deferred that resolves when data is available. */ load_data: function(region, mode, resolution, extra_params) { // Setup data request params. - var params = { + var dataset = this.get('dataset'), + params = { "data_type": this.get('data_type'), "chrom": region.get('chrom'), "low": region.get('start'), "high": region.get('end'), "mode": mode, - "resolution": resolution - }, - dataset = this.get('dataset'); - - // ReferenceDataManager does not have dataset. - if (dataset) { - params.dataset_id = dataset.id; - params.hda_ldda = dataset.get('hda_ldda'); - } - + "resolution": resolution, + "hda_ldda": dataset.get('hda_ldda') + }; + $.extend(params, extra_params); // Add track filters to params. @@ -218,10 +213,13 @@ } // Do request. - var manager = this; - return $.getJSON(dataset.url(), params, function (result) { - manager.set_data(region, result); - }); + var manager = this, + entry = $.getJSON(dataset.url(), params, function (result) { + manager.set_data(region, result); + }); + + this.set_data(region, entry); + return entry; }, /** @@ -268,12 +266,8 @@ } } } - - // Load data from server. The deferred is immediately saved until the - // data is ready, it then replaces itself with the actual data. - entry = this.load_data(region, mode, resolution, extra_params); - this.set_data(region, entry); - return entry; + + return this.load_data(region, mode, resolution, extra_params); }, /** @@ -293,15 +287,11 @@ * Gets more data for a region using either a depth-first or a breadth-first approach. */ get_more_data: function(region, mode, resolution, extra_params, req_type) { - // - // Get current data from cache and mark as stale. - // - var cur_data = this.get_elt(region); - if ( !(cur_data && this.get('data_mode_compatible')(cur_data, mode)) ) { - console.log("ERROR: no current data for: ", dataset, region.toString(), mode, resolution, extra_params); + var cur_data = this._mark_stale(region); + if (!(cur_data && this.get('data_mode_compatible')(cur_data, mode))) { + console.log('ERROR: problem with getting more data: current data is not compatible'); return; } - cur_data.stale = true; // // Set parameters based on request type. @@ -346,6 +336,43 @@ }); return new_data_available; }, + + /** + * Returns more detailed data for an entry. + */ + get_more_detailed_data: function(region, mode, resolution, detail_multiplier, extra_params) { + // Mark current entry as stale. + var cur_data = this._mark_stale(region); + if (!cur_data) { + console.log("ERROR getting more detailed data: no current data"); + return; + } + + if (!extra_params) { extra_params = {}; } + + // Use additional parameters to get more detailed data. + var mode; + if (cur_data.dataset_type === 'bigwig') { + extra_params.num_samples = cur_data.data.length * detail_multiplier; + } + else if (cur_data.dataset_type === 'summary_tree') { + extra_params.level = cur_data.level + 1; + } + + return this.load_data(region, mode, resolution, extra_params); + }, + + /** + * Marks cache data as stale. + */ + _mark_stale: function(region) { + var entry = this.get_elt(region); + if (!entry) { + console.log("ERROR: no data to mark as stale: ", this.get('dataset'), region.toString()); + } + entry.stale = true; + return entry; + }, /** * Get data from the cache. @@ -363,13 +390,21 @@ }); var ReferenceTrackDataManager = GenomeDataManager.extend({ - load_data: function(low, high, mode, resolution, extra_params) { + initialize: function(options) { + // Use generic object in place of dataset and set urlRoot to fetch data. + var dataset_placeholder = new Backbone.Model(); + dataset_placeholder.urlRoot = options.data_url; + this.set('dataset', dataset_placeholder); + }, + + load_data: function(region, mode, resolution, extra_params) { + console.log(region, mode, resolution); if (resolution > 1) { // Now that data is pre-fetched before draw, we don't load reference tracks // unless it's at the bottom level. return { data: null }; } - return GenomeDataManager.prototype.load_data.call(this, low, high, mode, resolution, extra_params); + return GenomeDataManager.prototype.load_data.call(this, region, mode, resolution, extra_params); } }); @@ -382,9 +417,29 @@ key: null, chroms_info: null }, + + initialize: function(options) { + this.id = options.dbkey; + }, + /** + * Shorthand for getting to chromosome information. + */ get_chroms_info: function() { return this.attributes.chroms_info.chrom_info; + }, + + /** + * Returns a GenomeRegion object denoting a complete chromosome. + */ + get_chrom_region: function(chr_name) { + var chrom_info = _.find(this.get_chroms_info(), function(chrom_info) { + return chrom_info.chrom == chr_name; + }); + return new GenomeRegion({ + chrom: chrom_info.chrom, + end: chrom_info.len + }); } }); @@ -533,69 +588,52 @@ model: BrowserBookmark }); -var GenomeWideBigWigData = Backbone.Model.extend({ - defaults: { - data: null, - min: 0, - max: 0 - }, - - initialize: function(options) { - // Set max across dataset by extracting all values, flattening them into a - // single array, and getting the min and max. - var values = _.flatten( _.map(this.get('data'), function(d) { - if (d.data.length !== 0) { - // Each data point has the form [position, value], so return all values. - return _.map(d.data, function(p) { - return p[1]; - }); - } - else { - return 0; - } - }) ); - this.set('max', _.max(values)); - this.set('min', _.min(values)); - } -}); - -/** - * Genome-wide summary tree dataset. - */ -var GenomeWideSummaryTreeData = Backbone.RelationalModel.extend({ - defaults: { - data: null, - min: 0, - max: 0 - }, - - initialize: function(options) { - // Set max across dataset. - var max_data = _.max(this.get('data'), function(d) { - if (!d || typeof d === 'string') { return 0; } - return d[1]; - }); - this.attributes.max = (max_data && typeof max_data !== 'string' ? max_data[1] : 0); - } -}); - /** * A track of data in a genome visualization. */ // TODO: rename to Track and merge with Trackster's Track object. -var BackboneTrack = data.Dataset.extend({ +var BackboneTrack = data_mod.Dataset.extend({ initialize: function(options) { // Dataset id is unique ID for now. this.set('id', options.dataset_id); - // Create genome-wide dataset if available. - var genome_wide_data = this.get('genome_wide_data'); - if (genome_wide_data) { - var gwd_class = (this.get('track_type') === 'LineTrack' ? - GenomeWideBigWigData : GenomeWideSummaryTreeData); - this.set('genome_wide_data', new gwd_class(genome_wide_data)); + // Set up data manager. + var data_manager = new GenomeDataManager({ + dataset: this + }); + this.set('data_manager', data_manager); + + // If there's preloaded data, add it to data manager. + var preloaded_data = this.get('preloaded_data'); + if (preloaded_data) { + // Increase size to accomodate all preloaded data. + data_manager.set('num_elements', preloaded_data.data.length); + + // Put data into manager. + _.each(preloaded_data.data, function(entry) { + data_manager.set_data(entry.region, entry); + }); } + }, + + /** + * Returns an array of data with each entry representing one chromosome/contig + * of data. + */ + get_genome_wide_data: function(genome) { + var data_manager = this.get('data_manager'); + + // Map chromosome data into track data. + return _.map(genome.get('chroms_info').chrom_info, function(chrom_info) { + return data_manager.get_elt( + new GenomeRegion({ + chrom: chrom_info.chrom, + start: 0, + end: chrom_info.len + }) + ); + }); } }); @@ -688,62 +726,6 @@ } }); -/** - * -- Helper functions. - */ - -/** - * Use a popup grid to add more datasets. - */ -var add_datasets = function(dataset_url, add_track_async_url, success_fn) { - $.ajax({ - url: dataset_url, - data: { "f-dbkey": view.dbkey }, - error: function() { alert( "Grid failed" ); }, - success: function(table_html) { - show_modal( - "Select datasets for new tracks", - table_html, { - "Cancel": function() { - hide_modal(); - }, - "Add": function() { - var requests = []; - $('input[name=id]:checked,input[name=ldda_ids]:checked').each(function() { - var data = { - data_type: 'track_config', - 'hda_ldda': 'hda' - }, - id = $(this).val(); - if ($(this).attr("name") !== "id") { - data['hda_ldda'] = 'ldda'; - } - requests[requests.length] = $.ajax({ - url: add_track_async_url + "/" + id, - data: data, - dataType: "json" - }); - }); - // To preserve order, wait until there are definitions for all tracks and then add - // them sequentially. - $.when.apply($, requests).then(function() { - // jQuery always returns an Array for arguments, so need to look at first element - // to determine whether multiple requests were made and consequently how to - // map arguments to track definitions. - var track_defs = (arguments[0] instanceof Array ? - $.map(arguments, function(arg) { return arg[0]; }) : - [ arguments[0] ] - ); - success_fn(track_defs); - }); - hide_modal(); - } - } - ); - } - }); -}; - return { BrowserBookmark: BrowserBookmark, BrowserBookmarkCollection: BrowserBookmarkCollection, @@ -754,13 +736,10 @@ GenomeRegion: GenomeRegion, GenomeRegionCollection: GenomeRegionCollection, GenomeVisualization: GenomeVisualization, - GenomeWideBigWigData: GenomeWideBigWigData, - GenomeWideSummaryTreeData: GenomeWideSummaryTreeData, ReferenceTrackDataManager: ReferenceTrackDataManager, TrackBrowserRouter: TrackBrowserRouter, TrackConfig: TrackConfig, - Visualization: Visualization, - add_datasets: add_datasets + Visualization: Visualization }; }); \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/admin/tool_shed_repository/browse_repository.mako --- a/templates/admin/tool_shed_repository/browse_repository.mako +++ b/templates/admin/tool_shed_repository/browse_repository.mako @@ -18,6 +18,9 @@ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup"><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> + %if has_readme: + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> + %endif <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a> %if repository.tool_dependencies: diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/admin/tool_shed_repository/browse_tool_dependency.mako --- a/templates/admin/tool_shed_repository/browse_tool_dependency.mako +++ b/templates/admin/tool_shed_repository/browse_tool_dependency.mako @@ -19,8 +19,11 @@ <ul class="manage-table-actions"><li><a class="action-button" id="tool_dependency-${tool_dependency.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="tool_dependency-${tool_dependency.id}-popup"> + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> + %if has_readme: + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> + %endif <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a> - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=tool_dependency_ids )}">Manage tool dependencies</a> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako --- a/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako +++ b/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako @@ -6,8 +6,11 @@ <ul class="manage-table-actions"><li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup"> + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> + %if has_readme: + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> + %endif <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a> - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> %if repository.tool_dependencies: <% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/admin/tool_shed_repository/manage_repository.mako --- a/templates/admin/tool_shed_repository/manage_repository.mako +++ b/templates/admin/tool_shed_repository/manage_repository.mako @@ -11,6 +11,9 @@ %elif can_install: <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ), operation='install' )}">Install</a> %else: + %if has_readme: + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> + %endif <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> %if repository.includes_tools: diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/admin/tool_shed_repository/manage_tool_dependencies.mako --- a/templates/admin/tool_shed_repository/manage_tool_dependencies.mako +++ /dev/null @@ -1,79 +0,0 @@ -<%inherit file="/base.mako"/> -<%namespace file="/message.mako" import="render_msg" /> - -<% import os %> - -<br/><br/> -<ul class="manage-table-actions"> - <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li> - <div popupmenu="repository-${repository.id}-popup"> - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a> - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> - %if repository.includes_tools: - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='set_tool_versions', id=trans.security.encode_id( repository.id ) )}">Set tool versions</a> - %endif - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a> - </div> -</ul> - -%if message: - ${render_msg( message, status )} -%endif - -<div class="toolForm"> - <div class="toolFormTitle">Repository '${repository.name}' tool dependencies</div> - <div class="toolFormBody"> - <div class="form-row"> - <table class="grid"> - %for tool_dependency in repository.tool_dependencies: - <% - name = tool_dependency.name - version = tool_dependency.version - type = tool_dependency.type - installed = tool_dependency.status == 'trans.model.ToolDependency.installation_status.INSTALLED - install_dir = tool_dependency.installation_directory( trans.app ) - %> - <tr> - <td bgcolor="#D8D8D8"> - <div style="float: left; margin-left: 1px;" class="menubutton split popup" id="dependency-${tool_dependency.id}-popup"> - %if not installed: - <a class="view-info" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', operation='browse', tool_dependency_id=trans.security.encode_id( tool_dependency.id ) )}"> - <b>Name</b> - </a> - <div popupmenu="dependency-${tool_dependency.id}-popup"> - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', operation='install', tool_dependency_id=trans.security.encode_id( tool_dependency.id ) )}">Install this tool dependency</a> - </div> - %else: - <a class="view-info" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', operation='browse', tool_dependency_id=trans.security.encode_id( tool_dependency.id ) )}"> - <b>Name</b> - </a> - <div popupmenu="dependency-${tool_dependency.id}-popup"> - <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', operation='uninstall', tool_dependency_id=trans.security.encode_id( tool_dependency.id ) )}">Uninstall this tool dependency</a> - </div> - %endif - </div> - </td> - <td bgcolor="#D8D8D8">${name}</td> - </tr> - <tr><th>Version</th><td>${version}</td></tr> - <tr><th>Type</th><td>${type}</td></tr> - <tr> - <th>Install directory</th> - <td> - %if not installed: - This dependency is not currently installed - %else: - <a class="view-info" href="${h.url_for( controller='admin_toolshed', action='browse_tool_dependency', id=trans.security.encode_id( tool_dependency.id ), repository_id=trans.security.encode_id( repository.id ) )}"> - ${install_dir} - </a> - %endif - </td> - </tr> - <tr><th>Installed</th><td>${not installed}</td></tr> - %endfor - </table> - <div style="clear: both"></div> - </div> - </div> -</div> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/admin/tool_shed_repository/reselect_tool_panel_section.mako --- a/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako +++ b/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako @@ -1,6 +1,7 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_tool_dependency_section" /> +<%namespace file="/webapps/community/common/common.mako" import="render_readme" /> %if message: ${render_msg( message, status )} @@ -42,3 +43,6 @@ </form></div></div> +%if readme_text: + ${render_readme( readme_text )} +%endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/admin/tool_shed_repository/select_tool_panel_section.mako --- a/templates/admin/tool_shed_repository/select_tool_panel_section.mako +++ b/templates/admin/tool_shed_repository/select_tool_panel_section.mako @@ -1,6 +1,7 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_tool_dependency_section" /> +<%namespace file="/webapps/community/common/common.mako" import="render_readme" /> %if message: ${render_msg( message, status )} @@ -77,13 +78,5 @@ </div></div> %if readme_text: - <div class="toolForm"> - <div class="toolFormTitle">Repository README file (may contain important installation or license information)</div> - <div class="toolFormBody"> - <input type="hidden" name="readme_text" value="${readme_text}"/> - <div class="form-row"> - <pre>${readme_text}</pre> - </div> - </div> - </div> + ${render_readme( readme_text )} %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/admin/tool_shed_repository/uninstall_tool_dependencies.mako --- a/templates/admin/tool_shed_repository/uninstall_tool_dependencies.mako +++ b/templates/admin/tool_shed_repository/uninstall_tool_dependencies.mako @@ -3,6 +3,24 @@ <% import os %> +<br/><br/> +<ul class="manage-table-actions"> + <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li> + <div popupmenu="repository-${repository.id}-popup"> + %if has_readme: + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> + %endif + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a> + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> + %if repository.tool_dependencies: + <% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %> + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=tool_dependency_ids )}">Manage tool dependencies</a> + %endif + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a> + </div> +</ul> + %if message: ${render_msg( message, status )} %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/admin/tool_shed_repository/view_tool_metadata.mako --- a/templates/admin/tool_shed_repository/view_tool_metadata.mako +++ b/templates/admin/tool_shed_repository/view_tool_metadata.mako @@ -5,6 +5,9 @@ <ul class="manage-table-actions"><li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup"> + %if repository_metadata and 'readme' in repository_metadata: + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a> + %endif <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> @@ -20,10 +23,10 @@ ${render_msg( message, status )} %endif -%if metadata: +%if tool_metadata: <p/><div class="toolForm"> - <div class="toolFormTitle">${metadata[ 'name' ]} tool metadata</div> + <div class="toolFormTitle">${tool_metadata[ 'name' ]} tool metadata</div><div class="toolFormBody"><div class="form-row"><table width="100%"> @@ -32,41 +35,41 @@ </div><div class="form-row"><label>Name:</label> - ${metadata[ 'name' ]} + ${tool_metadata[ 'name' ]} <div style="clear: both"></div></div> - %if 'description' in metadata: + %if 'description' in tool_metadata: <div class="form-row"><label>Description:</label> - ${metadata[ 'description' ]} + ${tool_metadata[ 'description' ]} <div style="clear: both"></div></div> %endif - %if 'id' in metadata: + %if 'id' in tool_metadata: <div class="form-row"><label>Id:</label> - ${metadata[ 'id' ]} + ${tool_metadata[ 'id' ]} <div style="clear: both"></div></div> %endif - %if 'guid' in metadata: + %if 'guid' in tool_metadata: <div class="form-row"><label>Guid:</label> - ${metadata[ 'guid' ]} + ${tool_metadata[ 'guid' ]} <div style="clear: both"></div></div> %endif - %if 'version' in metadata: + %if 'version' in tool_metadata: <div class="form-row"><label>Version:</label> - ${metadata[ 'version' ]} + ${tool_metadata[ 'version' ]} <div style="clear: both"></div></div> %endif - %if 'version_string_cmd' in metadata: + %if 'version_string_cmd' in tool_metadata: <div class="form-row"><label>Version command string:</label> - ${metadata[ 'version_string_cmd' ]} + ${tool_metadata[ 'version_string_cmd' ]} <div style="clear: both"></div></div> %endif @@ -81,7 +84,7 @@ %for guid in tool_lineage: <tr><td> - %if guid == metadata[ 'guid' ]: + %if guid == tool_metadata[ 'guid' ]: ${guid} <b>(this tool)</b> %else: ${guid} @@ -100,8 +103,8 @@ </table></div><% - if 'requirements' in metadata: - requirements = metadata[ 'requirements' ] + if 'requirements' in tool_metadata: + requirements = tool_metadata[ 'requirements' ] else: requirements = None %> @@ -172,8 +175,8 @@ </table></div><% - if 'tests' in metadata: - tests = metadata[ 'tests' ] + if 'tests' in tool_metadata: + tests = tool_metadata[ 'tests' ] else: tests = None %> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/base_panels.mako --- a/templates/base_panels.mako +++ b/templates/base_panels.mako @@ -48,7 +48,17 @@ <!--[if lt IE 7]> ${h.js( 'libs/IE/IE7', 'libs/IE/ie7-recalc' )} <![endif]--> - ${h.js( 'libs/jquery/jquery', 'libs/json2', 'libs/bootstrap', 'libs/underscore', 'libs/backbone/backbone', 'libs/backbone/backbone-relational', 'libs/handlebars.runtime', 'mvc/ui', 'galaxy.base' )} + ${h.js( + 'libs/jquery/jquery', + 'libs/json2', + 'libs/bootstrap', + 'libs/underscore', + 'libs/backbone/backbone', + 'libs/backbone/backbone-relational', + 'libs/handlebars.runtime', + 'mvc/ui', + 'galaxy.base' + )} <script type="text/javascript"> // Set up needed paths. var galaxy_paths = new GalaxyPaths({ diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/library/common/browse_library_opt.mako --- /dev/null +++ b/templates/library/common/browse_library_opt.mako @@ -0,0 +1,622 @@ +<%namespace file="/message.mako" import="render_msg" /> +<%namespace file="/library/common/library_item_info.mako" import="render_library_item_info" /> +<%namespace file="/library/common/common.mako" import="render_actions_on_multiple_items" /> +<%namespace file="/library/common/common.mako" import="render_compression_types_help" /> +<%namespace file="/library/common/common.mako" import="common_javascripts" /> + +<%! + def inherit(context): + if context.get('use_panels'): + return '/webapps/galaxy/base_panels.mako' + else: + return '/base.mako' +%> +<%inherit file="${inherit(context)}"/> + +<%def name="init()"> +<% + self.has_left_panel=False + self.has_right_panel=False + self.message_box_visible=False + self.active_view="user" + self.overlay_visible=False + self.has_accessible_datasets = False +%> +</%def> + +## +## Override methods from base.mako and base_panels.mako +## +<%def name="center_panel()"> + <div style="overflow: auto; height: 100%;"> + <div class="page-container" style="padding: 10px;"> + ${render_content()} + </div> + </div> +</%def> + +## Render the grid's basic elements. Each of these elements can be subclassed. +<%def name="body()"> + ${render_content()} +</%def> + +<%def name="title()">Browse data library</%def> +<%def name="stylesheets()"> + ${parent.stylesheets()} + ${h.css( "library" )} +</%def> + +<%def name="javascripts()"> + ${parent.javascripts()} + ${h.js("libs/json2")} + ${h.js("libs/jquery/jstorage")} + ${common_javascripts()} + ${self.grid_javascripts()} +</%def> + +<%def name="grid_javascripts()"> + <script type="text/javascript"> + var init_libraries = function() { + var storage_id = "library-expand-state-${trans.security.encode_id(library.id)}"; + + var restore_folder_state = function() { + var state = $.jStorage.get(storage_id); + if (state) { + for (var id in state) { + if (state[id] === true) { + var row = $("#" + id), + index = row.parent().children().index(row); + row.addClass("expanded").show(); + row.siblings().filter("tr[parent='" + index + "']").show(); + } + } + } + }; + + var save_folder_state = function() { + var state = {}; + $("tr.folderRow").each( function() { + var folder = $(this); + state[folder.attr("id")] = folder.hasClass("expanded"); + }); + $.jStorage.set(storage_id, state); + }; + + $("#library-grid").each(function() { + var child_of_parent_cache = {}; + // Recursively fill in children and descendents of each row + var process_row = function(q, parents) { + // Find my index + var parent = q.parent(), + this_level = child_of_parent_cache[parent] || (child_of_parent_cache[parent] = parent.children()); + + var index = this_level.index(q); + // Find my immediate children + var children = $(par_child_dict[index]); + // Recursively handle them + var descendents = children; + children.each( function() { + child_descendents = process_row( $(this), parents.add(q) ); + descendents = descendents.add(child_descendents); + }); + // Set up expand / hide link + var expand_fn = function() { + if ( q.hasClass("expanded") ) { + descendents.hide(); + descendents.removeClass("expanded"); + q.removeClass("expanded"); + } else { + children.show(); + q.addClass("expanded"); + } + save_folder_state(); + }; + $("." + q.attr("id") + "-click").click(expand_fn); + // Check/uncheck boxes in subfolders. + q.children("td").children("input[type=checkbox]").click( function() { + if ( $(this).is(":checked") ) { + descendents.find("input[type=checkbox]").attr("checked", true); + } else { + descendents.find("input[type=checkbox]").attr("checked", false); + // If you uncheck a lower level checkbox, uncheck the boxes above it + // (since deselecting a child means the parent is not fully selected any more). + parents.children("td").children("input[type=checkbox]").attr("checked", false); + } + }); + // return descendents for use by parent + return descendents; + } + + // Initialize dict[parent_id] = rows_which_have_that_parent_id_as_parent_attr + var par_child_dict = {}, + no_parent = []; + + $(this).find("tbody tr").each( function() { + if ( $(this).attr("parent")) { + var parent = $(this).attr("parent"); + if (par_child_dict[parent] !== undefined) { + par_child_dict[parent].push(this); + } else { + par_child_dict[parent] = [this]; + } + } else { + no_parent.push(this); + } + }); + + $(no_parent).each( function() { + descendents = process_row( $(this), $([]) ); + descendents.hide(); + }); + }); + + restore_folder_state(); + }; + $(function() { + init_libraries(); + }); + + // Looks for changes in dataset state using an async request. Keeps + // calling itself (via setTimeout) until all datasets are in a terminal + // state. + var updater = function ( tracked_datasets ) { + // Check if there are any items left to track + var empty = true; + for ( i in tracked_datasets ) { + empty = false; + break; + } + if ( ! empty ) { + setTimeout( function() { updater_callback( tracked_datasets ) }, 3000 ); + } + }; + var updater_callback = function ( tracked_datasets ) { + // Build request data + var ids = [] + var states = [] + $.each( tracked_datasets, function ( id, state ) { + ids.push( id ); + states.push( state ); + }); + // Make ajax call + $.ajax( { + type: "POST", + url: "${h.url_for( controller='library_common', action='library_item_updates' )}", + dataType: "json", + data: { ids: ids.join( "," ), states: states.join( "," ) }, + success : function ( data ) { + $.each( data, function( id, val ) { + // Replace HTML + var cell = $("#libraryItem-" + id).find("#libraryItemInfo"); + cell.html( val.html ); + // If new state was terminal, stop tracking + if (( val.state == "ok") || ( val.state == "error") || ( val.state == "empty") || ( val.state == "deleted" ) || ( val.state == "discarded" )) { + delete tracked_datasets[ parseInt(id) ]; + } else { + tracked_datasets[ parseInt(id) ] = val.state; + } + }); + updater( tracked_datasets ); + }, + error: function() { + // Just retry, like the old method, should try to be smarter + updater( tracked_datasets ); + } + }); + }; + </script> +</%def> + +<%def name="render_dataset( cntrller, ldda, library_dataset, can_modify, can_manage, selected, library, folder, pad, parent, row_counter, tracked_datasets, show_deleted=False, simple=False )"> + <% + ## The received ldda must always be a LibraryDatasetDatasetAssociation object. The object id passed to methods + ## from the drop down menu should be the ldda id to prevent id collision ( which could happen when displaying + ## children, which are always lddas ). We also need to make sure we're displaying the latest version of this + ## library_dataset, so we display the attributes from the ldda. + + from galaxy.web.controllers.library_common import branch_deleted + + is_admin = trans.user_is_admin() and cntrller == 'library_admin' + current_version = ( ldda == library_dataset.library_dataset_dataset_association ) + if current_version and ldda.state not in ( 'ok', 'error', 'empty', 'deleted', 'discarded' ): + tracked_datasets[ldda.id] = ldda.state + # SM: This causes a query to be emitted, but it quickly goes down a + # rabbit hole of many possible inheritable cases. It may not be + # possible to easily eliminate the extra query from this call. + info_association, inherited = ldda.get_info_association( restrict=True ) + form_type = trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE + %> + %if current_version and ( not ldda.library_dataset.deleted or show_deleted ): + <tr class="datasetRow" + %if parent is not None: + parent="${parent}" + %endif + id="libraryItem-${ldda.id}"> + <td style="padding-left: ${pad+20}px;"> + <input style="float: left;" type="checkbox" name="ldda_ids" id="${trans.security.encode_id( ldda.id )}" value="${trans.security.encode_id( ldda.id )}" + %if selected: + checked="checked" + %endif + /> + %if simple: + <label for="${trans.security.encode_id( ldda.id )}">${ util.unicodify( ldda.name )}</label> + %else: + <div style="float: left; margin-left: 1px;" class="menubutton split popup" id="dataset-${ldda.id}-popup"> + <a class="view-info" href="${h.url_for( controller='library_common', action='ldda_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}"> + %if ldda.library_dataset.deleted: + <div class="libraryItem-error">${util.unicodify( ldda.name )}</div> + %else: + ${util.unicodify( ldda.name )} + %endif + </a> + </div> + %if not library.deleted: + <div popupmenu="dataset-${ldda.id}-popup"> + %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_modify: + <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_edit_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit information</a> + <a class="action-button" href="${h.url_for( controller='library_common', action='move_library_item', cntrller=cntrller, item_type='ldda', item_id=trans.security.encode_id( ldda.id ), source_library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Move this dataset</a> + %else: + <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">View information</a> + %endif + %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_modify and not info_association: + <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='ldda', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Use template</a> + %endif + %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_modify and info_association: + <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='ldda', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit template</a> + <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type='ldda', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Unuse template</a> + %endif + %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_manage: + %if not trans.app.security_agent.dataset_is_public( ldda.dataset ): + <a class="action-button" href="${h.url_for( controller='library_common', action='make_library_item_public', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_type='ldda', id=trans.security.encode_id( ldda.dataset.id ), use_panels=use_panels, show_deleted=show_deleted )}">Make public</a> + %endif + <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_permissions', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a> + %endif + %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_modify: + <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), replace_id=trans.security.encode_id( library_dataset.id ), show_deleted=show_deleted )}">Upload a new version of this dataset</a> + %endif + %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ldda.has_data: + <a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), ldda_ids=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Import this dataset into selected histories</a> + <a class="action-button" href="${h.url_for( controller='library_common', action='download_dataset_from_folder', cntrller=cntrller, id=trans.security.encode_id( ldda.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels )}">Download this dataset</a> + %endif + %if can_modify: + %if not library.deleted and not branch_deleted( folder ) and not ldda.library_dataset.deleted: + <a class="action-button" confirm="Click OK to delete dataset '${util.unicodify( ldda.name )}'." href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library_dataset.id ), item_type='library_dataset', show_deleted=show_deleted )}">Delete this dataset</a> + %elif not library.deleted and not branch_deleted( folder ) and not ldda.library_dataset.purged and ldda.library_dataset.deleted: + <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library_dataset.id ), item_type='library_dataset', show_deleted=show_deleted )}">Undelete this dataset</a> + %endif + %endif + </div> + %endif + %endif + </td> + % if not simple: + <td id="libraryItemInfo">${render_library_item_info( ldda )}</td> + <td>${ldda.extension}</td> + % endif + <td>${ldda.create_time.strftime( "%Y-%m-%d" )}</td> + <td>${ldda.get_size( nice_size=True )}</td> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> + %endif +</%def> + +<%def name="format_delta( tdelta )"> + <% + from datetime import datetime + return "%d.%.6d" % ( tdelta.seconds, tdelta.microseconds ) + %> +</%def> + +<%def name="render_folder( cntrller, folder, folder_pad, created_ldda_ids, library, hidden_folder_ids, tracked_datasets, show_deleted=False, parent=None, row_counter=None, root_folder=False, simple=False )"> + <% + from galaxy.web.controllers.library_common import active_folders, active_folders_and_library_datasets, activatable_folders_and_library_datasets, map_library_datasets_to_lddas, branch_deleted, datasets_for_lddas + + # SM: DELETEME + from datetime import datetime, timedelta + import logging + log = logging.getLogger( __name__ ) + + is_admin = trans.user_is_admin() and cntrller == 'library_admin' + has_accessible_library_datasets = trans.app.security_agent.has_accessible_library_datasets( trans, folder, trans.user, current_user_roles, search_downward=False ) + + if root_folder: + pad = folder_pad + expander = h.url_for("/static/images/silk/resultset_bottom.png") + folder_img = h.url_for("/static/images/silk/folder_page.png") + else: + pad = folder_pad + 20 + expander = h.url_for("/static/images/silk/resultset_next.png") + folder_img = h.url_for("/static/images/silk/folder.png") + # SM: If this is a comma-delimited list of LDDAs, then split them up + # into a list. For anything else, turn created_ldda_ids into a single + # item list. + if created_ldda_ids: + created_ldda_ids = util.listify( created_ldda_ids ) + if str( folder.id ) in hidden_folder_ids: + return "" + my_row = None + if is_admin: + can_add = can_modify = can_manage = True + elif cntrller in [ 'library' ]: + can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, folder ) + if not can_access: + can_show, folder_ids = \ + trans.app.security_agent.show_library_item( trans.user, + current_user_roles, + folder, + [ trans.app.security_agent.permitted_actions.LIBRARY_ADD, + trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, + trans.app.security_agent.permitted_actions.LIBRARY_MANAGE ] ) + if not can_show: + return "" + can_add = trans.app.security_agent.can_add_library_item( current_user_roles, folder ) + can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, folder ) + can_manage = trans.app.security_agent.can_manage_library_item( current_user_roles, folder ) + else: + can_add = can_modify = can_manage = False + + form_type = trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE + info_association, inherited = folder.get_info_association( restrict=True ) + %> + %if not root_folder and ( not folder.deleted or show_deleted ): + <% encoded_id = trans.security.encode_id( folder.id ) %> + <tr id="folder-${encoded_id}" class="folderRow libraryOrFolderRow" + %if parent is not None: + parent="${parent}" + style="display: none;" + %endif + > + <td style="padding-left: ${folder_pad}px;"> + <input type="checkbox" class="folderCheckbox"/> + <span class="expandLink folder-${encoded_id}-click"> + <div style="float: left; margin-left: 2px;" class="menubutton split popup" id="folder_img-${folder.id}-popup"> + <a class="folder-${encoded_id}-click" href="javascript:void(0);"> + <span class="rowIcon"></span> + %if folder.deleted: + <div class="libraryItem-error">${folder.name}</div> + %else: + ${folder.name} + %endif + </a> + </div> + </span> + %if not library.deleted: + <div popupmenu="folder_img-${folder.id}-popup"> + %if not branch_deleted( folder ) and can_add: + <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add datasets</a> + <a class="action-button" href="${h.url_for( controller='library_common', action='create_folder', cntrller=cntrller, parent_id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add sub-folder</a> + %endif + %if not branch_deleted( folder ): + %if has_accessible_library_datasets: + <a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Select datasets for import into selected histories</a> + %endif + %if can_modify: + <a class="action-button" href="${h.url_for( controller='library_common', action='folder_info', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit information</a> + <a class="action-button" href="${h.url_for( controller='library_common', action='move_library_item', cntrller=cntrller, item_type='folder', item_id=trans.security.encode_id( folder.id ), source_library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Move this folder</a> + %else: + <a class="action-button" class="view-info" href="${h.url_for( controller='library_common', action='folder_info', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">View information</a> + %endif + %endif + %if not branch_deleted( folder ) and can_modify and not info_association: + <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Use template</a> + %endif + %if not branch_deleted( folder ) and can_modify and info_association: + <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit template</a> + <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Unuse template</a> + %endif + %if not branch_deleted( folder ) and can_manage: + %if not trans.app.security_agent.folder_is_public( folder ): + <a class="action-button" href="${h.url_for( controller='library_common', action='make_library_item_public', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_type='folder', id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Make public</a> + %endif + <a class="action-button" href="${h.url_for( controller='library_common', action='folder_permissions', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a> + %endif + %if can_modify: + %if not library.deleted and not folder.deleted: + <a class="action-button" confirm="Click OK to delete the folder '${folder.name}.'" href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Delete this folder</a> + %elif not library.deleted and folder.deleted and not folder.purged: + <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Undelete this folder</a> + %endif + %endif + </div> + %endif + <td> + %if folder.description: + ${folder.description} + %endif + <td colspan="3"></td> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> + %endif + <% + # TODO: If show_deleted is set to True, then nothing is displayed. Why? This wasn't the case + # in the past. + if show_deleted: + sub_folders, library_datasets = activatable_folders_and_library_datasets( trans, folder ) + else: + sub_folders, library_datasets = active_folders_and_library_datasets( trans, folder ) + # Render all the subfolders: + # TODO: Check permissions first. + for sub_folder in sub_folders: + render_folder( cntrller, sub_folder, pad, created_ldda_ids, library, [], tracked_datasets, show_deleted=show_deleted, parent=my_row, row_counter=row_counter, root_folder=False ) + + # Map LibraryDatasets to LDDAs, then map LDDAs to Datasets. + # Then determine which Datasets are accessible and which are not. + # For every LibraryDataset, if there's an LDDA for it and it's + # accessible then display it. + if ( len( library_datasets ) > 0 ): + lib_dataset_ldda_map = map_library_datasets_to_lddas( trans, library_datasets ) + dataset_list = datasets_for_lddas( trans, lib_dataset_ldda_map.values() ) + #can_access_datasets = trans.app.security_agent.dataset_access_mapping( trans, current_user_roles, dataset_list ) + can_access_datasets = trans.app.security_agent.dataset_permission_map_for_access( trans, current_user_roles, dataset_list ) + can_modify_datasets = trans.app.security_agent.item_permission_map_for_modify( trans, current_user_roles, dataset_list ) + can_manage_datasets = trans.app.security_agent.item_permission_map_for_manage( trans, current_user_roles, dataset_list ) + for library_dataset in library_datasets: + ldda = lib_dataset_ldda_map[ library_dataset.id ] + if ldda: + # SMTODO: Fix awkard modify/manage permission checks. + can_access = is_admin or can_access_datasets[ ldda.dataset_id ] + can_modify = is_admin or ( cntrller in ['library', 'requests'] and can_modify_datasets[ ldda.dataset_id ]) + can_manage = is_admin or ( cntrller in ['library', 'requests'] and can_manage_datasets[ ldda.dataset_id ]) + selected = created_ldda_ids and str( ldda.id ) in created_ldda_ids + if can_access: + render_dataset( cntrller, ldda, library_dataset, can_modify, can_manage, selected, library, folder, pad, my_row, row_counter, tracked_datasets, show_deleted=show_deleted ) + %> +</%def> + +<%def name="render_content(simple=False)"> + <% + from galaxy import util + from galaxy.web.controllers.library_common import branch_deleted + from time import strftime + import logging + log = logging.getLogger( __name__ ) + + is_admin = trans.user_is_admin() and cntrller == 'library_admin' + + if is_admin: + can_add = can_modify = can_manage = True + elif cntrller in [ 'library', 'requests' ]: + can_add = trans.app.security_agent.can_add_library_item( current_user_roles, library ) + can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, library ) + can_manage = trans.app.security_agent.can_manage_library_item( current_user_roles, library ) + else: + can_add = can_modify = can_manage = False + + info_association, inherited = library.get_info_association() + form_type = trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE + + # SM: These are mostly display-specific; ignore them for now. + # The has_accessible_folders determines if anything can be shown - use it. + self.has_accessible_datasets = trans.app.security_agent.has_accessible_library_datasets( trans, library.root_folder, trans.user, current_user_roles ) + root_folder_has_accessible_library_datasets = trans.app.security_agent.has_accessible_library_datasets( trans, library.root_folder, trans.user, current_user_roles, search_downward=False ) + has_accessible_folders = is_admin or trans.app.security_agent.has_accessible_folders( trans, library.root_folder, trans.user, current_user_roles ) + + tracked_datasets = {} + + class RowCounter( object ): + def __init__( self ): + self.count = 0 + def increment( self ): + self.count += 1 + def __str__( self ): + return str( self.count ) + %> + + <h2>Data Library “${library.name}”</h2> + + <ul class="manage-table-actions"> + %if not library.deleted and ( is_admin or can_add ): + <li><a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( library.root_folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add datasets</a></li> + <li><a class="action-button" href="${h.url_for( controller='library_common', action='create_folder', cntrller=cntrller, parent_id=trans.security.encode_id( library.root_folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add folder</a></li> + %endif + %if ( ( not library.deleted ) and ( can_modify or can_manage ) ) or ( can_modify and not library.purged ) or ( library.purged ): + <li><a class="action-button" id="library-${library.id}-popup" class="menubutton">Library Actions</a></li> + <div popupmenu="library-${library.id}-popup"> + %if not library.deleted: + %if can_modify: + <a class="action-button" href="${h.url_for( controller='library_common', action='library_info', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit information</a> + <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Delete this data library</a> + %if show_deleted: + <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=False )}">Hide deleted items</a> + %else: + <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=True )}">Show deleted items</a> + %endif + %endif + %if can_modify and not library.info_association: + <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='library', form_type=form_type, library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Use template</a> + %endif + %if can_modify and info_association: + <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='library', form_type=form_type, library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit template</a> + <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type='library', form_type=form_type, library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Unuse template</a> + %endif + %if can_manage: + %if not trans.app.security_agent.library_is_public( library, contents=True ): + <a class="action-button" href="${h.url_for( controller='library_common', action='make_library_item_public', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_type='library', id=trans.security.encode_id( library.id ), contents=True, use_panels=use_panels, show_deleted=show_deleted )}">Make public</a> + %endif + <a class="action-button" href="${h.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a> + %endif + %if root_folder_has_accessible_library_datasets: + <a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( library.root_folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Select datasets for import into selected histories</a> + %endif + %elif can_modify and not library.purged: + <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library', use_panels=use_panels )}">Undelete this data library</a> + %elif library.purged: + <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">This data library has been purged</a> + %endif + </div> + %endif + </ul> + + %if message: + ${render_msg( message, status )} + %endif + + %if library.synopsis not in [ '', 'None', None ]: + <div class="libraryItemBody"> + ${library.synopsis} + </div> + %endif + + %if self.has_accessible_datasets: + <form name="act_on_multiple_datasets" action="${h.url_for( controller='library_common', action='act_on_multiple_datasets', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}" onSubmit="javascript:return checkForm();" method="post"> + %endif + %if has_accessible_folders: + <table cellspacing="0" cellpadding="0" border="0" width="100%" class="grid" id="library-grid"> + <thead> + <tr class="libraryTitle"> + <th> + %if self.has_accessible_datasets: + <input type="checkbox" id="checkAll" name=select_all_datasets_checkbox value="true" onclick='checkAllFields(1);'/><input type="hidden" name=select_all_datasets_checkbox value="true"/> + %endif + Name + </th> + % if not simple: + <th>Message</th> + <th>Data type</th> + % endif + <th>Date uploaded</th> + <th>File size</th> + </tr> + </thead> + <% row_counter = RowCounter() %> + ## SM: Here is where we render the libraries based on admin/non-admin privileges: + %if cntrller in [ 'library', 'requests' ]: + ${self.render_folder( 'library', library.root_folder, 0, created_ldda_ids, library, hidden_folder_ids, tracked_datasets, show_deleted=show_deleted, parent=None, row_counter=row_counter, root_folder=True, simple=simple )} + ## SM: TODO: WTF? + %if not library.deleted and self.has_accessible_datasets and not simple: + ${render_actions_on_multiple_items()} + %endif + %elif ( trans.user_is_admin() and cntrller in [ 'library_admin', 'requests_admin' ] ): + ${self.render_folder( 'library_admin', library.root_folder, 0, created_ldda_ids, library, [], tracked_datasets, show_deleted=show_deleted, parent=None, row_counter=row_counter, root_folder=True )} + ## SM: TODO: WTF? + %if not library.deleted and not show_deleted and self.has_accessible_datasets: + ${render_actions_on_multiple_items()} + %endif + %endif + </table> + %endif + %if self.has_accessible_datasets: + </form> + %endif + + %if tracked_datasets: + <script type="text/javascript"> + // Updater + updater({${ ",".join( [ '"%s" : "%s"' % ( k, v ) for k, v in tracked_datasets.iteritems() ] ) }}); + </script> + <!-- running: do not change this comment, used by TwillTestCase.library_wait --> + %endif + + %if self.has_accessible_datasets and not simple: + ${render_compression_types_help( comptypes )} + %endif + %if not has_accessible_folders: + The data library '${library.name}' does not contain any datasets that you can access. + %endif +</%def> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/root/alternate_history.mako --- a/templates/root/alternate_history.mako +++ b/templates/root/alternate_history.mako @@ -54,35 +54,18 @@ <%def name="get_urls_for_hda( hda, encoded_data_id, for_editing )"><% from galaxy.datatypes.metadata import FileParameter + #print '\n', hda.name data_dict = {} def add_to_data( **kwargs ): data_dict.update( kwargs ) - # download links (for both main hda and associated meta files) - if hda.has_data(): - add_to_data( download_url=h.url_for( controller='/dataset', action='display', - dataset_id=encoded_data_id, to_ext=hda.ext ) ) - - download_meta_urls = {} - for file_type in hda.metadata.spec.keys(): - if not isinstance( hda.metadata.spec[ file_type ].param, FileParameter ): - continue - - download_meta_urls[ file_type ] = h.url_for( controller='/dataset', action='get_metadata_file', - hda_id=encoded_data_id, metadata_name=file_type ) - if download_meta_urls: - #TODO:?? needed? isn't this the same as download_url? - add_to_data( download_dataset_url=h.url_for( controller='dataset', action='display', - dataset_id=encoded_data_id, to_ext=hda.ext ) ) - add_to_data( download_meta_urls=download_meta_urls ) - #TODO??: better way to do urls (move into js galaxy_paths (decorate) - _not_ dataset specific) deleted = hda.deleted purged = hda.purged + # ................................................................ link actions #purged = purged or hda.dataset.purged //?? - # all of these urls are 'datasets/data_id/<action> if not ( dataset_purged or purged ) and for_editing: add_to_data( undelete_url=h.url_for( controller='dataset', action='undelete', dataset_id=encoded_data_id ) ) @@ -93,6 +76,8 @@ if not hda.visible: add_to_data( unhide_url=h.url_for( controller='dataset', action='unhide', dataset_id=encoded_data_id ) ) + + # ................................................................ title actions (display, edit, delete) display_url = '' if for_editing: display_url = h.url_for( controller='dataset', action='display', dataset_id=encoded_data_id, preview=True, filename='' ) @@ -122,11 +107,29 @@ show_deleted_on_refresh=show_deleted )) + # ................................................................ primary actions (error, info, download) + # download links (hda and associated meta files) + if not hda.purged: + add_to_data( download_url=h.url_for( controller='/dataset', action='display', + dataset_id=encoded_data_id, to_ext=hda.ext ) ) + + meta_files = [] + for k in hda.metadata.spec.keys(): + if isinstance( hda.metadata.spec[ k ].param, FileParameter ): + file_type = k + download_url = h.url_for( controller='/dataset', action='get_metadata_file', + hda_id=encoded_data_id, metadata_name=file_type ) + meta_files.append( dict( meta_file_type=file_type, meta_download_url=download_url ) ) + + if meta_files: + add_to_data( meta_files=meta_files ) + # error report if for_editing: #NOTE: no state == 'error' check add_to_data( report_error_url=h.url_for( h.url_for( controller='dataset', action='errors', id=encoded_data_id ) ) ) - + + # visualizations if hda.ext in app.datatypes_registry.get_available_tracks(): # do these need _localized_ dbkeys? trackster_urls = {} @@ -140,6 +143,48 @@ trackster_urls[ 'new-url' ] = h.url_for( controller='visualization', action='trackster', dataset_id=encoded_data_id, default_dbkey=hda.dbkey ) add_to_data( trackster_url=trackster_urls ) + # display apps (igv, uscs) + display_types = [] + display_apps = [] + if( hda.state in [ 'ok', 'failed_metadata' ] + and hda.has_data() ): + #NOTE: these two data share structures + #TODO: this doesn't seem to get called with the hda I'm using. What would call this? How can I spoof it? + for display_type in hda.datatype.get_display_types(): + display_label = hda.datatype.get_display_label( display_type ) + target_frame, display_links = hda.datatype.get_display_links( hda, display_type, app, request.base ) + if display_links: + display_links = [] + for display_name, display_href in display_links: + display_type_link = dict( + target = target_frame, + href = display_href, + text = display_name + ) + display_links.append( display_type_link ) + + # append the link list to the main map using the display_label + display_types.append( dict( label=display_label, links=display_links ) ) + + for display_app in hda.get_display_applications( trans ).itervalues(): + app_links = [] + for display_app_link in display_app.links.itervalues(): + app_link = dict( + target = display_app_link.url.get( 'target_frame', '_blank' ), + href = display_app_link.get_display_url( hda, trans ), + text = _( display_app_link.name ) + ) + app_links.append( app_link ) + + display_apps.append( dict( label=display_app.name, links=app_links ) ) + + # attach the display types and apps (if any) to the hda obj + #if display_types: print 'display_types:', display_types + #if display_apps: print 'display_apps:', display_apps + add_to_data( display_types=display_types ) + add_to_data( display_apps=display_apps ) + + # ................................................................ secondary actions (tagging, annotation) if trans.user: add_to_data( ajax_get_tag_url=( h.url_for( controller='tag', action='get_tagging_elt_async', @@ -154,34 +199,6 @@ add_to_data( ajax_set_annotation_url=( h.url_for( controller='/dataset', action='annotate_async', id=encoded_data_id ) ) ) - display_type_display_links = {} - #TODO: this doesn't seem to get called with the hda I'm using. What would call this? How can I spoof it? - for display_app in hda.datatype.get_display_types(): - # print "display_app:", display_app - target_frame, display_links = hda.datatype.get_display_links( hda, display_app, app, request.base ) - # print "target_frame:", target_frame, "display_links:", display_links - #if len( display_links ) > 0: - # display_type_display_links[ display_app ] = {} - # for display_name, display_link in display_links: - #NOTE!: localized name - #<a target="${target_frame}" href="${display_link}">${_(display_name)}</a> - #pass - # <br /> - - display_apps = {} - for display_app in hda.get_display_applications( trans ).itervalues(): - display_app_dict = display_apps[ display_app.name ] = {} - for link_app in display_app.links.itervalues(): - # print link_app.name, link_app.get_display_url( hda, trans ) - #NOTE!: localized name - display_app_dict[ _( link_app.name ) ] = { - 'url' : link_app.get_display_url( hda, trans ), - 'target' : link_app.url.get( 'target_frame', '_blank' ) - } - if display_apps: - # print display_apps - add_to_data( display_apps=display_apps ) - return data_dict %></%def> @@ -302,10 +319,12 @@ "template-history-warning-messages", "template-history-titleLink", + "template-history-failedMetadata", "template-history-hdaSummary", - "template-history-failedMetadata", + "template-history-downloadLinks", "template-history-tagArea", - "template-history-annotationArea" + "template-history-annotationArea", + "template-history-displayApps" )} ## if using in-dom templates they need to go here (before the Backbone classes are defined) @@ -339,15 +358,13 @@ createMockHistoryData(); return; + //TODO: handle empty history } else if ( window.USE_CURR_DATA ){ if( console && console.debug ){ console.debug( '\t using current history data' ); } glx_history = new History( pageData.history ).loadDatasetsAsHistoryItems( pageData.hdas ); glx_history_view = new HistoryView({ model: glx_history }); glx_history_view.render(); - hi = glx_history.items.at( 0 ); - hi_view = new HistoryItemView({ model: hi }); - $( 'body' ).append( hi_view.render() ); return; } @@ -409,3 +426,163 @@ </%def><body class="historyPage"></body> + +<script type="text/javascript"> +function createMockHistoryData(){ + mockHistory = {}; + mockHistory.data = { + + template : { + id : 'a799d38679e985db', + name : 'template', + data_type : 'fastq', + file_size : 226297533, + genome_build : '?', + metadata_data_lines : 0, + metadata_dbkey : '?', + metadata_sequences : 0, + misc_blurb : '215.8 MB', + misc_info : 'uploaded fastq file (misc_info)', + model_class : 'HistoryDatasetAssociation', + download_url : '', + state : 'ok', + visible : true, + deleted : false, + purged : false, + + hid : 0, + //TODO: move to history + for_editing : true, + //for_editing : false, + + //?? not needed + //can_edit : true, + //can_edit : false, + + accessible : true, + + //TODO: move into model functions (build there (and cache?)) + //!! be careful with adding these accrd. to permissions + //!! IOW, don't send them via template/API if the user doesn't have perms to use + //!! (even if they don't show up) + undelete_url : '', + purge_url : '', + unhide_url : '', + + display_url : 'example.com/display', + edit_url : 'example.com/edit', + delete_url : 'example.com/delete', + + show_params_url : 'example.com/show_params', + rerun_url : 'example.com/rerun', + + retag_url : 'example.com/retag', + annotate_url : 'example.com/annotate', + + peek : [ + '<table cellspacing="0" cellpadding="3"><tr><th>1.QNAME</th><th>2.FLAG</th><th>3.RNAME</th><th>4.POS</th><th>5.MAPQ</th><th>6.CIGAR</th><th>7.MRNM</th><th>8.MPOS</th><th>9.ISIZE</th><th>10.SEQ</th><th>11.QUAL</th><th>12.OPT</th></tr>', + '<tr><td colspan="100%">@SQ SN:gi|87159884|ref|NC_007793.1| LN:2872769</td></tr>', + '<tr><td colspan="100%">@PG ID:bwa PN:bwa VN:0.5.9-r16</td></tr>', + '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 73 gi|87159884|ref|NC_007793.1| 2720169 37 101M = 2720169 0 NAATATGACATTATTTTCAAAACAGCTGAAAATTTAGACGTACCGATTTATCTACATCCCGCGCCAGTTAACAGTGACATTTATCAATCATACTATAAAGG !!!!!!!!!!$!!!$!!!!!$!!!!!!$!$!$$$!!$!!$!!!!!!!!!!!$!</td></tr>', + '<tr><td colspan="100%">!!!$!$!$$!!$$!!$!!!!!!!!!!!!!!!!!!!!!!!!!!$!!$!! XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 X1:i:0 XM:i:1 XO:i:0 XG:i:0 MD:Z:0A100</td></tr>', + '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 133 gi|87159884|ref|NC_007793.1| 2720169 0 * = 2720169 0 NAAACTGTGGCTTCGTTNNNNNNNNNNNNNNNGTGANNNNNNNNNNNNNNNNNNNGNNNNNNNNNNNNNNNNNNNNCNAANNNNNNNNNNNNNNNNNNNNN !!!!!!!!!!!!$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>', + '<tr><td colspan="100%">!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>', + '</table>' + ].join( '' ) + } + + }; + _.extend( mockHistory.data, { + + notAccessible : + _.extend( _.clone( mockHistory.data.template ), + { accessible : false }), + + //deleted, purged, visible + deleted : + _.extend( _.clone( mockHistory.data.template ), + { deleted : true, + delete_url : '', + purge_url : 'example.com/purge', + undelete_url : 'example.com/undelete' }), + purgedNotDeleted : + _.extend( _.clone( mockHistory.data.template ), + { purged : true, + delete_url : '' }), + notvisible : + _.extend( _.clone( mockHistory.data.template ), + { visible : false, + unhide_url : 'example.com/unhide' }), + + hasDisplayApps : + _.extend( _.clone( mockHistory.data.template ), + { display_apps : { + 'display in IGB' : { + Web: "/display_application/63cd3858d057a6d1/igb_bam/Web", + Local: "/display_application/63cd3858d057a6d1/igb_bam/Local" + } + } + } + ), + canTrackster : + _.extend( _.clone( mockHistory.data.template ), + { trackster_urls : { + 'data-url' : "example.com/trackster-data", + 'action-url' : "example.com/trackster-action", + 'new-url' : "example.com/trackster-new" + } + } + ), + zeroSize : + _.extend( _.clone( mockHistory.data.template ), + { file_size : 0 }), + + hasMetafiles : + _.extend( _.clone( mockHistory.data.template ), { + download_meta_urls : { + 'bam_index' : "example.com/bam-index" + } + }), + + //states + upload : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.UPLOAD }), + queued : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.QUEUED }), + running : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.RUNNING }), + empty : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.EMPTY }), + error : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.ERROR, + report_error_url: 'example.com/report_err' }), + discarded : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.DISCARDED }), + setting_metadata : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.SETTING_METADATA }), + failed_metadata : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.FAILED_METADATA }) +/* +*/ + }); + + //mockHistory.views.deleted.logger = console; + mockHistory.items = {}; + mockHistory.views = {}; + for( key in mockHistory.data ){ + mockHistory.items[ key ] = new HistoryItem( mockHistory.data[ key ] ); + mockHistory.items[ key ].set( 'name', key ); + mockHistory.views[ key ] = new HistoryItemView({ model : mockHistory.items[ key ] }); + //console.debug( 'view: ', mockHistory.views[ key ] ); + $( 'body' ).append( mockHistory.views[ key ].render() ); + } +} +</script> \ No newline at end of file diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/root/index.mako --- a/templates/root/index.mako +++ b/templates/root/index.mako @@ -70,115 +70,6 @@ } }); - var menu_options = {}; // Holds dictionary of { label: toggle_fn } - - SHOW_TOOL = "${_("Show Tool Search")}"; - HIDE_TOOL = "${_("Hide Tool Search")}"; - SHOW_RECENT = "${_("Show Recently Used")}"; - HIDE_RECENT = "${_("Hide Recently Used")}"; - - var toggle_tool_search_fn = function() { - // Show/hide menu and update vars, user preferences. - var menu = $("#galaxy_tools").contents().find('#tool-search'), - pref_value, menu_option_text, old_text; - if (menu.is(":visible")) { - // Hide menu. - pref_value = "False"; - menu_option_text = SHOW_TOOL; - old_text = HIDE_TOOL; - - // Reset search. - reset_tool_search(true); - } else { - // Show menu. - pref_value = "True"; - menu_option_text = HIDE_TOOL; - old_text = SHOW_TOOL; - } - menu.toggle(); - - // Update menu option. - delete menu_options[old_text]; - - var new_menu_options = {}; - // Because we always want tool menu to be the first link in the dropdown, - // we re-create the menu_options dictionary by creating a new - // dict and then appending the old dict to it - new_menu_options[menu_option_text] = toggle_tool_search_fn; - menu_options = $.extend( new_menu_options, menu_options ); - make_popupmenu( $("#tools-options-button"), menu_options ); - galaxy_async.set_user_pref("show_tool_search", pref_value); - }; - - var toggle_recently_used_fn = function() { - // Show/hide menu. - var ru_menu = $('#galaxy_tools').contents().find('#recently_used_wrapper'), - ru_menu_body = ru_menu.find(".toolSectionBody"), - pref_value, old_text, menu_option_text; - if (ru_menu.hasClass("user_pref_visible")) { - // Hide menu. - ru_menu_body.slideUp(); - ru_menu.slideUp(); - - // Set vars used below and in tool menu frame. - pref_value = "False"; - old_text = HIDE_RECENT; - menu_option_text = SHOW_RECENT; - } else { - // "Show" menu. - if (!$('#galaxy_tools').contents().find('#tool-search-query').hasClass("search_active")) { - // Default. - ru_menu.slideDown(); - } else { - // Search active: tf there are matching tools in RU menu, show menu. - if ( ru_menu.find(".toolTitle.search_match").length !== 0 ) { - ru_menu.slideDown(); - ru_menu_body.slideDown(); - } - } - // Set vars used below and in tool menu frame. - pref_value = "True"; - old_text = SHOW_RECENT; - menu_option_text = HIDE_RECENT; - } - - // Update menu class and option. - ru_menu.toggleClass("user_pref_hidden user_pref_visible"); - delete menu_options[old_text]; - menu_options[menu_option_text] = toggle_recently_used_fn; - make_popupmenu( $("#tools-options-button"), menu_options ); - galaxy_async.set_user_pref("show_recently_used_menu", pref_value); - }; - - // Init tool options. - ## Search tools menu item. - %if trans.app.toolbox_search.enabled: - <% - show_tool_search = True - if trans.user: - show_tool_search = trans.user.preferences.get( "show_tool_search", "False" ) == "True" - - if show_tool_search: - action = "HIDE_TOOL" - else: - action = "SHOW_TOOL" - %> - menu_options[ ${action} ] = toggle_tool_search_fn; - %endif - ## Recently used tools menu. - %if trans.user: - <% - if trans.user.preferences.get( 'show_recently_used_menu', 'False' ) == 'True': - action = "HIDE_RECENT" - else: - action = "SHOW_RECENT" - %> - // TODO: make compatible with new tool menu. - //menu_options[ ${action} ] = toggle_recently_used_fn; - %endif - - - make_popupmenu( $("#tools-options-button"), menu_options ); }); </script></%def> @@ -202,9 +93,9 @@ <%def name="left_panel()"><div class="unified-panel-header" unselectable="on"><div class='unified-panel-header-inner'> - <div style="float: right"> - <a class='panel-header-button' id="tools-options-button" href="#"><span class="ficon large cog"></span></a> - </div> + ## <div style="float: right"> + ## <a class='panel-header-button' id="tools-options-button" href="#"><span class="ficon large cog"></span></a> + ## </div> ${n_('Tools')} </div></div> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/root/tool_menu.mako --- a/templates/root/tool_menu.mako +++ b/templates/root/tool_menu.mako @@ -19,12 +19,7 @@ ${h.templates( "tool_link", "panel_section", "tool_search" )} ${h.js( "libs/require", "galaxy.autocom_tagging" )} - <% - # Set up for creating tool panel. - tool_search_hidden = "false" - if trans.user and trans.user.preferences.get( "show_tool_search", "False" ) == "False": - tool_search_hidden = "true" - + <% dictified_panel = trans.app.toolbox.to_dict( trans ) %> @@ -42,11 +37,13 @@ // Init. on document load. var tool_panel, tool_panel_view, tool_search; $(function() { + // Set up search. - tool_search = new tools.ToolSearch( - { spinner_url: "${h.url_for('/static/images/loading_small_white_bg.gif')}", - search_url: "${h.url_for( controller='root', action='tool_search' )}", - hidden: ${tool_search_hidden} } ); + tool_search = new tools.ToolSearch({ + spinner_url: "${h.url_for('/static/images/loading_small_white_bg.gif')}", + 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 } ); diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/tracks/browser.mako --- a/templates/tracks/browser.mako +++ b/templates/tracks/browser.mako @@ -48,8 +48,10 @@ ${render_trackster_js_vars()} - var view, - browser_router, + // FIXME: deliberate global required for now due to requireJS integration. + view = null; + + var browser_router, ui = new (trackster_ui.TracksterUI)( "${h.url_for('/')}" ); /** diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/user/info.mako --- a/templates/user/info.mako +++ b/templates/user/info.mako @@ -59,16 +59,16 @@ %if not is_admin: <div class="form-row"><label>Current password:</label> - <input type="password" name="current" value="${current}" size="40"/> + <input type="password" name="current" value="" size="40"/></div> %endif <div class="form-row"><label>New password:</label> - <input type="password" name="password" value="${password}" size="40"/> + <input type="password" name="password" value="" size="40"/></div><div class="form-row"><label>Confirm:</label> - <input type="password" name="confirm" value="${confirm}" size="40"/> + <input type="password" name="confirm" value="" size="40"/></div><div class="form-row"><input type="submit" name="change_password_button" value="Save"/> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/user/login.mako --- a/templates/user/login.mako +++ b/templates/user/login.mako @@ -30,7 +30,7 @@ %if redirect_url: <script type="text/javascript"> - top.location.href = '${redirect_url}'; + top.location.href = '${redirect_url | h}'; </script> %endif @@ -81,9 +81,9 @@ <form name="login" id="login" action="${form_action}" method="post" ><div class="form-row"><label>Email address:</label> - <input type="text" name="email" value="${email}" size="40"/> - <input type="hidden" name="webapp" value="${webapp}" size="40"/> - <input type="hidden" name="redirect" value="${redirect}" size="40"/> + <input type="text" name="email" value="${email | h}" size="40"/> + <input type="hidden" name="webapp" value="${webapp | h}" size="40"/> + <input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"><label>Password:</label> @@ -107,8 +107,8 @@ <div class="form-row"><label>OpenID URL:</label><input type="text" name="openid_url" size="60" style="background-image:url('${h.url_for( '/static/images/openid-16x16.gif' )}' ); background-repeat: no-repeat; padding-right: 20px; background-position: 99% 50%;"/> - <input type="hidden" name="webapp" value="${webapp}" size="40"/> - <input type="hidden" name="redirect" value="${redirect}" size="40"/> + <input type="hidden" name="webapp" value="${webapp | h}" size="40"/> + <input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"> Or, authenticate with your <select name="openid_provider"> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/user/register.mako --- a/templates/user/register.mako +++ b/templates/user/register.mako @@ -3,7 +3,7 @@ %if redirect_url: <script type="text/javascript"> - top.location.href = '${redirect_url}'; + top.location.href = '${redirect_url | h}'; </script> %endif @@ -42,21 +42,21 @@ <div class="toolFormTitle">Create account</div><div class="form-row"><label>Email address:</label> - <input type="text" name="email" value="${email}" size="40"/> - <input type="hidden" name="webapp" value="${webapp}" size="40"/> - <input type="hidden" name="redirect" value="${redirect}" size="40"/> + <input type="text" name="email" value="${email | h}" size="40"/> + <input type="hidden" name="webapp" value="${webapp | h}" size="40"/> + <input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"><label>Password:</label> - <input type="password" name="password" value="${password}" size="40"/> + <input type="password" name="password" value="" size="40"/></div><div class="form-row"><label>Confirm password:</label> - <input type="password" name="confirm" value="${confirm}" size="40"/> + <input type="password" name="confirm" value="" size="40"/></div><div class="form-row"><label>Public name:</label> - <input type="text" name="username" size="40" value="${username}"/> + <input type="text" name="username" size="40" value="${username |h}"/> %if webapp == 'galaxy': <div class="toolParamHelp" style="clear: both;"> Your public name is an identifier that will be used to generate addresses for information diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/visualization/circster.mako --- a/templates/visualization/circster.mako +++ b/templates/visualization/circster.mako @@ -11,6 +11,11 @@ <%def name="stylesheets()"> ${parent.stylesheets()} + <style> + text { + font-size: 10px; + } + </style></%def><%def name="javascripts()"> @@ -23,6 +28,7 @@ require.config({ baseUrl: "${h.url_for('/static/scripts')}", shim: { + "libs/underscore": { exports: "_" }, "libs/d3": { exports: "d3" } } }); diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/visualization/display.mako --- a/templates/visualization/display.mako +++ b/templates/visualization/display.mako @@ -54,44 +54,59 @@ <div id="${trans.security.encode_id( visualization.id )}" class="unified-panel-body" style="overflow:none;top:0px;"></div><script type="text/javascript"> - // TODO: much of this code is copied from browser.mako -- create shared base and use in both places. - ${render_trackster_js_vars()} + require.config({ + baseUrl: "${h.url_for('/static/scripts') }", + shim: { + "libs/underscore": { exports: "_" }, + "libs/backbone/backbone": { exports: "Backbone" }, + "libs/backbone/backbone-relational": ["libs/backbone/backbone"] + } + }); + require( ["base", "viz/visualization", "viz/trackster_ui", "viz/trackster/tracks"], + function( base, visualization, trackster_ui, tracks ) { - var view, - container_element = $("#${trans.security.encode_id( visualization.id )}"); - - $(function() { - var is_embedded = (container_element.parents(".item-content").length > 0); + ${render_trackster_js_vars()} + + // FIXME: deliberate global required for now due to requireJS integration. + view = null; + + var ui = new (trackster_ui.TracksterUI)( "${h.url_for('/')}" ) + container_element = $("#${trans.security.encode_id( visualization.id )}"); - // HTML setup. - if (is_embedded) { - container_element.css( { "position": "relative" } ); - } else { // Viewing just one shared viz - $("#right-border").click(function() { view.resize_window(); }); - } - - // Create visualization. - var callback; - %if 'viewport' in config: - var callback = function() { view.change_chrom( '${config['viewport']['chrom']}', ${config['viewport']['start']}, ${config['viewport']['end']} ); } - %endif - view = create_visualization( { - container: container_element, - name: "${config.get('title') | h}", - vis_id: "${config.get('vis_id')}", - dbkey: "${config.get('dbkey')}" - }, - JSON.parse('${ h.to_json_string( config.get( 'viewport', dict() ) ) }'), - JSON.parse('${ h.to_json_string( config['tracks'] ).replace("'", "\\'") }'), - JSON.parse('${ h.to_json_string( config.get('bookmarks') ) }') - ); - - // Set up keyboard navigation. - init_keyboard_nav(view); - - // HACK: set viewport height because it cannot be set automatically. Currently, max height for embedded - // elts is 25em, so use 20em. - view.viewport_container.height("20em"); + $(function() { + var is_embedded = (container_element.parents(".item-content").length > 0); + + // HTML setup. + if (is_embedded) { + container_element.css( { "position": "relative" } ); + } else { // Viewing just one shared viz + $("#right-border").click(function() { view.resize_window(); }); + } + + // Create visualization. + var callback; + %if 'viewport' in config: + var callback = function() { view.change_chrom( '${config['viewport']['chrom']}', ${config['viewport']['start']}, ${config['viewport']['end']} ); } + %endif + view = ui.create_visualization( { + container: container_element, + name: "${config.get('title') | h}", + vis_id: "${config.get('vis_id')}", + dbkey: "${config.get('dbkey')}" + }, + JSON.parse('${ h.to_json_string( config.get( 'viewport', dict() ) ) }'), + JSON.parse('${ h.to_json_string( config['tracks'] ).replace("'", "\\'") }'), + JSON.parse('${ h.to_json_string( config.get('bookmarks') ) }') + ); + + // Set up keyboard navigation. + ui.init_keyboard_nav(view); + + // HACK: set viewport height because it cannot be set automatically. Currently, max height for embedded + // elts is 25em, so use 20em. + view.viewport_container.height("20em"); + }); + }); </script> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/visualization/scatterplot.mako --- a/templates/visualization/scatterplot.mako +++ b/templates/visualization/scatterplot.mako @@ -6,25 +6,25 @@ <style type="text/css"> .title { - margin: 0px; + margin: 0px; padding: 8px; background-color: #ebd9b2; border: 2px solid #ebd9b2; } .subtitle { - margin: 0px; + margin: 0px; padding: 0px 8px 8px 16px; background-color: #ebd9b2; - color: white; - font-size: small; + color: white; + font-size: small; } #chart-settings-form { /*from width + margin of chart?*/ - float: right; + float: right; width: 100%; - margin: 0px; + margin: 0px; padding-top: 1em; } @@ -45,80 +45,67 @@ overflow: auto; } -.clear { - clear: both; - margin: 0px; -} - - -svg .chart { - /*shape-rendering: crispEdges;*/ -} - svg .grid-line { - fill: none; - stroke: lightgrey; - stroke-opacity: 0.5; - shape-rendering: crispEdges; - stroke-dasharray: 3, 3; + fill: none; + stroke: lightgrey; + stroke-opacity: 0.5; + shape-rendering: crispEdges; + stroke-dasharray: 3, 3; } svg .axis path, svg .axis line { - fill: none; - stroke: black; - shape-rendering: crispEdges; + fill: none; + stroke: black; + shape-rendering: crispEdges; } svg .axis text { - font-family: sans-serif; - font-size: 12px; + font-family: sans-serif; + font-size: 12px; } - svg .glyph { - stroke: none; - fill: black; - fill-opacity: 0.2; + stroke: none; + fill: black; + fill-opacity: 0.2; } - + </style> - + </%def><%def name="javascripts()"> ${parent.javascripts()} -${h.js( - "libs/underscore", - "libs/backbone/backbone", - "libs/backbone/backbone-relational", - "libs/d3", - "mvc/base-mvc", - "viz/scatterplot" -)} +${h.js( "libs/require" )} <script type="text/javascript"> -$(function() { - var hda = ${h.to_json_string( hda )}, - historyID = '${historyID}' - apiDatasetsURL = "${h.url_for( controller='/api/datasets' )}"; - //?? hmmmm - //kwargs = ${h.to_json_string( kwargs )}; - - var settingsForm = new ScatterplotView({ - dataset : hda, - el : $( '#chart-settings-form' ), +require.config({ baseUrl : "${h.url_for( '/static/scripts' )}", }); + +require([ "viz/scatterplot" ], function( scatterplot ){ + + var hda = ${h.to_json_string( hda )}, + historyID = '${historyID}' + apiDatasetsURL = "${h.url_for( controller='/api/datasets' )}"; + //?? hmmmm + //kwargs = ${h.to_json_string( kwargs )}; + + var settingsForm = new scatterplot.ScatterplotView({ + dataset : hda, + el : $( '#chart-settings-form' ), apiDatasetsURL : apiDatasetsURL, + chartConfig : { containerSelector : '#chart-holder', marginTop : 20, } - }).render(); + }).render(); }); + </script></%def><%def name="body()"><h2 class="title">Scatterplot of '${hda['name']}'</h2><p class="subtitle">${hda['misc_info']}</p> - <div id="chart-holder"></div> - <div id="chart-settings-form"></div> + <div id="chart-holder"></div> + <div id="chart-settings-form"></div></%def> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/common/common.mako --- a/templates/webapps/community/common/common.mako +++ b/templates/webapps/community/common/common.mako @@ -13,3 +13,46 @@ %> ${html} </%def> + +<%def name="render_readme( readme_text )"> + <style type="text/css"> + #readme_table{ table-layout:fixed; + width:100%; + overflow-wrap:normal; + overflow:hidden; + border:0px; + word-break:keep-all; + word-wrap:break-word; + line-break:strict; } + </style> + <div class="toolForm"> + <div class="toolFormTitle">Repository README file (may contain important installation or license information)</div> + <div class="toolFormBody"> + <div class="form-row"> + <table id="readme_table"> + <tr><td>${readme_text}</td></tr> + </table> + </div> + </div> + </div> +</%def> + +<%def name="render_long_description( description_text )"> + <style type="text/css"> + #description_table{ table-layout:fixed; + width:100%; + overflow-wrap:normal; + overflow:hidden; + border:0px; + word-break:keep-all; + word-wrap:break-word; + line-break:strict; } + </style> + <div class="form-row"> + <label>Detailed description:</label> + <table id="description_table"> + <tr><td><pre>${description_text}</pre></td></tr> + </table> + <div style="clear: both"></div> + </div> +</%def> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/common/view_readme.mako --- /dev/null +++ b/templates/webapps/community/common/view_readme.mako @@ -0,0 +1,88 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> +<%namespace file="/webapps/community/common/common.mako" import="render_readme" /> + +<% + if webapp == 'community': + is_admin = trans.user_is_admin() + is_new = repository.is_new + can_contact_owner = trans.user and trans.user != repository.user + can_push = trans.app.security_agent.can_push( trans.user, repository ) + can_rate = not is_new and trans.user and repository.user != trans.user + can_upload = can_push + can_download = not is_new and ( not is_malicious or can_push ) + can_browse_contents = not is_new + can_view_change_log = not is_new + can_manage = is_admin or repository.user == trans.user + if can_push: + browse_label = 'Browse or delete repository tip files' + else: + browse_label = 'Browse repository tip files' +%> + +<br/><br/> +<ul class="manage-table-actions"> + %if webapp == 'community': + <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li> + <div popupmenu="repository-${repository.id}-popup"> + %if can_manage: + <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip )}">Manage repository</a> + %else: + <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View repository</a> + %endif + %if can_upload: + <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a> + %endif + %if can_view_change_log: + <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">View change log</a> + %endif + %if can_rate: + <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">Rate repository</a> + %endif + %if can_browse_contents: + <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">${browse_label}</a> + %endif + %if can_contact_owner: + <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ), webapp=webapp )}">Contact repository owner</a> + %endif + %if can_download: + <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz', webapp=webapp )}">Download as a .tar.gz file</a> + <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2', webapp=webapp )}">Download as a .tar.bz2 file</a> + <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip', webapp=webapp )}">Download as a zip file</a> + %endif + </div> + %else: + %if cntrller=='repository': + <li><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', operation='preview_tools_in_changeset', id=trans.security.encode_id( repository.id ), webapp=webapp )}">Preview tools for install</a></li> + <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li> + <div popupmenu="repository-${repository.id}-popup"> + <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories', webapp=webapp )}">Browse valid repositories</a> + <a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a> + <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a> + </div> + %else: + <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li> + <div popupmenu="repository-${repository.id}-popup"> + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a> + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a> + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a> + %if repository.includes_tools: + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='set_tool_versions', id=trans.security.encode_id( repository.id ) )}">Set tool versions</a> + %endif + %if repository.tool_dependencies: + <% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %> + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=tool_dependency_ids )}">Manage tool dependencies</a> + %endif + <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a> + </div> + %endif + %endif +</ul> + +%if message: + ${render_msg( message, status )} +%endif + +%if readme_text: + ${render_readme( readme_text )} +%endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/browse_repository.mako --- a/templates/webapps/community/repository/browse_repository.mako +++ b/templates/webapps/community/repository/browse_repository.mako @@ -15,6 +15,7 @@ can_rate = trans.user and repository.user != trans.user can_manage = is_admin or repository.user == trans.user can_view_change_log = not is_new + has_readme = metadata and 'readme' in metadata %><%! @@ -76,6 +77,9 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View README</a> + %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a> %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/contact_owner.mako --- a/templates/webapps/community/repository/contact_owner.mako +++ b/templates/webapps/community/repository/contact_owner.mako @@ -16,6 +16,7 @@ browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' + has_readme = metadata and 'readme' in metadata %><%! @@ -42,6 +43,9 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View README</a> + %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a> %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/manage_repository.mako --- a/templates/webapps/community/repository/manage_repository.mako +++ b/templates/webapps/community/repository/manage_repository.mako @@ -21,6 +21,7 @@ browse_label = 'Browse repository tip files' can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision == repository.tip can_reset_all_metadata = is_admin and len( repo ) > 0 + has_readme = metadata and 'readme' in metadata %><%! @@ -32,35 +33,6 @@ %><%inherit file="${inherit(context)}"/> -<%def name="stylesheets()"> - ${parent.stylesheets()} - ${h.css( "jquery.rating" )} - <style type="text/css"> - ul.fileBrowser, - ul.toolFile { - margin-left: 0; - padding-left: 0; - list-style: none; - } - ul.fileBrowser { - margin-left: 20px; - } - .fileBrowser li, - .toolFile li { - padding-left: 20px; - background-repeat: no-repeat; - background-position: 0; - min-height: 20px; - } - .toolFile li { - background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} ); - } - .fileBrowser li { - background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} ); - } - </style> -</%def> - <%def name="javascripts()"> ${parent.javascripts()} ${h.js( "libs/jquery/jquery.rating" )} @@ -77,6 +49,9 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp='community' )}">View README</a> + %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a> %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/preview_tools_in_changeset.mako --- a/templates/webapps/community/repository/preview_tools_in_changeset.mako +++ b/templates/webapps/community/repository/preview_tools_in_changeset.mako @@ -16,6 +16,7 @@ browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' + has_readme = metadata and 'readme' in metadata %><%! @@ -27,35 +28,6 @@ %><%inherit file="${inherit(context)}"/> -<%def name="stylesheets()"> - ${parent.stylesheets()} - ${h.css( "jquery.rating" )} - <style type="text/css"> - ul.fileBrowser, - ul.toolFile { - margin-left: 0; - padding-left: 0; - list-style: none; - } - ul.fileBrowser { - margin-left: 20px; - } - .fileBrowser li, - .toolFile li { - padding-left: 20px; - background-repeat: no-repeat; - background-position: 0; - min-height: 20px; - } - .toolFile li { - background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} ); - } - .fileBrowser li { - background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} ); - } - </style> -</%def> - <%def name="javascripts()"> ${parent.javascripts()} ${h.js( "libs/jquery/jquery.rating" )} @@ -67,6 +39,9 @@ <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revisions=changeset_revision )}">Install to local Galaxy</a></li><li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li><div popupmenu="repository-${repository.id}-popup"> + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp=webapp )}">View README</a> + %endif <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories', webapp=webapp )}">Browse valid repositories</a><a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a><a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/rate_repository.mako --- a/templates/webapps/community/repository/rate_repository.mako +++ b/templates/webapps/community/repository/rate_repository.mako @@ -19,6 +19,7 @@ browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' + has_readme = metadata and 'readme' in metadata %><%! @@ -83,6 +84,9 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View README</a> + %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a> %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/tool_form.mako --- a/templates/webapps/community/repository/tool_form.mako +++ b/templates/webapps/community/repository/tool_form.mako @@ -21,6 +21,7 @@ browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' + has_readme = metadata and 'readme' in metadata %><html> @@ -146,6 +147,9 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp=webapp )}">View README</a> + %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">View change log</a> %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/view_changelog.mako --- a/templates/webapps/community/repository/view_changelog.mako +++ b/templates/webapps/community/repository/view_changelog.mako @@ -18,6 +18,7 @@ browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' + has_readme = metadata and 'readme' in metadata %><%! @@ -51,6 +52,9 @@ %else: <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp='community' )}">View README</a> + %endif %if can_rate: <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a> %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/view_changeset.mako --- a/templates/webapps/community/repository/view_changeset.mako +++ b/templates/webapps/community/repository/view_changeset.mako @@ -19,6 +19,7 @@ browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' + has_readme = metadata and 'readme' in metadata %><%! @@ -52,6 +53,9 @@ %else: <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View README</a> + %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a> %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/view_repository.mako --- a/templates/webapps/community/repository/view_repository.mako +++ b/templates/webapps/community/repository/view_repository.mako @@ -17,6 +17,7 @@ browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' + has_readme = metadata and 'readme' in metadata %><%! @@ -28,35 +29,6 @@ %><%inherit file="${inherit(context)}"/> -<%def name="stylesheets()"> - ${parent.stylesheets()} - ${h.css( "jquery.rating" )} - <style type="text/css"> - ul.fileBrowser, - ul.toolFile { - margin-left: 0; - padding-left: 0; - list-style: none; - } - ul.fileBrowser { - margin-left: 20px; - } - .fileBrowser li, - .toolFile li { - padding-left: 20px; - background-repeat: no-repeat; - background-position: 0; - min-height: 20px; - } - .toolFile li { - background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} ); - } - .fileBrowser li { - background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} ); - } - </style> -</%def> - <%def name="javascripts()"> ${parent.javascripts()} ${h.js( "libs/jquery/jquery.rating" )} @@ -74,6 +46,9 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp=webapp )}">View README</a> + %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">View change log</a> %endif @@ -152,11 +127,7 @@ ${repository.description} </div> %if repository.long_description: - <div class="form-row"> - <label>Detailed description:</label> - <pre>${repository.long_description}</pre> - <div style="clear: both"></div> - </div> + ${render_long_description( repository.long_description )} %endif <div class="form-row"><label>Revision:</label> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/view_tool_metadata.mako --- a/templates/webapps/community/repository/view_tool_metadata.mako +++ b/templates/webapps/community/repository/view_tool_metadata.mako @@ -20,6 +20,7 @@ browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' + has_readme = metadata and 'readme' in metadata %><%! @@ -59,6 +60,9 @@ %if can_upload: <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp=webapp )}">View README</a> + %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">View change log</a> %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/webapps/community/repository/view_workflow.mako --- a/templates/webapps/community/repository/view_workflow.mako +++ b/templates/webapps/community/repository/view_workflow.mako @@ -22,6 +22,7 @@ browse_label = 'Browse or delete repository tip files' else: browse_label = 'Browse repository tip files' + has_readme = metadata and 'readme' in metadata %><%! @@ -54,6 +55,9 @@ %else: <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View repository</a> %endif + %if has_readme: + <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp='community' )}">View README</a> + %endif %if can_view_change_log: <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a> %endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/workflow/editor_tool_form.mako --- a/templates/workflow/editor_tool_form.mako +++ b/templates/workflow/editor_tool_form.mako @@ -98,6 +98,9 @@ <div class="toolForm"><div class="toolFormTitle">Tool: ${tool.name}</div> + %if tool.version: + <div class="form-row"><div class='titleRow'>Version: ${tool.version}</div></div> + %endif <div class="toolFormBody"><input type="hidden" name="tool_id" value="${tool.id}" /> %for i, inputs in enumerate( tool.inputs_by_page ): diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 templates/workflow/run.mako --- a/templates/workflow/run.mako +++ b/templates/workflow/run.mako @@ -379,6 +379,9 @@ <div class="toolForm"><div class="toolFormTitle"><span class='title_ul_text'>Step ${int(step.order_index)+1}: ${tool.name}</span> + %if tool.version: + (version ${tool.version}) + %endif % if step.annotations: <div class="step-annotation">${h.to_unicode( step.annotations[0].annotation )}</div> % endif diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 test-data/cuffdiff_out10.txt --- a/test-data/cuffdiff_out10.txt +++ b/test-data/cuffdiff_out10.txt @@ -1,88 +1,88 @@ test_id gene_id gene locus sample_1 sample_2 status value_1 value_2 sqrt(JS) test_stat p_value q_value significant -XLOC_000001 XLOC_000001 Xkr4 chr1:3204754-3204833 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000002 XLOC_000002 - chr1:3111449-3111490 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000003 XLOC_000003 - chr1:3111545-3111576 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000004 XLOC_000004 - chr1:3174765-3174792 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000005 XLOC_000005 - chr1:3187401-3187428 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000006 XLOC_000006 - chr1:3188521-3188548 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000007 XLOC_000007 - chr1:3189810-3190789 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000008 XLOC_000008 - chr1:3190858-3191434 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000009 XLOC_000009 - chr1:3191512-3192077 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000010 XLOC_000010 - chr1:3192250-3192336 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000011 XLOC_000011 - chr1:3192441-3192494 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000012 XLOC_000012 - chr1:3192550-3192629 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000013 XLOC_000013 - chr1:3192649-3192676 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000014 XLOC_000014 - chr1:3192731-3192811 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000015 XLOC_000015 - chr1:3192940-3193042 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000016 XLOC_000016 - chr1:3194185-3194226 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000017 XLOC_000017 - chr1:3194302-3194329 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000018 XLOC_000018 - chr1:3194706-3194733 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000019 XLOC_000019 - chr1:3195083-3195110 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000020 XLOC_000020 - chr1:3195450-3195477 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000021 XLOC_000021 - chr1:3197089-3197116 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000022 XLOC_000022 - chr1:3197246-3197273 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000023 XLOC_000023 - chr1:3197346-3197373 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000024 XLOC_000024 - chr1:3197425-3197452 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000025 XLOC_000025 - chr1:3200022-3200191 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000026 XLOC_000026 - chr1:3200325-3200352 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000027 XLOC_000027 - chr1:3200430-3200457 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000028 XLOC_000028 - chr1:3201007-3201039 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000029 XLOC_000029 - chr1:3201077-3201481 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000030 XLOC_000030 - chr1:3201596-3201666 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000031 XLOC_000031 - chr1:3201672-3201699 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000032 XLOC_000032 - chr1:3201725-3201809 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000033 XLOC_000033 Xkr4 chr1:3211521-3211561 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000034 XLOC_000034 Xkr4 chr1:3212213-3212292 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000035 XLOC_000035 Xkr4 chr1:3212367-3212439 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000036 XLOC_000036 Xkr4 chr1:3212717-3212801 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000037 XLOC_000037 Xkr4 chr1:3213095-3213242 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000038 XLOC_000038 Xkr4 chr1:3240606-3240633 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000039 XLOC_000039 Xkr4 chr1:3242479-3242512 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000040 XLOC_000040 Xkr4 chr1:3242633-3242923 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000041 XLOC_000041 Xkr4 chr1:3242924-3243005 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000042 XLOC_000042 Xkr4 chr1:3243018-3243079 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000043 XLOC_000043 Xkr4 chr1:3243108-3243154 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000044 XLOC_000044 Xkr4 chr1:3243347-3243401 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000045 XLOC_000045 Xkr4 chr1:3254079-3254106 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000046 XLOC_000046 Xkr4 chr1:3256974-3257011 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000047 XLOC_000047 Xkr4 chr1:3277155-3277182 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000048 XLOC_000048 Xkr4 chr1:3277190-3277218 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000049 XLOC_000049 Xkr4 chr1:3277913-3278390 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000050 XLOC_000050 Xkr4 chr1:3280117-3280144 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000051 XLOC_000051 Xkr4 chr1:3280498-3280525 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000052 XLOC_000052 Xkr4 chr1:3280686-3280741 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000053 XLOC_000053 Xkr4 chr1:3282504-3282531 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000054 XLOC_000054 Xkr4 chr1:3282650-3282677 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000055 XLOC_000055 Xkr4 chr1:3282760-3282832 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000056 XLOC_000056 Xkr4 chr1:3284966-3284993 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000057 XLOC_000057 Xkr4 chr1:3290488-3290553 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000058 XLOC_000058 Xkr4 chr1:3290798-3290859 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000059 XLOC_000059 Xkr4 chr1:3290919-3291273 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000060 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000061 XLOC_000061 Xkr4 chr1:3299691-3299733 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000062 XLOC_000062 Xkr4 chr1:3300051-3300078 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000063 XLOC_000063 Xkr4 chr1:3307748-3307775 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000064 XLOC_000064 Xkr4 chr1:3318620-3318647 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000065 XLOC_000065 Xkr4 chr1:3318999-3319051 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000066 XLOC_000066 Xkr4 chr1:3330527-3330554 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000067 XLOC_000067 Xkr4 chr1:3351240-3351311 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000068 XLOC_000068 Xkr4 chr1:3355887-3356119 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000069 XLOC_000069 Xkr4 chr1:3356180-3356225 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000070 XLOC_000070 Xkr4 chr1:3363076-3363176 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000071 XLOC_000071 Xkr4 chr1:3363214-3363278 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000072 XLOC_000072 Xkr4 chr1:3363387-3363446 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000073 XLOC_000073 Xkr4 chr1:3363753-3363849 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000074 XLOC_000074 Xkr4 chr1:3364871-3364919 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000075 XLOC_000075 Xkr4 chr1:3367135-3367162 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000076 XLOC_000076 Xkr4 chr1:3367210-3367237 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000077 XLOC_000077 Xkr4 chr1:3367333-3367382 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000078 XLOC_000078 Xkr4 chr1:3369580-3369607 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000079 XLOC_000079 Xkr4 chr1:3375001-3375028 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000080 XLOC_000080 Xkr4 chr1:3377211-3377262 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000081 XLOC_000081 Xkr4 chr1:3379888-3379915 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000082 XLOC_000082 Xkr4 chr1:3386739-3386836 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000083 XLOC_000083 Xkr4 chr1:3391325-3391352 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000084 XLOC_000084 Xkr4 chr1:3435841-3435880 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000085 XLOC_000085 Xkr4 chr1:3447761-3447788 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000086 XLOC_000086 Xkr4 chr1:3450906-3450965 q1 q2 NOTEST 0 0 0 0 0 1 no -XLOC_000087 XLOC_000087 Xkr4 chr1:3451051-3451109 q1 q2 NOTEST 0 0 0 0 0 1 no +XLOC_000001 XLOC_000001 Xkr4 chr1:3204754-3204833 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000002 XLOC_000002 - chr1:3111449-3111490 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000003 XLOC_000003 - chr1:3111545-3111576 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000004 XLOC_000004 - chr1:3174765-3174792 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000005 XLOC_000005 - chr1:3187401-3187428 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000006 XLOC_000006 - chr1:3188521-3188548 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000007 XLOC_000007 - chr1:3189810-3190789 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000008 XLOC_000008 - chr1:3190858-3191434 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000009 XLOC_000009 - chr1:3191512-3192077 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000010 XLOC_000010 - chr1:3192250-3192336 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000011 XLOC_000011 - chr1:3192441-3192494 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000012 XLOC_000012 - chr1:3192550-3192629 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000013 XLOC_000013 - chr1:3192649-3192676 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000014 XLOC_000014 - chr1:3192731-3192811 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000015 XLOC_000015 - chr1:3192940-3193042 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000016 XLOC_000016 - chr1:3194185-3194226 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000017 XLOC_000017 - chr1:3194302-3194329 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000018 XLOC_000018 - chr1:3194706-3194733 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000019 XLOC_000019 - chr1:3195083-3195110 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000020 XLOC_000020 - chr1:3195450-3195477 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000021 XLOC_000021 - chr1:3197089-3197116 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000022 XLOC_000022 - chr1:3197246-3197273 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000023 XLOC_000023 - chr1:3197346-3197373 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000024 XLOC_000024 - chr1:3197425-3197452 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000025 XLOC_000025 - chr1:3200022-3200191 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000026 XLOC_000026 - chr1:3200325-3200352 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000027 XLOC_000027 - chr1:3200430-3200457 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000028 XLOC_000028 - chr1:3201007-3201039 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000029 XLOC_000029 - chr1:3201077-3201481 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000030 XLOC_000030 - chr1:3201596-3201666 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000031 XLOC_000031 - chr1:3201672-3201699 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000032 XLOC_000032 - chr1:3201725-3201809 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000033 XLOC_000033 Xkr4 chr1:3211521-3211561 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000034 XLOC_000034 Xkr4 chr1:3212213-3212292 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000035 XLOC_000035 Xkr4 chr1:3212367-3212439 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000036 XLOC_000036 Xkr4 chr1:3212717-3212801 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000037 XLOC_000037 Xkr4 chr1:3213095-3213242 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000038 XLOC_000038 Xkr4 chr1:3240606-3240633 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000039 XLOC_000039 Xkr4 chr1:3242479-3242512 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000040 XLOC_000040 Xkr4 chr1:3242633-3242923 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000041 XLOC_000041 Xkr4 chr1:3242924-3243005 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000042 XLOC_000042 Xkr4 chr1:3243018-3243079 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000043 XLOC_000043 Xkr4 chr1:3243108-3243154 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000044 XLOC_000044 Xkr4 chr1:3243347-3243401 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000045 XLOC_000045 Xkr4 chr1:3254079-3254106 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000046 XLOC_000046 Xkr4 chr1:3256974-3257011 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000047 XLOC_000047 Xkr4 chr1:3277155-3277182 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000048 XLOC_000048 Xkr4 chr1:3277190-3277218 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000049 XLOC_000049 Xkr4 chr1:3277913-3278390 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000050 XLOC_000050 Xkr4 chr1:3280117-3280144 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000051 XLOC_000051 Xkr4 chr1:3280498-3280525 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000052 XLOC_000052 Xkr4 chr1:3280686-3280741 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000053 XLOC_000053 Xkr4 chr1:3282504-3282531 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000054 XLOC_000054 Xkr4 chr1:3282650-3282677 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000055 XLOC_000055 Xkr4 chr1:3282760-3282832 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000056 XLOC_000056 Xkr4 chr1:3284966-3284993 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000057 XLOC_000057 Xkr4 chr1:3290488-3290553 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000058 XLOC_000058 Xkr4 chr1:3290798-3290859 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000059 XLOC_000059 Xkr4 chr1:3290919-3291273 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000060 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000061 XLOC_000061 Xkr4 chr1:3299691-3299733 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000062 XLOC_000062 Xkr4 chr1:3300051-3300078 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000063 XLOC_000063 Xkr4 chr1:3307748-3307775 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000064 XLOC_000064 Xkr4 chr1:3318620-3318647 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000065 XLOC_000065 Xkr4 chr1:3318999-3319051 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000066 XLOC_000066 Xkr4 chr1:3330527-3330554 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000067 XLOC_000067 Xkr4 chr1:3351240-3351311 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000068 XLOC_000068 Xkr4 chr1:3355887-3356119 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000069 XLOC_000069 Xkr4 chr1:3356180-3356225 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000070 XLOC_000070 Xkr4 chr1:3363076-3363176 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000071 XLOC_000071 Xkr4 chr1:3363214-3363278 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000072 XLOC_000072 Xkr4 chr1:3363387-3363446 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000073 XLOC_000073 Xkr4 chr1:3363753-3363849 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000074 XLOC_000074 Xkr4 chr1:3364871-3364919 q1 q2 NOTEST 0 0 0 0 1 1 no +XLOC_000075 XLOC_000075 Xkr4 chr1:3367135-3367162 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000076 XLOC_000076 Xkr4 chr1:3367210-3367237 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000077 XLOC_000077 Xkr4 chr1:3367333-3367382 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000078 XLOC_000078 Xkr4 chr1:3369580-3369607 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000079 XLOC_000079 Xkr4 chr1:3375001-3375028 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000080 XLOC_000080 Xkr4 chr1:3377211-3377262 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000081 XLOC_000081 Xkr4 chr1:3379888-3379915 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000082 XLOC_000082 Xkr4 chr1:3386739-3386836 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000083 XLOC_000083 Xkr4 chr1:3391325-3391352 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000084 XLOC_000084 Xkr4 chr1:3435841-3435880 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000085 XLOC_000085 Xkr4 chr1:3447761-3447788 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000086 XLOC_000086 Xkr4 chr1:3450906-3450965 q1 q2 LOWDATA 0 0 0 0 0 1 no +XLOC_000087 XLOC_000087 Xkr4 chr1:3451051-3451109 q1 q2 LOWDATA 0 0 0 0 0 1 no diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 test-data/cuffdiff_out7.txt --- a/test-data/cuffdiff_out7.txt +++ b/test-data/cuffdiff_out7.txt @@ -1,15 +1,15 @@ tracking_id class_code nearest_ref_id gene_id gene_short_name tss_id locus length coverage q1_FPKM q1_conf_lo q1_conf_hi q1_status q2_FPKM q2_conf_lo q2_conf_hi q2_status -TSS1 - - XLOC_000001 Xkr4 TSS1 chr1:3204754-3204833 - - 0 0 0 OK 8.3103e+06 0 2.00628e+07 OK -TSS10 - - XLOC_000008 - TSS10 chr1:3190858-3191434 - - 474092 138279 809906 OK 369273 113039 625507 OK -TSS11 - - XLOC_000009 - TSS11 chr1:3191512-3192077 - - 502845 149756 855934 OK 739818 487934 991702 OK -TSS13 - - XLOC_000010 - TSS13 chr1:3192250-3192336 - - 3.994e+06 0 1.1982e+07 OK 2.93812e+06 0 8.81435e+06 OK -TSS14 - - XLOC_000011 - TSS14 chr1:3192441-3192494 - - 0 0 0 OK 8.52143e+07 0 1.83611e+08 OK -TSS15 - - XLOC_000012 - TSS15 chr1:3192550-3192629 - - 0 0 0 OK 4.15515e+06 0 1.24654e+07 OK +TSS1 - - XLOC_000001 Xkr4 TSS1 chr1:3204754-3204833 - - 0 0 0 OK 5.42247e+06 0 1.83844e+07 OK +TSS10 - - XLOC_000008 - TSS10 chr1:3190858-3191434 - - 227564 0 483427 OK 240951 0 505030 OK +TSS11 - - XLOC_000009 - TSS11 chr1:3191512-3192077 - - 241366 0 509259 OK 482731 109420 856042 OK +TSS13 - - XLOC_000010 - TSS13 chr1:3192250-3192336 - - 1.91712e+06 0 7.66198e+06 OK 1.91712e+06 0 7.66198e+06 OK +TSS14 - - XLOC_000011 - TSS14 chr1:3192441-3192494 - - 0 0 0 OK 5.56023e+07 0 1.86077e+08 OK +TSS15 - - XLOC_000012 - TSS15 chr1:3192550-3192629 - - 0 0 0 OK 2.71123e+06 0 1.08357e+07 OK TSS16 - - XLOC_000013 - TSS16 chr1:3192649-3192676 - - 0 0 0 OK 0 0 0 OK TSS17 - - XLOC_000014 - TSS17 chr1:3192731-3192811 - - 0 0 0 OK 0 0 0 OK -TSS18 - - XLOC_000015 - TSS18 chr1:3192940-3193042 - - 0 0 0 OK 6.02976e+06 0 1.34147e+07 OK -TSS19 - - XLOC_000016 - TSS19 chr1:3194185-3194226 - - 0 0 0 OK 2.1403e+08 0 6.42089e+08 OK -TSS2 - - XLOC_000002 - TSS2 chr1:3111449-3111490 - - 0 0 0 OK 2.1403e+08 0 6.42089e+08 OK +TSS18 - - XLOC_000015 - TSS18 chr1:3192940-3193042 - - 0 0 0 OK 3.93442e+06 0 1.25021e+07 OK +TSS19 - - XLOC_000016 - TSS19 chr1:3194185-3194226 - - 0 0 0 OK 1.39654e+08 0 5.58144e+08 OK +TSS2 - - XLOC_000002 - TSS2 chr1:3111449-3111490 - - 0 0 0 OK 1.39654e+08 0 5.58144e+08 OK TSS20 - - XLOC_000017 - TSS20 chr1:3194302-3194329 - - 0 0 0 OK 0 0 0 OK TSS21 - - XLOC_000018 - TSS21 chr1:3194706-3194733 - - 0 0 0 OK 0 0 0 OK TSS22 - - XLOC_000019 - TSS22 chr1:3195083-3195110 - - 0 0 0 OK 0 0 0 OK @@ -18,62 +18,62 @@ TSS25 - - XLOC_000022 - TSS25 chr1:3197246-3197273 - - 0 0 0 OK 0 0 0 OK TSS26 - - XLOC_000023 - TSS26 chr1:3197346-3197373 - - 0 0 0 OK 0 0 0 OK TSS27 - - XLOC_000024 - TSS27 chr1:3197425-3197452 - - 0 0 0 OK 0 0 0 OK -TSS28 - - XLOC_000025 - TSS28 chr1:3200022-3200191 - - 959058 0 2.06648e+06 OK 705514 0 1.52017e+06 OK +TSS28 - - XLOC_000025 - TSS28 chr1:3200022-3200191 - - 460348 0 1.54058e+06 OK 460348 0 1.54058e+06 OK TSS29 - - XLOC_000026 - TSS29 chr1:3200325-3200352 - - 0 0 0 OK 0 0 0 OK TSS3 - - XLOC_000003 - TSS3 chr1:3111545-3111576 - - 0 0 0 OK 0 0 0 OK TSS30 - - XLOC_000027 - TSS30 chr1:3200430-3200457 - - 0 0 0 OK 0 0 0 OK TSS31 - - XLOC_000028 - TSS31 chr1:3201007-3201039 - - 0 0 0 OK 0 0 0 OK -TSS32 - - XLOC_000029 - TSS32 chr1:3201077-3201481 - - 77513.9 0 167019 OK 285108 21736.5 548480 OK -TSS33 - - XLOC_000030 - TSS33 chr1:3201596-3201666 - - 1.89853e+07 0 4.58345e+07 OK 0 0 0 OK +TSS32 - - XLOC_000029 - TSS32 chr1:3201077-3201481 - - 37206.6 0 124514 OK 186033 0 476912 OK +TSS33 - - XLOC_000030 - TSS33 chr1:3201596-3201666 - - 9.11292e+06 0 3.08965e+07 OK 0 0 0 OK TSS34 - - XLOC_000031 - TSS34 chr1:3201672-3201699 - - 0 0 0 OK 0 0 0 OK -TSS35 - - XLOC_000032 - TSS35 chr1:3201725-3201809 - - 1.75659e+07 0 3.90796e+07 OK 0 0 0 OK +TSS35 - - XLOC_000032 - TSS35 chr1:3201725-3201809 - - 8.43162e+06 0 2.67925e+07 OK 0 0 0 OK TSS36 - - XLOC_000033 Xkr4 TSS36 chr1:3211521-3211561 - - 0 0 0 OK 0 0 0 OK -TSS37 - - XLOC_000034 Xkr4 TSS37 chr1:3212213-3212292 - - 0 0 0 OK 8.3103e+06 0 2.00628e+07 OK -TSS38 - - XLOC_000035 Xkr4 TSS38 chr1:3212367-3212439 - - 0 0 0 OK 2.4671e+07 0 5.48867e+07 OK -TSS39 - - XLOC_000036 Xkr4 TSS39 chr1:3212717-3212801 - - 4.39147e+06 0 1.31744e+07 OK 0 0 0 OK +TSS37 - - XLOC_000034 Xkr4 TSS37 chr1:3212213-3212292 - - 0 0 0 OK 5.42247e+06 0 1.83844e+07 OK +TSS38 - - XLOC_000035 Xkr4 TSS38 chr1:3212367-3212439 - - 0 0 0 OK 1.60978e+07 0 5.11527e+07 OK +TSS39 - - XLOC_000036 Xkr4 TSS39 chr1:3212717-3212801 - - 2.10791e+06 0 8.42447e+06 OK 0 0 0 OK TSS4 - - XLOC_000004 - TSS4 chr1:3174765-3174792 - - 0 0 0 OK 0 0 0 OK -TSS40 - - XLOC_000037 Xkr4 TSS40 chr1:3213095-3213242 - - 8.89174e+06 0 2.05036e+07 OK 1.82908e+06 0 5.48723e+06 OK +TSS40 - - XLOC_000037 Xkr4 TSS40 chr1:3213095-3213242 - - 2.84535e+06 0 1.07397e+07 OK 1.19347e+06 0 5.96736e+06 OK TSS41 - - XLOC_000038 Xkr4 TSS41 chr1:3240606-3240633 - - 0 0 0 OK 0 0 0 OK TSS42 - - XLOC_000039 Xkr4 TSS42 chr1:3242479-3242512 - - 0 0 0 OK 0 0 0 OK -TSS43 - - XLOC_000040 Xkr4 TSS43 chr1:3242633-3242923 - - 56312.4 0 168937 OK 372827 0 761430 OK +TSS43 - - XLOC_000040 Xkr4 TSS43 chr1:3242633-3242923 - - 27029.9 0 108028 OK 243269 0 681799 OK TSS44 - - XLOC_000041 Xkr4 TSS44 chr1:3242924-3243005 - - 0 0 0 OK 0 0 0 OK -TSS45 - - XLOC_000042 Xkr4 TSS45 chr1:3243018-3243079 - - 0 0 0 OK 2.66226e+07 0 6.42725e+07 OK -TSS46 - - XLOC_000043 Xkr4 TSS46 chr1:3243108-3243154 - - 9.99919e+07 0 2.99976e+08 OK 0 0 0 OK -TSS47 - - XLOC_000044 Xkr4 TSS47 chr1:3243347-3243401 - - 0 0 0 OK 5.0951e+07 0 1.23007e+08 OK +TSS45 - - XLOC_000042 Xkr4 TSS45 chr1:3243018-3243079 - - 0 0 0 OK 1.73712e+07 0 5.88955e+07 OK +TSS46 - - XLOC_000043 Xkr4 TSS46 chr1:3243108-3243154 - - 4.79961e+07 0 1.91822e+08 OK 0 0 0 OK +TSS47 - - XLOC_000044 Xkr4 TSS47 chr1:3243347-3243401 - - 0 0 0 OK 3.32455e+07 0 1.12716e+08 OK TSS48 - - XLOC_000045 Xkr4 TSS48 chr1:3254079-3254106 - - 0 0 0 OK 0 0 0 OK -TSS49 - - XLOC_000046 Xkr4 TSS49 chr1:3256974-3257011 - - 0 0 0 OK 2.06814e+09 0 4.99293e+09 OK +TSS49 - - XLOC_000046 Xkr4 TSS49 chr1:3256974-3257011 - - 0 0 0 OK 1.34946e+09 0 4.57522e+09 OK TSS5 - - XLOC_000005 - TSS5 chr1:3187401-3187428 - - 0 0 0 OK 0 0 0 OK TSS50 - - XLOC_000047 Xkr4 TSS50 chr1:3277155-3277182 - - 0 0 0 OK 0 0 0 OK TSS51 - - XLOC_000048 Xkr4 TSS51 chr1:3277190-3277218 - - 0 0 0 OK 0 0 0 OK -TSS52 - - XLOC_000049 Xkr4 TSS52 chr1:3277913-3278390 - - 265614 16793 514436 OK 41870.3 0 90217.9 OK +TSS52 - - XLOC_000049 Xkr4 TSS52 chr1:3277913-3278390 - - 127495 0 331348 OK 27320.3 0 91429.2 OK TSS54 - - XLOC_000050 Xkr4 TSS54 chr1:3280117-3280144 - - 0 0 0 OK 0 0 0 OK TSS55 - - XLOC_000051 Xkr4 TSS55 chr1:3280498-3280525 - - 0 0 0 OK 0 0 0 OK -TSS56 - - XLOC_000052 Xkr4 TSS56 chr1:3280686-3280741 - - 0 0 0 OK 2.29576e+07 0 6.88728e+07 OK +TSS56 - - XLOC_000052 Xkr4 TSS56 chr1:3280686-3280741 - - 0 0 0 OK 1.49798e+07 0 5.98686e+07 OK TSS57 - - XLOC_000053 Xkr4 TSS57 chr1:3282504-3282531 - - 0 0 0 OK 0 0 0 OK TSS58 - - XLOC_000054 Xkr4 TSS58 chr1:3282650-3282677 - - 0 0 0 OK 0 0 0 OK TSS59 - - XLOC_000055 Xkr4 TSS59 chr1:3282760-3282832 - - 0 0 0 OK 0 0 0 OK TSS6 - - XLOC_000006 - TSS6 chr1:3188521-3188548 - - 0 0 0 OK 0 0 0 OK TSS60 - - XLOC_000056 Xkr4 TSS60 chr1:3284966-3284993 - - 0 0 0 OK 0 0 0 OK -TSS61 - - XLOC_000057 Xkr4 TSS61 chr1:3290488-3290553 - - 0 0 0 OK 9.79535e+06 0 2.9386e+07 OK -TSS62 - - XLOC_000058 Xkr4 TSS62 chr1:3290798-3290859 - - 1.8095e+07 0 5.4285e+07 OK 0 0 0 OK -TSS63 - - XLOC_000059 Xkr4 TSS63 chr1:3290919-3291273 - - 342218 0 691214 OK 75524 0 162732 OK -TSS65 - - XLOC_000060 Xkr4 TSS65 chr1:3299443-3299664 - - 937403 0 1.99795e+06 OK 137917 0 413751 OK +TSS61 - - XLOC_000057 Xkr4 TSS61 chr1:3290488-3290553 - - 0 0 0 OK 6.39146e+06 0 2.55442e+07 OK +TSS62 - - XLOC_000058 Xkr4 TSS62 chr1:3290798-3290859 - - 8.68561e+06 0 3.4713e+07 OK 0 0 0 OK +TSS63 - - XLOC_000059 Xkr4 TSS63 chr1:3290919-3291273 - - 164265 0 453103 OK 49279.4 0 164917 OK +TSS65 - - XLOC_000060 Xkr4 TSS65 chr1:3299443-3299664 - - 449954 0 1.56567e+06 OK 89990.7 0 449954 OK TSS66 - - XLOC_000060 Xkr4 TSS66 chr1:3299443-3299664 - - 0 0 0 OK 0 0 0 OK TSS67 - - XLOC_000061 Xkr4 TSS67 chr1:3299691-3299733 - - 0 0 0 OK 0 0 0 OK TSS68 - - XLOC_000062 Xkr4 TSS68 chr1:3300051-3300078 - - 0 0 0 OK 0 0 0 OK TSS69 - - XLOC_000063 Xkr4 TSS69 chr1:3307748-3307775 - - 0 0 0 OK 0 0 0 OK -TSS7 - - XLOC_000007 - TSS7 chr1:3189810-3190789 - - 415851 231920 599782 OK 458870 363705 554035 OK +TSS7 - - XLOC_000007 - TSS7 chr1:3189810-3190789 - - 199608 33901.5 365315 OK 299412 183619 415206 OK TSS70 - - XLOC_000064 Xkr4 TSS70 chr1:3318620-3318647 - - 0 0 0 OK 0 0 0 OK TSS71 - - XLOC_000065 Xkr4 TSS71 chr1:3318999-3319051 - - 0 0 0 OK 0 0 0 OK TSS72 - - XLOC_000066 Xkr4 TSS72 chr1:3330527-3330554 - - 0 0 0 OK 0 0 0 OK -TSS73 - - XLOC_000067 Xkr4 TSS73 chr1:3351240-3351311 - - 8.91489e+06 0 2.67447e+07 OK 0 0 0 OK -TSS74 - - XLOC_000068 Xkr4 TSS74 chr1:3355887-3356119 - - 585828 0 1.30332e+06 OK 0 0 0 OK -TSS75 - - XLOC_000069 Xkr4 TSS75 chr1:3356180-3356225 - - 1.19208e+08 0 3.57623e+08 OK 0 0 0 OK -TSS76 - - XLOC_000070 Xkr4 TSS76 chr1:3363076-3363176 - - 4.42166e+06 0 1.06748e+07 OK 0 0 0 OK +TSS73 - - XLOC_000067 Xkr4 TSS73 chr1:3351240-3351311 - - 4.27915e+06 0 1.71021e+07 OK 0 0 0 OK +TSS74 - - XLOC_000068 Xkr4 TSS74 chr1:3355887-3356119 - - 281197 0 1.06014e+06 OK 0 0 0 OK +TSS75 - - XLOC_000069 Xkr4 TSS75 chr1:3356180-3356225 - - 5.72196e+07 0 2.28684e+08 OK 0 0 0 OK +TSS76 - - XLOC_000070 Xkr4 TSS76 chr1:3363076-3363176 - - 2.1224e+06 0 7.19579e+06 OK 0 0 0 OK TSS77 - - XLOC_000071 Xkr4 TSS77 chr1:3363214-3363278 - - 0 0 0 OK 0 0 0 OK -TSS78 - - XLOC_000072 Xkr4 TSS78 chr1:3363387-3363446 - - 6.42536e+07 0 1.38447e+08 OK 0 0 0 OK +TSS78 - - XLOC_000072 Xkr4 TSS78 chr1:3363387-3363446 - - 3.08417e+07 0 1.03214e+08 OK 0 0 0 OK TSS79 - - XLOC_000073 Xkr4 TSS79 chr1:3363753-3363849 - - 0 0 0 OK 0 0 0 OK -TSS80 - - XLOC_000074 Xkr4 TSS80 chr1:3364871-3364919 - - 7.29939e+07 0 2.18982e+08 OK 0 0 0 OK +TSS80 - - XLOC_000074 Xkr4 TSS80 chr1:3364871-3364919 - - 3.50371e+07 0 1.40029e+08 OK 0 0 0 OK TSS81 - - XLOC_000075 Xkr4 TSS81 chr1:3367135-3367162 - - 0 0 0 OK 0 0 0 OK TSS82 - - XLOC_000076 Xkr4 TSS82 chr1:3367210-3367237 - - 0 0 0 OK 0 0 0 OK TSS83 - - XLOC_000077 Xkr4 TSS83 chr1:3367333-3367382 - - 0 0 0 OK 0 0 0 OK diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 test-data/cuffdiff_out9.txt --- a/test-data/cuffdiff_out9.txt +++ b/test-data/cuffdiff_out9.txt @@ -1,89 +1,89 @@ test_id gene_id gene locus sample_1 sample_2 status value_1 value_2 sqrt(JS) test_stat p_value q_value significant -TSS1 XLOC_000001 Xkr4 chr1:3204754-3204833 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS10 XLOC_000008 - chr1:3190858-3191434 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS11 XLOC_000009 - chr1:3191512-3192077 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS13 XLOC_000010 - chr1:3192250-3192336 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS14 XLOC_000011 - chr1:3192441-3192494 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS15 XLOC_000012 - chr1:3192550-3192629 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS16 XLOC_000013 - chr1:3192649-3192676 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS17 XLOC_000014 - chr1:3192731-3192811 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS18 XLOC_000015 - chr1:3192940-3193042 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS19 XLOC_000016 - chr1:3194185-3194226 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS2 XLOC_000002 - chr1:3111449-3111490 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS20 XLOC_000017 - chr1:3194302-3194329 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS21 XLOC_000018 - chr1:3194706-3194733 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS22 XLOC_000019 - chr1:3195083-3195110 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS23 XLOC_000020 - chr1:3195450-3195477 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS24 XLOC_000021 - chr1:3197089-3197116 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS25 XLOC_000022 - chr1:3197246-3197273 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS26 XLOC_000023 - chr1:3197346-3197373 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS27 XLOC_000024 - chr1:3197425-3197452 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS28 XLOC_000025 - chr1:3200022-3200191 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS29 XLOC_000026 - chr1:3200325-3200352 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS3 XLOC_000003 - chr1:3111545-3111576 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS30 XLOC_000027 - chr1:3200430-3200457 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS31 XLOC_000028 - chr1:3201007-3201039 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS32 XLOC_000029 - chr1:3201077-3201481 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS33 XLOC_000030 - chr1:3201596-3201666 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS34 XLOC_000031 - chr1:3201672-3201699 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS35 XLOC_000032 - chr1:3201725-3201809 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS36 XLOC_000033 Xkr4 chr1:3211521-3211561 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS37 XLOC_000034 Xkr4 chr1:3212213-3212292 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS38 XLOC_000035 Xkr4 chr1:3212367-3212439 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS39 XLOC_000036 Xkr4 chr1:3212717-3212801 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS4 XLOC_000004 - chr1:3174765-3174792 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS40 XLOC_000037 Xkr4 chr1:3213095-3213242 q1 q2 OK 0 0 0.249945 0.143447 0.135175 0.135175 no -TSS41 XLOC_000038 Xkr4 chr1:3240606-3240633 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS42 XLOC_000039 Xkr4 chr1:3242479-3242512 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS43 XLOC_000040 Xkr4 chr1:3242633-3242923 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS44 XLOC_000041 Xkr4 chr1:3242924-3243005 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS45 XLOC_000042 Xkr4 chr1:3243018-3243079 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS46 XLOC_000043 Xkr4 chr1:3243108-3243154 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS47 XLOC_000044 Xkr4 chr1:3243347-3243401 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS48 XLOC_000045 Xkr4 chr1:3254079-3254106 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS49 XLOC_000046 Xkr4 chr1:3256974-3257011 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS5 XLOC_000005 - chr1:3187401-3187428 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS50 XLOC_000047 Xkr4 chr1:3277155-3277182 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS51 XLOC_000048 Xkr4 chr1:3277190-3277218 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS52 XLOC_000049 Xkr4 chr1:3277913-3278390 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS54 XLOC_000050 Xkr4 chr1:3280117-3280144 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS55 XLOC_000051 Xkr4 chr1:3280498-3280525 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS56 XLOC_000052 Xkr4 chr1:3280686-3280741 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS57 XLOC_000053 Xkr4 chr1:3282504-3282531 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS58 XLOC_000054 Xkr4 chr1:3282650-3282677 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS59 XLOC_000055 Xkr4 chr1:3282760-3282832 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS6 XLOC_000006 - chr1:3188521-3188548 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS60 XLOC_000056 Xkr4 chr1:3284966-3284993 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS61 XLOC_000057 Xkr4 chr1:3290488-3290553 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS62 XLOC_000058 Xkr4 chr1:3290798-3290859 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS63 XLOC_000059 Xkr4 chr1:3290919-3291273 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS65 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS66 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS67 XLOC_000061 Xkr4 chr1:3299691-3299733 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS68 XLOC_000062 Xkr4 chr1:3300051-3300078 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS69 XLOC_000063 Xkr4 chr1:3307748-3307775 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS7 XLOC_000007 - chr1:3189810-3190789 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS70 XLOC_000064 Xkr4 chr1:3318620-3318647 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS71 XLOC_000065 Xkr4 chr1:3318999-3319051 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS72 XLOC_000066 Xkr4 chr1:3330527-3330554 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS73 XLOC_000067 Xkr4 chr1:3351240-3351311 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS74 XLOC_000068 Xkr4 chr1:3355887-3356119 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS75 XLOC_000069 Xkr4 chr1:3356180-3356225 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS76 XLOC_000070 Xkr4 chr1:3363076-3363176 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS77 XLOC_000071 Xkr4 chr1:3363214-3363278 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS78 XLOC_000072 Xkr4 chr1:3363387-3363446 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS79 XLOC_000073 Xkr4 chr1:3363753-3363849 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS80 XLOC_000074 Xkr4 chr1:3364871-3364919 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS81 XLOC_000075 Xkr4 chr1:3367135-3367162 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS82 XLOC_000076 Xkr4 chr1:3367210-3367237 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS83 XLOC_000077 Xkr4 chr1:3367333-3367382 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS84 XLOC_000078 Xkr4 chr1:3369580-3369607 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS85 XLOC_000079 Xkr4 chr1:3375001-3375028 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS86 XLOC_000080 Xkr4 chr1:3377211-3377262 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS87 XLOC_000081 Xkr4 chr1:3379888-3379915 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS88 XLOC_000082 Xkr4 chr1:3386739-3386836 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS89 XLOC_000083 Xkr4 chr1:3391325-3391352 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS90 XLOC_000084 Xkr4 chr1:3435841-3435880 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS91 XLOC_000085 Xkr4 chr1:3447761-3447788 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS92 XLOC_000086 Xkr4 chr1:3450906-3450965 q1 q2 NOTEST 0 0 0 0 0 1 no -TSS93 XLOC_000087 Xkr4 chr1:3451051-3451109 q1 q2 NOTEST 0 0 0 0 0 1 no +TSS1 XLOC_000001 Xkr4 chr1:3204754-3204833 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS10 XLOC_000008 - chr1:3190858-3191434 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS11 XLOC_000009 - chr1:3191512-3192077 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS13 XLOC_000010 - chr1:3192250-3192336 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS14 XLOC_000011 - chr1:3192441-3192494 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS15 XLOC_000012 - chr1:3192550-3192629 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS16 XLOC_000013 - chr1:3192649-3192676 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS17 XLOC_000014 - chr1:3192731-3192811 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS18 XLOC_000015 - chr1:3192940-3193042 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS19 XLOC_000016 - chr1:3194185-3194226 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS2 XLOC_000002 - chr1:3111449-3111490 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS20 XLOC_000017 - chr1:3194302-3194329 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS21 XLOC_000018 - chr1:3194706-3194733 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS22 XLOC_000019 - chr1:3195083-3195110 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS23 XLOC_000020 - chr1:3195450-3195477 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS24 XLOC_000021 - chr1:3197089-3197116 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS25 XLOC_000022 - chr1:3197246-3197273 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS26 XLOC_000023 - chr1:3197346-3197373 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS27 XLOC_000024 - chr1:3197425-3197452 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS28 XLOC_000025 - chr1:3200022-3200191 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS29 XLOC_000026 - chr1:3200325-3200352 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS3 XLOC_000003 - chr1:3111545-3111576 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS30 XLOC_000027 - chr1:3200430-3200457 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS31 XLOC_000028 - chr1:3201007-3201039 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS32 XLOC_000029 - chr1:3201077-3201481 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS33 XLOC_000030 - chr1:3201596-3201666 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS34 XLOC_000031 - chr1:3201672-3201699 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS35 XLOC_000032 - chr1:3201725-3201809 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS36 XLOC_000033 Xkr4 chr1:3211521-3211561 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS37 XLOC_000034 Xkr4 chr1:3212213-3212292 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS38 XLOC_000035 Xkr4 chr1:3212367-3212439 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS39 XLOC_000036 Xkr4 chr1:3212717-3212801 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS4 XLOC_000004 - chr1:3174765-3174792 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS40 XLOC_000037 Xkr4 chr1:3213095-3213242 q1 q2 NOTEST 0 0 0.249947 0 0.557805 1 no +TSS41 XLOC_000038 Xkr4 chr1:3240606-3240633 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS42 XLOC_000039 Xkr4 chr1:3242479-3242512 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS43 XLOC_000040 Xkr4 chr1:3242633-3242923 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS44 XLOC_000041 Xkr4 chr1:3242924-3243005 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS45 XLOC_000042 Xkr4 chr1:3243018-3243079 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS46 XLOC_000043 Xkr4 chr1:3243108-3243154 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS47 XLOC_000044 Xkr4 chr1:3243347-3243401 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS48 XLOC_000045 Xkr4 chr1:3254079-3254106 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS49 XLOC_000046 Xkr4 chr1:3256974-3257011 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS5 XLOC_000005 - chr1:3187401-3187428 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS50 XLOC_000047 Xkr4 chr1:3277155-3277182 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS51 XLOC_000048 Xkr4 chr1:3277190-3277218 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS52 XLOC_000049 Xkr4 chr1:3277913-3278390 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS54 XLOC_000050 Xkr4 chr1:3280117-3280144 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS55 XLOC_000051 Xkr4 chr1:3280498-3280525 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS56 XLOC_000052 Xkr4 chr1:3280686-3280741 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS57 XLOC_000053 Xkr4 chr1:3282504-3282531 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS58 XLOC_000054 Xkr4 chr1:3282650-3282677 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS59 XLOC_000055 Xkr4 chr1:3282760-3282832 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS6 XLOC_000006 - chr1:3188521-3188548 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS60 XLOC_000056 Xkr4 chr1:3284966-3284993 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS61 XLOC_000057 Xkr4 chr1:3290488-3290553 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS62 XLOC_000058 Xkr4 chr1:3290798-3290859 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS63 XLOC_000059 Xkr4 chr1:3290919-3291273 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS65 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS66 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS67 XLOC_000061 Xkr4 chr1:3299691-3299733 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS68 XLOC_000062 Xkr4 chr1:3300051-3300078 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS69 XLOC_000063 Xkr4 chr1:3307748-3307775 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS7 XLOC_000007 - chr1:3189810-3190789 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS70 XLOC_000064 Xkr4 chr1:3318620-3318647 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS71 XLOC_000065 Xkr4 chr1:3318999-3319051 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS72 XLOC_000066 Xkr4 chr1:3330527-3330554 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS73 XLOC_000067 Xkr4 chr1:3351240-3351311 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS74 XLOC_000068 Xkr4 chr1:3355887-3356119 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS75 XLOC_000069 Xkr4 chr1:3356180-3356225 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS76 XLOC_000070 Xkr4 chr1:3363076-3363176 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS77 XLOC_000071 Xkr4 chr1:3363214-3363278 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS78 XLOC_000072 Xkr4 chr1:3363387-3363446 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS79 XLOC_000073 Xkr4 chr1:3363753-3363849 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS80 XLOC_000074 Xkr4 chr1:3364871-3364919 q1 q2 NOTEST 0 0 0 0 1 1 no +TSS81 XLOC_000075 Xkr4 chr1:3367135-3367162 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS82 XLOC_000076 Xkr4 chr1:3367210-3367237 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS83 XLOC_000077 Xkr4 chr1:3367333-3367382 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS84 XLOC_000078 Xkr4 chr1:3369580-3369607 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS85 XLOC_000079 Xkr4 chr1:3375001-3375028 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS86 XLOC_000080 Xkr4 chr1:3377211-3377262 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS87 XLOC_000081 Xkr4 chr1:3379888-3379915 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS88 XLOC_000082 Xkr4 chr1:3386739-3386836 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS89 XLOC_000083 Xkr4 chr1:3391325-3391352 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS90 XLOC_000084 Xkr4 chr1:3435841-3435880 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS91 XLOC_000085 Xkr4 chr1:3447761-3447788 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS92 XLOC_000086 Xkr4 chr1:3450906-3450965 q1 q2 LOWDATA 0 0 0 0 0 1 no +TSS93 XLOC_000087 Xkr4 chr1:3451051-3451109 q1 q2 LOWDATA 0 0 0 0 0 1 no diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 tools/ngs_rna/cuffcompare_wrapper.py --- a/tools/ngs_rna/cuffcompare_wrapper.py +++ b/tools/ngs_rna/cuffcompare_wrapper.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +# Supports Cuffcompare versions v1.3.0 and newer. + import optparse, os, shutil, subprocess, sys, tempfile def stop_err( msg ): diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 tools/ngs_rna/cuffcompare_wrapper.xml --- a/tools/ngs_rna/cuffcompare_wrapper.xml +++ b/tools/ngs_rna/cuffcompare_wrapper.xml @@ -1,5 +1,5 @@ <tool id="cuffcompare" name="Cuffcompare" version="0.0.5"> - <!-- Wrapper supports Cuffcompare versions v1.0.0-v1.3.0 --> + <!-- Wrapper supports Cuffcompare versions v1.3.0 and newer --><description>compare assembled transcripts to a reference annotation and track Cufflinks transcripts across multiple experiments</description><requirements><requirement type="package">cufflinks</requirement> @@ -80,13 +80,18 @@ from_work_dir="cc_output.stats" /><data format="tabular" name="input1_tmap" label="${tool.name} on ${on_string}: ${first_input.hid} data tmap file" from_work_dir="cc_output.input1.tmap" /> - <data format="tabular" name="input1_refmap" label="${tool.name} on ${on_string}: data ${first_input.hid} refmap file" - from_work_dir="cc_output.input1.refmap"/> + <data format="tabular" name="input1_refmap" + label="${tool.name} on ${on_string}: data ${first_input.hid} refmap file" + from_work_dir="cc_output.input1.refmap"> + <filter>annotation['use_ref_annotation'] == 'Yes'</filter> + </data><data format="tabular" name="input2_tmap" label="${tool.name} on ${on_string}: data ${input_files[0]['additional_input'].hid} tmap file" from_work_dir="cc_output.input2.tmap"> - <filter>len( input_files ) > 0</filter> + <filter>len( input_files ) > 1</filter></data> - <data format="tabular" name="input2_refmap" label="${tool.name} on ${on_string}: data ${input_files[0]['additional_input'].hid} refmap file" from_work_dir="cc_output.input2.refmap"> - <filter>len( input_files ) > 0</filter> + <data format="tabular" name="input2_refmap" + label="${tool.name} on ${on_string}: data ${input_files[0]['additional_input'].hid} refmap file" + from_work_dir="cc_output.input2.refmap"> + <filter>annotation['use_ref_annotation'] == 'Yes' and len( input_files ) > 1</filter></data><data format="tabular" name="transcripts_tracking" label="${tool.name} on ${on_string}: transcript tracking" from_work_dir="cc_output.tracking"><filter>len( input_files ) > 0</filter> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 tools/ngs_rna/cuffdiff_wrapper.py --- a/tools/ngs_rna/cuffdiff_wrapper.py +++ b/tools/ngs_rna/cuffdiff_wrapper.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +# Wrapper supports Cuffdiff versions v1.3.0-v2.0 + import optparse, os, shutil, subprocess, sys, tempfile def group_callback( option, op_str, value, parser ): @@ -59,6 +61,7 @@ where each end is 50bp, you should set -r to be 200. The default is 45bp.') parser.add_option( '-c', '--min-alignment-count', dest='min_alignment_count', help='The minimum number of alignments in a locus for needed to conduct significance testing on changes in that locus observed between samples. If no testing is performed, changes in the locus are deemed not signficant, and the locus\' observed changes don\'t contribute to correction for multiple testing. The default is 1,000 fragment alignments (up to 2,000 paired reads).' ) parser.add_option( '--FDR', dest='FDR', help='The allowed false discovery rate. The default is 0.05.' ) + parser.add_option( '-u', '--multi-read-correct', dest='multi_read_correct', action="store_true", help='Tells Cufflinks to do an initial estimation procedure to more accurately weight reads mapping to multiple locations in the genome') # Advanced Options: parser.add_option( '--num-importance-samples', dest='num_importance_samples', help='Sets the number of importance samples generated for each locus during abundance estimation. Default: 1000' ) @@ -153,6 +156,8 @@ cmd += ( " -c %i" % int ( options.min_alignment_count ) ) if options.FDR: cmd += ( " --FDR %f" % float( options.FDR ) ) + if options.multi_read_correct: + cmd += ( " -u" ) if options.num_importance_samples: cmd += ( " --num-importance-samples %i" % int ( options.num_importance_samples ) ) if options.max_mle_iterations: diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 tools/ngs_rna/cuffdiff_wrapper.xml --- a/tools/ngs_rna/cuffdiff_wrapper.xml +++ b/tools/ngs_rna/cuffdiff_wrapper.xml @@ -1,5 +1,5 @@ <tool id="cuffdiff" name="Cuffdiff" version="0.0.5"> - <!-- Wrapper supports Cuffdiff versions v1.0.0-v1.3.0 --> + <!-- Wrapper supports Cuffdiff versions v1.3.0-v2.0 --><description>find significant changes in transcript expression, splicing, and promoter use</description><requirements><requirement type="package">cufflinks</requirement> @@ -33,7 +33,11 @@ -N #end if - + ## Multi-read correct? + #if str($multiread_correct) == "Yes": + -u + #end if + ## Bias correction? #if $bias_correction.do_bias_correction == "Yes": -b @@ -89,11 +93,19 @@ </conditional><param name="fdr" type="float" value="0.05" label="False Discovery Rate" help="The allowed false discovery rate."/> + <param name="min_alignment_count" type="integer" value="10" label="Min Alignment Count" help="The minimum number of alignments in a locus for needed to conduct significance testing on changes in that locus observed between samples."/> + <param name="do_normalization" type="select" label="Perform quartile normalization" help="Removes top 25% of genes from FPKM denominator to improve accuracy of differential expression calls for low abundance transcripts."><option value="No">No</option><option value="Yes">Yes</option></param> + + <param name="multiread_correct" type="select" label="Use multi-read correct" help="Tells Cufflinks to do an initial estimation procedure to more accurately weight reads mapping to multiple locations in the genome."> + <option value="No" selected="true">No</option> + <option value="Yes">Yes</option> + </param> + <conditional name="bias_correction"><param name="do_bias_correction" type="select" label="Perform Bias Correction" help="Bias detection and correction can significantly improve accuracy of transcript abundance estimates."><option value="No">No</option> @@ -113,6 +125,7 @@ </when><when value="No"></when></conditional> + <conditional name="additional"><param name="sAdditional" type="select" label="Set Additional Parameters? (not recommended)"><option value="No">No</option> @@ -154,6 +167,7 @@ <param name="min_alignment_count" value="0" /><param name="do_bias_correction" value="No" /><param name="do_normalization" value="No" /> + <param name="multiread_correct" value="No"/><param name="sAdditional" value="No"/><!-- Line diffs are needed because cuffdiff does not produce deterministic output. diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 tools/ngs_rna/cufflinks_wrapper.py --- a/tools/ngs_rna/cufflinks_wrapper.py +++ b/tools/ngs_rna/cufflinks_wrapper.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +# Supports Cufflinks versions 1.3 and newer. + import optparse, os, shutil, subprocess, sys, tempfile from galaxy import eggs from galaxy.datatypes.util.gff_util import parse_gff_attributes, gff_attributes_to_str @@ -36,6 +38,7 @@ where each end is 50bp, you should set -r to be 200. The default is 45bp.') parser.add_option( '-G', '--GTF', dest='GTF', help='Tells Cufflinks to use the supplied reference annotation to estimate isoform expression. It will not assemble novel transcripts, and the program will ignore alignments not structurally compatible with any reference transcript.' ) parser.add_option( '-g', '--GTF-guide', dest='GTFguide', help='use reference transcript annotation to guide assembly' ) + parser.add_option( '-u', '--multi-read-correct', dest='multi_read_correct', action="store_true", help='Tells Cufflinks to do an initial estimation procedure to more accurately weight reads mapping to multiple locations in the genome') # Normalization options. parser.add_option( "-N", "--quartile-normalization", dest="do_normalization", action="store_true" ) @@ -116,7 +119,9 @@ if options.GTF: cmd += ( " -G %s" % options.GTF ) if options.GTFguide: - cmd += ( " -g %s" % options.GTFguide ) + cmd += ( " -g %s" % options.GTFguide ) + if options.multi_read_correct: + cmd += ( " -u" ) if options.num_importance_samples: cmd += ( " --num-importance-samples %i" % int ( options.num_importance_samples ) ) if options.max_mle_iterations: @@ -157,7 +162,7 @@ total_map_mass = -1 tmp_stderr = open( tmp_name, 'r' ) for line in tmp_stderr: - if line.lower().find( "total map mass" ) >= 0 or line.lower().find( "upper quartile" ) >= 0: + if line.lower().find( "map mass" ) >= 0 or line.lower().find( "upper quartile" ) >= 0: total_map_mass = float( line.split(":")[1].strip() ) break tmp_stderr.close() diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 tools/ngs_rna/cufflinks_wrapper.xml --- a/tools/ngs_rna/cufflinks_wrapper.xml +++ b/tools/ngs_rna/cufflinks_wrapper.xml @@ -1,5 +1,5 @@ <tool id="cufflinks" name="Cufflinks" version="0.0.5"> - <!-- Wrapper supports Cufflinks versions v1.0.0-v1.3.0 --> + <!-- Wrapper supports Cufflinks versions v1.3.0 and newer --><description>transcript assembly and FPKM (RPKM) estimates for RNA-Seq data</description><requirements><requirement type="package">cufflinks</requirement> @@ -20,12 +20,6 @@ #if $reference_annotation.use_ref == "Use reference annotation guide": -g $reference_annotation.reference_annotation_guide_file #end if - - ## Set paired-end parameters? - #if $singlePaired.sPaired == "Yes": - -m $singlePaired.mean_inner_distance - -s $singlePaired.inner_distance_std_dev - #end if ## Normalization? #if str($do_normalization) == "Yes": @@ -34,7 +28,7 @@ ## Bias correction? #if $bias_correction.do_bias_correction == "Yes": - -b + -b #if $bias_correction.seq_source.index_source == "history": --ref_file=$bias_correction.seq_source.ref_file #else: @@ -44,6 +38,11 @@ --index_dir=${GALAXY_DATA_INDEX_DIR} #end if + ## Multi-read correct? + #if str($multiread_correct) == "Yes": + -u + #end if + ## Include global model if available. #if $global_model: --global_model=$global_model @@ -55,12 +54,12 @@ <param name="min_isoform_fraction" type="float" value="0.10" min="0" max="1" label="Min Isoform Fraction" help=""/><param name="pre_mrna_fraction" type="float" value="0.15" min="0" max="1" label="Pre MRNA Fraction" help=""/><param name="do_normalization" type="select" label="Perform quartile normalization" help="Removes top 25% of genes from FPKM denominator to improve accuracy of differential expression calls for low abundance transcripts."> - <option value="No">No</option> + <option value="No" selected="true">No</option><option value="Yes">Yes</option></param><conditional name="reference_annotation"><param name="use_ref" type="select" label="Use Reference Annotation"> - <option value="No">No</option> + <option value="No" selected="true">No</option><option value="Use reference annotation">Use reference annotation</option><option value="Use reference annotation guide">Use reference annotation as guide</option></param> @@ -74,13 +73,13 @@ </conditional><conditional name="bias_correction"><param name="do_bias_correction" type="select" label="Perform Bias Correction" help="Bias detection and correction can significantly improve accuracy of transcript abundance estimates."> - <option value="No">No</option> - <option value="Yes">Yes</option> + <option value="No" selected="true">No</option> + <option value="Yes">Yes</option></param><when value="Yes"><conditional name="seq_source"><param name="index_source" type="select" label="Reference sequence data"> - <option value="cached">Locally cached</option> + <option value="cached" selected="true">Locally cached</option><option value="history">History</option></param><when value="cached"></when> @@ -91,17 +90,12 @@ </when><when value="No"></when></conditional> - <conditional name="singlePaired"> - <param name="sPaired" type="select" label="Set Parameters for Paired-end Reads? (not recommended)"> - <option value="No">No</option> - <option value="Yes">Yes</option> - </param> - <when value="No"></when> - <when value="Yes"> - <param name="mean_inner_distance" type="integer" value="20" label="Mean Inner Distance between Mate Pairs"/> - <param name="inner_distance_std_dev" type="integer" value="20" label="Standard Deviation for Inner Distance between Mate Pairs"/> - </when> - </conditional> + + <param name="multiread_correct" type="select" label="Use multi-read correct" help="Tells Cufflinks to do an initial estimation procedure to more accurately weight reads mapping to multiple locations in the genome."> + <option value="No" selected="true">No</option> + <option value="Yes">Yes</option> + </param> + <param name="global_model" type="hidden_data" label="Global model (for use in Trackster)" optional="True"/></inputs> @@ -121,7 +115,6 @@ Simple test that uses test data included with cufflinks. --><test> - <param name="sPaired" value="No"/><param name="input" value="cufflinks_in.bam"/><param name="max_intron_len" value="300000"/><param name="min_isoform_fraction" value="0.05"/> @@ -129,6 +122,7 @@ <param name="use_ref" value="No"/><param name="do_normalization" value="No" /><param name="do_bias_correction" value="No"/> + <param name="multiread_correct" value="No"/><output name="genes_expression" format="tabular" lines_diff="2" file="cufflinks_out3.fpkm_tracking"/><output name="transcripts_expression" format="tabular" lines_diff="2" file="cufflinks_out2.fpkm_tracking"/><output name="assembled_isoforms" file="cufflinks_out1.gtf"/> diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 tools/ngs_rna/cuffmerge_wrapper.py --- a/tools/ngs_rna/cuffmerge_wrapper.py +++ b/tools/ngs_rna/cuffmerge_wrapper.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +# Supports Cuffmerge versions 1.3 and newer. + import optparse, os, shutil, subprocess, sys, tempfile def stop_err( msg ): diff -r 20e1f9fb8da9975b130047aece6d3ee3d26482fd -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 tools/ngs_rna/cuffmerge_wrapper.xml --- a/tools/ngs_rna/cuffmerge_wrapper.xml +++ b/tools/ngs_rna/cuffmerge_wrapper.xml @@ -1,5 +1,5 @@ <tool id="cuffmerge" name="Cuffmerge" version="0.0.5"> - <!-- Wrapper supports Cuffmerge version v1.0.0 --> + <!-- Wrapper supports Cuffmerge versions 1.3 and newer --><description>merge together several Cufflinks assemblies</description><requirements><requirement type="package">cufflinks</requirement> @@ -88,7 +88,7 @@ <param name="reference_annotation" value="cuffcompare_in3.gtf" ftype="gtf"/><param name="use_seq_data" value="No"/><!-- oId assignment differ/are non-deterministic --> - <output name="merged_transcripts" file="cuffmerge_out1.gtf" lines_diff="8"/> + <output name="merged_transcripts" file="cuffmerge_out1.gtf" lines_diff="50"/></test></tests> https://bitbucket.org/galaxy/galaxy-central/changeset/f3705f69d822/ changeset: f3705f69d822 user: james_taylor date: 2012-09-28 21:13:07 summary: User inheritence to extend user controller in community webapp affected #: 2 files diff -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 -r f3705f69d8227fe08c56076528bf2c9356808d71 lib/galaxy/webapps/community/buildapp.py --- a/lib/galaxy/webapps/community/buildapp.py +++ b/lib/galaxy/webapps/community/buildapp.py @@ -42,21 +42,6 @@ T = getattr( module, key ) if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ): webapp.add_ui_controller( name, T( app ) ) - import galaxy.web.controllers - controller_dir = galaxy.web.controllers.__path__[0] - for fname in os.listdir( controller_dir ): - # TODO: fix this if we decide to use, we don't need to inspect all controllers... - if fname.startswith( 'user' ) and fname.endswith( ".py" ): - name = fname[:-3] - module_name = "galaxy.web.controllers." + name - module = __import__( module_name ) - for comp in module_name.split( "." )[1:]: - module = getattr( module, comp ) - # Look for a controller inside the modules - for key in dir( module ): - T = getattr( module, key ) - if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ): - webapp.add_ui_controller( name, T( app ) ) def app_factory( global_conf, **kwargs ): """Return a wsgi application serving the root object""" diff -r 08dbb6b88aeb89bb37b0dfa7641a463bd2a4fa52 -r f3705f69d8227fe08c56076528bf2c9356808d71 lib/galaxy/webapps/community/controllers/user.py --- /dev/null +++ b/lib/galaxy/webapps/community/controllers/user.py @@ -0,0 +1,1 @@ +from galaxy.webapps.main.controllers.user import * \ No newline at end of file https://bitbucket.org/galaxy/galaxy-central/changeset/974f6b70c570/ changeset: 974f6b70c570 user: james_taylor date: 2012-09-28 21:15:28 summary: Main webapp needs to be called 'galaxy' since that is what is used in templates currently affected #: 106 files Diff too large to display. https://bitbucket.org/galaxy/galaxy-central/changeset/ac3980d88740/ changeset: ac3980d88740 user: james_taylor date: 2012-09-28 21:17:18 summary: Use name galaxy when initializing controllers affected #: 1 file diff -r 974f6b70c570c866b98553dccff5af2a57c6ad4b -r ac3980d88740001c2291a6fc2d198aa5dee5bfbc lib/galaxy/webapps/galaxy/buildapp.py --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -38,7 +38,7 @@ atexit.register( app.shutdown ) # Create the universe WSGI application webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxysession' ) - webapp.add_ui_controllers( 'galaxy.webapps.main.controllers', app ) + webapp.add_ui_controllers( 'galaxy.webapps.galaxy.controllers', app ) # Force /history to go to /root/history -- needed since the tests assume this webapp.add_route( '/history', controller='root', action='history' ) # These two routes handle our simple needs at the moment @@ -56,7 +56,7 @@ webapp.add_route( '/u/:username/v/:slug', controller='visualization', action='display_by_username_and_slug' ) # Add the web API - webapp.add_api_controllers( 'galaxy.webapps.main.api', app ) + webapp.add_api_controllers( 'galaxy.webapps.galaxy.api', app ) webapp.api_mapper.resource( 'content', 'contents', controller='library_contents', https://bitbucket.org/galaxy/galaxy-central/changeset/b5fe81cc70be/ changeset: b5fe81cc70be user: james_taylor date: 2012-09-28 21:20:59 summary: Subclasses of WebApplication for different apps affected #: 3 files diff -r ac3980d88740001c2291a6fc2d198aa5dee5bfbc -r b5fe81cc70be18f720f2180bfe9c221995d0530e lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -215,7 +215,8 @@ class WebApplication( base.WebApplication ): - def __init__( self, galaxy_app, session_cookie='galaxysession' ): + def __init__( self, galaxy_app, session_cookie='galaxysession', name=None ): + self.name = name base.WebApplication.__init__( self ) self.set_transaction_factory( lambda e: self.transaction_chooser( e, galaxy_app, session_cookie ) ) # Mako support diff -r ac3980d88740001c2291a6fc2d198aa5dee5bfbc -r b5fe81cc70be18f720f2180bfe9c221995d0530e lib/galaxy/webapps/community/buildapp.py --- a/lib/galaxy/webapps/community/buildapp.py +++ b/lib/galaxy/webapps/community/buildapp.py @@ -21,6 +21,9 @@ log = logging.getLogger( __name__ ) +class CommunityWebApplication( galaxy.web.framework.WebApplication ): + pass + def add_ui_controllers( webapp, app ): """ Search for controllers in the 'galaxy.webapps.controllers' module and add @@ -58,7 +61,7 @@ sys.exit( 1 ) atexit.register( app.shutdown ) # Create the universe WSGI application - webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxycommunitysession' ) + webapp = CommunityWebApplication( app, session_cookie='galaxycommunitysession', name="community" ) add_ui_controllers( webapp, app ) webapp.add_route( '/:controller/:action', action='index' ) webapp.add_route( '/:action', controller='repository', action='index' ) diff -r ac3980d88740001c2291a6fc2d198aa5dee5bfbc -r b5fe81cc70be18f720f2180bfe9c221995d0530e lib/galaxy/webapps/galaxy/buildapp.py --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -20,6 +20,9 @@ import galaxy.datatypes.registry import galaxy.web.framework +class GalaxyWebApplication( galaxy.web.framework.WebApplication ): + pass + def app_factory( global_conf, **kwargs ): """ Return a wsgi application serving the root object @@ -37,7 +40,7 @@ sys.exit( 1 ) atexit.register( app.shutdown ) # Create the universe WSGI application - webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxysession' ) + webapp = GalaxyWebApplication( app, session_cookie='galaxysession', name='galaxy' ) webapp.add_ui_controllers( 'galaxy.webapps.galaxy.controllers', app ) # Force /history to go to /root/history -- needed since the tests assume this webapp.add_route( '/history', controller='root', action='history' ) https://bitbucket.org/galaxy/galaxy-central/changeset/170b9bda24b0/ changeset: 170b9bda24b0 user: james_taylor date: 2012-09-28 21:30:18 summary: Subclass of WebApplication for reports affected #: 1 file diff -r b5fe81cc70be18f720f2180bfe9c221995d0530e -r 170b9bda24b04b95cbce81a9d2fb4aafc898c1f2 lib/galaxy/webapps/reports/buildapp.py --- a/lib/galaxy/webapps/reports/buildapp.py +++ b/lib/galaxy/webapps/reports/buildapp.py @@ -20,6 +20,9 @@ import galaxy.model.mapping import galaxy.web.framework +class ReportsWebApplication( galaxy.web.framework.WebApplication ): + pass + def add_ui_controllers( webapp, app ): """ Search for controllers in the 'galaxy.webapps.controllers' module and add @@ -52,7 +55,7 @@ app = UniverseApplication( global_conf = global_conf, **kwargs ) atexit.register( app.shutdown ) # Create the universe WSGI application - webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxyreportssession' ) + webapp = ReportsWebApplication( app, session_cookie='galaxyreportssession', name="reports" ) add_ui_controllers( webapp, app ) # These two routes handle our simple needs at the moment webapp.add_route( '/:controller/:action', controller="root", action='index' ) https://bitbucket.org/galaxy/galaxy-central/changeset/a37d82881a49/ changeset: a37d82881a49 user: james_taylor date: 2012-09-28 21:30:25 summary: Automated merge with https://bitbucket.org/galaxy/galaxy-central affected #: 111 files Diff too large to display. 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.