lists.galaxyproject.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
List overview
Download
galaxy-dev
February 2010
----- 2024 -----
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
galaxy-dev@lists.galaxyproject.org
32 participants
180 discussions
Start a n
N
ew thread
[hg] galaxy 3386: fixes to allow downloading of composite files ...
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/8d9c8cf65dee
changeset: 3386:8d9c8cf65dee user: rerla@localhost date: Fri Feb 12 17:10:05 2010 -0500 description: fixes to allow downloading of composite files from a library. if a single file is chosen, act_on_multiple_datasets is used and zip is always the format. if act_on_multiple_datasets encounters any composite files, it adds the html file and all the files in extra_files_path to the archive diffstat: lib/galaxy/web/controllers/library_common.py | 80 ++++++++++++++++++++------- 1 files changed, 59 insertions(+), 21 deletions(-) diffs (117 lines): diff -r c1f22feda926 -r 8d9c8cf65dee lib/galaxy/web/controllers/library_common.py --- a/lib/galaxy/web/controllers/library_common.py Fri Feb 12 15:17:36 2010 -0500 +++ b/lib/galaxy/web/controllers/library_common.py Fri Feb 12 17:10:05 2010 -0500 @@ -1,4 +1,4 @@ -import os, os.path, shutil, urllib, StringIO, re, gzip, tempfile, shutil, zipfile, copy +import os, os.path, shutil, urllib, StringIO, re, gzip, tempfile, shutil, zipfile, copy, glob from galaxy.web.base.controller import * from galaxy import util, jobs from galaxy.datatypes import sniff @@ -1048,21 +1048,30 @@ show_deleted = util.string_as_bool( kwd.get( 'show_deleted', False ) ) ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( id ) ) if not ldda.dataset: - msg = 'Invalid LibraryDatasetDatasetAssociation id %s received for file downlaod' % str( id ) + msg = 'Invalid LibraryDatasetDatasetAssociation id %s received for file download' % str( id ) messagetype = 'error' else: - mime = trans.app.datatypes_registry.get_mimetype_by_extension( ldda.extension.lower() ) - trans.response.set_content_type( mime ) - fStat = os.stat( ldda.file_name ) - trans.response.headers[ 'Content-Length' ] = int( fStat.st_size ) - valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' - fname = ldda.name - fname = ''.join( c in valid_chars and c or '_' for c in fname )[ 0:150 ] - trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryDataset-%s-[%s]" % ( str( id ), fname ) - try: - return open( ldda.file_name ) - except: - msg = 'This dataset contains no content' + composite_extensions = trans.app.datatypes_registry.get_composite_extensions( ) + ext = ldda.extension + if ext in composite_extensions: + # is composite - must return a zip of contents and the html file itself - ugh - should be reversible at upload! + # use act_on_multiple_datasets( self, trans, cntrller, library_id, ldda_ids='', **kwd ) since it does what we need + kwd['do_action'] = 'zip' + return self.act_on_multiple_datasets( trans, cntrller, library_id, ldda_ids=id, **kwd ) + + else: + mime = trans.app.datatypes_registry.get_mimetype_by_extension( ldda.extension.lower() ) + trans.response.set_content_type( mime ) + fStat = os.stat( ldda.file_name ) + trans.response.headers[ 'Content-Length' ] = int( fStat.st_size ) + valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + fname = ldda.name + fname = ''.join( c in valid_chars and c or '_' for c in fname )[ 0:150 ] + trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryDataset-%s-[%s]" % ( str( id ), fname ) + try: + return open( ldda.file_name ) + except: + msg = 'This dataset contains no content' return trans.response.send_redirect( web.url_for( controller='library_common', action='browse_library', cntrller=cntrller, @@ -1246,6 +1255,7 @@ msg = "Unable to create archive for download, please report this error" messagetype = 'error' if not error: + composite_extensions = trans.app.datatypes_registry.get_composite_extensions( ) seen = [] current_user_roles = trans.get_current_user_roles() for ldda_id in ldda_ids: @@ -1254,6 +1264,9 @@ or not trans.app.security_agent.can_access_dataset( current_user_roles, ldda.dataset ) \ or ldda.dataset.state in [ 'new', 'upload', 'queued', 'running', 'empty', 'discarded' ]: continue + ext = ldda.extension + if ext in composite_extensions: + is_composite = True path = "" parent_folder = ldda.library_dataset.folder while parent_folder is not None: @@ -1267,13 +1280,38 @@ while path in seen: path += '_' seen.append( path ) - try: - archive.add( ldda.dataset.file_name, path ) - except IOError: - error = True - log.exception( "Unable to write to temporary library download archive" ) - msg = "Unable to create archive for download, please report this error" - messagetype = 'error' + if is_composite: # need to add all the components from the extra_files_path to the zip + zpath = os.path.split(path)[-1] # comes as base_name/fname + zpathext = os.path.splitext(zpath)[-1] + if zpathext == '': + zpath = '%s.html' % zpath # fake the real nature of the html file + try: + archive.add(ldda.dataset.file_name,zpath) + except IOError: + error = True + log.exception( "Unable to add composite parent %s to temporary library download archive" % ldda.dataset.file_name) + msg = "Unable to create archive for download, please report this error" + messagetype = 'error' + continue + flist = glob.glob(os.path.join(ldda.dataset.extra_files_path,'*.*')) # glob returns full paths + for fpath in flist: + efp,fname = os.path.split(fpath) + try: + archive.add( fpath,fname ) + except IOError: + error = True + log.exception( "Unable to add %s to temporary library download archive" % fname) + msg = "Unable to create archive for download, please report this error" + messagetype = 'error' + continue + else: # simple case + try: + archive.add( ldda.dataset.file_name, path ) + except IOError: + error = True + log.exception( "Unable to write %s to temporary library download archive" % ldda.dataset.file_name) + msg = "Unable to create archive for download, please report this error" + messagetype = 'error' if not error: if params.do_action == 'zip': archive.close()
1
0
0
0
[hg] galaxy 3385: LIMS: using threads for data transfer. first pass
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/b5786505e278
changeset: 3385:b5786505e278 user: rc date: Fri Feb 12 16:59:57 2010 -0500 description: LIMS: using threads for data transfer. first pass diffstat: lib/galaxy/web/controllers/requests_admin.py | 46 +++++++++++++++++------ scripts/galaxy_messaging/server/data_transfer.py | 4 +- 2 files changed, 34 insertions(+), 16 deletions(-) diffs (94 lines): diff -r 6cbd13376ce8 -r b5786505e278 lib/galaxy/web/controllers/requests_admin.py --- a/lib/galaxy/web/controllers/requests_admin.py Fri Feb 12 16:45:37 2010 -0500 +++ b/lib/galaxy/web/controllers/requests_admin.py Fri Feb 12 16:59:57 2010 -0500 @@ -11,7 +11,7 @@ from sqlalchemy.sql.expression import func, and_ from sqlalchemy.sql import select import pexpect -import ConfigParser +import ConfigParser, threading, time log = logging.getLogger( __name__ ) @@ -204,6 +204,18 @@ action='create_request_type' ) ) ] +class DataTransferThread(threading.Thread): + def __init__(self, **kwargs): + threading.Thread.__init__(self, name=kwargs['name']) + self.dataset_index = kwargs['dataset_index'] + self.cmd = kwargs['cmd'] + def run(self): + try: + retcode = subprocess.call(self.cmd) + except Exception, e: + error_msg = "Data transfer failed. " + str(e) + "<br/>" + log.debug(error_msg) + # # ---- Request Controller ------------------------------------------------------ @@ -1511,7 +1523,7 @@ trans.sa_session.add( dp ) trans.sa_session.flush() return datatx_user - + def __start_datatx(self, trans, sample): # data transfer user datatx_user = self.__setup_datatx_user(trans, sample.library, sample.folder) @@ -1542,20 +1554,28 @@ str(index), trans.security.encode_id(sample.library.id), trans.security.encode_id(sample.folder.id) ) - # set the transfer status +# # set the transfer status sample.dataset_files[index][1] = sample.transfer_status.IN_PROGRESS trans.sa_session.add( sample ) trans.sa_session.flush() - try: - retcode = subprocess.call(cmd) - except Exception, e: - error_msg = dfile.split('/')[-1] + ": Data transfer failed. " + str(e) + "<br/>" - return trans.response.send_redirect( web.url_for( controller='requests_admin', - action='show_datatx_page', - sample_id=trans.security.encode_id(sample.id), - folder_path=os.path.dirname(dfile), - messagetype='error', - msg=error_msg)) + dtt = DataTransferThread(name='thread_'+str(index), + dataset_index=index, + cmd=cmd) + dtt.start() +# # set the transfer status +# sample.dataset_files[index][1] = sample.transfer_status.IN_PROGRESS +# trans.sa_session.add( sample ) +# trans.sa_session.flush() +# try: +# retcode = subprocess.call(cmd) +# except Exception, e: +# error_msg = dfile.split('/')[-1] + ": Data transfer failed. " + str(e) + "<br/>" +# return trans.response.send_redirect( web.url_for( controller='requests_admin', +# action='show_datatx_page', +# sample_id=trans.security.encode_id(sample.id), +# folder_path=os.path.dirname(dfile), +# messagetype='error', +# msg=error_msg)) # set the sample state to the last state if sample.current_state().id != sample.request.type.states[-1].id: event = trans.app.model.SampleEvent(sample, sample.request.type.states[-1], diff -r 6cbd13376ce8 -r b5786505e278 scripts/galaxy_messaging/server/data_transfer.py --- a/scripts/galaxy_messaging/server/data_transfer.py Fri Feb 12 16:45:37 2010 -0500 +++ b/scripts/galaxy_messaging/server/data_transfer.py Fri Feb 12 16:59:57 2010 -0500 @@ -38,9 +38,7 @@ pkg_resources.require( "simplejson" ) import simplejson -curr_dir = os.getcwd() -logfile = os.path.join(os.getcwd(), 'data_transfer.log') -logging.basicConfig(filename=logfile, level=logging.DEBUG, +logging.basicConfig(filename=sys.stderr, level=logging.DEBUG, format="%(asctime)s [%(levelname)s] %(message)s") class DataTransferException(Exception):
1
0
0
0
[hg] galaxy 3384: Rudimentary support for embedding of histories...
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/6cbd13376ce8
changeset: 3384:6cbd13376ce8 user: jeremy goecks <jeremy.goecks(a)emory.edu> date: Fri Feb 12 16:45:37 2010 -0500 description: Rudimentary support for embedding of histories, datasets, and workflows into pages. Specifics: (1) added menus for inserting links to galaxy items and for embedding items to page editor; (2) framework code for producing HTML for embedded items on page display; and (3) toggling to display/hide embedded item content. Smaller improvements include (a) refactoring of controller code to create useful mixins and facilitate code reuse; (b) moving all fugue icons into static/images/fugue directory; and (c) improvement to display templates. diffstat: lib/galaxy/model/mapping.py | 15 + lib/galaxy/web/base/controller.py | 141 +++++++++++++- lib/galaxy/web/controllers/dataset.py | 64 +++--- lib/galaxy/web/controllers/history.py | 37 ++- lib/galaxy/web/controllers/page.py | 147 ++++++++++++--- lib/galaxy/web/controllers/root.py | 13 +- lib/galaxy/web/controllers/workflow.py | 96 ++++------ static/images/fugue/pencil.png | 0 static/images/fugue/sticky-note-text.png | 0 static/images/fugue/tag-label.png | 0 static/images/fugue/toggle-expand.png | 0 static/images/fugue/toggle.png | 0 static/images/pencil.png | 0 static/images/sticky-note-text.png | 0 static/images/tag-label.png | 0 static/june_2007_style/base.css.tmpl | 12 +- static/june_2007_style/blue/base.css | 6 +- static/june_2007_style/blue/embed_item.css | 4 + static/june_2007_style/embed_item.css.tmpl | 24 ++ templates/dataset/display.mako | 3 +- templates/dataset/embed.mako | 13 + templates/dataset/item_content.mako | 3 + templates/display_base.mako | 28 +- templates/display_common.mako | 24 ++ templates/embed_base.mako | 38 ++++ templates/history/embed.mako | 15 + templates/history/item_content.mako | 3 + templates/page/display.mako | 58 +++++- templates/page/editor.mako | 265 ++++++++++++++++++++++++---- templates/page/wymiframe.mako | 2 +- templates/sharing_base.mako | 2 +- templates/workflow/display.mako | 1 - templates/workflow/embed.mako | 15 + templates/workflow/item_content.mako | 3 + 34 files changed, 798 insertions(+), 234 deletions(-) diffs (1695 lines): diff -r c1f22feda926 -r 6cbd13376ce8 lib/galaxy/model/mapping.py --- a/lib/galaxy/model/mapping.py Fri Feb 12 15:17:36 2010 -0500 +++ b/lib/galaxy/model/mapping.py Fri Feb 12 16:45:37 2010 -0500 @@ -980,6 +980,11 @@ tags=relation( HistoryTagAssociation, order_by=HistoryTagAssociation.table.c.id, backref="histories" ), annotations=relation( HistoryAnnotationAssociation, order_by=HistoryAnnotationAssociation.table.c.id, backref="histories" ) ) ) + +# Set up proxy so that +# History.users_shared_with_dot_users +# returns a list of User objects. +History.users_shared_with_dot_users = association_proxy( 'users_shared_with', 'user' ) assign_mapper( context, HistoryUserShareAssociation, HistoryUserShareAssociation.table, properties=dict( user=relation( User, backref='histories_shared_by_others' ), @@ -1271,6 +1276,11 @@ tags=relation( StoredWorkflowTagAssociation, order_by=StoredWorkflowTagAssociation.table.c.id, backref="stored_workflows" ), annotations=relation( StoredWorkflowAnnotationAssociation, order_by=StoredWorkflowAnnotationAssociation.table.c.id, backref="stored_workflows" ) ) ) + +# Set up proxy so that +# StoredWorkflow.users_shared_with_dot_users +# returns a list of User objects. +StoredWorkflow.users_shared_with_dot_users = association_proxy( 'users_shared_with', 'user' ) assign_mapper( context, StoredWorkflowUserShareAssociation, StoredWorkflowUserShareAssociation.table, properties=dict( user=relation( User, backref='workflows_shared_by_others' ), @@ -1296,6 +1306,11 @@ tags=relation(PageTagAssociation, order_by=PageTagAssociation.table.c.id, backref="pages") ) ) +# Set up proxy so that +# Page.users_shared_with_dot_users +# returns a list of User objects. +Page.users_shared_with_dot_users = association_proxy( 'users_shared_with', 'user' ) + assign_mapper( context, PageUserShareAssociation, PageUserShareAssociation.table, properties=dict( user=relation( User, backref='pages_shared_by_others' ), page=relation( Page, backref='users_shared_with' ) diff -r c1f22feda926 -r 6cbd13376ce8 lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py Fri Feb 12 15:17:36 2010 -0500 +++ b/lib/galaxy/web/base/controller.py Fri Feb 12 16:45:37 2010 -0500 @@ -8,7 +8,7 @@ from galaxy import config, tools, web, model, util from galaxy.web import error, form, url_for from galaxy.model.orm import * -from galaxy.web.framework.helpers import grids +from galaxy.workflow.modules import * from Cheetah.Template import Template @@ -27,22 +27,6 @@ """Returns the application toolbox""" return self.app.toolbox - def get_history( self, trans, id, check_ownership=True ): - """Get a History from the database by id, verifying ownership.""" - # Load history from database - id = trans.security.decode_id( id ) - history = trans.sa_session.query( model.History ).get( id ) - if not history: - err+msg( "History not found" ) - if check_ownership: - # Verify ownership - user = trans.get_user() - if not user: - error( "Must be logged in to manage histories" ) - if history.user != user: - error( "History is not owned by current user" ) - return history - def get_class( self, class_name ): """ Returns the class object that a string denotes. Without this method, we'd have to do eval(<class_name>). """ if class_name == 'History': @@ -107,9 +91,124 @@ return True Root = BaseController + +class SharableItemSecurity: + """ Mixin for handling security for sharable items. """ + + def security_check( self, user, item, check_ownership=False, check_accessible=False ): + """ Security checks for an item: checks if (a) user owns item or (b) item is accessible to user. """ + if check_ownership: + # Verify ownership. + if not user: + error( "Must be logged in to manage Galaxy items" ) + if item.user != user: + error( "%s is not owned by current user" % item.__class__.__name__ ) + if check_accessible: + # Verify accessible. + if ( item.user != user ) and ( not item.importable ) and ( user not in item.users_shared_with_dot_users ): + raise "hi" + error( "%s is not accessible by current user" % item.__class__.__name__ ) + return item + +class UsesHistoryDatasetAssociation: + """ Mixin for controllers that use HistoryDatasetAssociation objects. """ + + def get_dataset( self, trans, dataset_id, check_accessible=True ): + """ Get an HDA object by id. """ + # DEPRECATION: We still support unencoded ids for backward compatibility + try: + dataset_id = int( dataset_id ) + except ValueError: + dataset_id = trans.security.decode_id( dataset_id ) + data = trans.sa_session.query( model.HistoryDatasetAssociation ).get( dataset_id ) + if not data: + raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid dataset id: %s." % str( dataset_id ) ) + if check_accessible: + current_user_roles = trans.get_current_user_roles() + if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): + if data.state == trans.model.Dataset.states.UPLOAD: + return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to view it." ) + else: + error( "You are not allowed to access this dataset" ) + return data + + def get_data( self, dataset, preview=True ): + """ Gets a dataset's data. """ + # Get data from file, truncating if necessary. + truncated = False + dataset_data = None + if os.path.exists( dataset.file_name ): + max_peek_size = 1000000 # 1 MB + if preview and os.stat( dataset.file_name ).st_size > max_peek_size: + dataset_data = open( dataset.file_name ).read(max_peek_size) + truncated = True + else: + dataset_data = open( dataset.file_name ).read(max_peek_size) + truncated = False + return truncated, dataset_data + +class UsesStoredWorkflow( SharableItemSecurity ): + """ Mixin for controllers that use StoredWorkflow objects. """ + + def get_stored_workflow( self, trans, id, check_ownership=True, check_accessible=False ): + """ Get a StoredWorkflow from the database by id, verifying ownership. """ + # Load workflow from database + id = trans.security.decode_id( id ) + stored = trans.sa_session.query( model.StoredWorkflow ).get( id ) + if not stored: + error( "Workflow not found" ) + else: + return self.security_check( trans.get_user(), stored, check_ownership, check_accessible ) + + def get_stored_workflow_steps( self, trans, stored_workflow ): + """ Restores states for a stored workflow's steps. """ + for step in stored_workflow.latest_workflow.steps: + if step.type == 'tool' or step.type is None: + # Restore the tool state for the step + module = module_factory.from_workflow_step( trans, step ) + # Any connected input needs to have value DummyDataset (these + # are not persisted so we need to do it every time) + module.add_dummy_datasets( connections=step.input_connections ) + # Store state with the step + step.module = module + step.state = module.state + # Error dict + if step.tool_errors: + errors[step.id] = step.tool_errors + else: + ## Non-tool specific stuff? + step.module = module_factory.from_workflow_step( trans, step ) + step.state = step.module.get_runtime_state() + # Connections by input name + step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections ) + +class UsesHistory( SharableItemSecurity ): + """ Mixin for controllers that use History objects. """ + + def get_history( self, trans, id, check_ownership=True, check_accessible=False ): + """Get a History from the database by id, verifying ownership.""" + # Load history from database + id = trans.security.decode_id( id ) + history = trans.sa_session.query( model.History ).get( id ) + if not history: + err+msg( "History not found" ) + else: + return self.security_check( trans.get_user(), history, check_ownership, check_accessible ) + + def get_history_datasets( self, trans, history, show_deleted=False ): + """ Returns history's datasets. """ + query = trans.sa_session.query( model.HistoryDatasetAssociation ) \ + .filter( model.HistoryDatasetAssociation.history == history ) \ + .options( eagerload( "children" ) ) \ + .join( "dataset" ).filter( model.Dataset.purged == False ) \ + .options( eagerload_all( "dataset.actions" ) ) \ + .order_by( model.HistoryDatasetAssociation.hid ) + if not show_deleted: + query = query.filter( model.HistoryDatasetAssociation.deleted == False ) + return query.all() class Sharable: - """ Mixin for a controller that manages and item that can be shared. """ + """ Mixin for a controller that manages an item that can be shared. """ # Implemented methods. @web.expose @@ -146,6 +245,12 @@ """ Returns item's name and link. """ pass + @web.expose + @web.require_login("get item content asynchronously") + def get_item_content_async( self, trans, id ): + """ Returns item content in HTML format. """ + pass + # Helper methods. def _make_item_accessible( self, sa_session, item ): diff -r c1f22feda926 -r 6cbd13376ce8 lib/galaxy/web/controllers/dataset.py --- a/lib/galaxy/web/controllers/dataset.py Fri Feb 12 15:17:36 2010 -0500 +++ b/lib/galaxy/web/controllers/dataset.py Fri Feb 12 16:45:37 2010 -0500 @@ -110,7 +110,7 @@ # a user relation. return query.select_from( model.HistoryDatasetAssociation.table.join( model.History.table ) ).filter( model.History.user == trans.user ) -class DatasetInterface( BaseController ): +class DatasetInterface( BaseController, UsesHistoryDatasetAssociation ): stored_list_grid = HistoryDatasetAssociationListGrid() @@ -293,9 +293,18 @@ @web.require_login( "use Galaxy datasets" ) def get_name_and_link_async( self, trans, id=None ): """ Returns dataset's name and link. """ - dataset = self.get_data( trans, id ) + dataset = self.get_dataset( trans, id ) return_dict = { "name" : dataset.name, "link" : url_for( action="display_by_username_and_slug", username=dataset.history.user.username, slug=trans.security.encode_id( dataset.id ) ) } return return_dict + + @web.expose + def get_embed_html_async( self, trans, id ): + """ Returns HTML for embedding a dataset in a page. """ + + # TODO: user should be able to embed any item he has access to. see display_by_username_and_slug for security code. + dataset = self.get_dataset( trans, id ) + if dataset: + return "Embedded Dataset '%s'" % dataset.name @web.expose @web.require_login( "use Galaxy datasets" ) @@ -306,20 +315,26 @@ @web.expose def display_by_username_and_slug( self, trans, username, slug, preview=True ): """ Display dataset by username and slug; because datasets do not yet have slugs, the slug is the dataset's id. """ - data = self.get_data( trans, slug ) - if data: - # Get data from file, truncating if necessary. - if os.path.exists( data.file_name ): - max_peek_size = 1000000 # 1 MB - if preview and os.stat( data.file_name ).st_size > max_peek_size: - dataset_data = open( data.file_name ).read(max_peek_size) - truncated = True - else: - dataset_data = open( data.file_name ).read(max_peek_size) - truncated = False - return trans.fill_template_mako( "dataset/display.mako", item=data, item_data=dataset_data, truncated=truncated ) + dataset = self.get_dataset( trans, slug ) + if dataset: + truncated, dataset_data = self.get_data( dataset, preview ) + return trans.fill_template_mako( "/dataset/display.mako", item=dataset, item_data=dataset_data, truncated=truncated ) else: raise web.httpexceptions.HTTPNotFound() + + @web.expose + @web.require_login("get item content asynchronously") + def get_item_content_async( self, trans, id ): + """ Returns item content in HTML format. """ + + dataset = self.get_dataset( trans, id ) + if dataset is None: + raise web.httpexceptions.HTTPNotFound() + truncated, dataset_data = self.get_data( dataset, preview=True ) + # Get annotation. + annotation = self.get_item_annotation_str( trans.sa_session, trans.get_user(), dataset ) + return trans.stream_template_mako( "/dataset/item_content.mako", item=dataset, item_data=dataset_data, truncated=truncated ) + @web.expose def display_at( self, trans, dataset_id, filename=None, **kwd ): @@ -513,23 +528,4 @@ new_history_name = new_history_name, done_msg = done_msg, error_msg = error_msg, - refresh_frames = refresh_frames ) - - def get_data( self, trans, dataset_id, check_user_can_access=True ): - """ Get an HDA from the database by id, verifying that user can access dataset.""" - # DEPRECATION: We still support unencoded ids for backward compatibility - try: - dataset_id = int( dataset_id ) - except ValueError: - dataset_id = trans.security.decode_id( dataset_id ) - data = trans.sa_session.query( model.HistoryDatasetAssociation ).get( dataset_id ) - if not data: - raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid dataset id: %s." % str( dataset_id ) ) - if check_user_can_access: - current_user_roles = trans.get_current_user_roles() - if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): - if data.state == trans.model.Dataset.states.UPLOAD: - return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to view it." ) - else: - error( "You are not allowed to access this dataset" ) - return data \ No newline at end of file + refresh_frames = refresh_frames ) \ No newline at end of file diff -r c1f22feda926 -r 6cbd13376ce8 lib/galaxy/web/controllers/history.py --- a/lib/galaxy/web/controllers/history.py Fri Feb 12 15:17:36 2010 -0500 +++ b/lib/galaxy/web/controllers/history.py Fri Feb 12 16:45:37 2010 -0500 @@ -146,7 +146,7 @@ # A public history is published, has a slug, and is not deleted. return query.filter( self.model_class.published == True ).filter( self.model_class.slug != None ).filter( self.model_class.deleted == False ) -class HistoryController( BaseController, Sharable ): +class HistoryController( BaseController, Sharable, UsesHistory ): @web.expose def index( self, trans ): return "" @@ -406,6 +406,21 @@ history.slug = new_slug trans.sa_session.flush() return history.slug + + @web.expose + @web.require_login("get item content asynchronously") + def get_item_content_async( self, trans, id ): + """ Returns item content in HTML format. """ + + history = self.get_history( trans, id, False, True ) + if history is None: + raise web.httpexceptions.HTTPNotFound() + + # Get datasets. + datasets = self.get_history_datasets( trans, history ) + # Get annotation. + annotation = self.get_item_annotation_str( trans.sa_session, trans.get_user(), history ) + return trans.stream_template_mako( "/history/item_content.mako", item = history, item_data = datasets ) @web.expose def name_autocomplete_data( self, trans, q=None, limit=None, timestamp=None ): @@ -489,17 +504,11 @@ if not trans.user_is_admin and not history_to_view.importable: error( "Either you are not allowed to view this history or the owner of this history has not made it accessible." ) # View history. - query = trans.sa_session.query( model.HistoryDatasetAssociation ) \ - .filter( model.HistoryDatasetAssociation.history == history_to_view ) \ - .options( eagerload( "children" ) ) \ - .join( "dataset" ).filter( model.Dataset.purged == False ) \ - .options( eagerload_all( "dataset.actions" ) ) - # Do not show deleted datasets. - query = query.filter( model.HistoryDatasetAssociation.deleted == False ) + datasets = self.get_history_datasets( trans, history_to_view ) user_owns_history = ( trans.get_user() == history_to_view.user ) return trans.stream_template_mako( "history/view.mako", history = history_to_view, - datasets = query.all(), + datasets = datasets, user_owns_history = user_owns_history, show_deleted = False ) @@ -521,15 +530,9 @@ raise web.httpexceptions.HTTPNotFound() # Get datasets. - query = trans.sa_session.query( model.HistoryDatasetAssociation ) \ - .filter( model.HistoryDatasetAssociation.history == history ) \ - .options( eagerload( "children" ) ) \ - .join( "dataset" ).filter( model.Dataset.purged == False ) \ - .options( eagerload_all( "dataset.actions" ) ) - # Do not show deleted datasets. - query = query.filter( model.HistoryDatasetAssociation.deleted == False ) + datasets = self.get_history_datasets( trans, history ) return trans.stream_template_mako( "history/display.mako", - item = history, item_data = query.all() ) + item = history, item_data = datasets ) @web.expose @web.require_login( "share Galaxy histories" ) diff -r c1f22feda926 -r 6cbd13376ce8 lib/galaxy/web/controllers/page.py --- a/lib/galaxy/web/controllers/page.py Fri Feb 12 15:17:36 2010 -0500 +++ b/lib/galaxy/web/controllers/page.py Fri Feb 12 16:45:37 2010 -0500 @@ -1,6 +1,6 @@ from galaxy.web.base.controller import * from galaxy.web.framework.helpers import time_ago, grids -from galaxy.util.sanitize_html import sanitize_html +from galaxy.util.sanitize_html import sanitize_html, _BaseHTMLProcessor from galaxy.util.odict import odict from galaxy.util.json import from_json_string @@ -222,7 +222,70 @@ key="free-text-search", visible=False, filterable="standard" ) ) -class PageController( BaseController, Sharable ): +class _PageContentProcessor( _BaseHTMLProcessor ): + """ Processes page content to produce HTML that is suitable for display. For now, processor renders embedded objects. """ + + def __init__( self, trans, encoding, type, render_embed_html_fn ): + _BaseHTMLProcessor.__init__( self, encoding, type) + self.trans = trans + self.ignore_content = False + self.num_open_tags_for_ignore = 0 + self.render_embed_html_fn = render_embed_html_fn + + def unknown_starttag( self, tag, attrs ): + """ Called for each start tag; attrs is a list of (attr, value) tuples. """ + + # If ignoring content, just increment tag count and ignore. + if self.ignore_content: + self.num_open_tags_for_ignore += 1 + return + + # Not ignoring tag; look for embedded content. + embedded_item = False + for attribute in attrs: + if ( attribute[0] == "class" ) and ( "embedded-item" in attribute[1].split(" ") ): + embedded_item = True + break + # For embedded content, set ignore flag to ignore current content and add new content for embedded item. + if embedded_item: + # Set processing attributes to ignore content. + self.ignore_content = True + self.num_open_tags_for_ignore = 1 + + # Insert content for embedded element. + for attribute in attrs: + name = attribute[0] + if name == "id": + # ID has form '<class_name>-<encoded_item_id>' + item_class, item_id = attribute[1].split("-") + embed_html = self.render_embed_html_fn( self.trans, item_class, item_id ) + self.pieces.append( embed_html ) + return + + # Default behavior: not ignoring and no embedded content. + _BaseHTMLProcessor.unknown_starttag( self, tag, attrs ) + + def handle_data( self, text ): + """ Called for each block of plain text. """ + if self.ignore_content: + return + _BaseHTMLProcessor.handle_data( self, text ) + + def unknown_endtag( self, tag ): + """ Called for each end tag. """ + + # If ignoring content, see if current tag is the end of content to ignore. + if self.ignore_content: + self.num_open_tags_for_ignore -= 1 + if self.num_open_tags_for_ignore == 0: + # Done ignoring content. + self.ignore_content = False + return + + # Default behavior: + _BaseHTMLProcessor.unknown_endtag( self, tag ) + +class PageController( BaseController, Sharable, UsesHistory, UsesStoredWorkflow, UsesHistoryDatasetAssociation ): _page_list = PageListGrid() _all_published_list = PageAllPublishedGrid() @@ -520,9 +583,13 @@ # User not logged in, so only way to view page is if it's importable. page = page_query_base.filter_by( importable=True ).first() if page is None: - raise web.httpexceptions.HTTPNotFound() - - return trans.fill_template_mako( "page/display.mako", item=page) + raise web.httpexceptions.HTTPNotFound() + + # Process page content. + processor = _PageContentProcessor( trans, 'utf-8', 'text/html', self._get_embed_html ) + processor.feed( page.latest_revision.content ) + page_content = processor.output() + return trans.fill_template_mako( "page/display.mako", item=page, item_data=page_content, content_only=True ) @web.expose @web.require_login( "use Galaxy pages" ) @@ -548,6 +615,15 @@ page.slug = new_slug trans.sa_session.flush() return page.slug + + @web.expose + def get_embed_html_async( self, trans, id ): + """ Returns HTML for embedding a workflow in a page. """ + + # TODO: user should be able to embed any item he has access to. see display_by_username_and_slug for security code. + page = self.get_page( trans, id ) + if page: + return "Embedded Page '%s'" % page.title @web.expose @web.json @@ -593,43 +669,50 @@ @web.require_login("get annotation table for history") def get_history_annotation_table( self, trans, id ): """ Returns HTML for an annotation table for a history. """ - - # TODO: users should be able to annotate a history if they own it, it is importable, or it is shared with them. This only - # returns a history if a user owns it. - history = self.get_history( trans, id, True ) + history = self.get_history( trans, id, False, True ) if history: - # TODO: Query taken from root/history; it should be moved either into history or trans object - # so that it can reused. - query = trans.sa_session.query( model.HistoryDatasetAssociation ) \ - .filter( model.HistoryDatasetAssociation.history == history ) \ - .options( eagerload( "children" ) ) \ - .join( "dataset" ).filter( model.Dataset.purged == False ) \ - .options( eagerload_all( "dataset.actions" ) ) \ - .order_by( model.HistoryDatasetAssociation.hid ) - # For now, do not show deleted datasets. - show_deleted = False - if not show_deleted: - query = query.filter( model.HistoryDatasetAssociation.deleted == False ) - return trans.fill_template( "page/history_annotation_table.mako", history=history, datasets=query.all(), show_deleted=False ) + datasets = self.get_history_datasets( trans, history ) + return trans.fill_template( "page/history_annotation_table.mako", history=history, datasets=datasets, show_deleted=False ) @web.expose def get_editor_iframe( self, trans ): """ Returns the document for the page editor's iframe. """ return trans.fill_template( "page/wymiframe.mako" ) - def get_page( self, trans, id, check_ownership=True ): + def get_page( self, trans, id, check_ownership=True, check_accessible=False ): """Get a page from the database by id, verifying ownership.""" # Load history from database id = trans.security.decode_id( id ) page = trans.sa_session.query( model.Page ).get( id ) if not page: - err+msg( "History not found" ) - if check_ownership: - # Verify ownership - user = trans.get_user() - if not user: - error( "Must be logged in to work with Pages" ) - if page.user != user: - error( "History is not owned by current user" ) - return page \ No newline at end of file + err+msg( "Page not found" ) + else: + return self.security_check( trans.get_user(), page, check_ownership, check_accessible ) + + def _get_embed_html( self, trans, item_class, item_id ): + """ Returns HTML for embedding an item in a page. """ + item_class = self.get_class( item_class ) + if item_class == model.History: + history = self.get_history( trans, item_id, False, True ) + if history: + datasets = self.get_history_datasets( trans, history ) + annotation = self.get_item_annotation_str( trans.sa_session, history.user, history ) + return trans.fill_template( "history/embed.mako", item=history, item_data=datasets, annotation=annotation ) + elif item_class == model.HistoryDatasetAssociation: + dataset = self.get_dataset( trans, item_id ) + if dataset: + data = self.get_data( dataset ) + annotation = self.get_item_annotation_str( trans.sa_session, dataset.history.user, dataset ) + return trans.fill_template( "dataset/embed.mako", item=dataset, item_data=data, annotation=annotation ) + elif item_class == model.StoredWorkflow: + workflow = self.get_stored_workflow( trans, item_id, False, True ) + if workflow: + self.get_stored_workflow_steps( trans, workflow ) + annotation = self.get_item_annotation_str( trans.sa_session, workflow.user, workflow ) + return trans.fill_template( "workflow/embed.mako", item=workflow, item_data=workflow.latest_workflow.steps, annotation=annotation ) + elif item_class == model.Page: + pass + + + \ No newline at end of file diff -r c1f22feda926 -r 6cbd13376ce8 lib/galaxy/web/controllers/root.py --- a/lib/galaxy/web/controllers/root.py Fri Feb 12 15:17:36 2010 -0500 +++ b/lib/galaxy/web/controllers/root.py Fri Feb 12 16:45:37 2010 -0500 @@ -10,7 +10,7 @@ log = logging.getLogger( __name__ ) -class RootController( BaseController ): +class RootController( BaseController, UsesHistory ): @web.expose def default(self, trans, target1=None, target2=None, **kwd): @@ -69,18 +69,11 @@ return trans.fill_template_mako( "root/history_as_xml.mako", history=history, show_deleted=util.string_as_bool( show_deleted ) ) else: show_deleted = util.string_as_bool( show_deleted ) - query = trans.sa_session.query( model.HistoryDatasetAssociation ) \ - .filter( model.HistoryDatasetAssociation.history == history ) \ - .options( eagerload( "children" ) ) \ - .join( "dataset" ).filter( model.Dataset.purged == False ) \ - .options( eagerload_all( "dataset.actions" ) ) \ - .order_by( model.HistoryDatasetAssociation.hid ) - if not show_deleted: - query = query.filter( model.HistoryDatasetAssociation.deleted == False ) + datasets = self.get_history_datasets( trans, history, show_deleted ) return trans.stream_template_mako( "root/history.mako", history = history, annotation = self.get_item_annotation_str( trans.sa_session, trans.get_user(), history ), - datasets = query.all(), + datasets = datasets, hda_id = hda_id, show_deleted = show_deleted ) diff -r c1f22feda926 -r 6cbd13376ce8 lib/galaxy/web/controllers/workflow.py --- a/lib/galaxy/web/controllers/workflow.py Fri Feb 12 15:17:36 2010 -0500 +++ b/lib/galaxy/web/controllers/workflow.py Fri Feb 12 16:45:37 2010 -0500 @@ -78,7 +78,7 @@ # A public workflow is published, has a slug, and is not deleted. return query.filter( self.model_class.published==True ).filter( self.model_class.slug != None ).filter( self.model_class.deleted == False ) -class WorkflowController( BaseController, Sharable ): +class WorkflowController( BaseController, Sharable, UsesStoredWorkflow ): stored_list_grid = StoredWorkflowListGrid() published_list_grid = StoredWorkflowAllPublishedGrid() @@ -93,7 +93,6 @@ status = message = None if 'operation' in kwargs: operation = kwargs['operation'].lower() - print operation if operation == "rename": return self.rename( trans, **kwargs ) history_ids = util.listify( kwargs.get( 'id', [] ) ) @@ -165,7 +164,6 @@ @web.expose def display_by_username_and_slug( self, trans, username, slug ): """ Display workflow based on a username and slug. """ - session = trans.sa_session # Get workflow. session = trans.sa_session @@ -181,34 +179,31 @@ raise web.httpexceptions.HTTPNotFound() # Get data for workflow's steps. - for step in stored_workflow.latest_workflow.steps: - if step.type == 'tool' or step.type is None: - # Restore the tool state for the step - module = module_factory.from_workflow_step( trans, step ) - # Any connected input needs to have value DummyDataset (these - # are not persisted so we need to do it every time) - module.add_dummy_datasets( connections=step.input_connections ) - # Store state with the step - step.module = module - step.state = module.state - # Error dict - if step.tool_errors: - errors[step.id] = step.tool_errors - else: - ## Non-tool specific stuff? - step.module = module_factory.from_workflow_step( trans, step ) - step.state = step.module.get_runtime_state() - # Connections by input name - step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections ) + self.get_stored_workflow_steps( trans, stored_workflow ) return trans.fill_template_mako( "workflow/display.mako", item=stored_workflow, item_data=stored_workflow.latest_workflow.steps ) + + @web.expose + @web.require_login("get item content asynchronously") + def get_item_content_async( self, trans, id ): + """ Returns item content in HTML format. """ + + stored = self.get_stored_workflow( trans, id, False, True ) + if stored is None: + raise web.httpexceptions.HTTPNotFound() + + # Get data for workflow's steps. + self.get_stored_workflow_steps( trans, stored ) + # Get annotation. + annotation = self.get_item_annotation_str( trans.sa_session, trans.get_user(), stored ) + return trans.stream_template_mako( "/workflow/item_content.mako", item = stored, item_data = stored.latest_workflow.steps ) @web.expose @web.require_login( "use Galaxy workflows" ) def share( self, trans, id, email="" ): msg = mtype = None # Load workflow from database - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) if email: other = trans.sa_session.query( model.User ) \ .filter( and_( model.User.table.c.email==email, @@ -247,7 +242,7 @@ # Get session and workflow. session = trans.sa_session - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) session.add( stored ) # Do operation on workflow. @@ -285,7 +280,7 @@ @web.require_login( "use Galaxy workflows" ) def imp( self, trans, id, **kwargs ): session = trans.sa_session - stored = get_stored_workflow( trans, id, check_ownership=False ) + stored = self.get_stored_workflow( trans, id, check_ownership=False ) if stored.importable == False: error( "The owner of this workflow has disabled imports via this link" ) elif stored.user == trans.user: @@ -309,7 +304,7 @@ @web.require_login( "use Galaxy workflows" ) def edit_attributes( self, trans, id, **kwargs ): # Get workflow and do error checking. - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) if not stored: error( "You do not own this workflow or workflow ID is invalid." ) @@ -331,7 +326,7 @@ @web.expose @web.require_login( "use Galaxy workflows" ) def rename( self, trans, id, new_name=None, **kwargs ): - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) if new_name is not None: stored.name = new_name trans.sa_session.flush() @@ -348,7 +343,7 @@ @web.expose @web.require_login( "use Galaxy workflows" ) def rename_async( self, trans, id, new_name=None, **kwargs ): - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) if new_name: stored.name = new_name trans.sa_session.flush() @@ -357,7 +352,7 @@ @web.expose @web.require_login( "use Galaxy workflows" ) def annotate_async( self, trans, id, new_annotation=None, **kwargs ): - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) if new_annotation: # Sanitize annotation before adding it. new_annotation = sanitize_html( new_annotation, 'utf-8', 'text/html' ) @@ -369,7 +364,7 @@ @web.require_login( "use Galaxy workflows" ) def set_accessible_async( self, trans, id=None, accessible=False ): """ Set workflow's importable attribute and slug. """ - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) # Only set if importable value would change; this prevents a change in the update_time unless attribute really changed. importable = accessible in ['True', 'true', 't', 'T']; @@ -385,18 +380,27 @@ @web.expose @web.require_login( "modify Galaxy items" ) def set_slug_async( self, trans, id, new_slug ): - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) if stored: stored.slug = new_slug trans.sa_session.flush() return stored.slug + + @web.expose + def get_embed_html_async( self, trans, id ): + """ Returns HTML for embedding a workflow in a page. """ + + # TODO: user should be able to embed any item he has access to. see display_by_username_and_slug for security code. + stored = self.get_stored_workflow( trans, id ) + if stored: + return "Embedded Workflow '%s'" % stored.name @web.expose @web.json @web.require_login( "use Galaxy workflows" ) def get_name_and_link_async( self, trans, id=None ): """ Returns workflow's name and link. """ - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) if self.set_item_slug( trans.sa_session, stored ): trans.sa_session.flush() @@ -406,7 +410,7 @@ @web.expose @web.require_login( "use Galaxy workflows" ) def clone( self, trans, id ): - stored = get_stored_workflow( trans, id, check_ownership=False ) + stored = self.get_stored_workflow( trans, id, check_ownership=False ) user = trans.get_user() if stored.user == user: owner = True @@ -463,7 +467,7 @@ Mark a workflow as deleted """ # Load workflow from database - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) # Marke as deleted and save stored.deleted = True trans.sa_session.add( stored ) @@ -482,7 +486,7 @@ """ if not id: error( "Invalid workflow id" ) - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) return trans.fill_template( "workflow/editor.mako", stored=stored, annotation=self.get_item_annotation_str( trans.sa_session, trans.get_user(), stored ) ) @web.json @@ -611,7 +615,7 @@ Save the workflow described by `workflow_data` with id `id`. """ # Get the stored workflow - stored = get_stored_workflow( trans, id ) + stored = self.get_stored_workflow( trans, id ) # Put parameters in workflow mode trans.workflow_building_mode = True # Convert incoming workflow data from json @@ -795,7 +799,7 @@ @web.expose def run( self, trans, id, check_user=True, **kwargs ): - stored = get_stored_workflow( trans, id, check_ownership=False ) + stored = self.get_stored_workflow( trans, id, check_ownership=False ) if check_user: user = trans.get_user() if stored.user != user: @@ -956,24 +960,6 @@ ids_in_menu=ids_in_menu ) ## ---- Utility methods ------------------------------------------------------- - -def get_stored_workflow( trans, id, check_ownership=True ): - """ - Get a StoredWorkflow from the database by id, verifying ownership. - """ - # Load workflow from database - id = trans.security.decode_id( id ) - stored = trans.sa_session.query( model.StoredWorkflow ).get( id ) - if not stored: - error( "Workflow not found" ) - # Verify ownership - user = trans.get_user() - if not user: - error( "Must be logged in to use workflows" ) - if check_ownership and not( stored.user == user ): - error( "Workflow is not owned by current user" ) - # Looks good - return stored def attach_ordered_steps( workflow, steps ): ordered_steps = order_workflow_steps( steps ) diff -r c1f22feda926 -r 6cbd13376ce8 static/images/fugue/pencil.png Binary file static/images/fugue/pencil.png has changed diff -r c1f22feda926 -r 6cbd13376ce8 static/images/fugue/sticky-note-text.png Binary file static/images/fugue/sticky-note-text.png has changed diff -r c1f22feda926 -r 6cbd13376ce8 static/images/fugue/tag-label.png Binary file static/images/fugue/tag-label.png has changed diff -r c1f22feda926 -r 6cbd13376ce8 static/images/fugue/toggle-expand.png Binary file static/images/fugue/toggle-expand.png has changed diff -r c1f22feda926 -r 6cbd13376ce8 static/images/fugue/toggle.png Binary file static/images/fugue/toggle.png has changed diff -r c1f22feda926 -r 6cbd13376ce8 static/images/pencil.png Binary file static/images/pencil.png has changed diff -r c1f22feda926 -r 6cbd13376ce8 static/images/sticky-note-text.png Binary file static/images/sticky-note-text.png has changed diff -r c1f22feda926 -r 6cbd13376ce8 static/images/tag-label.png Binary file static/images/tag-label.png has changed diff -r c1f22feda926 -r 6cbd13376ce8 static/june_2007_style/base.css.tmpl --- a/static/june_2007_style/base.css.tmpl Fri Feb 12 15:17:36 2010 -0500 +++ b/static/june_2007_style/base.css.tmpl Fri Feb 12 16:45:37 2010 -0500 @@ -703,7 +703,7 @@ } .icon-button.tag { - background-image: url(/static/images/tag-label.png); + background-image: url(/static/images/fugue/tag-label.png); } .icon-button.tags { @@ -713,9 +713,17 @@ .icon-button.tag--plus { background-image: url(/static/images/fugue/tag--plus.png); } + +.icon-button.toggle-expand { + background-image:url(/static/images/fugue/toggle-expand.png); +} + +.icon-button.toggle-contract { + background-image:url(/static/images/fugue/toggle.png); +} .icon-button.annotate { - background-image:url(/static/images/sticky-note-text.png); + background-image:url(/static/images/fugue/sticky-note-text.png); background-repeat:no-repeat; background-position:center; padding: 0; diff -r c1f22feda926 -r 6cbd13376ce8 static/june_2007_style/blue/base.css --- a/static/june_2007_style/blue/base.css Fri Feb 12 15:17:36 2010 -0500 +++ b/static/june_2007_style/blue/base.css Fri Feb 12 16:45:37 2010 -0500 @@ -117,10 +117,12 @@ .icon-button.delete:hover{background:url(history-buttons.png) no-repeat 0px -78px;} .icon-button.edit{background:url(history-buttons.png) no-repeat 0px -104px;} .icon-button.edit:hover{background:url(history-buttons.png) no-repeat 0px -130px;} -.icon-button.tag{background-image:url(/static/images/tag-label.png);} +.icon-button.tag{background-image:url(/static/images/fugue/tag-label.png);} .icon-button.tags{background-image:url(/static/images/fugue/tags.png);} .icon-button.tag--plus{background-image:url(/static/images/fugue/tag--plus.png);} -.icon-button.annotate{background-image:url(/static/images/sticky-note-text.png);background-repeat:no-repeat;background-position:center;padding:0;} +.icon-button.toggle-expand{background-image:url(/static/images/fugue/toggle-expand.png);} +.icon-button.toggle-contract{background-image:url(/static/images/fugue/toggle.png);} +.icon-button.annotate{background-image:url(/static/images/fugue/sticky-note-text.png);background-repeat:no-repeat;background-position:center;padding:0;} .tipsy{padding:5px;font-size:10px;filter:alpha(opacity=80);background-repeat:no-repeat;background-image:url(../images/tipsy.gif);} .tipsy-inner{padding:5px 8px 4px 8px;background-color:black;color:white;max-width:200px;text-align:center;} .tipsy-north{background-position:top center;} diff -r c1f22feda926 -r 6cbd13376ce8 static/june_2007_style/blue/embed_item.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/june_2007_style/blue/embed_item.css Fri Feb 12 16:45:37 2010 -0500 @@ -0,0 +1,4 @@ +.embedded-item{background-color: #BBBBBB; margin-left: auto; margin-right: auto; width: 90%; max-height: 25em; overflow: auto; padding: 0.5em;-moz-border-radius: .5em;-webkit-border-radius: .5em;border-radius: .5em;} +.embedded-item.placeholder{} +.embedded-item .title{font-weight: bold;font-size:120%;vertical-align:top;text-align:center;} +.embedded-item.placeholder .content{padding: 1em 1em;font-style:italic;text-align:center;} \ No newline at end of file diff -r c1f22feda926 -r 6cbd13376ce8 static/june_2007_style/embed_item.css.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/june_2007_style/embed_item.css.tmpl Fri Feb 12 16:45:37 2010 -0500 @@ -0,0 +1,24 @@ +.embedded-item { + background-color: #BBBBBB; + margin-left: auto; + margin-right: auto; + width: 90%; + max-height: 25em; + overflow: auto; + padding: 0.5em; + -moz-border-radius: .5em; + -webkit-border-radius: .5em; + border-radius: .5em; +} +.embedded-item.placeholder {} +.embedded-item .title { + font-weight: bold; + font-size:120%; + vertical-align:top; + text-align:center; +} +.embedded-item.placeholder .content{ + padding: 1em 1em; + font-style:italic; + text-align:center; + } \ No newline at end of file diff -r c1f22feda926 -r 6cbd13376ce8 templates/dataset/display.mako --- a/templates/dataset/display.mako Fri Feb 12 15:17:36 2010 -0500 +++ b/templates/dataset/display.mako Fri Feb 12 16:45:37 2010 -0500 @@ -27,7 +27,6 @@ </%def> <%def name="render_item( data, data_to_render )"> - <hr/> %if truncated: <div class="warningmessagelarge"> This dataset is large and only the first megabyte is shown below. | @@ -82,7 +81,7 @@ ## Tags. <p> - <h4>Tags</strong></h4> + <h4>Tags</h4> <p> ## Community tags. <div> diff -r c1f22feda926 -r 6cbd13376ce8 templates/dataset/embed.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/dataset/embed.mako Fri Feb 12 16:45:37 2010 -0500 @@ -0,0 +1,13 @@ +<%inherit file="/embed_base.mako"/> +<%! + from galaxy.web.framework.helpers import iff +%> + +<%def name="content( dataset, data )"> + %if annotation: + <div class='annotation'>${annotation}</div> + %endif + <ul> + <li>Format : ${dataset.extension} + </ul> +</%def> diff -r c1f22feda926 -r 6cbd13376ce8 templates/dataset/item_content.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/dataset/item_content.mako Fri Feb 12 16:45:37 2010 -0500 @@ -0,0 +1,3 @@ +<%namespace file="/dataset/display.mako" import="*" /> + +${render_item( item, item_data )} \ No newline at end of file diff -r c1f22feda926 -r 6cbd13376ce8 templates/display_base.mako --- a/templates/display_base.mako Fri Feb 12 15:17:36 2010 -0500 +++ b/templates/display_base.mako Fri Feb 12 16:45:37 2010 -0500 @@ -12,6 +12,10 @@ <%namespace file="/tagging_common.mako" import="render_individual_tagging_element, render_community_tagging_element" /> <%namespace file="/display_common.mako" import="*" /> +## +## Functions used by base.mako and base_panels.mako to display content. +## + <%def name="title()"> Galaxy | ${iff( item.published, "Published ", iff( item.importable , "Accessible ", iff( item.users_shared_with, "Shared ", "Private " ) ) ) + get_class_display_name( item.__class__ )} | ${get_item_name( item ) | h} </%def> @@ -48,7 +52,7 @@ <%def name="stylesheets()"> ${parent.stylesheets()} - ${h.css( "autocomplete_tagging" )} + ${h.css( "autocomplete_tagging", "embed_item" )} <style type="text/css"> .page-body { @@ -70,24 +74,28 @@ </%def> <%def name="render_item_links( item )"> - Item Links + ## Override. </%def> <%def name="render_item( item, item_data=None )"> - Item + ## Override. </%def> -## -## When page has no panels, center panel is body. -## +## For base.mako <%def name="body()"> - ${self.center_panel()} + ${self.render_content()} </%def> +## For base_panels.mako +<%def name="center_panel()"> + ${self.render_content()} +</%def> + + ## -## Page content. Pages that inherit this page should override render_item_links() and render_item() +## Render page content. Pages that inherit this page should override render_item_links() and render_item() ## -<%def name="center_panel()"> +<%def name="render_content()"> ## Get URL to other published items owned by user that owns this item. <% @@ -165,7 +173,7 @@ <a href="${href_to_user_items}">Published ${item_plural.lower()} by ${item.user.username | h}</a> ## Tags. - <h4>Tags</strong></h4> + <h4>Tags</h4> <p> ## Community tags. <div> diff -r c1f22feda926 -r 6cbd13376ce8 templates/display_common.mako --- a/templates/display_common.mako Fri Feb 12 15:17:36 2010 -0500 +++ b/templates/display_common.mako Fri Feb 12 16:45:37 2010 -0500 @@ -83,11 +83,35 @@ return "history" elif isinstance( item, model.StoredWorkflow ): return "workflow" + elif isinstance( item, model.HistoryDatasetAssociation ): + return "dataset" elif isinstance( item, model.Page ): return "page" %> </%def> +## Returns item user/owner. +<%def name="get_item_user( item )"> + <% + # Exceptions first, default last. + if isinstance( item, model.HistoryDatasetAssociation ): + return item.history.user + else: + return item.user + %> +</%def> + +## Returns item slug. +<%def name="get_item_slug( item )"> + <% + # Exceptions first, default last. + if isinstance( item, model.HistoryDatasetAssociation ): + return trans.security.encode_id( item.id ) + else: + return item.slug + %> +</%def> + ## Return a link to view a history. <%def name="get_history_link( history, qualify=False )"> %if history.slug and history.user.username: diff -r c1f22feda926 -r 6cbd13376ce8 templates/embed_base.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/embed_base.mako Fri Feb 12 16:45:37 2010 -0500 @@ -0,0 +1,38 @@ +## +## Base file for generating HTML for embedded objects. +## +## parameters: item, item_data +## +<%namespace file="/display_common.mako" import="*" /> + +## HTML structure. +<div class='embedded-item'> + <div class='title'> + ${self.title( item )} + </div> + <hr/> + <div class='summary-content'> + ${self.content( item, item_data )} + </div> + <div class='item-content'> + </div> +</div> + +<%def name="title( item )"> + Galaxy ${get_class_display_name( item.__class__ )} | ${get_item_name( item )} + <% + item_controller = "/%s" % get_controller_name( item ) + item_user = get_item_user( item ) + item_slug = get_item_slug( item ) + display_href = h.url_for( controller=item_controller, action='display_by_username_and_slug', username=item_user.username, slug=item_slug ) + %> + <a class="display_in_embed icon-button toggle-expand" item_id="${trans.security.encode_id( item.id )}" item_class="$item.__class__.__name__" href="${display_href}"></a> + <a class="toggle-contract icon-button" href="${display_href}"></a> + + ## Use a hidden var to store the ajax URL for getting an item's content. + <input type="hidden" name="ajax-item-content-url" value="${h.url_for( controller=item_controller, action='get_item_content_async', id=trans.security.encode_id( item.id ) )}"/> +</%def> + +## Methods to override to generate content. +<%def name="content( item, item_data )"> +</%def> diff -r c1f22feda926 -r 6cbd13376ce8 templates/history/embed.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/history/embed.mako Fri Feb 12 16:45:37 2010 -0500 @@ -0,0 +1,15 @@ +<%inherit file="/embed_base.mako"/> +<%! + from galaxy.web.framework.helpers import iff +%> + +<%def name="content( history, datasets )"> + %if annotation: + <div class='annotation'>${annotation}</div> + %endif + <ul> + <% num_datasets = len ( datasets ) %> + <li>${num_datasets} dataset${iff( num_datasets != 1, "s", "" )} + <li>Operations: ... + </ul> +</%def> diff -r c1f22feda926 -r 6cbd13376ce8 templates/history/item_content.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/history/item_content.mako Fri Feb 12 16:45:37 2010 -0500 @@ -0,0 +1,3 @@ +<%namespace file="/history/display.mako" import="*" /> + +${render_item( item, item_data )} \ No newline at end of file diff -r c1f22feda926 -r 6cbd13376ce8 templates/page/display.mako --- a/templates/page/display.mako Fri Feb 12 15:17:36 2010 -0500 +++ b/templates/page/display.mako Fri Feb 12 16:45:37 2010 -0500 @@ -25,6 +25,54 @@ }); }); + + // Setup embedded content: + // (a) toggles for showing/hiding embedded content; + // (b) ... + $('.embedded-item').each( function() + { + // Setup toggle expand. + var container = $(this); + var toggle_expand = $(this).find('.toggle-expand'); + toggle_expand.click( function() + { + var ajax_url = container.find("input[type=hidden]").val(); + // Only get item content if it's not already there. + var item_content = $.trim(container.find(".item-content").text()); + if (item_content == "") + $.ajax({ + type: "GET", + url: ajax_url, + error: function() { alert("Getting item content failed."); }, + success: function( item_content ) { + container.find(".summary-content").hide("fast"); + container.find(".item-content").html(item_content).show("fast"); + container.find(".toggle-expand").hide(); + container.find(".toggle-contract").show(); + } + }); + else + { + container.find(".summary-content").hide("fast"); + container.find(".item-content").show("fast"); + container.find(".toggle-expand").hide(); + container.find(".toggle-contract").show(); + } + return false; + }); + // Setup toggle contract. + var toggle_contract = $(this).find('.toggle-contract'); + toggle_contract.click( function() + { + container.find(".item-content").hide("fast"); + container.find(".summary-content").show("fast"); + container.find(".toggle-contract").hide(); + container.find(".toggle-expand").show(); + return false; + }); + + + }); }); // Functionized so AJAX'd datasets can call them function initShowHide() { @@ -148,15 +196,15 @@ <%def name="stylesheets()"> ${parent.stylesheets()} ${h.css( "base", "history", "autocomplete_tagging" )} -</%def> - -<%def name="get_item_name( page )"> - <% return page.title %> + <style type="text/css"> + .toggle-contract { display: none; } + .item-content { overflow: auto; } + </style> </%def> <%def name="render_item_links( page )"> </%def> <%def name="render_item( page, page_data=None )"> - ${page.latest_revision.content.decode( "utf-8" )} + ${page_data} </%def> \ No newline at end of file diff -r c1f22feda926 -r 6cbd13376ce8 templates/page/editor.mako --- a/templates/page/editor.mako Fri Feb 12 15:17:36 2010 -0500 +++ b/templates/page/editor.mako Fri Feb 12 16:45:37 2010 -0500 @@ -29,10 +29,25 @@ // Useful Galaxy stuff. var Galaxy = { - DIALOG_HISTORY_LINK : "history_link", - DIALOG_DATASET_LINK : "dataset_link", - DIALOG_WORKFLOW_LINK : "workflow_link", - DIALOG_PAGE_LINK : "page_link", + // Item types. + ITEM_HISTORY : "item_history", + ITEM_DATASET : "item_dataset", + ITEM_WORKFLOW : "item_workflow", + ITEM_PAGE : "item_page", + + // Link dialogs. + DIALOG_HISTORY_LINK : "link_history", + DIALOG_DATASET_LINK : "link_dataset", + DIALOG_WORKFLOW_LINK : "link_workflow", + DIALOG_PAGE_LINK : "link_page", + + // Embed dialogs. + DIALOG_EMBED_HISTORY : "embed_history", + DIALOG_EMBED_DATASET : "embed_dataset", + DIALOG_EMBED_WORKFLOW : "embed_workflow", + DIALOG_EMBED_PAGE : "embed_page", + + // Annotation dialogs. DIALOG_HISTORY_ANNOTATE : "history_annotate", }; @@ -55,6 +70,55 @@ }; + // Based on the dialog type, return a dictionary of information about an item + function get_item_info( dialog_type ) + { + var + item_singular, + item_plural, + item_controller; + switch( dialog_type ) { + case( Galaxy.ITEM_HISTORY ): + item_singular = "History"; + item_plural = "Histories"; + item_controller = "history"; + item_class = "History"; + break; + case( Galaxy.ITEM_DATASET ): + item_singular = "Dataset"; + item_plural = "Datasets"; + item_controller = "dataset"; + item_class = "HistoryDatasetAssociation"; + break; + case( Galaxy.ITEM_WORKFLOW ): + item_singular = "Workflow"; + item_plural = "Workflows"; + item_controller = "workflow"; + item_class = "StoredWorkflow"; + break; + case( Galaxy.ITEM_PAGE ): + item_singular = "Page"; + item_plural = "Pages"; + item_controller = "page"; + item_class = "Page"; + break; + } + + // Build ajax URL that lists items for selection. + var item_list_action = "list_" + item_plural.toLowerCase() + "_for_selection"; + var url_template = "${h.url_for( action='LIST_ACTION' )}"; + var ajax_url = url_template.replace( "LIST_ACTION", item_list_action ); + + // Set up and return dict. + return { + singular : item_singular, + plural : item_plural, + controller : item_controller, + iclass : item_class, + list_ajax_url : ajax_url + }; + }; + ## Completely replace WYM's dialog handling WYMeditor.editor.prototype.dialog = function( dialogType, dialogFeatures, bodyHtml ) { @@ -206,50 +270,35 @@ if ( dialogType == Galaxy.DIALOG_HISTORY_LINK || dialogType == Galaxy.DIALOG_DATASET_LINK || dialogType == Galaxy.DIALOG_WORKFLOW_LINK || dialogType == Galaxy.DIALOG_PAGE_LINK ) { // Based on item type, set useful vars. - var - item_singular, - item_plural, - item_controller, - item_list_action; - switch( dialogType ) { - case( Galaxy.DIALOG_HISTORY_LINK ): - item_singular = "History"; - item_plural = "Histories"; - item_controller = "history" + var item_info; + switch(dialogType) + { + case(Galaxy.DIALOG_HISTORY_LINK): + item_info = get_item_info(Galaxy.ITEM_HISTORY); break; - case( Galaxy.DIALOG_DATASET_LINK ): - item_singular = "Dataset"; - item_plural = "Datasets"; - item_controller = "dataset" + case(Galaxy.DIALOG_DATASET_LINK): + item_info = get_item_info(Galaxy.ITEM_DATASET); break; - case( Galaxy.DIALOG_WORKFLOW_LINK ): - item_singular = "Workflow"; - item_plural = "Workflows"; - item_controller = "workflow" + case(Galaxy.DIALOG_WORKFLOW_LINK): + item_info = get_item_info(Galaxy.ITEM_WORKFLOW); break; - case( Galaxy.DIALOG_PAGE_LINK ): - item_singular = "Page"; - item_plural = "Pages"; - item_controller = "page" - break; + case(Galaxy.DIALOG_PAGE_LINK): + item_info = get_item_info(Galaxy.ITEM_PAGE); + break; } - item_list_action = "list_" + item_plural.toLowerCase() + "_for_selection"; - // Show grid that enables user to select items. - var url_template = "${h.url_for( action='LIST_ACTION' )}"; - var ajax_url = url_template.replace( "LIST_ACTION", item_list_action ); $.ajax( { - url: ajax_url, + url: item_info.list_ajax_url, data: {}, - error: function() { alert( "Failed to list " + item_plural.toLowerCase() + " for selection"); }, + error: function() { alert( "Failed to list " + item_info.plural.toLowerCase() + " for selection"); }, success: function(table_html) { show_modal( - "Insert Link to " + item_singular, + "Insert Link to " + item_info.singular, table_html + "<div><input id='make-importable' type='checkbox' checked/>" + - "Make the selected " + item_plural.toLowerCase() + " accessible so that they can viewed by everyone.</div>" + "Make the selected " + item_info.plural.toLowerCase() + " accessible so that they can viewed by everyone.</div>" , { "Insert": function() @@ -264,23 +313,23 @@ $('input[name=id]:checked').each(function() { var item_id = $(this).val(); - // Make history importable? + // Make item importable? if (make_importable) { url_template = "${h.url_for( controller='ITEM_CONTROLLER', action='set_accessible_async' )}"; - ajax_url = url_template.replace( "ITEM_CONTROLLER", item_controller); + ajax_url = url_template.replace( "ITEM_CONTROLLER", item_info.controller); $.ajax({ type: "POST", url: ajax_url, data: { id: item_id, accessible: 'True' }, - error: function() { alert("Making " + item_plural.toLowerCase() + " accessible failed"); } + error: function() { alert("Making " + item_info.plural.toLowerCase() + " accessible failed"); } }); } // Insert link(s) to item(s). This is done by getting item info and then manipulating wym. url_template = "${h.url_for( controller='ITEM_CONTROLLER', action='get_name_and_link_async' )}?id=" + item_id; - ajax_url = url_template.replace( "ITEM_CONTROLLER", item_controller); - $.getJSON( ajax_url, function( item_info ) { + ajax_url = url_template.replace( "ITEM_CONTROLLER", item_info.controller); + $.getJSON( ajax_url, function( returned_item_info ) { // Get link text. wym._exec(WYMeditor.CREATE_LINK, sStamp); var link_text = $("a[href=" + sStamp + "]", wym._doc.body).text(); @@ -293,12 +342,12 @@ ) { // User selected no text; create link from scratch and use default text. - wym.insert("<a href='" + item_info.link + "'> '" + item_singular + " " + item_info.name + "'</a>"); + wym.insert("<a href='" + returned_item_info.link + "'>" + item_info.singular + " '" + returned_item_info.name + "'</a>"); } else { // Link created from selected text; add href and title. - $("a[href=" + sStamp + "]", wym._doc.body).attr(WYMeditor.HREF, item_info.link).attr(WYMeditor.TITLE, item_singular + item_id); + $("a[href=" + sStamp + "]", wym._doc.body).attr(WYMeditor.HREF, returned_item_info.link).attr(WYMeditor.TITLE, item_info.singular + item_id); } }); }); @@ -314,6 +363,72 @@ } }); } + // EMBED GALAXY OBJECT DIALOGS + if ( dialogType == Galaxy.DIALOG_EMBED_HISTORY || dialogType == Galaxy.DIALOG_EMBED_DATASET || dialogType == Galaxy.DIALOG_EMBED_WORKFLOW || dialogType == Galaxy.DIALOG_EMBED_PAGE ) { + // Based on item type, set useful vars. + var item_info; + switch(dialogType) + { + case(Galaxy.DIALOG_EMBED_HISTORY): + item_info = get_item_info(Galaxy.ITEM_HISTORY); + break; + case(Galaxy.DIALOG_EMBED_DATASET): + item_info = get_item_info(Galaxy.ITEM_DATASET); + break; + case(Galaxy.DIALOG_EMBED_WORKFLOW): + item_info = get_item_info(Galaxy.ITEM_WORKFLOW); + break; + case(Galaxy.DIALOG_EMBED_PAGE): + item_info = get_item_info(Galaxy.ITEM_PAGE); + break; + } + + $.ajax( + { + url: item_info.list_ajax_url, + data: {}, + error: function() { alert( "Failed to list " + item_info.plural.toLowerCase() + " for selection"); }, + success: function(list_html) + { + show_modal( + "Embed " + item_info.plural, + list_html, + { + "Embed": function() + { + // Embed a Galaxy item. + var item_ids = new Array(); + $('input[name=id]:checked').each(function() { + // Get item ID and name. + var item_id = $(this).val(); + // Use ':first' because there are many labels in table; the first one is the item name. + var item_name = $("label[for='" + item_id + "']:first").text(); + + // Embedded item HTML; item class is embedded in div container classes; this is necessary because the editor strips + // all non-standard attributes when it returns its content (e.g. it will not return an element attribute of the form + // item_class='History'). + var item_embed_html = + "<p><div id='" + item_info.iclass + "-" + item_id + "' class='embedded-item placeholder'> \ + <div class='title'> Embedded Galaxy " + item_info.singular + " '" + item_name + "'</div> \ + <div class='content'>[Do not edit this block; Galaxy will fill it in with the annotated " + \ + item_info.singular.toLowerCase() + " when it is displayed.]</div> \ + </div></p><p>"; + + // Insert embedded representation into document. + wym.insert(item_embed_html); + }); + hide_modal(); + }, + "Cancel": function() + { + hide_modal(); + } + } + ); + } + }); + } + // ANNOTATE HISTORY DIALOG if ( dialogType == Galaxy.DIALOG_ANNOTATE_HISTORY ) { $.ajax( @@ -418,6 +533,9 @@ var editor = $.wymeditors(0); var save = function ( callback ) { show_modal( "Saving page", "progress" ); + + /* + Not used right now. // Gather annotations. var annotations = new Array(); @@ -433,6 +551,8 @@ annotations[ annotations.length ] = annotation; }); + */ + // Do save. $.ajax( { url: "${h.url_for( action='save' )}", @@ -440,7 +560,8 @@ data: { id: "${trans.security.encode_id(page.id)}", content: editor.xhtml(), - annotations: JSON.stringify(annotations), + annotations: JSON.stringify(new Object()), + ## annotations: JSON.stringify(annotations), "_": "true" }, success: function() { @@ -500,13 +621,69 @@ }); // Initialize galaxy elements. //init_galaxy_elts(editor); + + // + // Create 'Insert Link to Galaxy Object' menu. + // + + // Add menu button. + var insert_link_menu_button = $("<div><a id='insert-galaxy-link' class='panel-header-button popup' href='#'>${_('Insert Link to Galaxy Object')}</a></div>").addClass('galaxy-page-editor-button'); + $(".wym_area_top").append(insert_link_menu_button); + + // Add menu options. + make_popupmenu( insert_link_menu_button, { + "Insert History Link": function() { + editor.dialog(Galaxy.DIALOG_HISTORY_LINK); + }, + "Insert Dataset Link": function() { + editor.dialog(Galaxy.DIALOG_DATASET_LINK); + }, + "Insert Workflow Link": function() { + editor.dialog(Galaxy.DIALOG_WORKFLOW_LINK); + }, + "Insert Page Link": function() { + editor.dialog(Galaxy.DIALOG_PAGE_LINK); + } + }); + + // + // Create 'Embed Galaxy Object' menu. + // + + // Add menu button. + var embed_object_button = $("<div><a id='embed-galaxy-object' class='panel-header-button popup' href='#'>${_('Embed Galaxy Object')}</a></div>").addClass('galaxy-page-editor-button'); + $(".wym_area_top").append(embed_object_button); + + // Add menu options. + make_popupmenu( embed_object_button, { + "Embed History": function() { + editor.dialog(Galaxy.DIALOG_EMBED_HISTORY); + }, + "Embed Dataset": function() { + editor.dialog(Galaxy.DIALOG_EMBED_DATASET); + }, + "Embed Workflow": function() { + editor.dialog(Galaxy.DIALOG_EMBED_WORKFLOW); + }, + ##"Embed Page": function() { + ## editor.dialog(Galaxy.DIALOG_EMBED_PAGE); + ##} + }); }); </script> </%def> <%def name="stylesheets()"> ${parent.stylesheets()} - ${h.css( "base", "history", "autocomplete_tagging" )} + ${h.css( "base", "autocomplete_tagging", "embed_item" )} + <style type='text/css'> + .galaxy-page-editor-button + { + position: relative; + float: left; + padding: 0.2em; + } + </style> </%def> <%def name="center_panel()"> diff -r c1f22feda926 -r 6cbd13376ce8 templates/page/wymiframe.mako --- a/templates/page/wymiframe.mako Fri Feb 12 15:17:36 2010 -0500 +++ b/templates/page/wymiframe.mako Fri Feb 12 16:45:37 2010 -0500 @@ -21,7 +21,7 @@ <title>WYMeditor iframe</title> <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /> <link rel="stylesheet" type="text/css" media="screen" href="/static/wymeditor/iframe/galaxy/wymiframe.css" /> - ${h.css("base", "history", "autocomplete_tagging")} + ${h.css("base", "autocomplete_tagging", "embed_item")} </head> <body class="wym_iframe text-content"></body> </html> diff -r c1f22feda926 -r 6cbd13376ce8 templates/sharing_base.mako --- a/templates/sharing_base.mako Fri Feb 12 15:17:36 2010 -0500 +++ b/templates/sharing_base.mako Fri Feb 12 16:45:37 2010 -0500 @@ -127,7 +127,7 @@ ${"/".join( url_parts[:-1] )}/<span id='item-identifier'>${url_parts[-1]}</span> </span> - <a href="#" id="edit-identifier"><img src="${h.url_for('/static/images/pencil.png')}"/></a> + <a href="#" id="edit-identifier"><img src="${h.url_for('/static/images/fugue/pencil.png')}"/></a> </blockquote> %if item.published: diff -r c1f22feda926 -r 6cbd13376ce8 templates/workflow/display.mako --- a/templates/workflow/display.mako Fri Feb 12 15:17:36 2010 -0500 +++ b/templates/workflow/display.mako Fri Feb 12 16:45:37 2010 -0500 @@ -58,7 +58,6 @@ other_values = {} value = other_values[ param.name ] = param.get_initial_value( t, other_values ) %> - <% print param.__class__ %> ${param.get_html_field( t, value, other_values ).get_html( str(step.id) + "|" + prefix )} %endif %else: diff -r c1f22feda926 -r 6cbd13376ce8 templates/workflow/embed.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/workflow/embed.mako Fri Feb 12 16:45:37 2010 -0500 @@ -0,0 +1,15 @@ +<%inherit file="/embed_base.mako"/> +<%! + from galaxy.web.framework.helpers import iff +%> + +<%def name="content( workflow, steps )"> + %if annotation: + <div class='annotation'>${annotation}</div> + %endif + <ul> + <% num_steps = len ( steps ) %> + <li>${num_steps} step${iff( num_steps != 1, "s", "" )} + <li>Operations: ... + </ul> +</%def> diff -r c1f22feda926 -r 6cbd13376ce8 templates/workflow/item_content.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/workflow/item_content.mako Fri Feb 12 16:45:37 2010 -0500 @@ -0,0 +1,3 @@ +<%namespace file="/workflow/display.mako" import="*" /> + +${render_item( item, item_data )} \ No newline at end of file
1
0
0
0
[hg] galaxy 3383: upgrade to jquery 1.4.1
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/c1f22feda926
changeset: 3383:c1f22feda926 user: Kanwei Li <kanwei(a)gmail.com> date: Fri Feb 12 15:17:36 2010 -0500 description: upgrade to jquery 1.4.1 diffstat: static/scripts/jquery.js | 4518 +------------------------------------- static/scripts/pack_scripts.py | 2 +- static/scripts/packed/jquery.js | 163 +- 3 files changed, 296 insertions(+), 4387 deletions(-) diffs (truncated from 4711 to 3000 lines): diff -r c8c472e6f341 -r c1f22feda926 static/scripts/jquery.js --- a/static/scripts/jquery.js Fri Feb 12 15:09:00 2010 -0500 +++ b/static/scripts/jquery.js Fri Feb 12 15:17:36 2010 -0500 @@ -1,4376 +1,152 @@ /*! - * jQuery JavaScript Library v1.3.2 + * jQuery JavaScript Library v1.4.1 *
http://jquery.com/
* - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - *
http://docs.jquery.com/License
+ * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + *
http://jquery.org/license
* - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 + * Includes Sizzle.js + *
http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Jan 25 19:43:33 2010 -0500 */ -(function(){ - -var - // Will speed up references to window, and allows munging its name. - window = this, - // Will speed up references to undefined, and allows munging its name. - undefined, - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - // Map over the $ in case of overwrite - _$ = window.$, - - jQuery = window.jQuery = window.$ = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context ); - }, - - // A simple way to check for HTML strings or ID strings - // (both of which we optimize for) - quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/, - // Is it a simple selector - isSimple = /^.[^:#\[\.,]*$/; - -jQuery.fn = jQuery.prototype = { - init: function( selector, context ) { - // Make sure that a selection was provided - selector = selector || document; - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this[0] = selector; - this.length = 1; - this.context = selector; - return this; - } - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - var match = quickExpr.exec( selector ); - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) - selector = jQuery.clean( [ match[1] ], context ); - - // HANDLE: $("#id") - else { - var elem = document.getElementById( match[3] ); - - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem && elem.id != match[3] ) - return jQuery().find( selector ); - - // Otherwise, we inject the element directly into the jQuery object - var ret = jQuery( elem || [] ); - ret.context = document; - ret.selector = selector; - return ret; - } - - // HANDLE: $(expr, [context]) - // (which is just equivalent to: $(content).find(expr) - } else - return jQuery( context ).find( selector ); - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) - return jQuery( document ).ready( selector ); - - // Make sure that old selector state is passed along - if ( selector.selector && selector.context ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return this.setArray(jQuery.isArray( selector ) ? - selector : - jQuery.makeArray(selector)); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.3.2", - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num === undefined ? - - // Return a 'clean' array - Array.prototype.slice.call( this ) : - - // Return just the object - this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new jQuery matched element set - var ret = jQuery( elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) - ret.selector = this.selector + (this.selector ? " " : "") + selector; - else if ( name ) - ret.selector = this.selector + "." + name + "(" + selector + ")"; - - // Return the newly-formed element set - return ret; - }, - - // Force the current matched set of elements to become - // the specified array of elements (destroying the stack in the process) - // You should use pushStack() in order to do this, but maintain the stack - setArray: function( elems ) { - // Resetting the length to 0, then using the native Array push - // is a super-fast way to populate an object with array-like properties - this.length = 0; - Array.prototype.push.apply( this, elems ); - - return this; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem && elem.jquery ? elem[0] : elem - , this ); - }, - - attr: function( name, value, type ) { - var options = name; - - // Look for the case where we're accessing a style value - if ( typeof name === "string" ) - if ( value === undefined ) - return this[0] && jQuery[ type || "attr" ]( this[0], name ); - - else { - options = {}; - options[ name ] = value; - } - - // Check to see if we're setting style values - return this.each(function(i){ - // Set all the styles - for ( name in options ) - jQuery.attr( - type ? - this.style : - this, - name, jQuery.prop( this, options[ name ], type, i, name ) - ); - }); - }, - - css: function( key, value ) { - // ignore negative width and height values - if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) - value = undefined; - return this.attr( key, value, "curCSS" ); - }, - - text: function( text ) { - if ( typeof text !== "object" && text != null ) - return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); - - var ret = ""; - - jQuery.each( text || this, function(){ - jQuery.each( this.childNodes, function(){ - if ( this.nodeType != 8 ) - ret += this.nodeType != 1 ? - this.nodeValue : - jQuery.fn.text( [ this ] ); - }); - }); - - return ret; - }, - - wrapAll: function( html ) { - if ( this[0] ) { - // The elements to wrap the target around - var wrap = jQuery( html, this[0].ownerDocument ).clone(); - - if ( this[0].parentNode ) - wrap.insertBefore( this[0] ); - - wrap.map(function(){ - var elem = this; - - while ( elem.firstChild ) - elem = elem.firstChild; - - return elem; - }).append(this); - } - - return this; - }, - - wrapInner: function( html ) { - return this.each(function(){ - jQuery( this ).contents().wrapAll( html ); - }); - }, - - wrap: function( html ) { - return this.each(function(){ - jQuery( this ).wrapAll( html ); - }); - }, - - append: function() { - return this.domManip(arguments, true, function(elem){ - if (this.nodeType == 1) - this.appendChild( elem ); - }); - }, - - prepend: function() { - return this.domManip(arguments, true, function(elem){ - if (this.nodeType == 1) - this.insertBefore( elem, this.firstChild ); - }); - }, - - before: function() { - return this.domManip(arguments, false, function(elem){ - this.parentNode.insertBefore( elem, this ); - }); - }, - - after: function() { - return this.domManip(arguments, false, function(elem){ - this.parentNode.insertBefore( elem, this.nextSibling ); - }); - }, - - end: function() { - return this.prevObject || jQuery( [] ); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: [].push, - sort: [].sort, - splice: [].splice, - - find: function( selector ) { - if ( this.length === 1 ) { - var ret = this.pushStack( [], "find", selector ); - ret.length = 0; - jQuery.find( selector, this[0], ret ); - return ret; - } else { - return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ - return jQuery.find( selector, elem ); - })), "find", selector ); - } - }, - - clone: function( events ) { - // Do the clone - var ret = this.map(function(){ - if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { - // IE copies events bound via attachEvent when - // using cloneNode. Calling detachEvent on the - // clone will also remove the events from the orignal - // In order to get around this, we use innerHTML. - // Unfortunately, this means some modifications to - // attributes in IE that are actually only stored - // as properties will not be copied (such as the - // the name attribute on an input). - var html = this.outerHTML; - if ( !html ) { - var div = this.ownerDocument.createElement("div"); - div.appendChild( this.cloneNode(true) ); - html = div.innerHTML; - } - - return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0]; - } else - return this.cloneNode(true); - }); - - // Copy the events from the original to the clone - if ( events === true ) { - var orig = this.find("*").andSelf(), i = 0; - - ret.find("*").andSelf().each(function(){ - if ( this.nodeName !== orig[i].nodeName ) - return; - - var events = jQuery.data( orig[i], "events" ); - - for ( var type in events ) { - for ( var handler in events[ type ] ) { - jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); - } - } - - i++; - }); - } - - // Return the cloned set - return ret; - }, - - filter: function( selector ) { - return this.pushStack( - jQuery.isFunction( selector ) && - jQuery.grep(this, function(elem, i){ - return selector.call( elem, i ); - }) || - - jQuery.multiFilter( selector, jQuery.grep(this, function(elem){ - return elem.nodeType === 1; - }) ), "filter", selector ); - }, - - closest: function( selector ) { - var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null, - closer = 0; - - return this.map(function(){ - var cur = this; - while ( cur && cur.ownerDocument ) { - if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) { - jQuery.data(cur, "closest", closer); - return cur; - } - cur = cur.parentNode; - closer++; - } - }); - }, - - not: function( selector ) { - if ( typeof selector === "string" ) - // test special case where just one selector is passed in - if ( isSimple.test( selector ) ) - return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector ); - else - selector = jQuery.multiFilter( selector, this ); - - var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; - return this.filter(function() { - return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; - }); - }, - - add: function( selector ) { - return this.pushStack( jQuery.unique( jQuery.merge( - this.get(), - typeof selector === "string" ? - jQuery( selector ) : - jQuery.makeArray( selector ) - ))); - }, - - is: function( selector ) { - return !!selector && jQuery.multiFilter( selector, this ).length > 0; - }, - - hasClass: function( selector ) { - return !!selector && this.is( "." + selector ); - }, - - val: function( value ) { - if ( value === undefined ) { - var elem = this[0]; - - if ( elem ) { - if( jQuery.nodeName( elem, 'option' ) ) - return (elem.attributes.value || {}).specified ? elem.value : elem.text; - - // We need to handle select boxes special - if ( jQuery.nodeName( elem, "select" ) ) { - var index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type == "select-one"; - - // Nothing was selected - if ( index < 0 ) - return null; - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[ i ]; - - if ( option.selected ) { - // Get the specifc value for the option - value = jQuery(option).val(); - - // We don't need an array for one selects - if ( one ) - return value; - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - } - - // Everything else, we just grab the value - return (elem.value || "").replace(/\r/g, ""); - - } - - return undefined; - } - - if ( typeof value === "number" ) - value += ''; - - return this.each(function(){ - if ( this.nodeType != 1 ) - return; - - if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) ) - this.checked = (jQuery.inArray(this.value, value) >= 0 || - jQuery.inArray(this.name, value) >= 0); - - else if ( jQuery.nodeName( this, "select" ) ) { - var values = jQuery.makeArray(value); - - jQuery( "option", this ).each(function(){ - this.selected = (jQuery.inArray( this.value, values ) >= 0 || - jQuery.inArray( this.text, values ) >= 0); - }); - - if ( !values.length ) - this.selectedIndex = -1; - - } else - this.value = value; - }); - }, - - html: function( value ) { - return value === undefined ? - (this[0] ? - this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : - null) : - this.empty().append( value ); - }, - - replaceWith: function( value ) { - return this.after( value ).remove(); - }, - - eq: function( i ) { - return this.slice( i, +i + 1 ); - }, - - slice: function() { - return this.pushStack( Array.prototype.slice.apply( this, arguments ), - "slice", Array.prototype.slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function(elem, i){ - return callback.call( elem, i, elem ); - })); - }, - - andSelf: function() { - return this.add( this.prevObject ); - }, - - domManip: function( args, table, callback ) { - if ( this[0] ) { - var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), - scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), - first = fragment.firstChild; - - if ( first ) - for ( var i = 0, l = this.length; i < l; i++ ) - callback.call( root(this[i], first), this.length > 1 || i > 0 ? - fragment.cloneNode(true) : fragment ); - - if ( scripts ) - jQuery.each( scripts, evalScript ); - } - - return this; - - function root( elem, cur ) { - return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ? - (elem.getElementsByTagName("tbody")[0] || - elem.appendChild(elem.ownerDocument.createElement("tbody"))) : - elem; - } - } -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -function evalScript( i, elem ) { - if ( elem.src ) - jQuery.ajax({ - url: elem.src, - async: false, - dataType: "script" - }); - - else - jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); - - if ( elem.parentNode ) - elem.parentNode.removeChild( elem ); -} - -function now(){ - return +new Date; -} - -jQuery.extend = jQuery.fn.extend = function() { - // copy reference to target object - var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) - target = {}; - - // extend jQuery itself if only one argument is passed - if ( length == i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) - // Extend the base object - for ( var name in options ) { - var src = target[ name ], copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) - continue; - - // Recurse if we're merging object values - if ( deep && copy && typeof copy === "object" && !copy.nodeType ) - target[ name ] = jQuery.extend( deep, - // Never move original objects, clone them - src || ( copy.length != null ? [ ] : { } ) - , copy ); - - // Don't bring in undefined values - else if ( copy !== undefined ) - target[ name ] = copy; - - } - - // Return the modified object - return target; -}; - -// exclude the following css properties to add px -var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, - // cache defaultView - defaultView = document.defaultView || {}, - toString = Object.prototype.toString; - -jQuery.extend({ - noConflict: function( deep ) { - window.$ = _$; - - if ( deep ) - window.jQuery = _jQuery; - - return jQuery; - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return toString.call(obj) === "[object Function]"; - }, - - isArray: function( obj ) { - return toString.call(obj) === "[object Array]"; - }, - - // check if an element is in a (or is an) XML document - isXMLDoc: function( elem ) { - return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || - !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument ); - }, - - // Evalulates a script in a global context - globalEval: function( data ) { - if ( data && /\S/.test(data) ) { - // Inspired by code by Andrea Giammarchi - //
http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.h…
- var head = document.getElementsByTagName("head")[0] || document.documentElement, - script = document.createElement("script"); - - script.type = "text/javascript"; - if ( jQuery.support.scriptEval ) - script.appendChild( document.createTextNode( data ) ); - else - script.text = data; - - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709). - head.insertBefore( script, head.firstChild ); - head.removeChild( script ); - } - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, length = object.length; - - if ( args ) { - if ( length === undefined ) { - for ( name in object ) - if ( callback.apply( object[ name ], args ) === false ) - break; - } else - for ( ; i < length; ) - if ( callback.apply( object[ i++ ], args ) === false ) - break; - - // A special, fast, case for the most common use of each - } else { - if ( length === undefined ) { - for ( name in object ) - if ( callback.call( object[ name ], name, object[ name ] ) === false ) - break; - } else - for ( var value = object[0]; - i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} - } - - return object; - }, - - prop: function( elem, value, type, i, name ) { - // Handle executable functions - if ( jQuery.isFunction( value ) ) - value = value.call( elem, i ); - - // Handle passing in a number to a CSS property - return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ? - value + "px" : - value; - }, - - className: { - // internal only, use addClass("class") - add: function( elem, classNames ) { - jQuery.each((classNames || "").split(/\s+/), function(i, className){ - if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) - elem.className += (elem.className ? " " : "") + className; - }); - }, - - // internal only, use removeClass("class") - remove: function( elem, classNames ) { - if (elem.nodeType == 1) - elem.className = classNames !== undefined ? - jQuery.grep(elem.className.split(/\s+/), function(className){ - return !jQuery.className.has( classNames, className ); - }).join(" ") : - ""; - }, - - // internal only, use hasClass("class") - has: function( elem, className ) { - return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; - } - }, - - // A method for quickly swapping in/out CSS properties to get correct calculations - swap: function( elem, options, callback ) { - var old = {}; - // Remember the old values, and insert the new ones - for ( var name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - callback.call( elem ); - - // Revert the old values - for ( var name in options ) - elem.style[ name ] = old[ name ]; - }, - - css: function( elem, name, force, extra ) { - if ( name == "width" || name == "height" ) { - var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; - - function getWH() { - val = name == "width" ? elem.offsetWidth : elem.offsetHeight; - - if ( extra === "border" ) - return; - - jQuery.each( which, function() { - if ( !extra ) - val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; - if ( extra === "margin" ) - val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0; - else - val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; - }); - } - - if ( elem.offsetWidth !== 0 ) - getWH(); - else - jQuery.swap( elem, props, getWH ); - - return Math.max(0, Math.round(val)); - } - - return jQuery.curCSS( elem, name, force ); - }, - - curCSS: function( elem, name, force ) { - var ret, style = elem.style; - - // We need to handle opacity special in IE - if ( name == "opacity" && !jQuery.support.opacity ) { - ret = jQuery.attr( style, "opacity" ); - - return ret == "" ? - "1" : - ret; - } - - // Make sure we're using the right name for getting the float value - if ( name.match( /float/i ) ) - name = styleFloat; - - if ( !force && style && style[ name ] ) - ret = style[ name ]; - - else if ( defaultView.getComputedStyle ) { - - // Only "float" is needed here - if ( name.match( /float/i ) ) - name = "float"; - - name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); - - var computedStyle = defaultView.getComputedStyle( elem, null ); - - if ( computedStyle ) - ret = computedStyle.getPropertyValue( name ); - - // We should always get a number back from opacity - if ( name == "opacity" && ret == "" ) - ret = "1"; - - } else if ( elem.currentStyle ) { - var camelCase = name.replace(/\-(\w)/g, function(all, letter){ - return letter.toUpperCase(); - }); - - ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; - - // From the awesome hack by Dean Edwards - //
http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
- - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { - // Remember the original values - var left = style.left, rsLeft = elem.runtimeStyle.left; - - // Put in the new values to get a computed value out - elem.runtimeStyle.left = elem.currentStyle.left; - style.left = ret || 0; - ret = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - elem.runtimeStyle.left = rsLeft; - } - } - - return ret; - }, - - clean: function( elems, context, fragment ) { - context = context || document; - - // !context.createElement fails in IE with an error but returns typeof 'object' - if ( typeof context.createElement === "undefined" ) - context = context.ownerDocument || context[0] && context[0].ownerDocument || document; - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { - var match = /^<(\w+)\s*\/?>$/.exec(elems[0]); - if ( match ) - return [ context.createElement( match[1] ) ]; - } - - var ret = [], scripts = [], div = context.createElement("div"); - - jQuery.each(elems, function(i, elem){ - if ( typeof elem === "number" ) - elem += ''; - - if ( !elem ) - return; - - // Convert html string into DOM nodes - if ( typeof elem === "string" ) { - // Fix "XHTML"-style tags in all browsers - elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ - return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? - all : - front + "></" + tag + ">"; - }); - - // Trim whitespace, otherwise indexOf won't work as expected - var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase(); - - var wrap = - // option or optgroup - !tags.indexOf("<opt") && - [ 1, "<select multiple='multiple'>", "</select>" ] || - - !tags.indexOf("<leg") && - [ 1, "<fieldset>", "</fieldset>" ] || - - tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && - [ 1, "<table>", "</table>" ] || - - !tags.indexOf("<tr") && - [ 2, "<table><tbody>", "</tbody></table>" ] || - - // <thead> matched above - (!tags.indexOf("<td") || !tags.indexOf("<th")) && - [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] || - - !tags.indexOf("<col") && - [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] || - - // IE can't serialize <link> and <script> tags normally - !jQuery.support.htmlSerialize && - [ 1, "div<div>", "</div>" ] || - - [ 0, "", "" ]; - - // Go to html and back, then peel off extra wrappers - div.innerHTML = wrap[1] + elem + wrap[2]; - - // Move to the right depth - while ( wrap[0]-- ) - div = div.lastChild; - - // Remove IE's autoinserted <tbody> from table fragments - if ( !jQuery.support.tbody ) { - - // String was a <table>, *may* have spurious <tbody> - var hasBody = /<tbody/i.test(elem), - tbody = !tags.indexOf("<table") && !hasBody ? - div.firstChild && div.firstChild.childNodes : - - // String was a bare <thead> or <tfoot> - wrap[1] == "<table>" && !hasBody ? - div.childNodes : - []; - - for ( var j = tbody.length - 1; j >= 0 ; --j ) - if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) - tbody[ j ].parentNode.removeChild( tbody[ j ] ); - - } - - // IE completely kills leading whitespace when innerHTML is used - if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) ) - div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild ); - - elem = jQuery.makeArray( div.childNodes ); - } - - if ( elem.nodeType ) - ret.push( elem ); - else - ret = jQuery.merge( ret, elem ); - - }); - - if ( fragment ) { - for ( var i = 0; ret[i]; i++ ) { - if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { - scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); - } else { - if ( ret[i].nodeType === 1 ) - ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) ); - fragment.appendChild( ret[i] ); - } - } - - return scripts; - } - - return ret; - }, - - attr: function( elem, name, value ) { - // don't set attributes on text and comment nodes - if (!elem || elem.nodeType == 3 || elem.nodeType == 8) - return undefined; - - var notxml = !jQuery.isXMLDoc( elem ), - // Whether we are setting (or getting) - set = value !== undefined; - - // Try to normalize/fix the name - name = notxml && jQuery.props[ name ] || name; - - // Only do all the following if this is a node (faster for style) - // IE elem.getAttribute passes even for style - if ( elem.tagName ) { - - // These attributes require special treatment - var special = /href|src|style/.test( name ); - - // Safari mis-reports the default selected property of a hidden option - // Accessing the parent's selectedIndex property fixes it - if ( name == "selected" && elem.parentNode ) - elem.parentNode.selectedIndex; - - // If applicable, access the attribute via the DOM 0 way - if ( name in elem && notxml && !special ) { - if ( set ){ - // We can't allow the type property to be changed (since it causes problems in IE) - if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode ) - throw "type property can't be changed"; - - elem[ name ] = value; - } - - // browsers index elements by id/name on forms, give priority to attributes. - if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) - return elem.getAttributeNode( name ).nodeValue; - - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - //
http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabind…
- if ( name == "tabIndex" ) { - var attributeNode = elem.getAttributeNode( "tabIndex" ); - return attributeNode && attributeNode.specified - ? attributeNode.value - : elem.nodeName.match(/(button|input|object|select|textarea)/i) - ? 0 - : elem.nodeName.match(/^(a|area)$/i) && elem.href - ? 0 - : undefined; - } - - return elem[ name ]; - } - - if ( !jQuery.support.style && notxml && name == "style" ) - return jQuery.attr( elem.style, "cssText", value ); - - if ( set ) - // convert the value to a string (all browsers do this but IE) see #1070 - elem.setAttribute( name, "" + value ); - - var attr = !jQuery.support.hrefNormalized && notxml && special - // Some attributes require a special call on IE - ? elem.getAttribute( name, 2 ) - : elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return attr === null ? undefined : attr; - } - - // elem is actually elem.style ... set the style - - // IE uses filters for opacity - if ( !jQuery.support.opacity && name == "opacity" ) { - if ( set ) { - // IE has trouble with opacity if it does not have layout - // Force it by setting the zoom level - elem.zoom = 1; - - // Set the alpha filter to set the opacity - elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) + - (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")"); - } - - return elem.filter && elem.filter.indexOf("opacity=") >= 0 ? - (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '': - ""; - } - - name = name.replace(/-([a-z])/ig, function(all, letter){ - return letter.toUpperCase(); - }); - - if ( set ) - elem[ name ] = value; - - return elem[ name ]; - }, - - trim: function( text ) { - return (text || "").replace( /^\s+|\s+$/g, "" ); - }, - - makeArray: function( array ) { - var ret = []; - - if( array != null ){ - var i = array.length; - // The window, strings (and functions) also have 'length' - if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval ) - ret[0] = array; - else - while( i ) - ret[--i] = array[i]; - } - - return ret; - }, - - inArray: function( elem, array ) { - for ( var i = 0, length = array.length; i < length; i++ ) - // Use === because on IE, window == document - if ( array[ i ] === elem ) - return i; - - return -1; - }, - - merge: function( first, second ) { - // We have to loop this way because IE & Opera overwrite the length - // expando of getElementsByTagName - var i = 0, elem, pos = first.length; - // Also, we need to make sure that the correct elements are being returned - // (IE returns comment nodes in a '*' query) - if ( !jQuery.support.getAll ) { - while ( (elem = second[ i++ ]) != null ) - if ( elem.nodeType != 8 ) - first[ pos++ ] = elem; - - } else - while ( (elem = second[ i++ ]) != null ) - first[ pos++ ] = elem; - - return first; - }, - - unique: function( array ) { - var ret = [], done = {}; - - try { - - for ( var i = 0, length = array.length; i < length; i++ ) { - var id = jQuery.data( array[ i ] ); - - if ( !done[ id ] ) { - done[ id ] = true; - ret.push( array[ i ] ); - } - } - - } catch( e ) { - ret = array; - } - - return ret; - }, - - grep: function( elems, callback, inv ) { - var ret = []; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; i < length; i++ ) - if ( !inv != !callback( elems[ i ], i ) ) - ret.push( elems[ i ] ); - - return ret; - }, - - map: function( elems, callback ) { - var ret = []; - - // Go through the array, translating each of the items to their - // new value (or values). - for ( var i = 0, length = elems.length; i < length; i++ ) { - var value = callback( elems[ i ], i ); - - if ( value != null ) - ret[ ret.length ] = value; - } - - return ret.concat.apply( [], ret ); - } -}); - -// Use of jQuery.browser is deprecated. -// It's included for backwards compatibility and plugins, -// although they should work to migrate away. - -var userAgent = navigator.userAgent.toLowerCase(); - -// Figure out what browser is being used -jQuery.browser = { - version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1], - safari: /webkit/.test( userAgent ), - opera: /opera/.test( userAgent ), - msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ), - mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ) -}; - -jQuery.each({ - parent: function(elem){return elem.parentNode;}, - parents: function(elem){return jQuery.dir(elem,"parentNode");}, - next: function(elem){return jQuery.nth(elem,2,"nextSibling");}, - prev: function(elem){return jQuery.nth(elem,2,"previousSibling");}, - nextAll: function(elem){return jQuery.dir(elem,"nextSibling");}, - prevAll: function(elem){return jQuery.dir(elem,"previousSibling");}, - siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);}, - children: function(elem){return jQuery.sibling(elem.firstChild);}, - contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);} -}, function(name, fn){ - jQuery.fn[ name ] = function( selector ) { - var ret = jQuery.map( this, fn ); - - if ( selector && typeof selector == "string" ) - ret = jQuery.multiFilter( selector, ret ); - - return this.pushStack( jQuery.unique( ret ), name, selector ); - }; -}); - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function(name, original){ - jQuery.fn[ name ] = function( selector ) { - var ret = [], insert = jQuery( selector ); - - for ( var i = 0, l = insert.length; i < l; i++ ) { - var elems = (i > 0 ? this.clone(true) : this).get(); - jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); - ret = ret.concat( elems ); - } - - return this.pushStack( ret, name, selector ); - }; -}); - -jQuery.each({ - removeAttr: function( name ) { - jQuery.attr( this, name, "" ); - if (this.nodeType == 1) - this.removeAttribute( name ); - }, - - addClass: function( classNames ) { - jQuery.className.add( this, classNames ); - }, - - removeClass: function( classNames ) { - jQuery.className.remove( this, classNames ); - }, - - toggleClass: function( classNames, state ) { - if( typeof state !== "boolean" ) - state = !jQuery.className.has( this, classNames ); - jQuery.className[ state ? "add" : "remove" ]( this, classNames ); - }, - - remove: function( selector ) { - if ( !selector || jQuery.filter( selector, [ this ] ).length ) { - // Prevent memory leaks - jQuery( "*", this ).add([this]).each(function(){ - jQuery.event.remove(this); - jQuery.removeData(this); - }); - if (this.parentNode) - this.parentNode.removeChild( this ); - } - }, - - empty: function() { - // Remove element nodes and prevent memory leaks - jQuery(this).children().remove(); - - // Remove any remaining nodes - while ( this.firstChild ) - this.removeChild( this.firstChild ); - } -}, function(name, fn){ - jQuery.fn[ name ] = function(){ - return this.each( fn, arguments ); - }; -}); - -// Helper function used by the dimensions and offset modules -function num(elem, prop) { - return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0; -} -var expando = "jQuery" + now(), uuid = 0, windowData = {}; - -jQuery.extend({ - cache: {}, - - data: function( elem, name, data ) { - elem = elem == window ? - windowData : - elem; - - var id = elem[ expando ]; - - // Compute a unique ID for the element - if ( !id ) - id = elem[ expando ] = ++uuid; - - // Only generate the data cache if we're - // trying to access or manipulate it - if ( name && !jQuery.cache[ id ] ) - jQuery.cache[ id ] = {}; - - // Prevent overriding the named cache with undefined values - if ( data !== undefined ) - jQuery.cache[ id ][ name ] = data; - - // Return the named cache data, or the ID for the element - return name ? - jQuery.cache[ id ][ name ] : - id; - }, - - removeData: function( elem, name ) { - elem = elem == window ? - windowData : - elem; - - var id = elem[ expando ]; - - // If we want to remove a specific section of the element's data - if ( name ) { - if ( jQuery.cache[ id ] ) { - // Remove the section of cache data - delete jQuery.cache[ id ][ name ]; - - // If we've removed all the data, remove the element's cache - name = ""; - - for ( name in jQuery.cache[ id ] ) - break; - - if ( !name ) - jQuery.removeData( elem ); - } - - // Otherwise, we want to remove all of the element's data - } else { - // Clean up the element expando - try { - delete elem[ expando ]; - } catch(e){ - // IE has trouble directly removing the expando - // but it's ok with using removeAttribute - if ( elem.removeAttribute ) - elem.removeAttribute( expando ); - } - - // Completely remove the data cache - delete jQuery.cache[ id ]; - } - }, - queue: function( elem, type, data ) { - if ( elem ){ - - type = (type || "fx") + "queue"; - - var q = jQuery.data( elem, type ); - - if ( !q || jQuery.isArray(data) ) - q = jQuery.data( elem, type, jQuery.makeArray(data) ); - else if( data ) - q.push( data ); - - } - return q; - }, - - dequeue: function( elem, type ){ - var queue = jQuery.queue( elem, type ), - fn = queue.shift(); - - if( !type || type === "fx" ) - fn = queue[0]; - - if( fn !== undefined ) - fn.call(elem); - } -}); - -jQuery.fn.extend({ - data: function( key, value ){ - var parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value === undefined ) { - var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - if ( data === undefined && this.length ) - data = jQuery.data( this[0], key ); - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - } else - return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ - jQuery.data( this, key, value ); - }); - }, - - removeData: function( key ){ - return this.each(function(){ - jQuery.removeData( this, key ); - }); - }, - queue: function(type, data){ - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - } - - if ( data === undefined ) - return jQuery.queue( this[0], type ); - - return this.each(function(){ - var queue = jQuery.queue( this, type, data ); - - if( type == "fx" && queue.length == 1 ) - queue[0].call(this); - }); - }, - dequeue: function(type){ - return this.each(function(){ - jQuery.dequeue( this, type ); - }); - } -});/*! - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information:
http://sizzlejs.com/
- */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g, - done = 0, - toString = Object.prototype.toString; - -var Sizzle = function(selector, context, results, seed) { - results = results || []; - context = context || document; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) - return []; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var parts = [], m, set, checkSet, check, mode, extra, prune = true; - - // Reset the position of the chunker regexp (start from head) - chunker.lastIndex = 0; - - while ( (m = chunker.exec(selector)) !== null ) { - parts.push( m[1] ); - - if ( m[2] ) { - extra = RegExp.rightContext; - break; - } - } - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context ); - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) - selector += parts.shift(); - - set = posProcess( selector, set ); - } - } - } else { - var ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) ); - set = Sizzle.filter( ret.expr, ret.set ); - - if ( parts.length > 0 ) { - checkSet = makeArray(set); - } else { - prune = false; - } - - while ( parts.length ) { - var cur = parts.pop(), pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, isXML(context) ); - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - throw "Syntax error, unrecognized expression: " + (cur || selector); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - } else if ( context.nodeType === 1 ) { - for ( var i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - } else { - for ( var i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, context, results, seed ); - - if ( sortOrder ) { - hasDuplicate = false; - results.sort(sortOrder); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[i-1] ) { - results.splice(i--, 1); - } - } - } - } - } - - return results; -}; - -Sizzle.matches = function(expr, set){ - return Sizzle(expr, null, null, set); -}; - -Sizzle.find = function(expr, context, isXML){ - var set, match; - - if ( !expr ) { - return []; - } - - for ( var i = 0, l = Expr.order.length; i < l; i++ ) { - var type = Expr.order[i], match; - - if ( (match = Expr.match[ type ].exec( expr )) ) { - var left = RegExp.leftContext; - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace(/\\/g, ""); - set = Expr.find[ type ]( match, context, isXML ); - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = context.getElementsByTagName("*"); - } - - return {set: set, expr: expr}; -}; - -Sizzle.filter = function(expr, set, inplace, not){ - var old = expr, result = [], curLoop = set, match, anyFound, - isXMLFilter = set && set[0] && isXML(set[0]); - - while ( expr && set.length ) { - for ( var type in Expr.filter ) { - if ( (match = Expr.match[ type ].exec( expr )) != null ) { - var filter = Expr.filter[ type ], found, item; - anyFound = false; - - if ( curLoop == result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( var i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - var pass = not ^ !!found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - } else { - curLoop[i] = false; - } - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr == old ) { - if ( anyFound == null ) { - throw "Syntax error, unrecognized expression: " + expr; - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - match: { - ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ - }, - attrMap: { - "class": "className", - "for": "htmlFor" - }, - attrHandle: { - href: function(elem){ - return elem.getAttribute("href"); - } - }, - relative: { - "+": function(checkSet, part, isXML){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !/\W/.test(part), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag && !isXML ) { - part = part.toUpperCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - ">": function(checkSet, part, isXML){ - var isPartStr = typeof part === "string"; - - if ( isPartStr && !/\W/.test(part) ) { - part = isXML ? part : part.toUpperCase(); - - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName === part ? parent : false; - } - } - } else { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - "": function(checkSet, part, isXML){ - var doneName = done++, checkFn = dirCheck; - - if ( !part.match(/\W/) ) { - var nodeCheck = part = isXML ? part : part.toUpperCase(); - checkFn = dirNodeCheck; - } - - checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); - }, - "~": function(checkSet, part, isXML){ - var doneName = done++, checkFn = dirCheck; - - if ( typeof part === "string" && !part.match(/\W/) ) { - var nodeCheck = part = isXML ? part : part.toUpperCase(); - checkFn = dirNodeCheck; - } - - checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); - } - }, - find: { - ID: function(match, context, isXML){ - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - return m ? [m] : []; - } - }, - NAME: function(match, context, isXML){ - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], results = context.getElementsByName(match[1]); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - TAG: function(match, context){ - return context.getElementsByTagName(match[1]); - } - }, - preFilter: { - CLASS: function(match, curLoop, inplace, result, not, isXML){ - match = " " + match[1].replace(/\\/g, "") + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { - if ( !inplace ) - result.push( elem ); - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - ID: function(match){ - return match[1].replace(/\\/g, ""); - }, - TAG: function(match, curLoop){ - for ( var i = 0; curLoop[i] === false; i++ ){} - return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); - }, - CHILD: function(match){ - if ( match[1] == "nth" ) { - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( - match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - ATTR: function(match, curLoop, inplace, result, not, isXML){ - var name = match[1].replace(/\\/g, ""); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - PSEUDO: function(match, curLoop, inplace, result, not){ - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - if ( !inplace ) { - result.push.apply( result, ret ); - } - return false; - } - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - POS: function(match){ - match.unshift( true ); - return match; - } - }, - filters: { - enabled: function(elem){ - return elem.disabled === false && elem.type !== "hidden"; - }, - disabled: function(elem){ - return elem.disabled === true; - }, - checked: function(elem){ - return elem.checked === true; - }, - selected: function(elem){ - // Accessing this property makes selected-by-default - // options in Safari work properly - elem.parentNode.selectedIndex; - return elem.selected === true; - }, - parent: function(elem){ - return !!elem.firstChild; - }, - empty: function(elem){ - return !elem.firstChild; - }, - has: function(elem, i, match){ - return !!Sizzle( match[3], elem ).length; - }, - header: function(elem){ - return /h\d/i.test( elem.nodeName ); - }, - text: function(elem){ - return "text" === elem.type; - }, - radio: function(elem){ - return "radio" === elem.type; - }, - checkbox: function(elem){ - return "checkbox" === elem.type; - }, - file: function(elem){ - return "file" === elem.type; - }, - password: function(elem){ - return "password" === elem.type; - }, - submit: function(elem){ - return "submit" === elem.type; - }, - image: function(elem){ - return "image" === elem.type; - }, - reset: function(elem){ - return "reset" === elem.type; - }, - button: function(elem){ - return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; - }, - input: function(elem){ - return /input|select|textarea|button/i.test(elem.nodeName); - } - }, - setFilters: { - first: function(elem, i){ - return i === 0; - }, - last: function(elem, i, match, array){ - return i === array.length - 1; - }, - even: function(elem, i){ - return i % 2 === 0; - }, - odd: function(elem, i){ - return i % 2 === 1; - }, - lt: function(elem, i, match){ - return i < match[3] - 0; - }, - gt: function(elem, i, match){ - return i > match[3] - 0; - }, - nth: function(elem, i, match){ - return match[3] - 0 == i; - }, - eq: function(elem, i, match){ - return match[3] - 0 == i; - } - }, - filter: { - PSEUDO: function(elem, match, i, array){ - var name = match[1], filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; - } else if ( name === "not" ) { - var not = match[3]; - - for ( var i = 0, l = not.length; i < l; i++ ) { - if ( not[i] === elem ) { - return false; - } - } - - return true; - } - }, - CHILD: function(elem, match){ - var type = match[1], node = elem; - switch (type) { - case 'only': - case 'first': - while (node = node.previousSibling) { - if ( node.nodeType === 1 ) return false; - } - if ( type == 'first') return true; - node = elem; - case 'last': - while (node = node.nextSibling) { - if ( node.nodeType === 1 ) return false; - } - return true; - case 'nth': - var first = match[2], last = match[3]; - - if ( first == 1 && last == 0 ) { - return true; - } - - var doneName = match[0], - parent = elem.parentNode; - - if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { - var count = 0; - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - parent.sizcache = doneName; - } - - var diff = elem.nodeIndex - last; - if ( first == 0 ) { - return diff == 0; - } else { - return ( diff % first == 0 && diff / first >= 0 ); - } - } - }, - ID: function(elem, match){ - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - TAG: function(elem, match){ - return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; - }, - CLASS: function(elem, match){ - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - ATTR: function(elem, match){ - var name = match[1], - result = Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value != check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - POS: function(elem, match, i, array){ - var name = match[2], filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS; - -for ( var type in Expr.match ) { - Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); -} - -var makeArray = function(array, results) { - array = Array.prototype.slice.call( array ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -try { - Array.prototype.slice.call( document.documentElement.childNodes ); - -// Provide a fallback method if it does not work -} catch(e){ - makeArray = function(array, results) { - var ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - } else { - if ( typeof array.length === "number" ) { - for ( var i = 0, l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - } else { - for ( var i = 0; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; - if ( ret === 0 ) { - hasDuplicate = true; - } - return ret; - }; -} else if ( "sourceIndex" in document.documentElement ) { - sortOrder = function( a, b ) { - var ret = a.sourceIndex - b.sourceIndex; - if ( ret === 0 ) { - hasDuplicate = true; - } - return ret; - }; -} else if ( document.createRange ) { - sortOrder = function( a, b ) { - var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); - aRange.selectNode(a); - aRange.collapse(true); - bRange.selectNode(b); - bRange.collapse(true); - var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); - if ( ret === 0 ) { - hasDuplicate = true; - } - return ret; - }; -} - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("form"), - id = "script" + (new Date).getTime(); - form.innerHTML = "<input name='" + id + "'/>"; - - // Inject it into the root element, check its status, and remove it quickly - var root = document.documentElement; - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( !!document.getElementById( id ) ) { - Expr.find.ID = function(match, context, isXML){ - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; - } - }; - - Expr.filter.ID = function(elem, match){ - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function(match, context){ - var results = context.getElementsByTagName(match[1]); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = "<a href='#'></a>"; - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - Expr.attrHandle.href = function(elem){ - return elem.getAttribute("href", 2); - }; - } -})(); - -if ( document.querySelectorAll ) (function(){ - var oldSizzle = Sizzle, div = document.createElement("div"); - div.innerHTML = "<p class='TEST'></p>"; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function(query, context, extra, seed){ - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && context.nodeType === 9 && !isXML(context) ) { - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(e){} - } - - return oldSizzle(query, context, extra, seed); - }; - - Sizzle.find = oldSizzle.find; - Sizzle.filter = oldSizzle.filter; - Sizzle.selectors = oldSizzle.selectors; - Sizzle.matches = oldSizzle.matches; -})(); - -if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ - var div = document.createElement("div"); - div.innerHTML = "<div class='test e'></div><div class='test'></div>"; - - // Opera can't find a second classname (in 9.6) - if ( div.getElementsByClassName("e").length === 0 ) - return; - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) - return; - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function(match, context, isXML) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - var sibDir = dir == "previousSibling" && !isXML; - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - if ( sibDir && elem.nodeType === 1 ){ - elem.sizcache = doneName; - elem.sizset = i; - } - elem = elem[dir]; - var match = false; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( elem.nodeName === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - var sibDir = dir == "previousSibling" && !isXML; - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - if ( sibDir && elem.nodeType === 1 ) { - elem.sizcache = doneName; - elem.sizset = i; - } - elem = elem[dir]; - var match = false; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem.sizcache = doneName; - elem.sizset = i; - } - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -var contains = document.compareDocumentPosition ? function(a, b){ - return a.compareDocumentPosition(b) & 16; -} : function(a, b){ - return a !== b && (a.contains ? a.contains(b) : true); -}; - -var isXML = function(elem){ - return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || - !!elem.ownerDocument && isXML( elem.ownerDocument ); -}; - -var posProcess = function(selector, context){ - var tmpSet = [], later = "", match, - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -jQuery.find = Sizzle; -jQuery.filter = Sizzle.filter; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.filters; - -Sizzle.selectors.filters.hidden = function(elem){ - return elem.offsetWidth === 0 || elem.offsetHeight === 0; -}; - -Sizzle.selectors.filters.visible = function(elem){ - return elem.offsetWidth > 0 || elem.offsetHeight > 0; -}; - -Sizzle.selectors.filters.animated = function(elem){ - return jQuery.grep(jQuery.timers, function(fn){ - return elem === fn.elem; - }).length; -}; - -jQuery.multiFilter = function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return Sizzle.matches(expr, elems); -}; - -jQuery.dir = function( elem, dir ){ - var matched = [], cur = elem[dir]; - while ( cur && cur != document ) { - if ( cur.nodeType == 1 ) - matched.push( cur ); - cur = cur[dir]; - } - return matched; -}; - -jQuery.nth = function(cur, result, dir, elem){ - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) - if ( cur.nodeType == 1 && ++num == result ) - break; - - return cur; -}; - -jQuery.sibling = function(n, elem){ - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType == 1 && n != elem ) - r.push( n ); - } - - return r; -}; - -return; - -window.Sizzle = Sizzle; - -})(); -/* - * A number of helper functions used for managing events. - * Many of the ideas behind this code originated from - * Dean Edwards' addEvent library. - */ -jQuery.event = { - - // Bind an event to an element - // Original by Dean Edwards - add: function(elem, types, handler, data) { - if ( elem.nodeType == 3 || elem.nodeType == 8 ) - return; - - // For whatever reason, IE has trouble passing the window object - // around, causing it to be cloned in the process - if ( elem.setInterval && elem != window ) - elem = window; - - // Make sure that the function being executed has a unique ID - if ( !handler.guid ) - handler.guid = this.guid++; - - // if data is passed, bind to handler - if ( data !== undefined ) { - // Create temporary function pointer to original handler - var fn = handler; - - // Create unique handler function, wrapped around original handler - handler = this.proxy( fn ); - - // Store data in unique handler - handler.data = data; - } - - // Init the element's event structure - var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}), - handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){ - // Handle the second event of a trigger and when - // an event is called after a page has unloaded - return typeof jQuery !== "undefined" && !jQuery.event.triggered ? - jQuery.event.handle.apply(arguments.callee.elem, arguments) : - undefined; - }); - // Add elem as a property of the handle function - // This is to prevent a memory leak with non-native - // event in IE. - handle.elem = elem; - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - jQuery.each(types.split(/\s+/), function(index, type) { - // Namespaced event handlers - var namespaces = type.split("."); - type = namespaces.shift(); - handler.type = namespaces.slice().sort().join("."); - - // Get the current list of functions bound to this event - var handlers = events[type]; - - if ( jQuery.event.specialAll[type] ) - jQuery.event.specialAll[type].setup.call(elem, data, namespaces); - - // Init the event handler queue - if (!handlers) { - handlers = events[type] = {}; - - // Check for a special event handler - // Only use addEventListener/attachEvent if the special - // events handler returns false - if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) { - // Bind the global event handler to the element - if (elem.addEventListener) - elem.addEventListener(type, handle, false); - else if (elem.attachEvent) - elem.attachEvent("on" + type, handle); - } - } - - // Add the function to the element's handler list - handlers[handler.guid] = handler; - - // Keep track of which events have been used, for global triggering - jQuery.event.global[type] = true; - }); - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - guid: 1, - global: {}, - - // Detach an event or set of events from an element - remove: function(elem, types, handler) { - // don't do events on text and comment nodes - if ( elem.nodeType == 3 || elem.nodeType == 8 ) - return; - - var events = jQuery.data(elem, "events"), ret, index; - - if ( events ) { - // Unbind all events for the element - if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") ) - for ( var type in events ) - this.remove( elem, type + (types || "") ); - else { - // types is actually an event object here - if ( types.type ) { - handler = types.handler; - types = types.type; - } - - // Handle multiple events seperated by a space - // jQuery(...).unbind("mouseover mouseout", fn); - jQuery.each(types.split(/\s+/), function(index, type){ - // Namespaced event handlers - var namespaces = type.split("."); - type = namespaces.shift(); - var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)"); - - if ( events[type] ) { - // remove the given handler for the given type - if ( handler ) - delete events[type][handler.guid]; - - // remove all handlers for the given type - else - for ( var handle in events[type] ) - // Handle the removal of namespaced events - if ( namespace.test(events[type][handle].type) ) - delete events[type][handle]; - - if ( jQuery.event.specialAll[type] ) - jQuery.event.specialAll[type].teardown.call(elem, namespaces); - - // remove generic event handler if no more handlers exist - for ( ret in events[type] ) break; - if ( !ret ) { - if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) { - if (elem.removeEventListener) - elem.removeEventListener(type, jQuery.data(elem, "handle"), false); - else if (elem.detachEvent) - elem.detachEvent("on" + type, jQuery.data(elem, "handle")); - } - ret = null; - delete events[type]; - } - } - }); - } - - // Remove the expando if it's no longer used - for ( ret in events ) break; - if ( !ret ) { - var handle = jQuery.data( elem, "handle" ); - if ( handle ) handle.elem = null; - jQuery.removeData( elem, "events" ); - jQuery.removeData( elem, "handle" ); - } - } - }, - - // bubbling is internal - trigger: function( event, data, elem, bubbling ) { - // Event object or event type - var type = event.type || event; - - if( !bubbling ){ - event = typeof event === "object" ? - // jQuery.Event object - event[expando] ? event : - // Object literal - jQuery.extend( jQuery.Event(type), event ) : - // Just the event type (string) - jQuery.Event(type); - - if ( type.indexOf("!") >= 0 ) { - event.type = type = type.slice(0, -1); - event.exclusive = true; - } - - // Handle a global trigger - if ( !elem ) { - // Don't bubble custom events when global (to avoid too much overhead) - event.stopPropagation(); - // Only trigger if we've ever bound an event for it - if ( this.global[type] ) - jQuery.each( jQuery.cache, function(){ - if ( this.events && this.events[type] ) - jQuery.event.trigger( event, data, this.handle.elem ); - }); - } - - // Handle triggering a single element - - // don't do events on text and comment nodes - if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 ) - return undefined; - - // Clean up in case it is reused - event.result = undefined; - event.target = elem; - - // Clone the incoming data, if any - data = jQuery.makeArray(data); - data.unshift( event ); - } - - event.currentTarget = elem; - - // Trigger the event, it is assumed that "handle" is a function - var handle = jQuery.data(elem, "handle"); - if ( handle ) - handle.apply( elem, data ); - - // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links) - if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false ) - event.result = false; - - // Trigger the native events (except for clicks on links) - if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) { - this.triggered = true; - try { - elem[ type ](); - // prevent IE from throwing an error for some hidden elements - } catch (e) {} - } - - this.triggered = false; - - if ( !event.isPropagationStopped() ) { - var parent = elem.parentNode || elem.ownerDocument; - if ( parent ) - jQuery.event.trigger(event, data, parent, true); - } - }, - - handle: function(event) { - // returned undefined or false - var all, handlers; - - event = arguments[0] = jQuery.event.fix( event || window.event ); - event.currentTarget = this; - - // Namespaced event handlers - var namespaces = event.type.split("."); - event.type = namespaces.shift(); - - // Cache this now, all = true means, any handler - all = !namespaces.length && !event.exclusive; - - var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)"); - - handlers = ( jQuery.data(this, "events") || {} )[event.type]; - - for ( var j in handlers ) { - var handler = handlers[j]; - - // Filter the functions by class - if ( all || namespace.test(handler.type) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handler; - event.data = handler.data; - - var ret = handler.apply(this, arguments); - - if( ret !== undefined ){ - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - - if( event.isImmediatePropagationStopped() ) - break; - - } - } - }, - - props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), - - fix: function(event) { - if ( event[expando] ) - return event; - - // store a copy of the original event object - // and "clone" to set read-only properties - var originalEvent = event; - event = jQuery.Event( originalEvent ); - - for ( var i = this.props.length, prop; i; ){ - prop = this.props[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary - if ( !event.target ) - event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either - - // check if target is a textnode (safari) - if ( event.target.nodeType == 3 ) - event.target = event.target.parentNode; - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && event.fromElement ) - event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && event.clientX != null ) { - var doc = document.documentElement, body = document.body; - event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0); - event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0); - } - - // Add which for key events - if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) - event.which = event.charCode || event.keyCode; - - // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) - if ( !event.metaKey && event.ctrlKey ) - event.metaKey = event.ctrlKey; - - // Add which for click: 1 == left; 2 == middle; 3 == right - // Note: button is not normalized, so don't use it - if ( !event.which && event.button ) - event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); - - return event; - }, - - proxy: function( fn, proxy ){ - proxy = proxy || function(){ return fn.apply(this, arguments); }; - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++; - // So proxy can be declared as an argument - return proxy; - }, - - special: { - ready: { - // Make sure the ready event is setup - setup: bindReady, - teardown: function() {} - } - }, - - specialAll: { - live: { - setup: function( selector, namespaces ){ - jQuery.event.add( this, namespaces[0], liveHandler ); - }, - teardown: function( namespaces ){ - if ( namespaces.length ) { - var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)"); - - jQuery.each( (jQuery.data(this, "events").live || {}), function(){ - if ( name.test(this.type) ) - remove++; - }); - - if ( remove < 1 ) - jQuery.event.remove( this, namespaces[0], liveHandler ); - } - } - } - } -}; - -jQuery.Event = function( src ){ - // Allow instantiation without the 'new' keyword - if( !this.preventDefault ) - return new jQuery.Event(src); - - // Event object - if( src && src.type ){ - this.originalEvent = src; - this.type = src.type; - // Event type - }else - this.type = src; - - // timeStamp is buggy for some events on Firefox(#3843) - // So we won't rely on the native value - this.timeStamp = now(); - - // Mark it as fixed - this[expando] = true; -}; - -function returnFalse(){ - return false; -} -function returnTrue(){ - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -//
http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-bindin…
-jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if( !e ) - return; - // if preventDefault exists run it on the original event - if (e.preventDefault) - e.preventDefault(); - // otherwise set the returnValue property of the original event to false (IE) - e.returnValue = false; - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if( !e ) - return; - // if stopPropagation exists run it on the original event - if (e.stopPropagation) - e.stopPropagation(); - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation:function(){ - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; -// Checks if an event happened on an element within another element -// Used in jQuery.event.special.mouseenter and mouseleave handlers -var withinElement = function(event) { - // Check if mouse(over|out) are still within the same parent element - var parent = event.relatedTarget; - // Traverse up the tree - while ( parent && parent != this ) - try { parent = parent.parentNode; } - catch(e) { parent = this; } - - if( parent != this ){ - // set the correct event type - event.type = event.data; - // handle event if we actually just moused on to a non sub-element - jQuery.event.handle.apply( this, arguments ); - } -}; - -jQuery.each({ - mouseover: 'mouseenter', - mouseout: 'mouseleave' -}, function( orig, fix ){ - jQuery.event.special[ fix ] = { - setup: function(){ - jQuery.event.add( this, orig, withinElement, fix ); - }, - teardown: function(){ - jQuery.event.remove( this, orig, withinElement ); - } - }; -}); - -jQuery.fn.extend({ - bind: function( type, data, fn ) { - return type == "unload" ? this.one(type, data, fn) : this.each(function(){ - jQuery.event.add( this, type, fn || data, fn && data ); - }); - }, - - one: function( type, data, fn ) { - var one = jQuery.event.proxy( fn || data, function(event) { - jQuery(this).unbind(event, one); - return (fn || data).apply( this, arguments ); - }); - return this.each(function(){ - jQuery.event.add( this, type, one, fn && data); - }); - }, - - unbind: function( type, fn ) { - return this.each(function(){ - jQuery.event.remove( this, type, fn ); - }); - }, - - trigger: function( type, data ) { - return this.each(function(){ - jQuery.event.trigger( type, data, this ); - }); - }, - - triggerHandler: function( type, data ) { - if( this[0] ){ - var event = jQuery.Event(type); - event.preventDefault(); - event.stopPropagation(); - jQuery.event.trigger( event, data, this[0] ); - return event.result; - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, i = 1; - - // link all the functions, so any of them can unbind this click handler - while( i < args.length ) - jQuery.event.proxy( fn, args[i++] ); - - return this.click( jQuery.event.proxy( fn, function(event) { - // Figure out which function to execute - this.lastToggle = ( this.lastToggle || 0 ) % i; - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ this.lastToggle++ ].apply( this, arguments ) || false; - })); - }, - - hover: function(fnOver, fnOut) { - return this.mouseenter(fnOver).mouseleave(fnOut); - }, - - ready: function(fn) { - // Attach the listeners - bindReady(); - - // If the DOM is already ready - if ( jQuery.isReady ) - // Execute the function immediately - fn.call( document, jQuery ); - - // Otherwise, remember the function for later - else - // Add the function to the wait list - jQuery.readyList.push( fn ); - - return this; - }, - - live: function( type, fn ){ - var proxy = jQuery.event.proxy( fn ); - proxy.guid += this.selector + type; - - jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy ); - - return this; - }, - - die: function( type, fn ){ - jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null ); - return this; - }
1
0
0
0
[hg] galaxy 3382: trackster: clicking enter should continue
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/c8c472e6f341
changeset: 3382:c8c472e6f341 user: Kanwei Li <kanwei(a)gmail.com> date: Fri Feb 12 15:09:00 2010 -0500 description: trackster: clicking enter should continue diffstat: templates/tracks/browser.mako | 11 ++++++----- templates/tracks/new_browser.mako | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diffs (36 lines): diff -r 205d55699a10 -r c8c472e6f341 templates/tracks/browser.mako --- a/templates/tracks/browser.mako Fri Feb 12 14:01:45 2010 -0500 +++ b/templates/tracks/browser.mako Fri Feb 12 15:09:00 2010 -0500 @@ -96,17 +96,18 @@ %endfor init(); %else: + continue_fn = function() { + view = new View( undefined, $("#new-title").val(), undefined, $("#new-dbkey").val() ); + init(); + hide_modal(); + }; $.ajax({ url: "${h.url_for( action='new_browser' )}", data: {}, error: function() { alert( "Couldn't create new browser" ) }, success: function(form_html) { show_modal("New Track Browser", form_html, { - "Continue": function() { - view = new View( undefined, $("#new-title").val(), undefined, $("#new-dbkey").val() ); - init(); - hide_modal(); - } + "Continue": continue_fn }); } }); diff -r 205d55699a10 -r c8c472e6f341 templates/tracks/new_browser.mako --- a/templates/tracks/new_browser.mako Fri Feb 12 14:01:45 2010 -0500 +++ b/templates/tracks/new_browser.mako Fri Feb 12 15:09:00 2010 -0500 @@ -1,4 +1,4 @@ -<form id="form" method="POST"> +<form id="new-browser-form" method="post" onsubmit="continue_fn(); return false;"> <div class="form-row"> <label for="title">Browser name:</label> <div class="form-row-input">
1
0
0
0
[hg] galaxy 3381: LIMS data transfer:
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/205d55699a10
changeset: 3381:205d55699a10 user: rc date: Fri Feb 12 14:01:45 2010 -0500 description: LIMS data transfer: - Fixed some config variable issues - Now for the time being, Galaxy can transfer one dataset at a time. diffstat: lib/galaxy/web/controllers/requests_admin.py | 5 +-- scripts/galaxy_messaging/server/data_transfer.py | 39 +++++++++++------------ transfer_datasets.ini.sample | 14 +++++++- 3 files changed, 31 insertions(+), 27 deletions(-) diffs (154 lines): diff -r 971389b682c7 -r 205d55699a10 lib/galaxy/web/controllers/requests_admin.py --- a/lib/galaxy/web/controllers/requests_admin.py Fri Feb 12 13:13:12 2010 -0500 +++ b/lib/galaxy/web/controllers/requests_admin.py Fri Feb 12 14:01:45 2010 -0500 @@ -1527,7 +1527,7 @@ messagetype='error', msg=msg)) error_msg = '' - transfer_script = "scripts/galaxy_messaging/server/daemon.py" + transfer_script = "scripts/galaxy_messaging/server/data_transfer.py" for index, dataset in enumerate(sample.dataset_files): dfile = dataset[0] status = dataset[1] @@ -1573,9 +1573,6 @@ action='show_datatx_page', sample_id=trans.security.encode_id(sample.id), folder_path=os.path.dirname(dfile))) - - - ## #### Request Type Stuff ################################################### ## diff -r 971389b682c7 -r 205d55699a10 scripts/galaxy_messaging/server/data_transfer.py --- a/scripts/galaxy_messaging/server/data_transfer.py Fri Feb 12 13:13:12 2010 -0500 +++ b/scripts/galaxy_messaging/server/data_transfer.py Fri Feb 12 14:01:45 2010 -0500 @@ -17,12 +17,11 @@ <library_id> <folder_id> """ - import ConfigParser import sys, os, time, traceback import optparse import urllib,urllib2, cookielib, shutil -import logging +import logging, time from galaxydb_interface import GalaxyDbInterface assert sys.version_info[:2] >= ( 2, 4 ) @@ -40,7 +39,7 @@ import simplejson curr_dir = os.getcwd() -logfile = os.path.join('/Users/rc/tmp', 'data_transfer.log') +logfile = os.path.join(os.getcwd(), 'data_transfer.log') logging.basicConfig(filename=logfile, level=logging.DEBUG, format="%(asctime)s [%(levelname)s] %(message)s") @@ -66,11 +65,13 @@ try: # Retrieve the upload user login information from the config file config = ConfigParser.ConfigParser() - config.read('universe_wsgi.ini') - self.server_host = config.get("server:main", "host") - self.server_port = config.get("server:main", "port") - self.database_connection = config.get("app:main", "database_connection") - self.import_dir = config.get("app:main", "library_import_dir") + config.read('transfer_datasets.ini') + self.datatx_email = config.get("data_transfer_user_login_info", "email") + self.datatx_password = config.get("data_transfer_user_login_info", "password") + self.server_host = config.get("universe_wsgi_config", "host") + self.server_port = config.get("universe_wsgi_config", "port") + self.database_connection = config.get("universe_wsgi_config", "database_connection") + self.import_dir = config.get("universe_wsgi_config", "library_import_dir") # create the destination directory within the import directory self.server_dir = os.path.join( self.import_dir, 'datatx_'+str(os.getpid()) ) os.mkdir(self.server_dir) @@ -90,7 +91,7 @@ ''' # datatx self.transfer_file() - # add the dataset to the given library + # add the dataset to the given library self.add_to_library() # update the data transfer status in the db self.update_status('Complete') @@ -104,6 +105,7 @@ before adding the same to the data library ''' try: + time.sleep(60) shutil.rmtree( self.server_dir ) except: self.error_and_exit() @@ -151,24 +153,19 @@ ''' try: logging.debug('Adding %s to library...' % os.path.basename(self.remote_file)) - # Retrieve the upload user login information from the config file - config = ConfigParser.ConfigParser() - config.read('transfer_datasets.ini') - email = config.get("data_transfer_user_login_info", "email") - password = config.get("data_transfer_user_login_info", "password") # create url base_url = "http://%s:%s" % (self.server_host, self.server_port) # login - url = "%s/user/login?email=%s&password=%s" % (base_url, email, password) + url = "%s/user/login?email=%s&password=%s" % (base_url, self.datatx_email, self.datatx_password) cj = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) f = opener.open(url) - if f.read().find("Now logged in as "+email) == -1: + if f.read().find("Now logged in as "+self.datatx_email) == -1: # if the user doesnt exist, create the user - url = "%s/user/create?email=%s&username=%s&password=%s&confirm=%s&create_user_button=Submit" % ( base_url, email, email, password, password ) + url = "%s/user/create?email=%s&username=%s&password=%s&confirm=%s&create_user_button=Submit" % ( base_url, self.datatx_email, self.datatx_email, self.datatx_password, self.datatx_password ) f = opener.open(url) - if f.read().find("Now logged in as "+email) == -1: - raise DataTransferException("The "+email+" user could not login to Galaxy") + if f.read().find("Now logged in as "+self.datatx_email) == -1: + raise DataTransferException("The "+self.datatx_email+" user could not login to Galaxy") # after login, add dataset to the library params = urllib.urlencode(dict( cntrller='library_admin', tool_id='upload1', @@ -191,7 +188,7 @@ # finally logout f = opener.open(base_url+'/user/logout') if f.read().find("You are no longer logged in.") == -1: - raise DataTransferException("The "+email+" user could not logout of Galaxy") + raise DataTransferException("The "+self.datatx_email+" user could not logout of Galaxy") except DataTransferException, (e): self.error_and_exit(e.msg) except: @@ -199,7 +196,7 @@ def update_status(self, status): ''' - + Update the data transfer status for this dataset in the database ''' try: galaxy = GalaxyDbInterface(self.database_connection) diff -r 971389b682c7 -r 205d55699a10 transfer_datasets.ini.sample --- a/transfer_datasets.ini.sample Fri Feb 12 13:13:12 2010 -0500 +++ b/transfer_datasets.ini.sample Fri Feb 12 14:01:45 2010 -0500 @@ -1,5 +1,15 @@ # Galaxy LIMS Transfer Datasets Configuration File [data_transfer_user_login_info] -#email = user(a)example.com -#password = +#email = datatx(a)bx.psu.edu +#password = datatx + +# The following section contains 4 config variables neede for the data transfer. +# Please copy the exact values for each of these variables from the universe_wsgi.ini +# configuration file for this installation + +[universe_wsgi_config] +#host = 127.0.0.1 +#port = +#database_connection = +#library_import_dir = \ No newline at end of file
1
0
0
0
[hg] galaxy 3380: Fix typo
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/971389b682c7
changeset: 3380:971389b682c7 user: Dan Blankenberg <dan(a)bx.psu.edu> date: Fri Feb 12 13:13:12 2010 -0500 description: Fix typo diffstat: lib/galaxy/datatypes/binary.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 7de8cf4f1581 -r 971389b682c7 lib/galaxy/datatypes/binary.py --- a/lib/galaxy/datatypes/binary.py Fri Feb 12 13:10:52 2010 -0500 +++ b/lib/galaxy/datatypes/binary.py Fri Feb 12 13:13:12 2010 -0500 @@ -108,7 +108,7 @@ if stderr: if exit_code != 0: os.unlink( stderr_name ) #clean up - raise Exception, "Error Grooming BAM file contents: %s" % stderr + raise Exception, "Error Setting BAM Metadata: %s" % stderr else: print stderr
1
0
0
0
[hg] galaxy 3379: Fix BAM groom_dataset_content and set_meta met...
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/7de8cf4f1581
changeset: 3379:7de8cf4f1581 user: Dan Blankenberg <dan(a)bx.psu.edu> date: Fri Feb 12 13:10:52 2010 -0500 description: Fix BAM groom_dataset_content and set_meta methods to respect exit codes. diffstat: lib/galaxy/datatypes/binary.py | 16 ++++++++++++---- 1 files changed, 12 insertions(+), 4 deletions(-) diffs (40 lines): diff -r 6d217bad7496 -r 7de8cf4f1581 lib/galaxy/datatypes/binary.py --- a/lib/galaxy/datatypes/binary.py Fri Feb 12 12:41:21 2010 -0500 +++ b/lib/galaxy/datatypes/binary.py Fri Feb 12 13:10:52 2010 -0500 @@ -70,12 +70,16 @@ samtools_created_sorted_file_name = "%s.bam" % tmp_sorted_dataset_file_name_prefix #samtools accepts a prefix, not a filename, it always adds .bam to the prefix command = "samtools sort %s %s" % ( file_name, tmp_sorted_dataset_file_name_prefix ) proc = subprocess.Popen( args=command, shell=True, cwd=tmp_dir, stderr=open( stderr_name, 'wb' ) ) - proc.wait() + exit_code = proc.wait() #Did sort succeed? stderr = open( stderr_name ).read().strip() if stderr: - raise Exception, "Error Grooming BAM file contents: %s" % stderr + if exit_code != 0: + shutil.rmtree( tmp_dir) #clean up + raise Exception, "Error Grooming BAM file contents: %s" % stderr + else: + print stderr # Move samtools_created_sorted_file_name to our output dataset location shutil.move( samtools_created_sorted_file_name, file_name ) @@ -98,11 +102,15 @@ stderr_name = tempfile.NamedTemporaryFile( prefix = "bam_index_stderr" ).name command = 'samtools index %s %s' % ( dataset.file_name, index_file.file_name ) proc = subprocess.Popen( args=command, shell=True, stderr=open( stderr_name, 'wb' ) ) - proc.wait() + exit_code = proc.wait() #Did index succeed? stderr = open( stderr_name ).read().strip() if stderr: - raise Exception, "Error Setting BAM Metadata: %s" % stderr + if exit_code != 0: + os.unlink( stderr_name ) #clean up + raise Exception, "Error Grooming BAM file contents: %s" % stderr + else: + print stderr dataset.metadata.bam_index = index_file
1
0
0
0
[hg] galaxy 3378: Make it possible to place grids in panels; spe...
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/6d217bad7496
changeset: 3378:6d217bad7496 user: jeremy goecks <jeremy.goecks(a)emory.edu> date: Fri Feb 12 12:41:21 2010 -0500 description: Make it possible to place grids in panels; specifically, make it possible to display a grid with the Galaxy masthead. diffstat: lib/galaxy/web/framework/helpers/grids.py | 4 +++- templates/grid_base.mako | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diffs (51 lines): diff -r 465daec3fb8f -r 6d217bad7496 lib/galaxy/web/framework/helpers/grids.py --- a/lib/galaxy/web/framework/helpers/grids.py Fri Feb 12 12:13:37 2010 -0500 +++ b/lib/galaxy/web/framework/helpers/grids.py Fri Feb 12 12:41:21 2010 -0500 @@ -234,7 +234,8 @@ else: new_kwargs[ 'id' ] = trans.security.encode_id( id ) return url_for( **new_kwargs ) - + + use_panels = ( 'use_panels' in kwargs ) and ( kwargs['use_panels'] == True ) async_request = ( ( self.use_async ) and ( 'async' in kwargs ) and ( kwargs['async'] in [ 'True', 'true'] ) ) return trans.fill_template( iff( async_request, self.async_template, self.template), grid=self, @@ -251,6 +252,7 @@ url = url, message_type = status, message = message, + use_panels=use_panels, # Pass back kwargs so that grid template can set and use args without grid explicitly having to pass them. kwargs=kwargs ) diff -r 465daec3fb8f -r 6d217bad7496 templates/grid_base.mako --- a/templates/grid_base.mako Fri Feb 12 12:13:37 2010 -0500 +++ b/templates/grid_base.mako Fri Feb 12 12:41:21 2010 -0500 @@ -10,6 +10,16 @@ %> <%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 +%> +</%def> + ## ## Override methods from base.mako and base_panels.mako ## @@ -666,7 +676,8 @@ </%def> <%def name="stylesheets()"> - ${h.css( "base", "autocomplete_tagging" )} + ${parent.stylesheets()} + ${h.css( "autocomplete_tagging" )} <style> ## Not generic to all grids -- move to base? .count-box {
1
0
0
0
[hg] galaxy 3377: Fix for Display Applications viewing access pr...
by Greg Von Kuster
16 Feb '10
16 Feb '10
details:
http://www.bx.psu.edu/hg/galaxy/rev/465daec3fb8f
changeset: 3377:465daec3fb8f user: Dan Blankenberg <dan(a)bx.psu.edu> date: Fri Feb 12 12:13:37 2010 -0500 description: Fix for Display Applications viewing access protected data. diffstat: lib/galaxy/datatypes/display_applications/parameters.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 0f4e5a057322 -r 465daec3fb8f lib/galaxy/datatypes/display_applications/parameters.py --- a/lib/galaxy/datatypes/display_applications/parameters.py Fri Feb 12 11:19:37 2010 -0500 +++ b/lib/galaxy/datatypes/display_applications/parameters.py Fri Feb 12 12:13:37 2010 -0500 @@ -140,7 +140,7 @@ self.parameter = parameter self.other_values = other_values self.trans = trans - self._dataset_hash, self._user_hash = encode_dataset_user( trans, self.other_values[ DEFAULT_DATASET_NAME ], trans.user ) + self._dataset_hash, self._user_hash = encode_dataset_user( trans, self.other_values[ DEFAULT_DATASET_NAME ], self.other_values[ DEFAULT_DATASET_NAME ].history.user ) def __str__( self ): return str( self.value ) def mime_type( self ):
1
0
0
0
← Newer
1
...
6
7
8
9
10
11
12
...
18
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Results per page:
10
25
50
100
200