galaxy-dev
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
February 2010
- 32 participants
- 180 discussions
15 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
15 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
15 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
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
15 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
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
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
15 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
15 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
15 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