galaxy-commits
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
November 2010
- 1 participants
- 286 discussions
galaxy-dist commit bc690ccf2339: Have rerun action make use of tool.check_and_update_param_values(). Fixes Server Error issue when trying to rerun updated tools.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Daniel Blankenberg <dan(a)bx.psu.edu>
# Date 1288897385 14400
# Node ID bc690ccf23396e1c7e29e8ee801996ac3e3d3409
# Parent 6838e10e5912cec46060bda189841edba305ac1d
Have rerun action make use of tool.check_and_update_param_values(). Fixes Server Error issue when trying to rerun updated tools.
--- a/lib/galaxy/web/controllers/tool_runner.py
+++ b/lib/galaxy/web/controllers/tool_runner.py
@@ -123,6 +123,7 @@ class ToolRunner( BaseController ):
params_objects = job.get_param_values( trans.app )
except:
raise Exception( "Failed to get paramemeters for dataset id %d " % data.id )
+ upgrade_messages = tool.check_and_update_param_values( params_objects, trans )
# Need to remap dataset parameters. Job parameters point to original
# dataset used; parameter should be the analygous dataset in the
# current history.
@@ -152,7 +153,7 @@ class ToolRunner( BaseController ):
state.inputs = params_objects
tool_state_string = util.object_to_string(state.encode(tool, trans.app))
# Setup context for template
- vars = dict( tool_state=state, errors = {} )
+ vars = dict( tool_state=state, errors = upgrade_messages )
# Is the "add frame" stuff neccesary here?
add_frame = AddFrameData()
add_frame.debug = trans.debug
1
0
galaxy-dist commit cdf8d61425cc: Fix typo when running a workflow that contains an updated tool.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Daniel Blankenberg <dan(a)bx.psu.edu>
# Date 1288898016 14400
# Node ID cdf8d61425cce011f98b1f24bd9fe19dc59b10ab
# Parent bc690ccf23396e1c7e29e8ee801996ac3e3d3409
Fix typo when running a workflow that contains an updated tool.
--- a/templates/workflow/run.mako
+++ b/templates/workflow/run.mako
@@ -123,7 +123,7 @@ from galaxy.jobs.actions.post import Act
%if has_upgrade_messages:
<div class="warningmessage">
- Problems were encourered when loading this workflow, likely due to tool
+ Problems were encountered when loading this workflow, likely due to tool
version changes. Missing parameter values have been replaced with default.
Please review the parameter values below.
</div>
1
0
galaxy-dist commit 27c152bb441a: More sample tracking bug fixes - tweaked permissions on displaying buttons, and fixed exceptions thrown when ddata transfer congid file is incorrect.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Greg Von Kuster <greg(a)bx.psu.edu>
# Date 1288730067 14400
# Node ID 27c152bb441a0136720dbbc0c7cb293e581b8f5f
# Parent 6497a8cfd12e477e9c92dd183c4abb81d469ba51
More sample tracking bug fixes - tweaked permissions on displaying buttons, and fixed exceptions thrown when ddata transfer congid file is incorrect.
--- a/lib/galaxy/web/controllers/requests_admin.py
+++ b/lib/galaxy/web/controllers/requests_admin.py
@@ -541,7 +541,7 @@ class RequestsAdmin( BaseController, Use
return sample.request.name + '_' + sample.name + '_' + name
if opt == options.EXPERIMENT_NAME:
return sample.request.name + '_' + name
- def __setup_datatx_user( self, trans, library, folder ):
+ def __setup_datatx_user( self, trans, sample ):
"""
Sets up the datatx user:
- Checks if the user exists, if not creates them.
@@ -550,9 +550,25 @@ class RequestsAdmin( BaseController, Use
"""
# 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" )
+ ok = True
+ try:
+ config.read( 'transfer_datasets.ini' )
+ except Exception, e:
+ message = "Error attempting to read config file named 'transfer_datasets.ini'. Make sure this file is correct."
+ ok = False
+ try:
+ email = config.get( "data_transfer_user_login_info", "email" )
+ password = config.get( "data_transfer_user_login_info", "password" )
+ except Exception, e:
+ message = "The 'data_transfer_user_login_info' section is missing from the 'transfer_datasets.ini'. Make sure this file is correct."
+ ok = False
+ if not ok:
+ status = 'error'
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='manage_datasets',
+ sample_id=trans.security.encode_id( sample.id ),
+ status=status,
+ message=message ) )
# check if the user already exists
datatx_user = trans.sa_session.query( trans.model.User ) \
.filter( trans.model.User.table.c.email==email ) \
@@ -570,14 +586,14 @@ class RequestsAdmin( BaseController, Use
datatx_user_private_role = trans.app.security_agent.get_private_user_role( datatx_user )
# Make sure this user has LIBRARY_ADD permissions on the target library and folder.
# If not, give them permission.
- if not trans.app.security_agent.can_add_library_item( datatx_user_roles, library ):
+ if not trans.app.security_agent.can_add_library_item( datatx_user_roles, sample.library ):
lp = trans.model.LibraryPermissions( trans.app.security_agent.permitted_actions.LIBRARY_ADD.action,
- library,
+ sample.library,
datatx_user_private_role )
trans.sa_session.add( lp )
- if not trans.app.security_agent.can_add_library_item( datatx_user_roles, folder ):
+ if not trans.app.security_agent.can_add_library_item( datatx_user_roles, sample.folder ):
lfp = trans.model.LibraryFolderPermissions( trans.app.security_agent.permitted_actions.LIBRARY_ADD.action,
- folder,
+ sample.folder,
datatx_user_private_role )
trans.sa_session.add( lfp )
trans.sa_session.flush()
@@ -646,7 +662,7 @@ class RequestsAdmin( BaseController, Use
message=message) )
def __start_datatx( self, trans, sample, selected_sample_datasets ):
- datatx_user = self.__setup_datatx_user( trans, sample.library, sample.folder )
+ datatx_user = self.__setup_datatx_user( trans, sample )
# Validate sequencer information
datatx_info = sample.request.type.datatx_info
if not datatx_info['host'] or not datatx_info['username'] or not datatx_info['password']:
@@ -660,7 +676,7 @@ class RequestsAdmin( BaseController, Use
action='manage_datasets',
sample_id=trans.security.encode_id( sample.id ),
status=status,
- message=message) )
+ message=message ) )
@web.expose
def update_sample_dataset_status(self, trans, cntrller, sample_dataset_ids, new_status, error_msg=None ):
# check if the new status is a valid transfer status
--- a/templates/requests/common/common.mako
+++ b/templates/requests/common/common.mako
@@ -120,20 +120,25 @@
if sample:
trans.sa_session.refresh( sample.request )
is_complete = sample.request.is_complete
+ is_rejected = request.is_rejected
is_submitted = sample.request.is_submitted
is_unsubmitted = sample.request.is_unsubmitted
+ display_checkboxes = editing_samples and ( is_complete or is_rejected or is_submitted )
+ display_bar_code = request.samples and ( is_complete or is_rejected or is_submitted )
+ display_datasets = request.samples and ( is_complete or is_rejected or is_submitted )
else:
is_complete = False
is_submitted = False
is_unsubmitted = False
+ display_checkboxes = False
%><%
- if is_submitted and editing_samples and trans.security.encode_id( sample.id ) in encoded_selected_sample_ids:
+ if display_checkboxes and trans.security.encode_id( sample.id ) in encoded_selected_sample_ids:
checked_str = "checked"
else:
checked_str = ""
%>
- %if is_submitted and editing_samples:
+ %if display_checkboxes:
<td><input type="checkbox" name=select_sample_${sample.id} id="sample_checkbox" value="true" ${checked_str}/><input type="hidden" name=select_sample_${sample.id} id="sample_checkbox" value="true"/></td>
%endif
<td valign="top">
@@ -142,12 +147,14 @@
<i>${' (required)' }</i></div></td>
- %if sample and is_submitted or is_complete:
- %if is_admin:
- <td valign="top"><input type="text" name="sample_${current_sample_index}_barcode" value="${current_sample['barcode']}" size="10"/></td>
- %else:
- ${current_sample['barcode']}
- %endif
+ %if display_bar_code:
+ <td valign="top">
+ %if is_admin:
+ <input type="text" name="sample_${current_sample_index}_barcode" value="${current_sample['barcode']}" size="10"/>
+ %else:
+ ${current_sample['barcode']}
+ %endif
+ </td>
%endif
%if sample:
%if is_unsubmitted:
@@ -160,7 +167,7 @@
%endif
<td valign="top">${current_sample['library_select_field'].get_html()}</td><td valign="top">${current_sample['folder_select_field'].get_html()}</td>
- %if is_submitted or is_complete:
+ %if display_datasets:
<%
if sample:
label = str( len( sample.datasets ) )
@@ -182,11 +189,15 @@
trans.sa_session.refresh( request )
is_admin = cntrller == 'requests_admin' and trans.user_is_admin()
is_complete = request.is_complete
+ is_rejected = request.is_rejected
is_submitted = request.is_submitted
is_unsubmitted = request.is_unsubmitted
can_add_samples = request.is_unsubmitted
can_delete_samples = request.samples and not is_complete
can_edit_samples = request.samples and ( is_admin or not is_complete )
+ display_checkboxes = editing_samples and ( is_complete or is_rejected or is_submitted )
+ display_bar_code = request.samples and ( is_complete or is_rejected or is_submitted )
+ display_datasets = request.samples and ( is_complete or is_rejected or is_submitted )
%>
${grid_header}
%if render_buttons and ( can_add_samples or can_edit_samples ):
@@ -202,22 +213,22 @@
<table class="grid"><thead><tr>
- %if is_submitted and editing_samples:
+ %if display_checkboxes:
<th><input type="checkbox" id="checkAll" name=select_all_samples_checkbox value="true" onclick='checkAllFields(1);'/><input type="hidden" name=select_all_samples_checkbox value="true"/></th>
%endif
<th>Name</th>
- %if is_submitted or is_complete:
+ %if display_bar_code:
<th>Barcode</th>
%endif
<th>State</th><th>Data Library</th><th>Folder</th>
- %if is_submitted or is_complete:
+ %if display_datasets:
<th>Datasets Selected</th><th>Datasets Transferred</th>
%endif
<th>
- %if editing_samples:
+ %if can_delete_samples:
Delete
%endif
</th>
@@ -245,7 +256,7 @@
except:
sample = None
%>
- %if not is_complete and editing_samples:
+ %if editing_samples:
<tr>${render_editable_sample_row( is_admin, sample, current_sample_index, current_sample, encoded_selected_sample_ids )}</tr>
%elif sample:
<tr>
1
0
galaxy-dist commit 6497a8cfd12e: More miscellaneous bug fixes in Sample Tracking, all due to the recent UI changes. Changes the name of the test_forms_and_requests.py functional test script to be test_sample_tracking.py to more clearly reeflect what's being tested.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Greg Von Kuster <greg(a)bx.psu.edu>
# Date 1288723785 14400
# Node ID 6497a8cfd12e477e9c92dd183c4abb81d469ba51
# Parent b7ac22fab1588a565a07acc4972564c2b9198489
More miscellaneous bug fixes in Sample Tracking, all due to the recent UI changes. Changes the name of the test_forms_and_requests.py functional test script to be test_sample_tracking.py to more clearly reeflect what's being tested.
--- a/templates/requests/common/edit_samples.mako
+++ b/templates/requests/common/edit_samples.mako
@@ -12,58 +12,6 @@
<%def name="javascripts()">
${parent.javascripts()}
${common_javascripts()}
- ${local_javascripts()}
-</%def>
-
-<%def name="local_javascripts()">
- <script type="text/javascript">
- // Looks for changes in sample states using an async request. Keeps
- // calling itself (via setTimeout) until all samples are in a terminal
- // state.
- var updater = function ( sample_states ) {
- // Check if there are any items left to track
- var empty = true;
- for ( i in sample_states ) {
- empty = false;
- break;
- }
- if ( ! empty ) {
- setTimeout( function() { updater_callback( sample_states ) }, 1000 );
- }
- };
-
- var updater_callback = function ( sample_states ) {
- // Build request data
- var ids = []
- var states = []
- $.each( sample_states, function ( id, state ) {
- ids.push( id );
- states.push( state );
- });
- // Make ajax call
- $.ajax( {
- type: "POST",
- url: "${h.url_for( controller='requests_common', action='sample_state_updates' )}",
- dataType: "json",
- data: { ids: ids.join( "," ), states: states.join( "," ) },
- success : function ( data ) {
- $.each( data, function( id, val ) {
- // Replace HTML
- var cell1 = $("#sampleState-" + id);
- cell1.html( val.html_state );
- var cell2 = $("#sampleDatasets-" + id);
- cell2.html( val.html_datasets );
- sample_states[ parseInt( id ) ] = val.state;
- });
- updater( sample_states );
- },
- error: function() {
- // Just retry, like the old method, should try to be smarter
- updater( sample_states );
- }
- });
- };
- </script></%def><%
@@ -73,7 +21,8 @@
is_complete = request.is_complete
is_unsubmitted = request.is_unsubmitted
can_add_samples = is_unsubmitted
- can_edit_or_delete_samples = request.samples and not is_complete
+ can_delete_samples = request.samples and not is_complete
+ can_edit_samples = request.samples and ( is_admin or not is_complete )
can_edit_request = ( is_admin and not request.is_complete ) or request.is_unsubmitted
can_reject_or_transfer = is_admin and request.is_submitted
can_submit = request.samples and is_unsubmitted
@@ -82,7 +31,7 @@
<br/><br/><ul class="manage-table-actions">
- %if not editing_samples and can_edit_or_delete_samples:
+ %if not editing_samples and can_edit_samples:
<li><a class="action-button" href="${h.url_for( controller='requests_common', action='edit_samples', cntrller=cntrller, id=trans.security.encode_id( request.id ), editing_samples='True' )}">Edit samples</a></li>
%endif
%if editing_samples and can_add_samples:
@@ -131,13 +80,13 @@
grid_header = '<h3>Add Samples to Request "%s"</h3>' % request.name
%>
${render_samples_grid( cntrller, request, current_samples, action='edit_samples', editing_samples=editing_samples, encoded_selected_sample_ids=encoded_selected_sample_ids, render_buttons=False, grid_header=grid_header )}
- %if editing_samples and len( sample_operation_select_field.options ) > 1 and not ( is_unsubmitted or is_complete ):
+ %if editing_samples and len( sample_operation_select_field.options ) > 1 and not is_unsubmitted:
<div class="form-row" style="background-color:#FAFAFA;">
For selected samples:
${sample_operation_select_field.get_html()}
</div><% sample_operation_selected_value = sample_operation_select_field.get_selected( return_value=True ) %>
- %if sample_operation_selected_value != 'none' and encoded_selected_sample_ids:
+ %if ( is_admin or not is_complete ) and sample_operation_selected_value != 'none' and encoded_selected_sample_ids:
<div class="form-row" style="background-color:#FAFAFA;">
%if sample_operation_selected_value == trans.model.Sample.bulk_operations.CHANGE_STATE:
## sample_operation_selected_value == 'Change state'
@@ -150,7 +99,7 @@
Optional
</div></div>
- %elif sample_operation_selected_value == trans.app.model.Sample.bulk_operations.SELECT_LIBRARY:
+ %elif not is_complete and sample_operation_selected_value == trans.app.model.Sample.bulk_operations.SELECT_LIBRARY:
<% libraries_selected_value = libraries_select_field.get_selected( return_value=True ) %><div class="form-row"><label>Select data library:</label>
@@ -210,12 +159,12 @@
Click the <b>Save</b> button when you have finished editing the samples
</div>
%endif
- ##%if request.samples and request.is_submitted:
- ## <script type="text/javascript">
- ## // Updater
- ## updater( {${ ",".join( [ '"%s" : "%s"' % ( s.id, s.state.name ) for s in request.samples ] ) }});
- ## </script>
- ##%endif
+ %if request.samples and request.is_submitted:
+ <script type="text/javascript">
+ // Updater
+ updater( {${ ",".join( [ '"%s" : "%s"' % ( s.id, s.state.name ) for s in request.samples ] ) }});
+ </script>
+ %endif
</form></div>
%if is_unsubmitted and not editing_samples:
--- a/test/functional/test_forms_and_requests.py
+++ /dev/null
@@ -1,436 +0,0 @@
-import galaxy.model
-from galaxy.model.orm import *
-from base.twilltestcase import *
-from base.test_db_util import *
-
-sample_states = [ ( 'New', 'Sample entered into the system' ),
- ( 'Received', 'Sample tube received' ),
- ( 'Done', 'Sequence run complete' ) ]
-address_dict = dict( short_desc="Office",
- name="James Bond",
- institution="MI6" ,
- address="MI6 Headquarters",
- city="London",
- state="London",
- postal_code="007",
- country="United Kingdom",
- phone="007-007-0007" )
-
-class TestFormsAndRequests( TwillTestCase ):
- def test_000_initiate_users( self ):
- """Ensuring all required user accounts exist"""
- self.logout()
- self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
- global regular_user1
- regular_user1 = get_user( 'test1(a)bx.psu.edu' )
- assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
- global regular_user1_private_role
- regular_user1_private_role = get_private_role( regular_user1 )
- self.logout()
- self.login( email='test2(a)bx.psu.edu', username='regular-user2' )
- global regular_user2
- regular_user2 = get_user( 'test2(a)bx.psu.edu' )
- assert regular_user2 is not None, 'Problem retrieving user with email "test2(a)bx.psu.edu" from the database'
- global regular_user2_private_role
- regular_user2_private_role = get_private_role( regular_user2 )
- self.logout()
- self.login( email='test3(a)bx.psu.edu', username='regular-user3' )
- global regular_user3
- regular_user3 = get_user( 'test3(a)bx.psu.edu' )
- assert regular_user3 is not None, 'Problem retrieving user with email "test3(a)bx.psu.edu" from the database'
- global regular_user3_private_role
- regular_user3_private_role = get_private_role( regular_user3 )
- self.logout()
- self.login( email='test(a)bx.psu.edu', username='admin-user' )
- global admin_user
- admin_user = get_user( 'test(a)bx.psu.edu' )
- assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
- global admin_user_private_role
- admin_user_private_role = get_private_role( admin_user )
- def test_005_create_required_groups_and_roles( self ):
- """Testing creating all required groups and roles for this script"""
- # Logged in as admin_user
- # Create role_one
- name = 'Role One'
- description = "This is Role One's description"
- user_ids = [ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ]
- self.create_role( name=name,
- description=description,
- in_user_ids=user_ids,
- in_group_ids=[],
- create_group_for_role='no',
- private_role=admin_user.email )
- # Get the role object for later tests
- global role_one
- role_one = get_role_by_name( name )
- # Create group_one
- name = 'Group One'
- self.create_group( name=name, in_user_ids=[ str( regular_user1.id ) ], in_role_ids=[ str( role_one.id ) ] )
- # Get the group object for later tests
- global group_one
- group_one = get_group_by_name( name )
- assert group_one is not None, 'Problem retrieving group named "Group One" from the database'
- # NOTE: To get this to work with twill, all select lists on the ~/admin/role page must contain at least
- # 1 option value or twill throws an exception, which is: ParseError: OPTION outside of SELECT
- # Due to this bug in twill, we create the role, we bypass the page and visit the URL in the
- # associate_users_and_groups_with_role() method.
- #
- #create role_two
- name = 'Role Two'
- description = 'This is Role Two'
- user_ids = [ str( admin_user.id ) ]
- group_ids = [ str( group_one.id ) ]
- private_role = admin_user.email
- self.create_role( name=name,
- description=description,
- in_user_ids=user_ids,
- in_group_ids=group_ids,
- private_role=private_role )
- # Get the role object for later tests
- global role_two
- role_two = get_role_by_name( name )
- assert role_two is not None, 'Problem retrieving role named "Role Two" from the database'
- def test_010_create_request_form( self ):
- """Testing creating a request form definition, editing the name and description and adding fields"""
- # Logged in as admin_user
- # Create a form definition
- tmp_name = "Temp form"
- tmp_desc = "Temp form description"
- form_type = galaxy.model.FormDefinition.types.REQUEST
- self.create_form( name=tmp_name,
- desc=tmp_desc,
- form_type=form_type,
- num_fields=0,
- strings_displayed=[ 'Create a new form definition' ],
- strings_displayed_after_submit=[ tmp_name, tmp_desc, form_type ] )
- tmp_form = get_form( tmp_name )
- # Edit the name and description of the form definition, and add 3 fields.
- new_name = "Request Form"
- new_desc = "Request Form description"
- global test_field_name1
- test_field_name1 = 'Test field name one'
- global test_field_name2
- test_field_name2 = 'Test field name two'
- global test_field_name3
- test_field_name3 = 'Test field name three'
- field_dicts = [ dict( name=test_field_name1,
- desc='Test field description one',
- type='SelectField',
- required='optional',
- selectlist=[ 'option1', 'option2' ] ),
- dict( name=test_field_name2,
- desc='Test field description two',
- type='AddressField',
- required='optional' ),
- dict( name=test_field_name3,
- desc='Test field description three',
- type='TextField',
- required='required' ) ]
- self.edit_form( id=self.security.encode_id( tmp_form.current.id ),
- new_form_name=new_name,
- new_form_desc=new_desc,
- field_dicts=field_dicts,
- field_index=len( tmp_form.fields ),
- strings_displayed=[ 'Edit form definition "%s"' % tmp_name ],
- strings_displayed_after_submit=[ "The form '%s' has been updated with the changes." % new_name ] )
- # Get the form_definition object for later tests
- global form_one
- form_one = get_form( new_name )
- assert form_one is not None, 'Problem retrieving form named "%s" from the database' % new_name
- assert len( form_one.fields ) == len( tmp_form.fields ) + len( field_dicts )
- def test_015_create_sample_form( self ):
- """Testing creating sample form definition"""
- name = "Sample Form"
- desc = "This is Form Two's description"
- form_type = galaxy.model.FormDefinition.types.SAMPLE
- form_layout_name = 'Layout Grid One'
- self.create_form( name=name,
- desc=desc,
- form_type=form_type,
- form_layout_name=form_layout_name,
- strings_displayed=[ 'Create a new form definition' ],
- strings_displayed_after_submit=[ "The form '%s' has been updated with the changes." % name ] )
- global form_two
- form_two = get_form( name )
- assert form_two is not None, "Error retrieving form %s from db" % name
- def test_020_create_request_type( self ):
- """Testing creating a request_type"""
- request_form = get_form( form_one.name )
- sample_form = get_form( form_two.name )
- name = 'Test Requestype'
- self.create_request_type( name,
- "test sequencer configuration",
- self.security.encode_id( request_form.id ),
- self.security.encode_id( sample_form.id ),
- sample_states,
- strings_displayed=[ 'Create a new sequencer configuration' ],
- strings_displayed_after_submit=[ "Sequencer configuration (%s) has been created" % name ] )
- global request_type1
- request_type1 = get_request_type_by_name( name )
- assert request_type1 is not None, 'Problem retrieving sequencer configuration named "%s" from the database' % name
- # Set permissions
- permissions_in = [ k for k, v in galaxy.model.RequestType.permitted_actions.items() ]
- permissions_out = []
- # Role one members are: admin_user, regular_user1, regular_user3. Each of these users will be permitted for
- # REQUEST_TYPE_ACCESS on this request_type
- self.request_type_permissions( self.security.encode_id( request_type1.id ),
- request_type1.name,
- str( role_one.id ),
- permissions_in,
- permissions_out )
- # Make sure the request_type1 is not accessible by regular_user2 since regular_user2 does not have Role1.
- self.logout()
- self.login( email=regular_user2.email )
- self.visit_url( '%s/requests_common/create_request?cntrller=requests&request_type=True' % self.url )
- try:
- self.check_page_for_string( 'There are no sequencer configurations created for a new request.' )
- raise AssertionError, 'The request_type %s is accessible by %s when it should be restricted' % ( request_type1.name, regular_user2.email )
- except:
- pass
- self.logout()
- self.login( email=admin_user.email )
- def test_025_create_request( self ):
- """Testing creating a sequence run request"""
- # logged in as admin_user
- # Create a user_address
- self.logout()
- self.login( email=regular_user1.email )
- self.add_user_address( regular_user1.id, address_dict )
- global user_address1
- user_address1 = get_user_address( regular_user1, address_dict[ 'short_desc' ] )
- # Set field values - the tuples in the field_values list include the field_value, and True if refresh_on_change
- # is required for that field.
- field_value_tuples = [ ( 'option1', False ), ( str( user_address1.id ), True ), ( 'field three value', False ) ]
- # Create the request
- name = 'Request One'
- desc = 'Request One Description'
- self.create_request( cntrller='requests',
- request_type_id=self.security.encode_id( request_type1.id ),
- name=name,
- desc=desc,
- field_value_tuples=field_value_tuples,
- strings_displayed=[ 'Create a new sequencing request',
- test_field_name1,
- test_field_name2,
- test_field_name3 ],
- strings_displayed_after_submit=[ name, desc ] )
- global request_one
- request_one = get_request_by_name( name )
- # Make sure the request's state is now set to NEW
- assert request_one.state is not request_one.states.NEW, "The state of the request '%s' should be set to '%s'" \
- % ( request_one.name, request_one.states.NEW )
- # Sample fields - the tuple represents a sample name and a list of sample form field values
- sample_value_tuples = [ ( 'Sample One', [ 'S1 Field 0 Value' ] ),
- ( 'Sample Two', [ 'S2 Field 0 Value' ] ) ]
- strings_displayed_after_submit = [ 'Unsubmitted' ]
- for sample_name, field_values in sample_value_tuples:
- strings_displayed_after_submit.append( sample_name )
- # Add samples to the request
- self.add_samples( cntrller='requests',
- request_id=self.security.encode_id( request_one.id ),
- request_name=request_one.name,
- sample_value_tuples=sample_value_tuples,
- strings_displayed=[ 'There are no samples.' ],
- strings_displayed_after_submit=strings_displayed_after_submit )
- def test_030_edit_basic_request_info( self ):
- """Testing editing the basic information of a sequence run request"""
- # logged in as regular_user1
- fields = [ 'option2', str( user_address1.id ), 'field three value (edited)' ]
- new_name=request_one.name + ' (Renamed)'
- new_desc=request_one.desc + ' (Re-described)'
- self.edit_basic_request_info( request_id=self.security.encode_id( request_one.id ),
- cntrller='requests',
- name=request_one.name,
- new_name=new_name,
- new_desc=new_desc,
- new_fields=fields,
- strings_displayed=[ 'Edit sequencing request "%s"' % request_one.name ],
- strings_displayed_after_submit=[ new_name, new_desc ] )
- refresh( request_one )
- # check if the request is showing in the 'new' filter
- self.check_request_grid( cntrller='requests',
- state=request_one.states.NEW,
- strings_displayed=[ request_one.name ] )
- def test_035_submit_request( self ):
- """Testing editing a sequence run request"""
- # logged in as regular_user1
- self.submit_request( cntrller='requests',
- request_id=self.security.encode_id( request_one.id ),
- request_name=request_one.name,
- strings_displayed_after_submit=[ 'The request has been submitted.' ] )
- refresh( request_one )
- # Make sure the request is showing in the 'submitted' filter
- self.check_request_grid( cntrller='requests',
- state=request_one.states.SUBMITTED,
- strings_displayed=[ request_one.name ] )
- # Make sure the request's state is now set to 'submitted'
- assert request_one.state is not request_one.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" \
- % ( request_one.name, request_one.states.SUBMITTED )
- def test_040_request_lifecycle( self ):
- """Testing request life-cycle as it goes through all the states"""
- # logged in as regular_user1
- self.logout()
- self.login( email=admin_user.email )
- self.check_request_grid( cntrller='requests_admin',
- state=request_one.states.SUBMITTED,
- strings_displayed=[ request_one.name ] )
- self.visit_url( "%s/requests_common/view_request?cntrller=requests&id=%s" % ( self.url, self.security.encode_id( request_one.id ) ) )
- # TODO: add some string for checking on the page above...
- # Set bar codes for the samples
- bar_codes = [ '1234567890', '0987654321' ]
- strings_displayed_after_submit=[ 'Changes made to the samples have been saved.' ]
- for bar_code in bar_codes:
- strings_displayed_after_submit.append( bar_code )
- self.add_bar_codes( request_id=self.security.encode_id( request_one.id ),
- request_name=request_one.name,
- bar_codes=bar_codes,
- samples=request_one.samples,
- strings_displayed_after_submit=strings_displayed_after_submit )
- # Change the states of all the samples of this request to ultimately be COMPLETE
- self.change_sample_state( request_id=self.security.encode_id( request_one.id ),
- request_name=request_one.name,
- sample_names=[ sample.name for sample in request_one.samples ],
- sample_ids=[ sample.id for sample in request_one.samples ],
- new_sample_state_id=request_type1.states[1].id,
- new_state_name=request_type1.states[1].name )
- self.change_sample_state( request_id=self.security.encode_id( request_one.id ),
- request_name=request_one.name,
- sample_names=[ sample.name for sample in request_one.samples ],
- sample_ids=[ sample.id for sample in request_one.samples ],
- new_sample_state_id=request_type1.states[2].id,
- new_state_name=request_type1.states[2].name )
- refresh( request_one )
- self.logout()
- self.login( email=regular_user1.email )
- # check if the request's state is now set to 'complete'
- self.check_request_grid( cntrller='requests',
- state='Complete',
- strings_displayed=[ request_one.name ] )
- assert request_one.state is not request_one.states.COMPLETE, "The state of the request '%s' should be set to '%s'" \
- % ( request_one.name, request_one.states.COMPLETE )
-
- def test_045_admin_create_request_on_behalf_of_regular_user( self ):
- """Testing creating and submitting a request as an admin on behalf of a regular user"""
- # Logged in as regular_user1
- self.logout()
- self.login( email=admin_user.email )
- # Create the request
- name = "RequestTwo"
- desc = 'Request Two Description'
- # Set field values - the tuples in the field_values list include the field_value, and True if refresh_on_change
- # is required for that field.
- field_value_tuples = [ ( 'option2', False ), ( str( user_address1.id ), True ), ( 'field_2_value', False ) ]
- self.create_request( cntrller='requests_admin',
- request_type_id=self.security.encode_id( request_type1.id ),
- other_users_id=self.security.encode_id( regular_user1.id ),
- name=name,
- desc=desc,
- field_value_tuples=field_value_tuples,
- strings_displayed=[ 'Create a new sequencing request',
- test_field_name1,
- test_field_name2,
- test_field_name3 ],
- strings_displayed_after_submit=[ "The request has been created." ] )
- global request_two
- request_two = get_request_by_name( name )
- # Make sure the request is showing in the 'new' filter
- self.check_request_grid( cntrller='requests_admin',
- state=request_two.states.NEW,
- strings_displayed=[ request_two.name ] )
- # Make sure the request's state is now set to 'new'
- assert request_two.state is not request_two.states.NEW, "The state of the request '%s' should be set to '%s'" \
- % ( request_two.name, request_two.states.NEW )
- # Sample fields - the tuple represents a sample name and a list of sample form field values
- sample_value_tuples = [ ( 'Sample One', [ 'S1 Field 0 Value' ] ),
- ( 'Sample Two', [ 'S2 Field 0 Value' ] ) ]
- strings_displayed_after_submit = [ 'Unsubmitted' ]
- for sample_name, field_values in sample_value_tuples:
- strings_displayed_after_submit.append( sample_name )
- # Add samples to the request
- self.add_samples( cntrller='requests_admin',
- request_id=self.security.encode_id( request_two.id ),
- request_name=request_two.name,
- sample_value_tuples=sample_value_tuples,
- strings_displayed=[ 'There are no samples.' ],
- strings_displayed_after_submit=strings_displayed_after_submit )
- # Submit the request
- self.submit_request( cntrller='requests_admin',
- request_id=self.security.encode_id( request_two.id ),
- request_name=request_two.name,
- strings_displayed_after_submit=[ 'The request has been submitted.' ] )
- refresh( request_two )
- # Make sure the request is showing in the 'submitted' filter
- self.check_request_grid( cntrller='requests_admin',
- state=request_two.states.SUBMITTED,
- strings_displayed=[ request_two.name ] )
- # Make sure the request's state is now set to 'submitted'
- assert request_two.state is not request_two.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" \
- % ( request_two.name, request_two.states.SUBMITTED )
- # Make sure both requests are showing in the 'All' filter
- self.check_request_grid( cntrller='requests_admin',
- state='All',
- strings_displayed=[ request_one.name, request_two.name ] )
- def test_050_reject_request( self ):
- """Testing rejecting a request"""
- # Logged in as admin_user
- self.reject_request( request_id=self.security.encode_id( request_two.id ),
- request_name=request_two.name,
- comment="Rejection test comment",
- strings_displayed=[ 'Reject Sequencing Request "%s"' % request_two.name ],
- strings_displayed_after_submit=[ 'Request (%s) has been rejected.' % request_two.name ] )
- refresh( request_two )
- # Make sure the request is showing in the 'rejected' filter
- self.check_request_grid( cntrller='requests_admin',
- state=request_two.states.REJECTED,
- strings_displayed=[ request_two.name ] )
- # Make sure the request's state is now set to REJECTED
- assert request_two.state is not request_two.states.REJECTED, "The state of the request '%s' should be set to '%s'" \
- % ( request_two.name, request_two.states.REJECTED )
- def test_055_reset_data_for_later_test_runs( self ):
- """Reseting data to enable later test runs to pass"""
- """
- # Logged in as admin_user
- ##################
- # Delete request_type permissions
- ##################
- for request_type in [ request_type1 ]:
- delete_request_type_permissions( request_type.id )
- ##################
- # Mark all request_types deleted
- ##################
- for request_type in [ request_type1 ]:
- mark_obj_deleted( request_type )
- ##################
- # Mark all requests deleted
- ##################
- for request in [ request_one, request_two ]:
- mark_obj_deleted( request )
- ##################
- # Mark all forms deleted
- ##################
- for form in [ form_one, form_two ]:
- self.mark_form_deleted( self.security.encode_id( form.current.id ) )
- ##################
- # Mark all user_addresses deleted
- ##################
- for user_address in [ user_address1 ]:
- mark_obj_deleted( user_address )
- ##################
- # Delete all non-private roles
- ##################
- for role in [ role_one, role_two ]:
- self.mark_role_deleted( self.security.encode_id( role.id ), role.name )
- self.purge_role( self.security.encode_id( role.id ), role.name )
- # Manually delete the role from the database
- refresh( role )
- delete( role )
- ##################
- # Delete all groups
- ##################
- for group in [ group_one ]:
- self.mark_group_deleted( self.security.encode_id( group.id ), group.name )
- self.purge_group( self.security.encode_id( group.id ), group.name )
- # Manually delete the group from the database
- refresh( group )
- delete( group )
- """
--- a/lib/galaxy/web/controllers/requests_common.py
+++ b/lib/galaxy/web/controllers/requests_common.py
@@ -1047,10 +1047,15 @@ class RequestsCommon( BaseController, Us
action='update_request_state',
request_id=trans.security.encode_id( request.id ) ) )
elif sample_operation == 'Select data library and folder':
+ # TODO: fix the code so that the sample_operation_select_field does not use
+ # sample_0_library_id as it's name. it should use something like sample_operation_library_id
+ # and sample_operation-folder_id because the name sample_0_library_id should belong to the
+ # first sample since all other form field values are named like this. The library and folder
+ # are skewed to be named +1 resulting in the forced use of id_index everywhere...
library_id = params.get( 'sample_0_library_id', 'none' )
folder_id = params.get( 'sample_0_folder_id', 'none' )
library, folder = self.__get_library_and_folder( trans, library_id, folder_id )
- self.__update_samples( trans, request, samples, **kwd )
+ self.__update_samples( trans, cntrller, request, samples, **kwd )
# Samples will not have an associated SampleState until the request is submitted, at which
# time all samples of the request will be set to the first SampleState configured for the
# request's RequestType defined by the admin.
@@ -1092,7 +1097,7 @@ class RequestsCommon( BaseController, Us
editing_samples=editing_samples,
status=status,
message=message ) )
- def __update_samples( self, trans, request, sample_widgets, **kwd ):
+ def __update_samples( self, trans, cntrller, request, sample_widgets, **kwd ):
# Determine if the values in kwd require updating the request's samples. The list of
# sample_widgets must have the same number of objects as request.samples, but some of
# the objects can be None. Those that are not None correspond to samples selected by
--- /dev/null
+++ b/test/functional/test_sample_tracking.py
@@ -0,0 +1,434 @@
+import galaxy.model
+from galaxy.model.orm import *
+from base.twilltestcase import *
+from base.test_db_util import *
+
+sample_states = [ ( 'New', 'Sample entered into the system' ),
+ ( 'Received', 'Sample tube received' ),
+ ( 'Done', 'Sequence run complete' ) ]
+address_dict = dict( short_desc="Office",
+ name="James Bond",
+ institution="MI6" ,
+ address="MI6 Headquarters",
+ city="London",
+ state="London",
+ postal_code="007",
+ country="United Kingdom",
+ phone="007-007-0007" )
+
+class TestFormsAndRequests( TwillTestCase ):
+ def test_000_initiate_users( self ):
+ """Ensuring all required user accounts exist"""
+ self.logout()
+ self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
+ global regular_user1
+ regular_user1 = get_user( 'test1(a)bx.psu.edu' )
+ assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
+ global regular_user1_private_role
+ regular_user1_private_role = get_private_role( regular_user1 )
+ self.logout()
+ self.login( email='test2(a)bx.psu.edu', username='regular-user2' )
+ global regular_user2
+ regular_user2 = get_user( 'test2(a)bx.psu.edu' )
+ assert regular_user2 is not None, 'Problem retrieving user with email "test2(a)bx.psu.edu" from the database'
+ global regular_user2_private_role
+ regular_user2_private_role = get_private_role( regular_user2 )
+ self.logout()
+ self.login( email='test3(a)bx.psu.edu', username='regular-user3' )
+ global regular_user3
+ regular_user3 = get_user( 'test3(a)bx.psu.edu' )
+ assert regular_user3 is not None, 'Problem retrieving user with email "test3(a)bx.psu.edu" from the database'
+ global regular_user3_private_role
+ regular_user3_private_role = get_private_role( regular_user3 )
+ self.logout()
+ self.login( email='test(a)bx.psu.edu', username='admin-user' )
+ global admin_user
+ admin_user = get_user( 'test(a)bx.psu.edu' )
+ assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
+ global admin_user_private_role
+ admin_user_private_role = get_private_role( admin_user )
+ def test_005_create_required_groups_and_roles( self ):
+ """Testing creating all required groups and roles for this script"""
+ # Logged in as admin_user
+ # Create role_one
+ name = 'Role One'
+ description = "This is Role One's description"
+ user_ids = [ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ]
+ self.create_role( name=name,
+ description=description,
+ in_user_ids=user_ids,
+ in_group_ids=[],
+ create_group_for_role='no',
+ private_role=admin_user.email )
+ # Get the role object for later tests
+ global role_one
+ role_one = get_role_by_name( name )
+ # Create group_one
+ name = 'Group One'
+ self.create_group( name=name, in_user_ids=[ str( regular_user1.id ) ], in_role_ids=[ str( role_one.id ) ] )
+ # Get the group object for later tests
+ global group_one
+ group_one = get_group_by_name( name )
+ assert group_one is not None, 'Problem retrieving group named "Group One" from the database'
+ # NOTE: To get this to work with twill, all select lists on the ~/admin/role page must contain at least
+ # 1 option value or twill throws an exception, which is: ParseError: OPTION outside of SELECT
+ # Due to this bug in twill, we create the role, we bypass the page and visit the URL in the
+ # associate_users_and_groups_with_role() method.
+ #
+ #create role_two
+ name = 'Role Two'
+ description = 'This is Role Two'
+ user_ids = [ str( admin_user.id ) ]
+ group_ids = [ str( group_one.id ) ]
+ private_role = admin_user.email
+ self.create_role( name=name,
+ description=description,
+ in_user_ids=user_ids,
+ in_group_ids=group_ids,
+ private_role=private_role )
+ # Get the role object for later tests
+ global role_two
+ role_two = get_role_by_name( name )
+ assert role_two is not None, 'Problem retrieving role named "Role Two" from the database'
+ def test_010_create_request_form( self ):
+ """Testing creating a request form definition, editing the name and description and adding fields"""
+ # Logged in as admin_user
+ # Create a form definition
+ tmp_name = "Temp form"
+ tmp_desc = "Temp form description"
+ form_type = galaxy.model.FormDefinition.types.REQUEST
+ self.create_form( name=tmp_name,
+ desc=tmp_desc,
+ form_type=form_type,
+ num_fields=0,
+ strings_displayed=[ 'Create a new form definition' ],
+ strings_displayed_after_submit=[ tmp_name, tmp_desc, form_type ] )
+ tmp_form = get_form( tmp_name )
+ # Edit the name and description of the form definition, and add 3 fields.
+ new_name = "Request Form"
+ new_desc = "Request Form description"
+ global test_field_name1
+ test_field_name1 = 'Test field name one'
+ global test_field_name2
+ test_field_name2 = 'Test field name two'
+ global test_field_name3
+ test_field_name3 = 'Test field name three'
+ field_dicts = [ dict( name=test_field_name1,
+ desc='Test field description one',
+ type='SelectField',
+ required='optional',
+ selectlist=[ 'option1', 'option2' ] ),
+ dict( name=test_field_name2,
+ desc='Test field description two',
+ type='AddressField',
+ required='optional' ),
+ dict( name=test_field_name3,
+ desc='Test field description three',
+ type='TextField',
+ required='required' ) ]
+ self.edit_form( id=self.security.encode_id( tmp_form.current.id ),
+ new_form_name=new_name,
+ new_form_desc=new_desc,
+ field_dicts=field_dicts,
+ field_index=len( tmp_form.fields ),
+ strings_displayed=[ 'Edit form definition "%s"' % tmp_name ],
+ strings_displayed_after_submit=[ "The form '%s' has been updated with the changes." % new_name ] )
+ # Get the form_definition object for later tests
+ global form_one
+ form_one = get_form( new_name )
+ assert form_one is not None, 'Problem retrieving form named "%s" from the database' % new_name
+ assert len( form_one.fields ) == len( tmp_form.fields ) + len( field_dicts )
+ def test_015_create_sample_form( self ):
+ """Testing creating sample form definition"""
+ name = "Sample Form"
+ desc = "This is Form Two's description"
+ form_type = galaxy.model.FormDefinition.types.SAMPLE
+ form_layout_name = 'Layout Grid One'
+ self.create_form( name=name,
+ desc=desc,
+ form_type=form_type,
+ form_layout_name=form_layout_name,
+ strings_displayed=[ 'Create a new form definition' ],
+ strings_displayed_after_submit=[ "The form '%s' has been updated with the changes." % name ] )
+ global form_two
+ form_two = get_form( name )
+ assert form_two is not None, "Error retrieving form %s from db" % name
+ def test_020_create_request_type( self ):
+ """Testing creating a request_type"""
+ request_form = get_form( form_one.name )
+ sample_form = get_form( form_two.name )
+ name = 'Test Requestype'
+ self.create_request_type( name,
+ "test sequencer configuration",
+ self.security.encode_id( request_form.id ),
+ self.security.encode_id( sample_form.id ),
+ sample_states,
+ strings_displayed=[ 'Create a new sequencer configuration' ],
+ strings_displayed_after_submit=[ "Sequencer configuration (%s) has been created" % name ] )
+ global request_type1
+ request_type1 = get_request_type_by_name( name )
+ assert request_type1 is not None, 'Problem retrieving sequencer configuration named "%s" from the database' % name
+ # Set permissions
+ permissions_in = [ k for k, v in galaxy.model.RequestType.permitted_actions.items() ]
+ permissions_out = []
+ # Role one members are: admin_user, regular_user1, regular_user3. Each of these users will be permitted for
+ # REQUEST_TYPE_ACCESS on this request_type
+ self.request_type_permissions( self.security.encode_id( request_type1.id ),
+ request_type1.name,
+ str( role_one.id ),
+ permissions_in,
+ permissions_out )
+ # Make sure the request_type1 is not accessible by regular_user2 since regular_user2 does not have Role1.
+ self.logout()
+ self.login( email=regular_user2.email )
+ self.visit_url( '%s/requests_common/create_request?cntrller=requests&request_type=True' % self.url )
+ try:
+ self.check_page_for_string( 'There are no sequencer configurations created for a new request.' )
+ raise AssertionError, 'The request_type %s is accessible by %s when it should be restricted' % ( request_type1.name, regular_user2.email )
+ except:
+ pass
+ self.logout()
+ self.login( email=admin_user.email )
+ def test_025_create_request( self ):
+ """Testing creating a sequence run request"""
+ # logged in as admin_user
+ # Create a user_address
+ self.logout()
+ self.login( email=regular_user1.email )
+ self.add_user_address( regular_user1.id, address_dict )
+ global user_address1
+ user_address1 = get_user_address( regular_user1, address_dict[ 'short_desc' ] )
+ # Set field values - the tuples in the field_values list include the field_value, and True if refresh_on_change
+ # is required for that field.
+ field_value_tuples = [ ( 'option1', False ), ( str( user_address1.id ), True ), ( 'field three value', False ) ]
+ # Create the request
+ name = 'Request One'
+ desc = 'Request One Description'
+ self.create_request( cntrller='requests',
+ request_type_id=self.security.encode_id( request_type1.id ),
+ name=name,
+ desc=desc,
+ field_value_tuples=field_value_tuples,
+ strings_displayed=[ 'Create a new sequencing request',
+ test_field_name1,
+ test_field_name2,
+ test_field_name3 ],
+ strings_displayed_after_submit=[ name, desc ] )
+ global request_one
+ request_one = get_request_by_name( name )
+ # Make sure the request's state is now set to NEW
+ assert request_one.state is not request_one.states.NEW, "The state of the request '%s' should be set to '%s'" \
+ % ( request_one.name, request_one.states.NEW )
+ # Sample fields - the tuple represents a sample name and a list of sample form field values
+ sample_value_tuples = [ ( 'Sample One', [ 'S1 Field 0 Value' ] ),
+ ( 'Sample Two', [ 'S2 Field 0 Value' ] ) ]
+ strings_displayed_after_submit = [ 'Unsubmitted' ]
+ for sample_name, field_values in sample_value_tuples:
+ strings_displayed_after_submit.append( sample_name )
+ # Add samples to the request
+ self.add_samples( cntrller='requests',
+ request_id=self.security.encode_id( request_one.id ),
+ request_name=request_one.name,
+ sample_value_tuples=sample_value_tuples,
+ strings_displayed=[ 'There are no samples.' ],
+ strings_displayed_after_submit=strings_displayed_after_submit )
+ def test_030_edit_basic_request_info( self ):
+ """Testing editing the basic information of a sequence run request"""
+ # logged in as regular_user1
+ fields = [ 'option2', str( user_address1.id ), 'field three value (edited)' ]
+ new_name=request_one.name + ' (Renamed)'
+ new_desc=request_one.desc + ' (Re-described)'
+ self.edit_basic_request_info( request_id=self.security.encode_id( request_one.id ),
+ cntrller='requests',
+ name=request_one.name,
+ new_name=new_name,
+ new_desc=new_desc,
+ new_fields=fields,
+ strings_displayed=[ 'Edit sequencing request "%s"' % request_one.name ],
+ strings_displayed_after_submit=[ new_name, new_desc ] )
+ refresh( request_one )
+ # check if the request is showing in the 'new' filter
+ self.check_request_grid( cntrller='requests',
+ state=request_one.states.NEW,
+ strings_displayed=[ request_one.name ] )
+ def test_035_submit_request( self ):
+ """Testing editing a sequence run request"""
+ # logged in as regular_user1
+ self.submit_request( cntrller='requests',
+ request_id=self.security.encode_id( request_one.id ),
+ request_name=request_one.name,
+ strings_displayed_after_submit=[ 'The request has been submitted.' ] )
+ refresh( request_one )
+ # Make sure the request is showing in the 'submitted' filter
+ self.check_request_grid( cntrller='requests',
+ state=request_one.states.SUBMITTED,
+ strings_displayed=[ request_one.name ] )
+ # Make sure the request's state is now set to 'submitted'
+ assert request_one.state is not request_one.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" \
+ % ( request_one.name, request_one.states.SUBMITTED )
+ def test_040_request_lifecycle( self ):
+ """Testing request life-cycle as it goes through all the states"""
+ # logged in as regular_user1
+ self.logout()
+ self.login( email=admin_user.email )
+ self.check_request_grid( cntrller='requests_admin',
+ state=request_one.states.SUBMITTED,
+ strings_displayed=[ request_one.name ] )
+ self.visit_url( "%s/requests_common/view_request?cntrller=requests&id=%s" % ( self.url, self.security.encode_id( request_one.id ) ) )
+ # TODO: add some string for checking on the page above...
+ # Set bar codes for the samples
+ bar_codes = [ '1234567890', '0987654321' ]
+ strings_displayed_after_submit=[ 'Changes made to the samples have been saved.' ]
+ for bar_code in bar_codes:
+ strings_displayed_after_submit.append( bar_code )
+ self.add_bar_codes( request_id=self.security.encode_id( request_one.id ),
+ request_name=request_one.name,
+ bar_codes=bar_codes,
+ samples=request_one.samples,
+ strings_displayed_after_submit=strings_displayed_after_submit )
+ # Change the states of all the samples of this request to ultimately be COMPLETE
+ self.change_sample_state( request_id=self.security.encode_id( request_one.id ),
+ request_name=request_one.name,
+ sample_names=[ sample.name for sample in request_one.samples ],
+ sample_ids=[ sample.id for sample in request_one.samples ],
+ new_sample_state_id=request_type1.states[1].id,
+ new_state_name=request_type1.states[1].name )
+ self.change_sample_state( request_id=self.security.encode_id( request_one.id ),
+ request_name=request_one.name,
+ sample_names=[ sample.name for sample in request_one.samples ],
+ sample_ids=[ sample.id for sample in request_one.samples ],
+ new_sample_state_id=request_type1.states[2].id,
+ new_state_name=request_type1.states[2].name )
+ refresh( request_one )
+ self.logout()
+ self.login( email=regular_user1.email )
+ # check if the request's state is now set to 'complete'
+ self.check_request_grid( cntrller='requests',
+ state='Complete',
+ strings_displayed=[ request_one.name ] )
+ assert request_one.state is not request_one.states.COMPLETE, "The state of the request '%s' should be set to '%s'" \
+ % ( request_one.name, request_one.states.COMPLETE )
+
+ def test_045_admin_create_request_on_behalf_of_regular_user( self ):
+ """Testing creating and submitting a request as an admin on behalf of a regular user"""
+ # Logged in as regular_user1
+ self.logout()
+ self.login( email=admin_user.email )
+ # Create the request
+ name = "RequestTwo"
+ desc = 'Request Two Description'
+ # Set field values - the tuples in the field_values list include the field_value, and True if refresh_on_change
+ # is required for that field.
+ field_value_tuples = [ ( 'option2', False ), ( str( user_address1.id ), True ), ( 'field_2_value', False ) ]
+ self.create_request( cntrller='requests_admin',
+ request_type_id=self.security.encode_id( request_type1.id ),
+ other_users_id=self.security.encode_id( regular_user1.id ),
+ name=name,
+ desc=desc,
+ field_value_tuples=field_value_tuples,
+ strings_displayed=[ 'Create a new sequencing request',
+ test_field_name1,
+ test_field_name2,
+ test_field_name3 ],
+ strings_displayed_after_submit=[ "The request has been created." ] )
+ global request_two
+ request_two = get_request_by_name( name )
+ # Make sure the request is showing in the 'new' filter
+ self.check_request_grid( cntrller='requests_admin',
+ state=request_two.states.NEW,
+ strings_displayed=[ request_two.name ] )
+ # Make sure the request's state is now set to 'new'
+ assert request_two.state is not request_two.states.NEW, "The state of the request '%s' should be set to '%s'" \
+ % ( request_two.name, request_two.states.NEW )
+ # Sample fields - the tuple represents a sample name and a list of sample form field values
+ sample_value_tuples = [ ( 'Sample One', [ 'S1 Field 0 Value' ] ),
+ ( 'Sample Two', [ 'S2 Field 0 Value' ] ) ]
+ strings_displayed_after_submit = [ 'Unsubmitted' ]
+ for sample_name, field_values in sample_value_tuples:
+ strings_displayed_after_submit.append( sample_name )
+ # Add samples to the request
+ self.add_samples( cntrller='requests_admin',
+ request_id=self.security.encode_id( request_two.id ),
+ request_name=request_two.name,
+ sample_value_tuples=sample_value_tuples,
+ strings_displayed=[ 'There are no samples.' ],
+ strings_displayed_after_submit=strings_displayed_after_submit )
+ # Submit the request
+ self.submit_request( cntrller='requests_admin',
+ request_id=self.security.encode_id( request_two.id ),
+ request_name=request_two.name,
+ strings_displayed_after_submit=[ 'The request has been submitted.' ] )
+ refresh( request_two )
+ # Make sure the request is showing in the 'submitted' filter
+ self.check_request_grid( cntrller='requests_admin',
+ state=request_two.states.SUBMITTED,
+ strings_displayed=[ request_two.name ] )
+ # Make sure the request's state is now set to 'submitted'
+ assert request_two.state is not request_two.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" \
+ % ( request_two.name, request_two.states.SUBMITTED )
+ # Make sure both requests are showing in the 'All' filter
+ self.check_request_grid( cntrller='requests_admin',
+ state='All',
+ strings_displayed=[ request_one.name, request_two.name ] )
+ def test_050_reject_request( self ):
+ """Testing rejecting a request"""
+ # Logged in as admin_user
+ self.reject_request( request_id=self.security.encode_id( request_two.id ),
+ request_name=request_two.name,
+ comment="Rejection test comment",
+ strings_displayed=[ 'Reject Sequencing Request "%s"' % request_two.name ],
+ strings_displayed_after_submit=[ 'Request (%s) has been rejected.' % request_two.name ] )
+ refresh( request_two )
+ # Make sure the request is showing in the 'rejected' filter
+ self.check_request_grid( cntrller='requests_admin',
+ state=request_two.states.REJECTED,
+ strings_displayed=[ request_two.name ] )
+ # Make sure the request's state is now set to REJECTED
+ assert request_two.state is not request_two.states.REJECTED, "The state of the request '%s' should be set to '%s'" \
+ % ( request_two.name, request_two.states.REJECTED )
+ def test_055_reset_data_for_later_test_runs( self ):
+ """Reseting data to enable later test runs to pass"""
+ # Logged in as admin_user
+ ##################
+ # Delete request_type permissions
+ ##################
+ for request_type in [ request_type1 ]:
+ delete_request_type_permissions( request_type.id )
+ ##################
+ # Mark all request_types deleted
+ ##################
+ for request_type in [ request_type1 ]:
+ mark_obj_deleted( request_type )
+ ##################
+ # Mark all requests deleted
+ ##################
+ for request in [ request_one, request_two ]:
+ mark_obj_deleted( request )
+ ##################
+ # Mark all forms deleted
+ ##################
+ for form in [ form_one, form_two ]:
+ self.mark_form_deleted( self.security.encode_id( form.current.id ) )
+ ##################
+ # Mark all user_addresses deleted
+ ##################
+ for user_address in [ user_address1 ]:
+ mark_obj_deleted( user_address )
+ ##################
+ # Delete all non-private roles
+ ##################
+ for role in [ role_one, role_two ]:
+ self.mark_role_deleted( self.security.encode_id( role.id ), role.name )
+ self.purge_role( self.security.encode_id( role.id ), role.name )
+ # Manually delete the role from the database
+ refresh( role )
+ delete( role )
+ ##################
+ # Delete all groups
+ ##################
+ for group in [ group_one ]:
+ self.mark_group_deleted( self.security.encode_id( group.id ), group.name )
+ self.purge_group( self.security.encode_id( group.id ), group.name )
+ # Manually delete the group from the database
+ refresh( group )
+ delete( group )
--- a/templates/requests/common/common.mako
+++ b/templates/requests/common/common.mako
@@ -65,12 +65,60 @@
}
}
}
+
+ // Looks for changes in sample states using an async request. Keeps
+ // calling itself (via setTimeout) until all samples are in a terminal
+ // state.
+ var updater = function ( sample_states ) {
+ // Check if there are any items left to track
+ var empty = true;
+ for ( i in sample_states ) {
+ empty = false;
+ break;
+ }
+ if ( ! empty ) {
+ setTimeout( function() { updater_callback( sample_states ) }, 1000 );
+ }
+ };
+
+ var updater_callback = function ( sample_states ) {
+ // Build request data
+ var ids = []
+ var states = []
+ $.each( sample_states, function ( id, state ) {
+ ids.push( id );
+ states.push( state );
+ });
+ // Make ajax call
+ $.ajax( {
+ type: "POST",
+ url: "${h.url_for( controller='requests_common', action='sample_state_updates' )}",
+ dataType: "json",
+ data: { ids: ids.join( "," ), states: states.join( "," ) },
+ success : function ( data ) {
+ $.each( data, function( id, val ) {
+ // Replace HTML
+ var cell1 = $("#sampleState-" + id);
+ cell1.html( val.html_state );
+ var cell2 = $("#sampleDatasets-" + id);
+ cell2.html( val.html_datasets );
+ sample_states[ parseInt( id ) ] = val.state;
+ });
+ updater( sample_states );
+ },
+ error: function() {
+ // Just retry, like the old method, should try to be smarter
+ updater( sample_states );
+ }
+ });
+ };
</script></%def><%def name="render_editable_sample_row( is_admin, sample, current_sample_index, current_sample, encoded_selected_sample_ids )"><%
if sample:
+ trans.sa_session.refresh( sample.request )
is_complete = sample.request.is_complete
is_submitted = sample.request.is_submitted
is_unsubmitted = sample.request.is_unsubmitted
@@ -80,12 +128,12 @@
is_unsubmitted = False
%><%
- if is_admin and is_submitted and editing_samples and trans.security.encode_id( sample.id ) in encoded_selected_sample_ids:
+ if is_submitted and editing_samples and trans.security.encode_id( sample.id ) in encoded_selected_sample_ids:
checked_str = "checked"
else:
checked_str = ""
%>
- %if is_admin and is_submitted and editing_samples:
+ %if is_submitted and editing_samples:
<td><input type="checkbox" name=select_sample_${sample.id} id="sample_checkbox" value="true" ${checked_str}/><input type="hidden" name=select_sample_${sample.id} id="sample_checkbox" value="true"/></td>
%endif
<td valign="top">
@@ -95,7 +143,11 @@
</div></td>
%if sample and is_submitted or is_complete:
- <td valign="top"><input type="text" name="sample_${current_sample_index}_barcode" value="${current_sample['barcode']}" size="10"/></td>
+ %if is_admin:
+ <td valign="top"><input type="text" name="sample_${current_sample_index}_barcode" value="${current_sample['barcode']}" size="10"/></td>
+ %else:
+ ${current_sample['barcode']}
+ %endif
%endif
%if sample:
%if is_unsubmitted:
@@ -118,7 +170,7 @@
<td valign="top"><a href="${h.url_for( controller='requests_common', action='view_dataset_transfer', cntrller=cntrller, sample_id=trans.security.encode_id( sample.id ) )}">${label}</a></td><td valign="top"><a href="${h.url_for( controller='requests_common', action='view_dataset_transfer', cntrller=cntrller, sample_id=trans.security.encode_id( sample.id ) )}">${label}</a></td>
%endif
- %if sample and ( is_admin or is_unsubmitted ):
+ %if sample and ( is_admin or is_unsubmitted ) and not is_complete:
## Delete button
<td valign="top"><a class="action-button" href="${h.url_for( controller='requests_common', action='delete_sample', cntrller=cntrller, request_id=trans.security.encode_id( request.id ), sample_id=current_sample_index )}"><img src="${h.url_for('/static/images/delete_icon.png')}" style="cursor:pointer;"/></a></td>
%endif
@@ -127,20 +179,22 @@
<%def name="render_samples_grid( cntrller, request, current_samples, action, editing_samples=False, encoded_selected_sample_ids=[], render_buttons=False, grid_header='<h3>Samples</h3>' )">
## Displays the "Samples" grid
<%
+ trans.sa_session.refresh( request )
is_admin = cntrller == 'requests_admin' and trans.user_is_admin()
is_complete = request.is_complete
is_submitted = request.is_submitted
is_unsubmitted = request.is_unsubmitted
can_add_samples = request.is_unsubmitted
- can_edit_or_delete_samples = request.samples and not is_complete
+ can_delete_samples = request.samples and not is_complete
+ can_edit_samples = request.samples and ( is_admin or not is_complete )
%>
${grid_header}
- %if render_buttons and ( can_add_samples or can_edit_or_delete_samples ):
+ %if render_buttons and ( can_add_samples or can_edit_samples ):
<ul class="manage-table-actions">
%if can_add_samples:
<li><a class="action-button" href="${h.url_for( controller='requests_common', action='add_sample', cntrller=cntrller, request_id=trans.security.encode_id( request.id ), add_sample_button='Add sample' )}">Add sample</a></li>
%endif
- %if can_edit_or_delete_samples:
+ %if can_edit_samples:
<li><a class="action-button" href="${h.url_for( controller='requests_common', action='edit_samples', cntrller=cntrller, id=trans.security.encode_id( request.id ), editing_samples='True' )}">Edit samples</a></li>
%endif
</ul>
@@ -148,7 +202,7 @@
<table class="grid"><thead><tr>
- %if is_admin and is_submitted and editing_samples:
+ %if is_submitted and editing_samples:
<th><input type="checkbox" id="checkAll" name=select_all_samples_checkbox value="true" onclick='checkAllFields(1);'/><input type="hidden" name=select_all_samples_checkbox value="true"/></th>
%endif
<th>Name</th>
@@ -191,7 +245,7 @@
except:
sample = None
%>
- %if editing_samples:
+ %if not is_complete and editing_samples:
<tr>${render_editable_sample_row( is_admin, sample, current_sample_index, current_sample, encoded_selected_sample_ids )}</tr>
%elif sample:
<tr>
@@ -220,6 +274,7 @@
%endif
</tr>
%else:
+ ## The Add sample button was clicked for this sample_widget
<tr>${render_editable_sample_row( is_admin, None, current_sample_index, current_sample, encoded_selected_sample_ids )}</tr>
%endif
%endfor
@@ -231,9 +286,7 @@
<tr><td>${sample_name}</td>
%for field_index, field in fields_dict.items():
- <%
- field_type = field[ 'type' ]
- %>
+ <% field_type = field[ 'type' ] %><td>
%if display_only:
%if sample_values[field_index]:
--- a/templates/requests/common/view_request.mako
+++ b/templates/requests/common/view_request.mako
@@ -22,7 +22,8 @@
is_unsubmitted = request.is_unsubmitted
can_edit_request = ( is_admin and not request.is_complete ) or request.is_unsubmitted
can_add_samples = is_unsubmitted
- can_edit_or_delete_samples = request.samples and not is_complete
+ can_delete_samples = request.samples and not is_complete
+ can_edit_samples = request.samples and ( is_admin or not is_complete )
can_submit = request.samples and is_unsubmitted
%>
@@ -131,14 +132,23 @@
${states}
<div style="clear: both"></div></div>
+ %if request.samples and request.is_submitted:
+ <script type="text/javascript">
+ // Updater
+ updater( {${ ",".join( [ '"%s" : "%s"' % ( s.id, s.state.name ) for s in request.samples ] ) }});
+ </script>
+ %endif
</div></div></div></div><p/>
%if current_samples:
- <% grid_header = '<h3>Samples</h3>' %>
- ${render_samples_grid( cntrller, request, current_samples=current_samples, action='view_request', editing_samples=False, encoded_selected_sample_ids=[], render_buttons=can_edit_or_delete_samples, grid_header=grid_header )}
+ <%
+ grid_header = '<h3>Samples</h3>'
+ render_buttons = can_edit_samples
+ %>
+ ${render_samples_grid( cntrller, request, current_samples=current_samples, action='view_request', editing_samples=False, encoded_selected_sample_ids=[], render_buttons=render_buttons, grid_header=grid_header )}
%else:
There are no samples.
%if can_add_samples:
1
0
galaxy-dist commit 4053c425b536: No longer pre-generate menus on page load for popup-style menus. Instead, create menu dynamically when needed, greatly improving load time especially on data libraries with large number of potential menus.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1288748718 14400
# Node ID 4053c425b536b9878f6f8bdfac75453adec7bdf3
# Parent e000a6800e1cbfa15a190bb2aff90a5956882a43
No longer pre-generate menus on page load for popup-style menus. Instead, create menu dynamically when needed, greatly improving load time especially on data libraries with large number of potential menus.
Remove the creation of a background element that closes the active menu clicked. Instead, bind an event to close active menus to the document object of current and all other framesets. Tested in IE.
Update Tool Search/Recently Used code to reflect new changes.
Made some small tweaks to pass JSlint
--- a/templates/root/index.mako
+++ b/templates/root/index.mako
@@ -46,10 +46,8 @@
"Export to File": function() {
galaxy_main.location = "${h.url_for( controller='history', action='export_archive' )}";
},
- "Delete": function()
- {
- if ( confirm( "Really delete the current history?" ) )
- {
+ "Delete": function() {
+ if ( confirm( "Really delete the current history?" ) ) {
galaxy_main.location = "${h.url_for( controller='history', action='delete_current' )}";
}
},
@@ -59,98 +57,108 @@
}
});
+ var menu_options = {}; // Holds dictionary of { label: toggle_fn }
+
+ SHOW_TOOL = "Show Tool Search";
+ HIDE_TOOL = "Hide Tool Search";
+ SHOW_RECENT = "Show Recently Used";
+ HIDE_RECENT = "Hide Recently Used";
+
+ var toggle_tool_search_fn = function() {
+ // Show/hide menu and update vars, user preferences.
+ var menu = $("#galaxy_tools").contents().find('#tool-search'),
+ pref_value, menu_option_text, old_text;
+ if (menu.is(":visible")) {
+ // Hide menu.
+ pref_value = "False";
+ menu_option_text = SHOW_TOOL;
+ old_text = HIDE_TOOL;
+
+ // Reset search.
+ reset_tool_search(true);
+ } else {
+ // Show menu.
+ pref_value = "True";
+ menu_option_text = HIDE_TOOL;
+ old_text = SHOW_TOOL;
+ }
+ menu.toggle();
+
+ // Update menu option.
+ delete menu_options[old_text];
+ menu_options[menu_option_text] = toggle_tool_search_fn;
+ make_popupmenu( $("#tools-options-button"), menu_options );
+ galaxy_async.set_user_pref("show_tool_search", pref_value);
+ };
+
+ var toggle_recently_used_fn = function() {
+ // Show/hide menu.
+ var ru_menu = $('#galaxy_tools').contents().find('#recently_used_wrapper'),
+ ru_menu_body = ru_menu.find(".toolSectionBody"),
+ pref_value, old_text, menu_option_text;
+ if (ru_menu.hasClass("user_pref_visible")) {
+ // Hide menu.
+ ru_menu_body.slideUp();
+ ru_menu.slideUp();
+
+ // Set vars used below and in tool menu frame.
+ pref_value = "False";
+ old_text = HIDE_RECENT;
+ menu_option_text = SHOW_RECENT;
+ } else {
+ // "Show" menu.
+ if (!$('#galaxy_tools').contents().find('#tool-search-query').hasClass("search_active")) {
+ // Default.
+ ru_menu.slideDown();
+ } else {
+ // Search active: tf there are matching tools in RU menu, show menu.
+ if ( ru_menu.find(".toolTitle.search_match").length !== 0 ) {
+ ru_menu.slideDown();
+ ru_menu_body.slideDown();
+ }
+ }
+ // Set vars used below and in tool menu frame.
+ pref_value = "True";
+ old_text = SHOW_RECENT;
+ menu_option_text = HIDE_RECENT;
+ }
+
+ // Update menu class and option.
+ ru_menu.toggleClass("user_pref_hidden user_pref_visible");
+ delete menu_options[old_text];
+ menu_options[menu_option_text] = toggle_recently_used_fn;
+ make_popupmenu( $("#tools-options-button"), menu_options );
+ galaxy_async.set_user_pref("show_recently_used_menu", pref_value);
+ };
+
// Init tool options.
- make_popupmenu( $("#tools-options-button"), {
- ## Search tools menu item.
- %if trans.app.toolbox_search.enabled:
- <%
- show_tool_search = False
- if trans.user:
- show_tool_search = trans.user.preferences.get( "show_tool_search", "False" )
-
- if show_tool_search == "True":
- initial_text = "Hide Search"
- else:
- initial_text = "Search Tools"
- %>
- "${initial_text}": function() {
- // Show/hide menu and update vars, user preferences.
- var menu = $("#galaxy_tools").contents().find('#tool-search');
- if (menu.is(":visible"))
- {
- // Hide menu.
- pref_value = "False";
- menu_option_text = "Search Tools";
- menu.toggle();
-
- // Reset search.
- reset_tool_search(true);
- }
- else
- {
- // Show menu.
- pref_value = "True";
- menu_option_text = "Hide Search";
- menu.toggle();
- }
-
- // Update menu option.
- $("#tools-options-button-menu").find("li").eq(0).text(menu_option_text);
-
- galaxy_async.set_user_pref("show_tool_search", pref_value);
- },
- %endif
- ## Recently used tools menu.
- %if trans.user:
- <%
- if trans.user.preferences.get( 'show_recently_used_menu', 'False' ) == 'True':
- action = "Hide"
- else:
- action = "Show"
- %>
- "${action} Recently Used": function() {
- // Show/hide menu.
- var ru_menu = $('#galaxy_tools').contents().find('#recently_used_wrapper');
- var ru_menu_body = ru_menu.find(".toolSectionBody");
- var pref_value = null;
- var menu_option_text = null;
- if (ru_menu.hasClass("user_pref_visible"))
- {
- // Hide menu.
- ru_menu_body.slideUp();
- ru_menu.slideUp();
-
- // Set vars used below and in tool menu frame.
- pref_value = "False";
- menu_option_text = "Show Recently Used";
- }
- else
- {
- // "Show" menu.
- if (!$('#galaxy_tools').contents().find('#tool-search-query').hasClass("search_active"))
- // Default.
- ru_menu.slideDown();
- else
- // Search active: tf there are matching tools in RU menu, show menu.
- if ( ru_menu.find(".toolTitle.search_match").length != 0 )
- {
- ru_menu.slideDown();
- ru_menu_body.slideDown();
- }
-
- // Set vars used below and in tool menu frame.
- pref_value = "True";
- menu_option_text = "Hide Recently Used";
- }
-
- // Update menu class and option.
- ru_menu.toggleClass("user_pref_hidden user_pref_visible");
- $("#tools-options-button-menu").find("li").eq(1).text(menu_option_text);
-
- galaxy_async.set_user_pref("show_recently_used_menu", pref_value);
- }
- %endif
- });
+ ## Search tools menu item.
+ %if trans.app.toolbox_search.enabled:
+ <%
+ show_tool_search = False
+ if trans.user:
+ show_tool_search = trans.user.preferences.get( "show_tool_search", "False" )
+
+ if show_tool_search == "True":
+ action = "HIDE_TOOL"
+ else:
+ action = "SHOW_TOOL"
+ %>
+ menu_options[ ${action} ] = toggle_tool_search_fn;
+ %endif
+ ## Recently used tools menu.
+ %if trans.user:
+ <%
+ if trans.user.preferences.get( 'show_recently_used_menu', 'False' ) == 'True':
+ action = "HIDE_RECENT"
+ else:
+ action = "SHOW_RECENT"
+ %>
+ menu_options[ ${action} ] = toggle_recently_used_fn;
+ %endif
+
+
+ make_popupmenu( $("#tools-options-button"), menu_options );
});
</script></%def>
--- a/static/scripts/galaxy.base.js
+++ b/static/scripts/galaxy.base.js
@@ -7,7 +7,7 @@ if (!Array.indexOf) {
}
}
return -1;
- }
+ };
}
// Returns the number of keys (elements) in an array/dictionary.
@@ -39,93 +39,89 @@ function obj_length(obj) {
});
};
-function ensure_popup_helper() {
- // And the helper below the popup menus
- if ( $( "#popup-helper" ).length === 0 ) {
- $( "<div id='popup-helper'/>" ).css( {
- background: 'white', opacity: 0, zIndex: 15000,
- position: 'absolute', top: 0, left: 0, width: '100%', height: '100%'
- } ).appendTo( "body" ).hide();
- }
-}
-
-function attach_popupmenu( button_element, wrapper ) {
- var clean = function() {
- wrapper.unbind().hide();
- $("#popup-helper").unbind( "click.popupmenu" ).hide();
- // $(document).unbind( "click.popupmenu" );
- };
- var click_handler = function( e ) {
- // var o = $(button_element).offset();
- $("#popup-helper").bind( "click.popupmenu", clean ).show();
- // $(document).bind( "click.popupmenu", clean );
- // Show off screen to get size right
- wrapper.click( clean ).css( { left: 0, top: -1000 } ).show();
- // console.log( e.pageX, $(document).scrollLeft() + $(window).width(), $(menu_element).width() );
- var x = e.pageX - wrapper.width() / 2 ;
- x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 20 );
- x = Math.max( x, $(document).scrollLeft() + 20 );
- // console.log( e.pageX, $(document).scrollLeft() + $(window).width(), $(menu_element).width() );
-
-
- wrapper.css( {
- top: e.pageY - 5,
- left: x
- } );
- return false;
- };
- $(button_element).bind("click", click_handler);
+// Toggle popup menu options using regular expression on option names.
+function show_hide_popupmenu_options( menu, option_name_re, show ) {
+ show = (show === undefined ? true : show );
+ var re = new RegExp(option_name_re);
+ $(menu).find("li").each( function() {
+ if ( re.exec($(this).text()) ) {
+ if (show) {
+ $(this).show();
+ } else {
+ $(this).hide();
+ }
+ }
+ });
}
function make_popupmenu( button_element, options ) {
- ensure_popup_helper();
- // var container_element = $(button_element);
- // if ( container_element.parent().hasClass( "combo-button" ) ) {
- // container_element = container_element.parent();
- // }
- // container_element).css( "position", "relative" );
- var menu_element = $( "<ul id='" + button_element.attr('id') + "-menu'></ul>" );
- if (obj_length(options) <= 0) {
- $("<li/>").html("No options").appendTo(menu_element);
- }
- $.each( options, function( k, v ) {
- if (v) {
- $("<li/>").html(k).click(v).appendTo(menu_element);
- } else {
- $("<li class='head'/>").html(k).appendTo(menu_element);
- }
+ button_element.bind("click.show_popup", function(e) {
+ // Close existing visible menus
+ $(".popmenu-wrapper").remove();
+
+
+ // Need setTimeouts so clicks don't interfere with each other
+ setTimeout( function() {
+ // Dynamically generate the wrapper holding all the selectable options of the menu.
+ var menu_element = $( "<ul id='" + button_element.attr('id') + "-menu'></ul>" );
+ if (obj_length(options) <= 0) {
+ $("<li>No Options.</li>").appendTo(menu_element);
+ }
+ $.each( options, function( k, v ) {
+ if (v) {
+ $("<li/>").html(k).click(v).appendTo(menu_element);
+ } else {
+ $("<li class='head'/>").html(k).appendTo(menu_element);
+ }
+ });
+ var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'>" );
+ wrapper.append( menu_element )
+ .append( "<div class='overlay-border'>" )
+ .appendTo( "body" );
+
+ var x = e.pageX - wrapper.width() / 2 ;
+ x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 20 );
+ x = Math.max( x, $(document).scrollLeft() + 20 );
+
+ wrapper.css( {
+ top: e.pageY - 5,
+ left: x
+ } );
+ }, 10);
+
+ setTimeout( function() {
+ // Bind click event to current window and all frames to remove any visible menus
+ // Bind to document object instead of window object for IE compat
+ var close_popup = function(el) {
+ $(el).bind("click.close_popup", function() {
+ $(".popmenu-wrapper").remove();
+ el.unbind("click.close_popup");
+ });
+ };
+ close_popup( $(window.document) ); // Current frame
+ close_popup( $(window.top.document) ); // Parent frame
+ for (var frame_id = window.top.frames.length; frame_id--;) { // Sibling frames
+ var frame = $(window.top.frames[frame_id].document);
+ close_popup(frame);
+ }
+ }, 50);
+
+ return false;
});
- var wrapper = $( "<div class='popmenu-wrapper'>" );
- wrapper.append( menu_element )
- .append( "<div class='overlay-border'>" )
- .css( "position", "absolute" )
- .appendTo( "body" )
- .hide();
- attach_popupmenu( button_element, wrapper );
- return menu_element;
-}
-
-// Toggle popup menu options using regular expression on option names.
-function show_hide_popupmenu_options( menu, option_name_re, show ) {
- var show = (show === undefined ? true : show );
- var re = new RegExp(option_name_re);
- $(menu).find("li").each( function() {
- if ( re.exec( $(this).text() ) )
- if (show)
- $(this).show();
- else
- $(this).hide();
- });
+
}
function make_popup_menus() {
jQuery( "div[popupmenu]" ).each( function() {
var options = {};
- $(this).find( "a" ).each( function() {
- var confirmtext = $(this).attr( "confirm" ),
- href = $(this).attr( "href" ),
- target = $(this).attr( "target" );
- options[ $(this).text() ] = function() {
+ var menu = $(this);
+ menu.find( "a" ).each( function() {
+ var link = $(this),
+ link_dom = link.get(0);
+ var confirmtext = link_dom.getAttribute( "confirm" ),
+ href = link_dom.getAttribute( "href" ),
+ target = link_dom.getAttribute( "target" );
+ options[ link.text() ] = function() {
if ( !confirmtext || confirm( confirmtext ) ) {
var f = window;
if ( target == "_parent" ) {
@@ -137,14 +133,18 @@ function make_popup_menus() {
}
};
});
- var b = $( "#" + $(this).attr( 'popupmenu' ) );
- b.find("a").bind("click", function(e) {
+ var box = $( "#" + menu.attr( 'popupmenu' ) );
+
+ // For menus with clickable link text, make clicking on the link go through instead
+ // of activating the popup menu
+ box.find("a").bind("click", function(e) {
e.stopPropagation(); // Stop bubbling so clicking on the link goes through
return true;
});
- make_popupmenu( b, options );
- $(this).remove();
- b.addClass( "popup" ).show();
+
+ make_popupmenu(box, options);
+ box.addClass("popup");
+ menu.remove();
});
}
@@ -160,15 +160,17 @@ function naturalSort(a, b) {
xD = (new Date(x)).getTime(),
yD = xD ? (new Date(y)).getTime() : null;
// natural sorting of dates
- if ( yD )
- if ( xD < yD ) return -1;
- else if ( xD > yD ) return 1;
+ if ( yD ) {
+ if ( xD < yD ) { return -1; }
+ else if ( xD > yD ) { return 1; }
+ }
// natural sorting through split numeric strings and default strings
- for( var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++ ) {
+ var oFxNcL, oFyNcL;
+ for ( var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++ ) {
oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];
oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];
- if (oFxNcL < oFyNcL) return -1;
- else if (oFxNcL > oFyNcL) return 1;
+ if (oFxNcL < oFyNcL) { return -1; }
+ else if (oFxNcL > oFyNcL) { return 1; }
}
return 0;
}
@@ -176,14 +178,17 @@ function naturalSort(a, b) {
// Replace select box with a text input box + autocomplete.
function replace_big_select_inputs(min_length, max_length) {
// To do replace, jQuery's autocomplete plugin must be loaded.
- if (!jQuery().autocomplete)
+ if (!jQuery().autocomplete) {
return;
+ }
// Set default for min_length and max_length
- if (min_length === undefined)
+ if (min_length === undefined) {
min_length = 20;
- if (max_length === undefined)
+ }
+ if (max_length === undefined) {
max_length = 3000;
+ }
$('select').each( function() {
var select_elt = $(this);
@@ -194,7 +199,7 @@ function replace_big_select_inputs(min_l
}
// Skip multi-select because widget cannot handle multi-select.
- if (select_elt.attr('multiple') == true) {
+ if (select_elt.attr('multiple') === true) {
return;
}
@@ -240,13 +245,14 @@ function replace_big_select_inputs(min_l
});
// Set initial text if it's empty.
- if ( start_value == '' || start_value == '?') {
+ if ( start_value === '' || start_value === '?') {
text_input_elt.attr('value', 'Click to Search or Select');
}
// Sort dbkey options list only.
- if (select_elt.attr('name') == 'dbkey')
+ if (select_elt.attr('name') == 'dbkey') {
select_options = select_options.sort(naturalSort);
+ }
// Do autocomplete.
var autocomplete_options = { selectFirst: false, autoFill: false, mustMatch: false, matchContains: true, max: max_length, minChars : 0, hideForLessThanMinChars : false };
@@ -265,7 +271,7 @@ function replace_big_select_inputs(min_l
}
else {
// If there is a non-empty start value, use that; otherwise unknown.
- if (start_value != "") {
+ if (start_value !== "") {
text_input_elt.attr('value', start_value);
} else {
// This is needed to make the DB key work.
@@ -283,9 +289,9 @@ function replace_big_select_inputs(min_l
// Get refresh vals.
var ref_on_change_vals = select_elt.attr('refresh_on_change_values'),
last_selected_value = select_elt.attr("last_selected_value");
- if (ref_on_change_vals !== undefined)
+ if (ref_on_change_vals !== undefined) {
ref_on_change_vals = ref_on_change_vals.split(',');
-
+ }
// Function that attempts to refresh based on the value in the text element.
var try_refresh_fn = function() {
// Get new value and see if it can be matched.
@@ -371,10 +377,11 @@ function async_save_text(click_to_edit_e
},
success: function(processed_text) {
// Set new text and call finish method.
- if (processed_text != "")
+ if (processed_text !== "") {
text_elt.text(processed_text);
- else
+ } else {
text_elt.html("<em>None</em>");
+ }
if (on_finish) {
on_finish(t);
}
@@ -415,15 +422,16 @@ function init_history_items(historywrapp
// If Mozilla, hide scrollbars in hidden items since they cause animation bugs
if ( $.browser.mozilla ) {
$( "div.historyItemBody" ).each( function() {
- if ( ! $(this).is( ":visible" ) ) $(this).find( "pre.peek" ).css( "overflow", "hidden" );
- })
+ if ( !$(this).is(":visible") ) { $(this).find( "pre.peek" ).css( "overflow", "hidden" ); }
+ });
}
historywrapper.each( function() {
- var id = this.id;
- var body = $(this).children( "div.historyItemBody" );
- var peek = body.find( "pre.peek" )
+ var id = this.id,
+ body = $(this).children( "div.historyItemBody" ),
+ peek = body.find( "pre.peek" );
$(this).find( ".historyItemTitleBar > .historyItemTitle" ).wrap( "<a href='javascript:void(0);'></a>" ).click( function() {
+ var prefs;
if ( body.is(":visible") ) {
// Hiding stuff here
if ( $.browser.mozilla ) { peek.css( "overflow", "hidden" ); }
@@ -431,7 +439,7 @@ function init_history_items(historywrapp
if (!nochanges) { // Ignore embedded item actions
// Save setting
- var prefs = $.jStore.store("history_expand_state");
+ prefs = $.jStore.store("history_expand_state");
if (prefs) {
delete prefs[id];
$.jStore.store("history_expand_state", prefs);
@@ -445,7 +453,7 @@ function init_history_items(historywrapp
if (!nochanges) {
// Save setting
- var prefs = $.jStore.store("history_expand_state");
+ prefs = $.jStore.store("history_expand_state");
if (prefs === undefined) { prefs = {}; }
prefs[id] = true;
$.jStore.store("history_expand_state", prefs);
@@ -470,7 +478,7 @@ function init_history_items(historywrapp
});
$.jStore.store("history_expand_state", prefs);
}).show();
- }
+ };
if (noinit) {
action();
@@ -497,7 +505,7 @@ function reset_tool_search( initValue )
// Function may be called in top frame or in tool_menu_frame;
// in either case, get the tool menu frame.
var tool_menu_frame = $("#galaxy_tools").contents();
- if (tool_menu_frame.length == 0) {
+ if (tool_menu_frame.length === 0) {
tool_menu_frame = $(document);
}
@@ -532,7 +540,7 @@ function reset_tool_search( initValue )
var GalaxyAsync = function(log_action) {
this.url_dict = {};
this.log_action = (log_action === undefined ? false : log_action);
-}
+};
GalaxyAsync.prototype.set_func_url = function( func_name, url ) {
this.url_dict[func_name] = url;
@@ -566,36 +574,6 @@ GalaxyAsync.prototype.log_user_action =
});
};
-// Add to trackster browser functionality
-$(".trackster-add").live("click", function() {
- var dataset = this,
- dataset_jquery = $(this);
- $.ajax({
- url: dataset_jquery.attr("data-url"),
- dataType: "html",
- error: function() { alert( "Could not add this dataset to browser." ); },
- success: function(table_html) {
- var parent = window.parent;
- parent.show_modal("Add to Browser:", table_html, {
- "Cancel": function() {
- parent.hide_modal();
- },
- "Insert into selected": function() {
- $(parent.document).find('input[name=id]:checked').each(function() {
- var vis_id = $(this).val();
- parent.location = dataset_jquery.attr("action-url") + "&id=" + vis_id;
- });
- },
- "Insert into new browser": function() {
- parent.location = dataset_jquery.attr("new-url");
- }
- });
- }
- });
-});
-
-
-
$(document).ready( function() {
$("select[refresh_on_change='true']").change( function() {
var select_field = $(this),
--- a/static/scripts/packed/galaxy.base.js
+++ b/static/scripts/packed/galaxy.base.js
@@ -1,1 +1,1 @@
-if(!Array.indexOf){Array.prototype.indexOf=function(c){for(var b=0,a=this.length;b<a;b++){if(this[b]==c){return b}}return -1}}function obj_length(c){if(c.length!==undefined){return c.length}var b=0;for(var a in c){b++}return b}$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scr
ollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).bind("click",c)}function make_popupmenu(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id")+"-menu'></ul>");if(obj_length(b)<=0){$("<li/>").html("No options").appendTo(a)}$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d);return a}function show_hide_popupmenu_options(d,c,a){var a=(a===undefined?true:a);var b=new RegExp(c);$(d).find("li").each(function(){if(b.exec($(this).text())){if(a){$(this).show()}else{$(this).hide()}}})}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("ta
rget");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));a.find("a").bind("click",function(b){b.stopPropagation();return true});make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function naturalSort(i,g){var n=/(-?[0-9\.]+)/g,j=i.toString().toLowerCase()||"",f=g.toString().toLowerCase()||"",k=String.fromCharCode(0),l=j.replace(n,k+"$1"+k).split(k),e=f.replace(n,k+"$1"+k).split(k),d=(new Date(j)).getTime(),m=d?(new Date(f)).getTime():null;if(m){if(d<m){return -1}else{if(d>m){return 1}}}for(var h=0,c=Math.max(l.length,e.length);h<c;h++){oFxNcL=parseFloat(l[h])||l[h];oFyNcL=parseFloat(e[h])||e[h];if(oFxNcL<oFyNcL){return -1}else{if(oFxNcL>oFyNcL){return 1}}}return 0}function replace_big_select_inputs(a,b){if(!jQuery().autocomplete){return}if(a===undefined){a=20}if(b===undefined){b=3000}$("select").each(function(){var d=$(this);var
g=d.find("option").length;if((g<a)||(g>b)){return}if(d.attr("multiple")==true){return}if(d.hasClass("no-autocomplete")){return}var m=d.attr("value");var c=$("<input type='text' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",d.attr("name"));c.attr("id",d.attr("id"));c.click(function(){var n=$(this).val();$(this).val("Loading...");$(this).showAllInCache();$(this).val(n);$(this).select()});var e=[];var i={};d.children("option").each(function(){var o=$(this).text();var n=$(this).attr("value");e.push(o);i[o]=n;i[n]=n;if(n==m){c.attr("value",o)}});if(m==""||m=="?"){c.attr("value","Click to Search or Select")}if(d.attr("name")=="dbkey"){e=e.sort(naturalSort)}var f={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:b,minChars:0,hideForLessThanMinChars:false};c.autocomplete(e,f);d.replaceWith(c);var k=function(){var o=c.attr("value");var n=i[o];if(n!==null&&n!==undefined){c.attr("value",n)}else{if(m!=""){c.attr("value",m)}else{c.
attr("value","?")}}};c.parents("form").submit(function(){k()});$(document).bind("convert_dbkeys",function(){k()});if(d.attr("refresh_on_change")=="true"){var h=d.attr("refresh_on_change_values"),l=d.attr("last_selected_value");if(h!==undefined){h=h.split(",")}var j=function(){var n=i[c.attr("value")];if(l!==n&&n!==null&&n!==undefined){if(h!==undefined&&$.inArray(n,h)===-1&&$.inArray(l,h)===-1){return}c.attr("value",n);$(window).trigger("refresh_on_change");c.parents("form").submit()}};c.bind("result",j);c.keyup(function(n){if(n.keyCode===13){j()}});c.keydown(function(n){if(n.keyCode===13){return false}})}})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text($.trim(k))}else{j=$("<input type='text'></input>").attr({value:$.trim(k),size:c})}j.attr("id","renaming-active");j.blur(
function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){if(o!=""){l.text(o)}else{l.html("<em>None</em>")}if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(d,a,c){var b=function(){try{var e=$.jStore.store("history_expand_state");if(e){for(var g in e){$("#"+g+" div.historyItemBody").show()}}}catch(f){$.jStore.remove("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}d.each(function(){var j=this.id;var h=$(this).children("div.historyItemBody");var i=h.find("pre.peek");$(this).find(".historyItemTitleBar > .historyItemTitle").wrap("<a href='javascript:void(0);'></a>").cl
ick(function(){if(h.is(":visible")){if($.browser.mozilla){i.css("overflow","hidden")}h.slideUp("fast");if(!c){var k=$.jStore.store("history_expand_state");if(k){delete k[j];$.jStore.store("history_expand_state",k)}}}else{h.slideDown("fast",function(){if($.browser.mozilla){i.css("overflow","auto")}});if(!c){var k=$.jStore.store("history_expand_state");if(k===undefined){k={}}k[j]=true;$.jStore.store("history_expand_state",k)}}return false})});$("#top-links > a.toggle").click(function(){var h=$.jStore.store("history_expand_state");if(h===undefined){h={}}$("div.historyItemBody:visible").each(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(h){delete h[$(this).parent().attr("id")]}});$.jStore.store("history_expand_state",h)}).show()};if(a){b()}else{$.jStore.init("galaxy");$.jStore.engineReady(function(){b()})}}function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}function rese
t_tool_search(a){var c=$("#galaxy_tools").contents();if(c.length==0){c=$(document)}$(this).removeClass("search_active");c.find(".toolTitle").removeClass("search_match");c.find(".toolSectionBody").hide();c.find(".toolTitle").show();c.find(".toolPanelLabel").show();c.find(".toolSectionWrapper").each(function(){if($(this).attr("id")!="recently_used_wrapper"){$(this).show()}else{if($(this).hasClass("user_pref_visible")){$(this).show()}}});c.find("#search-no-results").hide();c.find("#search-spinner").hide();if(a){var b=c.find("#tool-search-query");b.val("search tools");b.css("font-style","italic")}}var GalaxyAsync=function(a){this.url_dict={};this.log_action=(a===undefined?false:a)};GalaxyAsync.prototype.set_func_url=function(a,b){this.url_dict[a]=b};GalaxyAsync.prototype.set_user_pref=function(a,b){var c=this.url_dict[arguments.callee];if(c===undefined){return false}$.ajax({url:c,data:{pref_name:a,pref_value:b},error:function(){return false},success:function(){return true}})};Ga
laxyAsync.prototype.log_user_action=function(c,b,d){if(!this.log_action){return}var a=this.url_dict[arguments.callee];if(a===undefined){return false}$.ajax({url:a,data:{action:c,context:b,params:d},error:function(){return false},success:function(){return true}})};$(".trackster-add").live("click",function(){var b=this,a=$(this);$.ajax({url:a.attr("data-url"),dataType:"html",error:function(){alert("Could not add this dataset to browser.")},success:function(c){var d=window.parent;d.show_modal("Add to Browser:",c,{Cancel:function(){d.hide_modal()},"Insert into selected":function(){$(d.document).find("input[name=id]:checked").each(function(){var e=$(this).val();d.location=a.attr("action-url")+"&id="+e})},"Insert into new browser":function(){d.location=a.attr("new-url")}})}})});$(document).ready(function(){$("select[refresh_on_change='true']").change(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_val
ue");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");a.get(0).form.submit()});$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus();replace_big_select_inputs(20,1500)});
+if(!Array.indexOf){Array.prototype.indexOf=function(c){for(var b=0,a=this.length;b<a;b++){if(this[b]==c){return b}}return -1}}function obj_length(c){if(c.length!==undefined){return c.length}var b=0;for(var a in c){b++}return b}$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function show_hide_popupmenu_options(d,c,a){a=(a===undefined?true:a);var b=new RegExp(c);$(d).find("li").each(function(){if(b.exec($(this).text())){if(a){$(this).show()}else{$(this).hide()}}})}function make_popupmenu(b,a){b.bind("click.show_popup",function(c){$(".popmenu-wrapper").remove();setTimeout(function(){var e=$("<ul id='"+b.attr("id")+"-menu'></ul>");if(obj_length(a)<=0){$("<li>No Options.</li>").appendTo(e)}$.each(a,function(h,g){if(g){$("<li/>").html(h).click(g).appendTo(e)}else{$("<li class='head'/
>").html(h).appendTo(e)}});var f=$("<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'>");f.append(e).append("<div class='overlay-border'>").appendTo("body");var d=c.pageX-f.width()/2;d=Math.min(d,$(document).scrollLeft()+$(window).width()-$(f).width()-20);d=Math.max(d,$(document).scrollLeft()+20);f.css({top:c.pageY-5,left:d})},10);setTimeout(function(){var e=function(g){$(g).bind("click.close_popup",function(){$(".popmenu-wrapper").remove();g.unbind("click.close_popup")})};e($(window.document));e($(window.top.document));for(var d=window.top.frames.length;d--;){var f=$(window.top.frames[d].document);e(f)}},50);return false})}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var a={};var c=$(this);c.find("a").each(function(){var f=$(this),h=f.get(0);var d=h.getAttribute("confirm"),e=h.getAttribute("href"),g=h.getAttribute("target");a[f.text()]=function(){if(!d||confirm(d)){var i=window;if(g=="_parent"){i=window.parent}else{if(g=="_
top"){i=window.top}}i.location=e}}});var b=$("#"+c.attr("popupmenu"));b.find("a").bind("click",function(d){d.stopPropagation();return true});make_popupmenu(b,a);b.addClass("popup");c.remove()})}function naturalSort(j,h){var p=/(-?[0-9\.]+)/g,k=j.toString().toLowerCase()||"",g=h.toString().toLowerCase()||"",l=String.fromCharCode(0),n=k.replace(p,l+"$1"+l).split(l),e=g.replace(p,l+"$1"+l).split(l),d=(new Date(k)).getTime(),o=d?(new Date(g)).getTime():null;if(o){if(d<o){return -1}else{if(d>o){return 1}}}var m,f;for(var i=0,c=Math.max(n.length,e.length);i<c;i++){m=parseFloat(n[i])||n[i];f=parseFloat(e[i])||e[i];if(m<f){return -1}else{if(m>f){return 1}}}return 0}function replace_big_select_inputs(a,b){if(!jQuery().autocomplete){return}if(a===undefined){a=20}if(b===undefined){b=3000}$("select").each(function(){var d=$(this);var g=d.find("option").length;if((g<a)||(g>b)){return}if(d.attr("multiple")===true){return}if(d.hasClass("no-autocomplete")){return}var m=d.attr("value");var c
=$("<input type='text' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",d.attr("name"));c.attr("id",d.attr("id"));c.click(function(){var n=$(this).val();$(this).val("Loading...");$(this).showAllInCache();$(this).val(n);$(this).select()});var e=[];var i={};d.children("option").each(function(){var o=$(this).text();var n=$(this).attr("value");e.push(o);i[o]=n;i[n]=n;if(n==m){c.attr("value",o)}});if(m===""||m==="?"){c.attr("value","Click to Search or Select")}if(d.attr("name")=="dbkey"){e=e.sort(naturalSort)}var f={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:b,minChars:0,hideForLessThanMinChars:false};c.autocomplete(e,f);d.replaceWith(c);var k=function(){var o=c.attr("value");var n=i[o];if(n!==null&&n!==undefined){c.attr("value",n)}else{if(m!==""){c.attr("value",m)}else{c.attr("value","?")}}};c.parents("form").submit(function(){k()});$(document).bind("convert_dbkeys",function(){k()});if(d.attr("refresh_on_change")=="true
"){var h=d.attr("refresh_on_change_values"),l=d.attr("last_selected_value");if(h!==undefined){h=h.split(",")}var j=function(){var n=i[c.attr("value")];if(l!==n&&n!==null&&n!==undefined){if(h!==undefined&&$.inArray(n,h)===-1&&$.inArray(l,h)===-1){return}c.attr("value",n);$(window).trigger("refresh_on_change");c.parents("form").submit()}};c.bind("result",j);c.keyup(function(n){if(n.keyCode===13){j()}});c.keydown(function(n){if(n.keyCode===13){return false}})}})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text($.trim(k))}else{j=$("<input type='text'></input>").attr({value:$.trim(k),size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]
=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){if(o!==""){l.text(o)}else{l.html("<em>None</em>")}if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(d,a,c){var b=function(){try{var e=$.jStore.store("history_expand_state");if(e){for(var g in e){$("#"+g+" div.historyItemBody").show()}}}catch(f){$.jStore.remove("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}d.each(function(){var j=this.id,h=$(this).children("div.historyItemBody"),i=h.find("pre.peek");$(this).find(".historyItemTitleBar > .historyItemTitle").wrap("<a href='javascript:void(0);'></a>").click(function(){var k;if(h.is(":visible")){if($.browser.mozilla){i.css("overflow","hidden")}h.slideUp("fast");if(!c){k=$.jStore.store("history_expand_state");i
f(k){delete k[j];$.jStore.store("history_expand_state",k)}}}else{h.slideDown("fast",function(){if($.browser.mozilla){i.css("overflow","auto")}});if(!c){k=$.jStore.store("history_expand_state");if(k===undefined){k={}}k[j]=true;$.jStore.store("history_expand_state",k)}}return false})});$("#top-links > a.toggle").click(function(){var h=$.jStore.store("history_expand_state");if(h===undefined){h={}}$("div.historyItemBody:visible").each(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(h){delete h[$(this).parent().attr("id")]}});$.jStore.store("history_expand_state",h)}).show()};if(a){b()}else{$.jStore.init("galaxy");$.jStore.engineReady(function(){b()})}}function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}function reset_tool_search(a){var c=$("#galaxy_tools").contents();if(c.length===0){c=$(document)}$(this).removeClass("search_active");c.find(".toolTitle").removeClass("searc
h_match");c.find(".toolSectionBody").hide();c.find(".toolTitle").show();c.find(".toolPanelLabel").show();c.find(".toolSectionWrapper").each(function(){if($(this).attr("id")!="recently_used_wrapper"){$(this).show()}else{if($(this).hasClass("user_pref_visible")){$(this).show()}}});c.find("#search-no-results").hide();c.find("#search-spinner").hide();if(a){var b=c.find("#tool-search-query");b.val("search tools");b.css("font-style","italic")}}var GalaxyAsync=function(a){this.url_dict={};this.log_action=(a===undefined?false:a)};GalaxyAsync.prototype.set_func_url=function(a,b){this.url_dict[a]=b};GalaxyAsync.prototype.set_user_pref=function(a,b){var c=this.url_dict[arguments.callee];if(c===undefined){return false}$.ajax({url:c,data:{pref_name:a,pref_value:b},error:function(){return false},success:function(){return true}})};GalaxyAsync.prototype.log_user_action=function(c,b,d){if(!this.log_action){return}var a=this.url_dict[arguments.callee];if(a===undefined){return false}$.ajax({ur
l:a,data:{action:c,context:b,params:d},error:function(){return false},success:function(){return true}})};$(document).ready(function(){$("select[refresh_on_change='true']").change(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_value");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");a.get(0).form.submit()});$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus();replace_big_select_inputs(20,1500)});
1
0
galaxy-dist commit e000a6800e1c: trackster: Fix summary_tree data provider to reflect bottom level not being indexed anymore.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1288748135 14400
# Node ID e000a6800e1cbfa15a190bb2aff90a5956882a43
# Parent 56948309109207f932a113e464409432c7a38df7
trackster: Fix summary_tree data provider to reflect bottom level not being indexed anymore.
- Fix a bug causing no display modes to appear.
- Update "Visualize in Trackster" init code in root/history.mako
Fix small typo in root/tool_menu.mako
--- a/templates/root/tool_menu.mako
+++ b/templates/root/tool_menu.mako
@@ -32,7 +32,7 @@
<div class="toolTitleNoSection">
%endif
<% encoded_id = key.lstrip( 'workflow_' ) %>
- <a id="link-${workflow.id}" href="${ h.url_for( controller='workflow', action='run', id=encoded_id, check_user=False )}" target="_parent"}">${_(workflow.name)}</a>
+ <a id="link-${workflow.id}" href="${ h.url_for( controller='workflow', action='run', id=encoded_id, check_user=False )}" target="_parent">${_(workflow.name)}</a></div></%def>
--- a/static/scripts/trackster.js
+++ b/static/scripts/trackster.js
@@ -677,7 +677,7 @@ var TiledTrack = function() {
track.draw();
};
var mode_mapping = {};
- for (var i, len = track.display_modes.length; i < len; i++) {
+ for (var i = 0, len = track.display_modes.length; i < len; i++) {
var mode = track.display_modes[i];
mode_mapping[mode] = function(mode) {
return function() { change_mode(mode); };
--- a/lib/galaxy/visualization/tracks/data_providers.py
+++ b/lib/galaxy/visualization/tracks/data_providers.py
@@ -102,14 +102,14 @@ class SummaryTreeDataProvider( TracksDat
level = ceil( log( resolution, st.block_size ) ) - 1
level = int(max( level, 0 ))
- if level <= 0:
+ if level <= 1:
return None
stats = st.chrom_stats[chrom]
results = st.query(chrom, int(start), int(end), level)
if results == "detail":
return None
- elif results == "draw" or level <= 1:
+ elif results == "draw":
return "no_detail"
else:
return results, stats[level]["max"], stats[level]["avg"], stats[level]["delta"]
--- a/templates/root/history.mako
+++ b/templates/root/history.mako
@@ -157,29 +157,33 @@ TERMINAL_STATES = ${ h.to_json_string(TE
// Trackster links
function init_trackster_links() {
- $("a.trackster").live( "click", function() {
- var link = $(this),
- hid = link.attr("id").split("_")[1]; // visualize_{id}
-
+ // Add to trackster browser functionality
+ $(".trackster-add").live("click", function() {
+ var dataset = this,
+ dataset_jquery = $(this);
$.ajax({
- url: "${h.url_for( controller='tracks', action='list_tracks' )}",
- data: {'hid': hid},
- error: function() { alert( "Visualization error" ); },
- success: function(html) {
- show_modal("Add Track — Select Dataset(s)", html, {
- "New Browser": function() {
- hide_modal();
+ url: dataset_jquery.attr("data-url"),
+ dataType: "html",
+ error: function() { alert( "Could not add this dataset to browser." ); },
+ success: function(table_html) {
+ var parent = window.parent;
+ parent.show_modal("Add to Browser:", table_html, {
+ "Cancel": function() {
+ parent.hide_modal();
},
- "Insert": function() {
- hide_modal();
+ "Insert into selected": function() {
+ $(parent.document).find('input[name=id]:checked').each(function() {
+ var vis_id = $(this).val();
+ parent.location = dataset_jquery.attr("action-url") + "&id=" + vis_id;
+ });
},
- "Cancel": function() {
- hide_modal();
+ "Insert into new browser": function() {
+ parent.location = dataset_jquery.attr("new-url");
}
});
}
});
- });
+ });
}
init_trackster_links();
--- a/static/scripts/packed/trackster.js
+++ b/static/scripts/packed/trackster.js
@@ -1,1 +1,1 @@
-var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=50,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset.",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}CONTEXT=DUMMY_CANVAS.getContext("2d");PX_PER_CHAR=CONTEXT.measureText("A").width;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPa
ttern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,d,c,b){this.container=a;this.vis_id=c;this.dbkey=b;this.ti
tle=d;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init();this.reset()};$.extend(View.prototype,{init:function(){var c=this.container,a=this;this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_container=$("<div/>").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.nav);this.overview_viewport=$("<div/>").addClas
s("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div />").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(d){if(d.type==="focusout"||(d.keyCode||d.which)===13||(d.keyCode||d.which)===27){if((d.keyCode||d.wh
ich)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<span/>").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a/>").click(function(){a.zoom_out();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom-out.png" />').appendTo(this.chrom_form);this.zi_link=$("<a/>").click(function(){a.zoom_in();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom.png" />').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:
this.dbkey}),dataType:"json",success:function(e){if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}a.chrom_select.html(h);a.intro_div.show();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.overview_close.bind("click",function(){for(var e=0,d=a.tracks.length;e<d;e++){a.tracks[e].is_overview=false}$(this).siblings().filter("canvas").remove();
$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.enable_pan=(d.clientX<a.viewport_container.width()-16)?true:false}).bind("drag",function(g){if(!this.enable_pan||this.in_reordering){return}var d=$(this);var i=g.offsetX-this.current_x;var f=d.scrollTop()-(g.clientY-this.current_height);d.scrollTop(f);this.current_height=g.clientY;this.current_x=g.offsetX;var h=Math.round(i/a.viewport_container.width()*(a.high-a.low));a.move_delta(h)});this.top_labeltrack.bind("dragstart",function(d){this.drag_origin_x=d.clientX;this.drag_origin_pos=d.clientX/a.viewport_container.width()*(a.high-a.low)+a.low;this.drag_div=$("<div />").css({height:a.content_div.height()+30,top:"0px",position:"absolute","background-color":"#cfc",border:"1px solid #6a6",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag
",function(i){var f=Math.min(i.clientX,this.drag_origin_x)-a.container.offset().left,d=Math.max(i.clientX,this.drag_origin_x)-a.container.offset().left,h=(a.high-a.low),g=a.viewport_container.width();a.update_location(Math.round(f/g*h)+a.low,Math.round(d/g*h)+a.low);this.drag_div.css({left:f+"px",width:(d-f)+"px"})}).bind("dragend",function(j){var f=Math.min(j.clientX,this.drag_origin_x),d=Math.max(j.clientX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width(),i=a.low;a.low=Math.round(f/g*h)+i;a.high=Math.round(d/g*h)+i;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+c
ommatize(b))},change_chrom:function(e,b,g){var d=this;var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){return}if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()},go_to:function(f){var j=this,a,d,b=f.split(":"),h=b[0],i=b[1];if(i!==undefined){try{var g=i.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}j.change_chrom(h,a,d)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counte
r;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max
_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);th
is.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.nav_container.height()-45);this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b
){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var Track=function(b,a,d,c){this.name=b;this.view=a;this.parent_element=d;this.filters=(c!==undefined?get_filters(c):[]);this.init_global()};$.extend(Track.prototype,{init_global:function(){this.container_div=$("<div />").addClass("track").css("position","relative");i
f(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.filtering_div=$("<div class='track-filters'>").appendTo(this.container_div);this.filtering_div.hide();this.filtering_div.bind("drag",function(i){i.stopPropagation()});var b=$("<table class='filters'>").appendTo(this.filtering_div);var c=this;for(var e=0;e<this.filters.length;e++){var a=this.filters[e];var f=$("<tr>").appendTo(b);var g=$("<th class='filter-info'>").appendTo(f);var j=$("<span class='name'>").appendTo(g);j.text(a.name+" ");var d=$("<span class='values'>").appendTo(g);var h=$("<td>").appendTo(f);a.control_element=$("<div id='"+a.name+"-filter-control' style='width: 200
px; position: relative'>").appendTo(h);a.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(k,l){var i=l.values;d.text("["+i[0]+"-"+i[1]+"]");a.low=i[0];a.high=i[1];c.draw(true)},change:function(i,k){a.control_element.slider("option","slide").call(a.control_element,i,k)}});a.slider=a.control_element;a.slider_label=d}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("
<a href='javascript:void(0);'></a>").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var b=this,j=b.view;if(b.hidden){return}if(b.display_modes!==undefined){if(b.mode_div===undefined){b.mode_div=$("<div class='right-float menubutton popup' />").appendTo(b.header_div);var e=
b.display_modes[0];b.mode=e;b.mode_div.text(e);var c=function(i){b.mode_div.text(i);b.mode=i;b.tile_cache.clear();b.draw()};var a={};for(var f,h=b.display_modes.length;f<h;f++){var g=b.display_modes[f];a[g]=function(i){return function(){c(i)}}(g)}make_popupmenu(b.mode_div,a)}else{b.mode_div.hide()}}var d={};d["Set as overview"]=function(){j.overview_viewport.find("canvas").remove();b.is_overview=true;b.set_overview();for(var i in j.tracks){if(j.tracks[i]!==b){j.tracks[i].is_overview=false}}};d["Edit configuration"]=function(){var l=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},i=function(){b.update_options(b.track_id);hide_modal();$(window).unbind("keypress.check_enter_esc")},k=function(m){if((m.keyCode||m.which)===27){l()}else{if((m.keyCode||m.which)===13){i()}}};$(window).bind("keypress.check_enter_esc",k);show_modal("Configure Track",b.gen_options(b.track_id),{Cancel:l,OK:i})};if(b.filters.length>0){d["Show filters"]=function(){var i;if(!b.filterin
g_div.is(":visible")){i="Hide filters";b.filters_visible=true}else{i="Show filters";b.filters_visible=false}$("#"+b.name_div.attr("id")+"-menu").find("li").eq(2).text(i);b.filtering_div.toggle()}}d.Remove=function(){j.remove_track(b);if(j.num_tracks===0){$("#no-tracks").show()}};b.popup_menu=make_popupmenu(b.name_div,d);show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(a){var k=this.view.low,g=this.view.high,h=g-k,f=this.view.resolution;var n=$("<div style='position: relative;'></div>"),o=this.content_div.width()/h;this.content_div.append(n);this.max_height=0;var b=Math.floor(k/f/DENSITY);var j={};while((b*DENSITY*f)<g){var l=this.content_div.width()+"_"+o+"_"+b;var e=this.tile_cache.get(l);if(!a&&e){var i=b*DENSITY*f;var d=(i-k)*o;if(this.left_offset){d-=this.left_offset}e.css({left:d});this.show_tile(e,n)}else{this.delayed_draw(this,l,k,g,b,f,n,o,j)}b+=1}var c=this;var m=setInterval(function(
){if(obj_length(j)===0){if(c.content_div.children().length>1){c.content_div.children(":first").remove()}for(var p=0;p<c.filters.length;p++){c.filters[p].update_ui_elt()}clearInterval(m)}},50)},delayed_draw:function(c,h,g,e,b,d,i,j,f){var a=setTimeout(function(){if(g<=c.view.high&&e>=c.view.low){var k=c.draw_tile(d,b,i,j);if(k){if(!c.initial_canvas&&!window.G_vmlCanvasManager){c.initial_canvas=$(k).clone();var n=k.get(0).getContext("2d");var l=c.initial_canvas.get(0).getContext("2d");var m=n.getImageData(0,0,n.canvas.width,n.canvas.height);l.putImageData(m,0,0);c.set_overview()}c.tile_cache.set(h,k);c.show_tile(k,i)}}delete f[a]},50);f[a]=true},show_tile:function(a,c){var b=this;c.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|H
ide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.
append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,j=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var n=e.get(0).getContext("2d");if(o>PX_PER_CHAR){if(this.data_
cache.get(j)===undefined){this.get_data(f,b);return}var m=this.data_cache.get(j);if(m===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*o+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*o-this.left_offset});for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o),i=Math.round(o/2);n.fillText(m[h],a+this.left_offset+i,10)}k.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(d,b,a,c){this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=80;this.dataset_id=a;this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.prefs={color:"black",min_value:undefined,max_value:undefined,mode:this.mode}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a);a.verti
cal_range=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"22px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",top:a.height_px+11+"px",left:"10px"});f.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b
+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,w=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(w)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(w);if(!v){return}b.css({position:"absolute",top:0,left:(s-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;n.beginPath();n.fillStyle=this.prefs.colo
r;var u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(d-(h-k)/m*d);n.fillRect(u,h,f,d-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,d)}n.fill()}else{n.stroke()}c.append(b);return b},gen_options:function(m){var a=$("<div />").addClass("form-row");var e="track_"+m+"_color",b=$("<label />").attr("for",e).text("Color:"),c=$("<input />").attr("id",e).attr("name",e).val(this.prefs.color),h="track_"+m+"_minval",l=$("<label></label>").attr("for",h).text("Min value:"),d=(this.prefs.min_value===undefined?"":this.prefs.min_value),k=$("<input></inp
ut>").attr("id",h).val(d),j="track_"+m+"_maxval",g=$("<label></label>").attr("for",j).text("Max value:"),i=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",j).val(i);return a.append(l).append(k).append(g).append(f).append(b).append(c)},update_options:function(d){var a=$("#track_"+d+"_minval").val(),c=$("#track_"+d+"_maxval").val(),b=$("#track_"+d+"_color").val();if(a!==this.prefs.min_value||c!==this.prefs.max_value||b!==this.prefs.color){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(c);this.prefs.color=b;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+d+"_minval").text(this.prefs.min_value);$("#linetrack_"+d+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,e,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,b.viewport_container,e);TiledTrack.call(this);this.height_px=
0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=2;this.summary_draw_height=30;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"#444",label_color:"black",show_counts:true}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,mode:a.mode},function(c){a.mode_div.show();a.data_cache.set(b,c);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.
resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,g,b,q){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=q;this.s_e_by_tile[a]={}}var m=this.inc_slots[a].w_scale,y=[],h=0,n=this.view.max_low;var A=[];if(this.inc_slots[a].mode!==q){delete this.inc_slots[a];this.inc_slots[a]={mode:q,w_scale:m};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var v=0,w=g.length;v<w;v++){var f=g[v],l=f[0];if(this.inc_slots[a][l]!==undefined){h=Math.max(h,this.inc_slots[a][l]);A.push(this.inc_slots[a][l])}else{y.push(v)}}for(var v=0,w=y.length;v<w;v++){var f=g[y[v]],l=f[0],r=f[1],c=f[2],p=f[3],d=Math.floor((r-n)*m),e=Math.ceil((c-n)*m);if(p!==undefined&&!b){var s=CONTEXT.measureText(p).width;if(d-s<0){e+=s}else{d-=s}}var u=0;while(u<=MAX_FEATURE_DEPTH){var o=true;if(this.s_e_by_tile[a][u]!==undefined){for(var t=0,z=this.s_e_by_tile[a][u].length;t<z;t++){var x=this.s_e_by
_tile[a][u][t];if(e>x[0]&&d<x[1]){o=false;break}}}if(o){if(this.s_e_by_tile[a][u]===undefined){this.s_e_by_tile[a][u]=[]}this.s_e_by_tile[a][u].push([d,e]);this.inc_slots[a][l]=u;h=Math.max(h,u);break}u++}}return h},rect_or_text:function(r,l,t,b,q,f,i,e){r.textAlign="center";var k=0,p=Math.round(l/2);for(var m=0,s=i.length;m<s;m++){var j=i[m],d="MIDNSHP"[j[0]],n=j[1];if(d==="H"||d==="S"){k-=n}var g=q+k,w=Math.floor(Math.max(0,(g-t)*l)),h=Math.floor(Math.max(0,(g+n-t)*l));switch(d){case"S":case"H":case"M":var o=f.slice(k,n);if((this.mode==="Pack"||this.mode==="Auto")&&f!==undefined&&l>PX_PER_CHAR){r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+1,h-w,9);r.fillStyle=CONNECTOR_COLOR;for(var u=0,a=o.length;u<a;u++){if(g+u>=t&&g+u<=b){var v=Math.floor(Math.max(0,(g+u-t)*l));r.fillText(o[u],v+this.left_offset+p,e+9)}}}else{r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+4,h-w,3)}break;case"N":r.fillStyle=CONNECTOR_COLOR;r.fillRect(w+this.left_
offset,e+5,h-w,1);break;case"D":r.fillStyle="red";r.fillRect(w+this.left_offset,e+4,h-w,3);break;case"P":case"I":break}k+=n}},draw_tile:function(ag,o,s,av){var N=o*DENSITY*ag,al=(o+1)*DENSITY*ag,M=al-N;var an=(!this.initial_canvas?"initial":N+"_"+al);var I=this.data_cache.get(an);var e;if(I===undefined||(this.mode!=="Auto"&&I.dataset_type==="summary_tree")){this.data_queue[[N,al]]=true;this.get_data(N,al);return}var a=Math.ceil(M*av),ai=this.prefs.label_color,l=this.prefs.block_color,r=this.mode,z=25,ae=(r==="Squish")||(r==="Dense")&&(r!=="Pack")||(r==="Auto"&&(I.extra_info==="no_detail")),W=this.left_offset,au,D,aw;var q=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(q)}q=$(q);if(I.dataset_type==="summary_tree"){D=this.summary_draw_height}else{if(r==="Dense"){D=z;aw=10}else{aw=(ae?this.vertical_nodetail_px:this.vertical_detail_px);var A=(av<0.0001?1/this.view.zoom_res:av);D=this.incremental_slots(A,I.data,ae,r)*aw+z;au=this.inc
_slots[A]}}q.css({position:"absolute",top:0,left:(N-this.view.low)*av-W});q.get(0).width=a+W;q.get(0).height=D;s.parent().css("height",Math.max(this.height_px,D)+"px");var J=q.get(0).getContext("2d");J.fillStyle=l;J.font=this.default_font;J.textAlign="right";this.container_div.find(".yaxislabel").remove();if(I.dataset_type=="summary_tree"){var Y=I.data,L=I.max,b=Math.ceil(I.delta*av);var p=$("<div />").addClass("yaxislabel").text(L);p.css({position:"absolute",top:"22px",left:"10px"});p.prependTo(this.container_div);for(var ap=0,H=Y.length;ap<H;ap++){var aa=Math.floor((Y[ap][0]-N)*av);var Z=Y[ap][1];if(!Z){continue}var am=Z/L*this.summary_draw_height;J.fillStyle="black";J.fillRect(aa+W,this.summary_draw_height-am,b,am);if(this.prefs.show_counts&&J.measureText(Z).width<b){J.fillStyle="#bbb";J.textAlign="center";J.fillText(Z,aa+W+(b/2),this.summary_draw_height-5)}}e="Summary";s.append(q);return q}if(I.message){q.css({border:"solid red","border-width":"2px 2px 2px 0px"});J.fillS
tyle="red";J.textAlign="left";J.fillText(I.message,100+W,aw)}var ad=false;if(I.data){ad=true;for(var ar=0;ar<this.filters.length;ar++){if(!this.filters[ar].applies_to(I.data[0])){ad=false}}}if(ad){q.addClass(FILTERABLE_CLASS)}var at=I.data;var ao=0;for(var ap=0,H=at.length;ap<H;ap++){var S=at[ap],R=S[0],aq=S[1],ac=S[2],O=S[3];if(au[R]===undefined){continue}var ab=false;var U;for(var ar=0;ar<this.filters.length;ar++){U=this.filters[ar];U.update_attrs(S);if(!U.keep(S)){ab=true;break}}if(ab){continue}if(aq<=al&&ac>=N){var af=Math.floor(Math.max(0,(aq-N)*av)),K=Math.ceil(Math.min(a,Math.max(0,(ac-N)*av))),X=(r==="Dense"?1:(1+au[R]))*aw;var G,aj,P=null,ax=null;if(I.dataset_type==="bai"){var v=S[4];J.fillStyle=l;if(S[5] instanceof Array){var E=Math.floor(Math.max(0,(S[5][0]-N)*av)),Q=Math.ceil(Math.min(a,Math.max(0,(S[5][1]-N)*av))),C=Math.floor(Math.max(0,(S[6][0]-N)*av)),w=Math.ceil(Math.min(a,Math.max(0,(S[6][1]-N)*av)));if(S[5][1]>=N&&S[5][0]<=al){this.rect_or_text(J,av,N,al,S
[5][0],S[5][2],v,X)}if(S[6][1]>=N&&S[6][0]<=al){this.rect_or_text(J,av,N,al,S[6][0],S[6][2],v,X)}if(C>Q){J.fillStyle=CONNECTOR_COLOR;J.fillRect(Q+W,X+5,C-Q,1)}}else{J.fillStyle=l;this.rect_or_text(J,av,N,al,aq,O,v,X)}if(r!=="Dense"&&!ae&&aq>N){J.fillStyle=this.prefs.label_color;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(R,K+2+W,X+8)}else{J.textAlign="right";J.fillText(R,af-2+W,X+8)}J.fillStyle=l}}else{if(I.dataset_type==="interval_index"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var F=S[4],V=S[5],ah=S[6],h=S[7];if(V&&ah){P=Math.floor(Math.max(0,(V-N)*av));ax=Math.ceil(Math.min(a,Math.max(0,(ah-N)*av)))}if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}if(h){if(F){if(F=="+"){J.fillStyle=RIGHT_STRAND}else{if(F=="-"){J.fillStyle=LEFT_STRAND}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}for(var an=0
,g=h.length;an<g;an++){var u=h[an],d=Math.floor(Math.max(0,(u[0]-N)*av)),T=Math.ceil(Math.min(a,Math.max((u[1]-N)*av)));if(d>T){continue}G=5;aj=3;J.fillRect(d+W,X+aj,T-d,G);if(P!==undefined&&!(d>ax||T<P)){G=9;aj=1;var ak=Math.max(d,P),B=Math.min(T,ax);J.fillRect(ak+W,X+aj,B-ak,G)}}}else{G=9;aj=1;J.fillRect(af+W,X+aj,K-af,G);if(S.strand){if(S.strand=="+"){J.fillStyle=RIGHT_STRAND_INV}else{if(S.strand=="-"){J.fillStyle=LEFT_STRAND_INV}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}}}}else{if(I.dataset_type==="vcf"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var t=S[4],n=S[5],c=S[6];G=9;aj=1;J.fillRect(af+W,X,K-af,G);if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}var m=t+" / "+n;if(aq>N&&J.measureText(m).width<(K-af)){J.fillStyle="white";J.textAlign="center";J.fillText(m,W+af+(K-af)/2,X+8);J.fillStyle=l}}}}}ao++}}return q},
gen_options:function(i){var a=$("<div />").addClass("form-row");var e="track_"+i+"_block_color",k=$("<label />").attr("for",e).text("Block color:"),l=$("<input />").attr("id",e).attr("name",e).val(this.prefs.block_color),j="track_"+i+"_label_color",g=$("<label />").attr("for",j).text("Text color:"),h=$("<input />").attr("id",j).attr("name",j).val(this.prefs.label_color),f="track_"+i+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(k).append(l).append(g).append(h).append(d)},update_options:function(d){var b=$("#track_"+d+"_block_color").val(),c=$("#track_"+d+"_label_color").val(),a=$("#track_"+d+"_show_count").attr("checked");if(b!==this.prefs.block_color||c!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=c;this.prefs.show_co
unts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,e,c){FeatureTrack.call(this,d,b,a,e,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
+var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=50,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset.",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}CONTEXT=DUMMY_CANVAS.getContext("2d");PX_PER_CHAR=CONTEXT.measureText("A").width;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPa
ttern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,d,c,b){this.container=a;this.vis_id=c;this.dbkey=b;this.ti
tle=d;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init();this.reset()};$.extend(View.prototype,{init:function(){var c=this.container,a=this;this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_container=$("<div/>").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.nav);this.overview_viewport=$("<div/>").addClas
s("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div />").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(d){if(d.type==="focusout"||(d.keyCode||d.which)===13||(d.keyCode||d.which)===27){if((d.keyCode||d.wh
ich)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<span/>").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a/>").click(function(){a.zoom_out();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom-out.png" />').appendTo(this.chrom_form);this.zi_link=$("<a/>").click(function(){a.zoom_in();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom.png" />').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:
this.dbkey}),dataType:"json",success:function(e){if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}a.chrom_select.html(h);a.intro_div.show();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.overview_close.bind("click",function(){for(var e=0,d=a.tracks.length;e<d;e++){a.tracks[e].is_overview=false}$(this).siblings().filter("canvas").remove();
$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.enable_pan=(d.clientX<a.viewport_container.width()-16)?true:false}).bind("drag",function(g){if(!this.enable_pan||this.in_reordering){return}var d=$(this);var i=g.offsetX-this.current_x;var f=d.scrollTop()-(g.clientY-this.current_height);d.scrollTop(f);this.current_height=g.clientY;this.current_x=g.offsetX;var h=Math.round(i/a.viewport_container.width()*(a.high-a.low));a.move_delta(h)});this.top_labeltrack.bind("dragstart",function(d){this.drag_origin_x=d.clientX;this.drag_origin_pos=d.clientX/a.viewport_container.width()*(a.high-a.low)+a.low;this.drag_div=$("<div />").css({height:a.content_div.height()+30,top:"0px",position:"absolute","background-color":"#cfc",border:"1px solid #6a6",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag
",function(i){var f=Math.min(i.clientX,this.drag_origin_x)-a.container.offset().left,d=Math.max(i.clientX,this.drag_origin_x)-a.container.offset().left,h=(a.high-a.low),g=a.viewport_container.width();a.update_location(Math.round(f/g*h)+a.low,Math.round(d/g*h)+a.low);this.drag_div.css({left:f+"px",width:(d-f)+"px"})}).bind("dragend",function(j){var f=Math.min(j.clientX,this.drag_origin_x),d=Math.max(j.clientX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width(),i=a.low;a.low=Math.round(f/g*h)+i;a.high=Math.round(d/g*h)+i;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+c
ommatize(b))},change_chrom:function(e,b,g){var d=this;var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){return}if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()},go_to:function(f){var j=this,a,d,b=f.split(":"),h=b[0],i=b[1];if(i!==undefined){try{var g=i.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}j.change_chrom(h,a,d)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counte
r;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max
_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);th
is.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.nav_container.height()-45);this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b
){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var Track=function(b,a,d,c){this.name=b;this.view=a;this.parent_element=d;this.filters=(c!==undefined?get_filters(c):[]);this.init_global()};$.extend(Track.prototype,{init_global:function(){this.container_div=$("<div />").addClass("track").css("position","relative");i
f(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.filtering_div=$("<div class='track-filters'>").appendTo(this.container_div);this.filtering_div.hide();this.filtering_div.bind("drag",function(i){i.stopPropagation()});var b=$("<table class='filters'>").appendTo(this.filtering_div);var c=this;for(var e=0;e<this.filters.length;e++){var a=this.filters[e];var f=$("<tr>").appendTo(b);var g=$("<th class='filter-info'>").appendTo(f);var j=$("<span class='name'>").appendTo(g);j.text(a.name+" ");var d=$("<span class='values'>").appendTo(g);var h=$("<td>").appendTo(f);a.control_element=$("<div id='"+a.name+"-filter-control' style='width: 200
px; position: relative'>").appendTo(h);a.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(k,l){var i=l.values;d.text("["+i[0]+"-"+i[1]+"]");a.low=i[0];a.high=i[1];c.draw(true)},change:function(i,k){a.control_element.slider("option","slide").call(a.control_element,i,k)}});a.slider=a.control_element;a.slider_label=d}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("
<a href='javascript:void(0);'></a>").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var b=this,j=b.view;if(b.hidden){return}if(b.display_modes!==undefined){if(b.mode_div===undefined){b.mode_div=$("<div class='right-float menubutton popup' />").appendTo(b.header_div);var e=
b.display_modes[0];b.mode=e;b.mode_div.text(e);var c=function(i){b.mode_div.text(i);b.mode=i;b.tile_cache.clear();b.draw()};var a={};for(var f=0,h=b.display_modes.length;f<h;f++){var g=b.display_modes[f];a[g]=function(i){return function(){c(i)}}(g)}make_popupmenu(b.mode_div,a)}else{b.mode_div.hide()}}var d={};d["Set as overview"]=function(){j.overview_viewport.find("canvas").remove();b.is_overview=true;b.set_overview();for(var i in j.tracks){if(j.tracks[i]!==b){j.tracks[i].is_overview=false}}};d["Edit configuration"]=function(){var l=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},i=function(){b.update_options(b.track_id);hide_modal();$(window).unbind("keypress.check_enter_esc")},k=function(m){if((m.keyCode||m.which)===27){l()}else{if((m.keyCode||m.which)===13){i()}}};$(window).bind("keypress.check_enter_esc",k);show_modal("Configure Track",b.gen_options(b.track_id),{Cancel:l,OK:i})};if(b.filters.length>0){d["Show filters"]=function(){var i;if(!b.filter
ing_div.is(":visible")){i="Hide filters";b.filters_visible=true}else{i="Show filters";b.filters_visible=false}$("#"+b.name_div.attr("id")+"-menu").find("li").eq(2).text(i);b.filtering_div.toggle()}}d.Remove=function(){j.remove_track(b);if(j.num_tracks===0){$("#no-tracks").show()}};b.popup_menu=make_popupmenu(b.name_div,d);show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(a){var k=this.view.low,g=this.view.high,h=g-k,f=this.view.resolution;var n=$("<div style='position: relative;'></div>"),o=this.content_div.width()/h;this.content_div.append(n);this.max_height=0;var b=Math.floor(k/f/DENSITY);var j={};while((b*DENSITY*f)<g){var l=this.content_div.width()+"_"+o+"_"+b;var e=this.tile_cache.get(l);if(!a&&e){var i=b*DENSITY*f;var d=(i-k)*o;if(this.left_offset){d-=this.left_offset}e.css({left:d});this.show_tile(e,n)}else{this.delayed_draw(this,l,k,g,b,f,n,o,j)}b+=1}var c=this;var m=setInterval(functio
n(){if(obj_length(j)===0){if(c.content_div.children().length>1){c.content_div.children(":first").remove()}for(var p=0;p<c.filters.length;p++){c.filters[p].update_ui_elt()}clearInterval(m)}},50)},delayed_draw:function(c,h,g,e,b,d,i,j,f){var a=setTimeout(function(){if(g<=c.view.high&&e>=c.view.low){var k=c.draw_tile(d,b,i,j);if(k){if(!c.initial_canvas&&!window.G_vmlCanvasManager){c.initial_canvas=$(k).clone();var n=k.get(0).getContext("2d");var l=c.initial_canvas.get(0).getContext("2d");var m=n.getImageData(0,0,n.canvas.width,n.canvas.height);l.putImageData(m,0,0);c.set_overview()}c.tile_cache.set(h,k);c.show_tile(k,i)}}delete f[a]},50);f[a]=true},show_tile:function(a,c){var b=this;c.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show
|Hide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_di
v.append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,j=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var n=e.get(0).getContext("2d");if(o>PX_PER_CHAR){if(this.dat
a_cache.get(j)===undefined){this.get_data(f,b);return}var m=this.data_cache.get(j);if(m===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*o+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*o-this.left_offset});for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o),i=Math.round(o/2);n.fillText(m[h],a+this.left_offset+i,10)}k.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(d,b,a,c){this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=80;this.dataset_id=a;this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.prefs={color:"black",min_value:undefined,max_value:undefined,mode:this.mode}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a);a.ver
tical_range=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"22px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",top:a.height_px+11+"px",left:"10px"});f.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=
(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,w=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(w)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(w);if(!v){return}b.css({position:"absolute",top:0,left:(s-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;n.beginPath();n.fillStyle=this.prefs.co
lor;var u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(d-(h-k)/m*d);n.fillRect(u,h,f,d-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,d)}n.fill()}else{n.stroke()}c.append(b);return b},gen_options:function(m){var a=$("<div />").addClass("form-row");var e="track_"+m+"_color",b=$("<label />").attr("for",e).text("Color:"),c=$("<input />").attr("id",e).attr("name",e).val(this.prefs.color),h="track_"+m+"_minval",l=$("<label></label>").attr("for",h).text("Min value:"),d=(this.prefs.min_value===undefined?"":this.prefs.min_value),k=$("<input></i
nput>").attr("id",h).val(d),j="track_"+m+"_maxval",g=$("<label></label>").attr("for",j).text("Max value:"),i=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",j).val(i);return a.append(l).append(k).append(g).append(f).append(b).append(c)},update_options:function(d){var a=$("#track_"+d+"_minval").val(),c=$("#track_"+d+"_maxval").val(),b=$("#track_"+d+"_color").val();if(a!==this.prefs.min_value||c!==this.prefs.max_value||b!==this.prefs.color){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(c);this.prefs.color=b;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+d+"_minval").text(this.prefs.min_value);$("#linetrack_"+d+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,e,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,b.viewport_container,e);TiledTrack.call(this);this.height_p
x=0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=2;this.summary_draw_height=30;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"#444",label_color:"black",show_counts:true}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,mode:a.mode},function(c){a.mode_div.show();a.data_cache.set(b,c);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.vie
w.resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,g,b,q){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=q;this.s_e_by_tile[a]={}}var m=this.inc_slots[a].w_scale,y=[],h=0,n=this.view.max_low;var A=[];if(this.inc_slots[a].mode!==q){delete this.inc_slots[a];this.inc_slots[a]={mode:q,w_scale:m};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var v=0,w=g.length;v<w;v++){var f=g[v],l=f[0];if(this.inc_slots[a][l]!==undefined){h=Math.max(h,this.inc_slots[a][l]);A.push(this.inc_slots[a][l])}else{y.push(v)}}for(var v=0,w=y.length;v<w;v++){var f=g[y[v]],l=f[0],r=f[1],c=f[2],p=f[3],d=Math.floor((r-n)*m),e=Math.ceil((c-n)*m);if(p!==undefined&&!b){var s=CONTEXT.measureText(p).width;if(d-s<0){e+=s}else{d-=s}}var u=0;while(u<=MAX_FEATURE_DEPTH){var o=true;if(this.s_e_by_tile[a][u]!==undefined){for(var t=0,z=this.s_e_by_tile[a][u].length;t<z;t++){var x=this.s_e_
by_tile[a][u][t];if(e>x[0]&&d<x[1]){o=false;break}}}if(o){if(this.s_e_by_tile[a][u]===undefined){this.s_e_by_tile[a][u]=[]}this.s_e_by_tile[a][u].push([d,e]);this.inc_slots[a][l]=u;h=Math.max(h,u);break}u++}}return h},rect_or_text:function(r,l,t,b,q,f,i,e){r.textAlign="center";var k=0,p=Math.round(l/2);for(var m=0,s=i.length;m<s;m++){var j=i[m],d="MIDNSHP"[j[0]],n=j[1];if(d==="H"||d==="S"){k-=n}var g=q+k,w=Math.floor(Math.max(0,(g-t)*l)),h=Math.floor(Math.max(0,(g+n-t)*l));switch(d){case"S":case"H":case"M":var o=f.slice(k,n);if((this.mode==="Pack"||this.mode==="Auto")&&f!==undefined&&l>PX_PER_CHAR){r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+1,h-w,9);r.fillStyle=CONNECTOR_COLOR;for(var u=0,a=o.length;u<a;u++){if(g+u>=t&&g+u<=b){var v=Math.floor(Math.max(0,(g+u-t)*l));r.fillText(o[u],v+this.left_offset+p,e+9)}}}else{r.fillStyle=this.prefs.block_color;r.fillRect(w+this.left_offset,e+4,h-w,3)}break;case"N":r.fillStyle=CONNECTOR_COLOR;r.fillRect(w+this.lef
t_offset,e+5,h-w,1);break;case"D":r.fillStyle="red";r.fillRect(w+this.left_offset,e+4,h-w,3);break;case"P":case"I":break}k+=n}},draw_tile:function(ag,o,s,av){var N=o*DENSITY*ag,al=(o+1)*DENSITY*ag,M=al-N;var an=(!this.initial_canvas?"initial":N+"_"+al);var I=this.data_cache.get(an);var e;if(I===undefined||(this.mode!=="Auto"&&I.dataset_type==="summary_tree")){this.data_queue[[N,al]]=true;this.get_data(N,al);return}var a=Math.ceil(M*av),ai=this.prefs.label_color,l=this.prefs.block_color,r=this.mode,z=25,ae=(r==="Squish")||(r==="Dense")&&(r!=="Pack")||(r==="Auto"&&(I.extra_info==="no_detail")),W=this.left_offset,au,D,aw;var q=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(q)}q=$(q);if(I.dataset_type==="summary_tree"){D=this.summary_draw_height}else{if(r==="Dense"){D=z;aw=10}else{aw=(ae?this.vertical_nodetail_px:this.vertical_detail_px);var A=(av<0.0001?1/this.view.zoom_res:av);D=this.incremental_slots(A,I.data,ae,r)*aw+z;au=this.i
nc_slots[A]}}q.css({position:"absolute",top:0,left:(N-this.view.low)*av-W});q.get(0).width=a+W;q.get(0).height=D;s.parent().css("height",Math.max(this.height_px,D)+"px");var J=q.get(0).getContext("2d");J.fillStyle=l;J.font=this.default_font;J.textAlign="right";this.container_div.find(".yaxislabel").remove();if(I.dataset_type=="summary_tree"){var Y=I.data,L=I.max,b=Math.ceil(I.delta*av);var p=$("<div />").addClass("yaxislabel").text(L);p.css({position:"absolute",top:"22px",left:"10px"});p.prependTo(this.container_div);for(var ap=0,H=Y.length;ap<H;ap++){var aa=Math.floor((Y[ap][0]-N)*av);var Z=Y[ap][1];if(!Z){continue}var am=Z/L*this.summary_draw_height;J.fillStyle="black";J.fillRect(aa+W,this.summary_draw_height-am,b,am);if(this.prefs.show_counts&&J.measureText(Z).width<b){J.fillStyle="#bbb";J.textAlign="center";J.fillText(Z,aa+W+(b/2),this.summary_draw_height-5)}}e="Summary";s.append(q);return q}if(I.message){q.css({border:"solid red","border-width":"2px 2px 2px 0px"});J.fil
lStyle="red";J.textAlign="left";J.fillText(I.message,100+W,aw)}var ad=false;if(I.data){ad=true;for(var ar=0;ar<this.filters.length;ar++){if(!this.filters[ar].applies_to(I.data[0])){ad=false}}}if(ad){q.addClass(FILTERABLE_CLASS)}var at=I.data;var ao=0;for(var ap=0,H=at.length;ap<H;ap++){var S=at[ap],R=S[0],aq=S[1],ac=S[2],O=S[3];if(au[R]===undefined){continue}var ab=false;var U;for(var ar=0;ar<this.filters.length;ar++){U=this.filters[ar];U.update_attrs(S);if(!U.keep(S)){ab=true;break}}if(ab){continue}if(aq<=al&&ac>=N){var af=Math.floor(Math.max(0,(aq-N)*av)),K=Math.ceil(Math.min(a,Math.max(0,(ac-N)*av))),X=(r==="Dense"?1:(1+au[R]))*aw;var G,aj,P=null,ax=null;if(I.dataset_type==="bai"){var v=S[4];J.fillStyle=l;if(S[5] instanceof Array){var E=Math.floor(Math.max(0,(S[5][0]-N)*av)),Q=Math.ceil(Math.min(a,Math.max(0,(S[5][1]-N)*av))),C=Math.floor(Math.max(0,(S[6][0]-N)*av)),w=Math.ceil(Math.min(a,Math.max(0,(S[6][1]-N)*av)));if(S[5][1]>=N&&S[5][0]<=al){this.rect_or_text(J,av,N,al
,S[5][0],S[5][2],v,X)}if(S[6][1]>=N&&S[6][0]<=al){this.rect_or_text(J,av,N,al,S[6][0],S[6][2],v,X)}if(C>Q){J.fillStyle=CONNECTOR_COLOR;J.fillRect(Q+W,X+5,C-Q,1)}}else{J.fillStyle=l;this.rect_or_text(J,av,N,al,aq,O,v,X)}if(r!=="Dense"&&!ae&&aq>N){J.fillStyle=this.prefs.label_color;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(R,K+2+W,X+8)}else{J.textAlign="right";J.fillText(R,af-2+W,X+8)}J.fillStyle=l}}else{if(I.dataset_type==="interval_index"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var F=S[4],V=S[5],ah=S[6],h=S[7];if(V&&ah){P=Math.floor(Math.max(0,(V-N)*av));ax=Math.ceil(Math.min(a,Math.max(0,(ah-N)*av)))}if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}if(h){if(F){if(F=="+"){J.fillStyle=RIGHT_STRAND}else{if(F=="-"){J.fillStyle=LEFT_STRAND}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}for(var an
=0,g=h.length;an<g;an++){var u=h[an],d=Math.floor(Math.max(0,(u[0]-N)*av)),T=Math.ceil(Math.min(a,Math.max((u[1]-N)*av)));if(d>T){continue}G=5;aj=3;J.fillRect(d+W,X+aj,T-d,G);if(P!==undefined&&!(d>ax||T<P)){G=9;aj=1;var ak=Math.max(d,P),B=Math.min(T,ax);J.fillRect(ak+W,X+aj,B-ak,G)}}}else{G=9;aj=1;J.fillRect(af+W,X+aj,K-af,G);if(S.strand){if(S.strand=="+"){J.fillStyle=RIGHT_STRAND_INV}else{if(S.strand=="-"){J.fillStyle=LEFT_STRAND_INV}}J.fillRect(af+W,X,K-af,10);J.fillStyle=l}}}}else{if(I.dataset_type==="vcf"){if(ae){J.fillStyle=l;J.fillRect(af+W,X+5,K-af,1)}else{var t=S[4],n=S[5],c=S[6];G=9;aj=1;J.fillRect(af+W,X,K-af,G);if(r!=="Dense"&&O!==undefined&&aq>N){J.fillStyle=ai;if(o===0&&af-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+W,X+8)}else{J.textAlign="right";J.fillText(O,af-2+W,X+8)}J.fillStyle=l}var m=t+" / "+n;if(aq>N&&J.measureText(m).width<(K-af)){J.fillStyle="white";J.textAlign="center";J.fillText(m,W+af+(K-af)/2,X+8);J.fillStyle=l}}}}}ao++}}return q
},gen_options:function(i){var a=$("<div />").addClass("form-row");var e="track_"+i+"_block_color",k=$("<label />").attr("for",e).text("Block color:"),l=$("<input />").attr("id",e).attr("name",e).val(this.prefs.block_color),j="track_"+i+"_label_color",g=$("<label />").attr("for",j).text("Text color:"),h=$("<input />").attr("id",j).attr("name",j).val(this.prefs.label_color),f="track_"+i+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(k).append(l).append(g).append(h).append(d)},update_options:function(d){var b=$("#track_"+d+"_block_color").val(),c=$("#track_"+d+"_label_color").val(),a=$("#track_"+d+"_show_count").attr("checked");if(b!==this.prefs.block_color||c!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=c;this.prefs.show_
counts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,e,c){FeatureTrack.call(this,d,b,a,e,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
1
0
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1288760547 14400
# Node ID 49f0e8441a4da6b1ec03250448ab84854f07aa77
# Parent 37477f7d10e7407186bd189fdec9e114e4b8f3d2
sample tracking
- new file browser for selecting datasets in the sequencer
--- a/templates/admin/requests/get_data.mako
+++ b/templates/admin/requests/get_data.mako
@@ -1,71 +1,71 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
+${h.js( "ui.core", "jquery.cookie" )}
+<link href='/static/june_2007_style/blue/dynatree_skin/ui.dynatree.css' rel='stylesheet' type='text/css'>
+${h.js( "jquery.dynatree" )}
<script type="text/javascript">
- $(document).ready(function(){
- //hide the all of the element with class msg_body
- $(".msg_body").hide();
- //toggle the component with class msg_body
- $(".msg_head").click(function(){
- $(this).next(".msg_body").slideToggle(450);
- });
+ $(function(){
+ $("#tree").ajaxComplete(function(event, XMLHttpRequest, ajaxOptions) {
+ _log("debug", "ajaxComplete: %o", this); // dom element listening
+ });
+ // --- Initialize sample trees
+ $("#tree").dynatree({
+ title: "${request.type.datatx_info['data_dir']}",
+ rootVisible: true,
+ minExpandLevel: 0, // 1: root node is not collapsible
+ persist: false,
+ checkbox: true,
+ selectMode: 3,
+ onPostInit: function(isReloading, isError) {
+// alert("reloading: "+isReloading+", error:"+isError);
+ logMsg("onPostInit(%o, %o) - %o", isReloading, isError, this);
+ // Re-fire onActivate, so the text is updated
+ this.reactivate();
+ },
+ fx: { height: "toggle", duration: 200 },
+ // initAjax is hard to fake, so we pass the children as object array:
+ initAjax: {url: "${h.url_for( controller='requests_admin', action='open_folder' )}",
+ dataType: "json",
+ data: { id: "${request.id}", key: "${request.type.datatx_info['data_dir']}" },
+ },
+ onLazyRead: function(dtnode){
+ dtnode.appendAjax({
+ url: "${h.url_for( controller='requests_admin', action='open_folder' )}",
+ dataType: "json",
+ data: { id: "${request.id}", key: dtnode.data.key },
+ });
+ },
+ onSelect: function(select, dtnode) {
+ // Display list of selected nodes
+ var selNodes = dtnode.tree.getSelectedNodes();
+ // convert to title/key array
+ var selKeys = $.map(selNodes, function(node){
+ return node.data.key;
+ });
+ document.get_data.selected_files.value = selKeys.join(",")
+ },
+ onActivate: function(dtnode) {
+ var cell = $("#file_details");
+ var selected_value = dtnode.data.key
+ if(selected_value.charAt(selected_value.length-1) != '/') {
+ // Make ajax call
+ $.ajax( {
+ type: "POST",
+ url: "${h.url_for( controller='requests_admin', action='get_file_details' )}",
+ dataType: "json",
+ data: { id: "${request.id}", folder_path: dtnode.data.key },
+ success : function ( data ) {
+ cell.html( '<label>'+data+'</label>' )
+ }
+ });
+ } else {
+ cell.html( '' )
+ }
+ },
+ });
});
- function display_file_details(request_id, folder_path)
- {
- var w = document.get_data.files_list.selectedIndex;
- var selected_value = document.get_data.files_list.options[w].value;
- var cell = $("#file_details");
- if(selected_value.charAt(selected_value.length-1) != '/')
- {
- // Make ajax call
- $.ajax( {
- type: "POST",
- url: "${h.url_for( controller='requests_admin', action='get_file_details' )}",
- dataType: "json",
- data: { id: request_id, folder_path: document.get_data.folder_path.value + selected_value },
- success : function ( data ) {
- cell.html( '<label>'+data+'</label>' )
- }
- });
- }
- else
- {
- cell.html( '' )
- }
- }
-
- function open_folder1( request_id, folder_path )
- {
- var w = document.get_data.files_list.selectedIndex;
- var selected_value = document.get_data.files_list.options[w].value;
- var cell = $("#file_details");
- if(selected_value.charAt(selected_value.length-1) == '/')
- {
- document.get_data.folder_path.value = document.get_data.folder_path.value+selected_value
- // Make ajax call
- $.ajax( {
- type: "POST",
- url: "${h.url_for( controller='requests_admin', action='open_folder' )}",
- dataType: "json",
- data: { id: request_id, folder_path: document.get_data.folder_path.value },
- success : function ( data ) {
- document.get_data.files_list.options.length = 0
- for(i=0; i<data.length; i++)
- {
- var newOpt = new Option(data[i], data[i]);
- document.get_data.files_list.options[i] = newOpt;
- }
- //cell.html( '<label>'+data+'</label>' )
-
- }
- });
- }
- else
- {
- cell.html( '' )
- }
- }
</script><br/>
@@ -92,18 +92,16 @@
<div class="toolParamHelp" style="clear: both;">
Select the sample with which you want to associate the datasets
</div>
- <br/>
- <label>Folder path on the sequencer:</label>
- <input type="text" name="folder_path" value="${folder_path}" size="100"/>
- <input type="submit" name="browse_button" value="List contents"/>
- <input type="submit" name="folder_up" value="Up"/></div>
- <div class="form-row">
- <select name="files_list" id="files_list" style="max-width: 60%; width: 98%; height: 150px; font-size: 100%;" ondblclick="open_folder1(${request.id}, '${folder_path}')" onChange="display_file_details(${request.id}, '${folder_path}')" multiple>
- %for index, f in enumerate( files ):
- <option value="${f}">${f}</option>
- %endfor
- </select>
+ <div class="form-row" >
+ <label>Select dataset files in the sequencer:</label>
+ <div id="tree" >
+ Loading...
+ </div>
+ <input id="selected_files" name="selected_files" type="hidden" size=40"/>
+ <div class="toolParamHelp" style="clear: both;">
+ To select a folder, select all the individual files in that folder.
+ </div></div><div class="form-row"><div id="file_details" class="toolParamHelp" style="clear: both;background-color:#FAFAFA;"></div>
Binary file static/june_2007_style/blue/dynatree_skin/rbUnchecked_hover.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/cbChecked.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltError.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/cbIntermediate.gif has changed
--- a/lib/galaxy/web/controllers/requests_admin.py
+++ b/lib/galaxy/web/controllers/requests_admin.py
@@ -316,7 +316,6 @@ class RequestsAdmin( BaseController, Use
dict( controller='requests_admin',
action='get_data',
request_id=request_id,
- folder_path=sample.request.type.datatx_info[ 'data_dir' ],
sample_id=sample_id ) ),
grids.GridAction( "Browse target data library",
dict( controller='library_common',
@@ -383,67 +382,61 @@ class RequestsAdmin( BaseController, Use
request = trans.sa_session.query( trans.model.Request ).get( trans.security.decode_id( request_id ) )
except:
return invalid_id_redirect( trans, 'requests_admin', request_id )
- selected_files = util.listify( params.get( 'files_list', [] ) )
- folder_path = util.restore_text( params.get( 'folder_path', request.type.datatx_info[ 'data_dir' ] ) )
+ selected_files = util.restore_text( params.get( 'selected_files', '' ) )
+ if len( selected_files ):
+ selected_files = selected_files.split(',')
+ else:
+ selected_files = []
selected_sample_id = kwd.get( 'sample_id', 'none' )
sample_id_select_field = self.__build_sample_id_select_field( trans, request, selected_sample_id )
# The __get_files() method redirects here with a status of 'error' and a message if there
# was a problem retrieving the files.
- if folder_path and status != 'error':
- folder_path = self.__check_path( folder_path )
- if params.get( 'folder_up', False ):
- if folder_path[-1] == os.sep:
- folder_path = os.path.dirname( folder_path[:-1] )
- folder_path = self.__check_path( folder_path )
- elif params.get( 'open_folder', False ):
- if len(selected_files) == 1:
- folder_path = os.path.join(folder_path, selected_files[0])
- folder_path = self.__check_path( folder_path )
- elif params.get( 'select_show_datasets_button', False ) or params.get( 'select_more_button', False ):
- # get the sample these datasets are associated with
- try:
- sample = trans.sa_session.query( trans.model.Sample ).get( trans.security.decode_id( selected_sample_id ) )
- except:
- return invalid_id_redirect( trans, 'requests_admin', selected_sample_id )
- if sample in sample.request.samples_without_library_destinations:
- # Display an error if a sample has been selected that
- # has not yet been associated with a destination library.
- status = 'error'
- message = 'Select a sample with associated data library and folder before selecting the datasets.'
- return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='get_data',
- request_id=request_id,
- folder_path=folder_path,
- status=status,
- message=message ) )
- # Save the sample datasets
- sample_dataset_file_names = self.__save_sample_datasets( trans, sample, selected_files, folder_path )
- if sample_dataset_file_names:
- message = 'Datasets (%s) have been selected for sample (%s)' % \
- ( str( sample_dataset_file_names )[1:-1].replace( "'", "" ), sample.name )
- if params.get( 'select_show_datasets_button', False ):
- return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='manage_datasets',
- request_id=request_id,
- sample_id=selected_sample_id,
- message=message,
- status=status ) )
- else: # 'select_more_button' was clicked
- return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='get_data',
- request_id=request_id,
- folder_path=folder_path,
- sample_id=sample.id,
- message=message,
- status=status ) )
- # Get the filenames from the remote host
- files = self.__get_files( trans, request, folder_path )
+ if params.get( 'select_show_datasets_button', False ) or params.get( 'select_more_button', False ):
+ # get the sample these datasets are associated with
+ try:
+ sample = trans.sa_session.query( trans.model.Sample ).get( trans.security.decode_id( selected_sample_id ) )
+ except:
+ message = 'Select a sample before selecting its associated datasets.'
+ return trans.fill_template( '/admin/requests/get_data.mako',
+ cntrller='requests_admin',
+ request=request,
+ sample_id_select_field=sample_id_select_field,
+ status='error',
+ message=message )
+ if sample in sample.request.samples_without_library_destinations:
+ # Display an error if a sample has been selected that
+ # has not yet been associated with a destination library.
+ status = 'error'
+ message = 'Select a sample with associated data library and folder before selecting the datasets.'
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='get_data',
+ request_id=request_id,
+ sample_id=sample.id,
+ status=status,
+ message=message ) )
+ # Save the sample datasets
+ sample_dataset_file_names = self.__save_sample_datasets( trans, sample, selected_files )
+ if sample_dataset_file_names:
+ message = 'Datasets (%s) have been selected for sample (%s)' % \
+ ( str( sample_dataset_file_names )[1:-1].replace( "'", "" ), sample.name )
+ if params.get( 'select_show_datasets_button', False ):
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='manage_datasets',
+ request_id=request_id,
+ sample_id=selected_sample_id,
+ message=message,
+ status=status ) )
+ else: # 'select_more_button' was clicked
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='get_data',
+ request_id=request_id,
+ sample_id=sample.id,
+ message=message,
+ status=status ) )
return trans.fill_template( '/admin/requests/get_data.mako',
cntrller='requests_admin',
request=request,
sample_id_select_field=sample_id_select_field,
- files=files,
- folder_path=folder_path,
status=status,
message=message )
@web.json
@@ -464,15 +457,27 @@ class RequestsAdmin( BaseController, Use
timeout=10 )
return unicode( output.replace( '\n', '<br/>' ) )
@web.json
- def open_folder( self, trans, id, folder_path ):
- def print_ticks( d ):
- # pexpect timeout method
- pass
+ def open_folder( self, trans, id, key ):
# Avoid caching
trans.response.headers['Pragma'] = 'no-cache'
trans.response.headers['Expires'] = '0'
request = trans.sa_session.query( trans.model.Request ).get( int( id ) )
- return self.__get_files( trans, request, folder_path )
+ folder_path = key
+ files_list = self.__get_files( trans, request, folder_path )
+ folder_contents = []
+ for filename in files_list:
+ is_folder = False
+ if filename[-1] == os.sep:
+ is_folder = True
+ full_path = os.path.join(folder_path, filename)
+ node = {"title": filename,
+ "isFolder": is_folder,
+ "isLazy": is_folder,
+ "tooltip": full_path,
+ "key": full_path
+ }
+ folder_contents.append(node)
+ return folder_contents
def __get_files( self, trans, request, folder_path ):
# Retrieves the filenames to be transferred from the remote host.
ok = True
@@ -496,7 +501,6 @@ class RequestsAdmin( BaseController, Use
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='get_data',
request_id=trans.security.encode_id( request.id ),
- folder_path=folder_path,
status=status,
message=message ) )
def __check_path( self, a_path ):
@@ -504,20 +508,13 @@ class RequestsAdmin( BaseController, Use
if a_path and not a_path.endswith( os.sep ):
a_path += os.sep
return a_path
- def __save_sample_datasets( self, trans, sample, selected_files, folder_path ):
+ def __save_sample_datasets( self, trans, sample, selected_files ):
sample_dataset_file_names = []
if selected_files:
- for f in selected_files:
- filepath = os.path.join( folder_path, f )
- if f[-1] == os.sep:
- # FIXME: The selected item is a folder so transfer all the folder contents
- request_id = trans.security.ecnode_id( sample.request.id )
- return trans.response.send_redirect( web.url_for( controller='requests_admin',
- action='get_data',
- request_id=request_id,
- folder_path=folder_path,
- open_folder=True ) )
- else:
+ for filepath in selected_files:
+ # FIXME: handle folder selection
+ # ignore folders for now
+ if filepath[-1] != os.sep:
name = self.__dataset_name( sample, filepath.split( '/' )[-1] )
sample_dataset = trans.model.SampleDataset( sample=sample,
file_path=filepath,
Binary file static/june_2007_style/blue/dynatree_skin/ltP_nes.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltFld.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/rbIntermediate.gif has changed
--- /dev/null
+++ b/static/scripts/packed/ui.core.js
@@ -0,0 +1,1 @@
+jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.1",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m<n.length;m++){if(j.options[n[m][0]]){n[m][1].apply(j.element,k)}}}},contains:function(k,j){return document.compareDocumentPosition?k.compareDocumentPosition(j)&16:k!==j&&k.contains(j)},hasScroll:function(m,k){if(c(m).css("overflow")=="hidden"){return false}var j=(k&&k=="left")?"scrollLeft":"scrollTop",l=false;if(m[j]>0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NU
MPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","no
ne").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function
(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bin
d("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:f
unction(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalE
vent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j
)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);
Binary file static/june_2007_style/blue/dynatree_skin/ltP_ne.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/cbIntermediate_hover.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltDoc.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/rbUnchecked.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltWait.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/cbChecked_hover.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/customDoc1.gif has changed
--- /dev/null
+++ b/static/scripts/ui.core.js
@@ -0,0 +1,519 @@
+/*
+ * jQuery UI 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+;jQuery.ui || (function($) {
+
+var _remove = $.fn.remove,
+ isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
+
+//Helper functions and ui object
+$.ui = {
+ version: "1.7.1",
+
+ // $.ui.plugin is deprecated. Use the proxy pattern instead.
+ plugin: {
+ add: function(module, option, set) {
+ var proto = $.ui[module].prototype;
+ for(var i in set) {
+ proto.plugins[i] = proto.plugins[i] || [];
+ proto.plugins[i].push([option, set[i]]);
+ }
+ },
+ call: function(instance, name, args) {
+ var set = instance.plugins[name];
+ if(!set || !instance.element[0].parentNode) { return; }
+
+ for (var i = 0; i < set.length; i++) {
+ if (instance.options[set[i][0]]) {
+ set[i][1].apply(instance.element, args);
+ }
+ }
+ }
+ },
+
+ contains: function(a, b) {
+ return document.compareDocumentPosition
+ ? a.compareDocumentPosition(b) & 16
+ : a !== b && a.contains(b);
+ },
+
+ hasScroll: function(el, a) {
+
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
+ if ($(el).css('overflow') == 'hidden') { return false; }
+
+ var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
+ has = false;
+
+ if (el[scroll] > 0) { return true; }
+
+ // TODO: determine which cases actually cause this to happen
+ // if the element doesn't have the scroll set, see if it's possible to
+ // set the scroll
+ el[scroll] = 1;
+ has = (el[scroll] > 0);
+ el[scroll] = 0;
+ return has;
+ },
+
+ isOverAxis: function(x, reference, size) {
+ //Determines when x coordinate is over "b" element axis
+ return (x > reference) && (x < (reference + size));
+ },
+
+ isOver: function(y, x, top, left, height, width) {
+ //Determines when x, y coordinates is over "b" element
+ return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
+ },
+
+ keyCode: {
+ BACKSPACE: 8,
+ CAPS_LOCK: 20,
+ COMMA: 188,
+ CONTROL: 17,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ INSERT: 45,
+ LEFT: 37,
+ NUMPAD_ADD: 107,
+ NUMPAD_DECIMAL: 110,
+ NUMPAD_DIVIDE: 111,
+ NUMPAD_ENTER: 108,
+ NUMPAD_MULTIPLY: 106,
+ NUMPAD_SUBTRACT: 109,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SHIFT: 16,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38
+ }
+};
+
+// WAI-ARIA normalization
+if (isFF2) {
+ var attr = $.attr,
+ removeAttr = $.fn.removeAttr,
+ ariaNS = "http://www.w3.org/2005/07/aaa",
+ ariaState = /^aria-/,
+ ariaRole = /^wairole:/;
+
+ $.attr = function(elem, name, value) {
+ var set = value !== undefined;
+
+ return (name == 'role'
+ ? (set
+ ? attr.call(this, elem, name, "wairole:" + value)
+ : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
+ : (ariaState.test(name)
+ ? (set
+ ? elem.setAttributeNS(ariaNS,
+ name.replace(ariaState, "aaa:"), value)
+ : attr.call(this, elem, name.replace(ariaState, "aaa:")))
+ : attr.apply(this, arguments)));
+ };
+
+ $.fn.removeAttr = function(name) {
+ return (ariaState.test(name)
+ ? this.each(function() {
+ this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
+ }) : removeAttr.call(this, name));
+ };
+}
+
+//jQuery plugins
+$.fn.extend({
+ remove: function() {
+ // Safari has a native remove event which actually removes DOM elements,
+ // so we have to use triggerHandler instead of trigger (#3037).
+ $("*", this).add(this).each(function() {
+ $(this).triggerHandler("remove");
+ });
+ return _remove.apply(this, arguments );
+ },
+
+ enableSelection: function() {
+ return this
+ .attr('unselectable', 'off')
+ .css('MozUserSelect', '')
+ .unbind('selectstart.ui');
+ },
+
+ disableSelection: function() {
+ return this
+ .attr('unselectable', 'on')
+ .css('MozUserSelect', 'none')
+ .bind('selectstart.ui', function() { return false; });
+ },
+
+ scrollParent: function() {
+ var scrollParent;
+ if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
+ scrollParent = this.parents().filter(function() {
+ return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+ }).eq(0);
+ } else {
+ scrollParent = this.parents().filter(function() {
+ return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+ }).eq(0);
+ }
+
+ return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
+ }
+});
+
+
+//Additional selectors
+$.extend($.expr[':'], {
+ data: function(elem, i, match) {
+ return !!$.data(elem, match[3]);
+ },
+
+ focusable: function(element) {
+ var nodeName = element.nodeName.toLowerCase(),
+ tabIndex = $.attr(element, 'tabindex');
+ return (/input|select|textarea|button|object/.test(nodeName)
+ ? !element.disabled
+ : 'a' == nodeName || 'area' == nodeName
+ ? element.href || !isNaN(tabIndex)
+ : !isNaN(tabIndex))
+ // the element and all of its ancestors must be visible
+ // the browser may report that the area is hidden
+ && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
+ },
+
+ tabbable: function(element) {
+ var tabIndex = $.attr(element, 'tabindex');
+ return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
+ }
+});
+
+
+// $.widget is a factory to create jQuery plugins
+// taking some boilerplate code out of the plugin code
+function getter(namespace, plugin, method, args) {
+ function getMethods(type) {
+ var methods = $[namespace][plugin][type] || [];
+ return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
+ }
+
+ var methods = getMethods('getter');
+ if (args.length == 1 && typeof args[0] == 'string') {
+ methods = methods.concat(getMethods('getterSetter'));
+ }
+ return ($.inArray(method, methods) != -1);
+}
+
+$.widget = function(name, prototype) {
+ var namespace = name.split(".")[0];
+ name = name.split(".")[1];
+
+ // create plugin method
+ $.fn[name] = function(options) {
+ var isMethodCall = (typeof options == 'string'),
+ args = Array.prototype.slice.call(arguments, 1);
+
+ // prevent calls to internal methods
+ if (isMethodCall && options.substring(0, 1) == '_') {
+ return this;
+ }
+
+ // handle getter methods
+ if (isMethodCall && getter(namespace, name, options, args)) {
+ var instance = $.data(this[0], name);
+ return (instance ? instance[options].apply(instance, args)
+ : undefined);
+ }
+
+ // handle initialization and non-getter methods
+ return this.each(function() {
+ var instance = $.data(this, name);
+
+ // constructor
+ (!instance && !isMethodCall &&
+ $.data(this, name, new $[namespace][name](this, options))._init());
+
+ // method call
+ (instance && isMethodCall && $.isFunction(instance[options]) &&
+ instance[options].apply(instance, args));
+ });
+ };
+
+ // create widget constructor
+ $[namespace] = $[namespace] || {};
+ $[namespace][name] = function(element, options) {
+ var self = this;
+
+ this.namespace = namespace;
+ this.widgetName = name;
+ this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
+ this.widgetBaseClass = namespace + '-' + name;
+
+ this.options = $.extend({},
+ $.widget.defaults,
+ $[namespace][name].defaults,
+ $.metadata && $.metadata.get(element)[name],
+ options);
+
+ this.element = $(element)
+ .bind('setData.' + name, function(event, key, value) {
+ if (event.target == element) {
+ return self._setData(key, value);
+ }
+ })
+ .bind('getData.' + name, function(event, key) {
+ if (event.target == element) {
+ return self._getData(key);
+ }
+ })
+ .bind('remove', function() {
+ return self.destroy();
+ });
+ };
+
+ // add widget prototype
+ $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
+
+ // TODO: merge getter and getterSetter properties from widget prototype
+ // and plugin prototype
+ $[namespace][name].getterSetter = 'option';
+};
+
+$.widget.prototype = {
+ _init: function() {},
+ destroy: function() {
+ this.element.removeData(this.widgetName)
+ .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
+ .removeAttr('aria-disabled');
+ },
+
+ option: function(key, value) {
+ var options = key,
+ self = this;
+
+ if (typeof key == "string") {
+ if (value === undefined) {
+ return this._getData(key);
+ }
+ options = {};
+ options[key] = value;
+ }
+
+ $.each(options, function(key, value) {
+ self._setData(key, value);
+ });
+ },
+ _getData: function(key) {
+ return this.options[key];
+ },
+ _setData: function(key, value) {
+ this.options[key] = value;
+
+ if (key == 'disabled') {
+ this.element
+ [value ? 'addClass' : 'removeClass'](
+ this.widgetBaseClass + '-disabled' + ' ' +
+ this.namespace + '-state-disabled')
+ .attr("aria-disabled", value);
+ }
+ },
+
+ enable: function() {
+ this._setData('disabled', false);
+ },
+ disable: function() {
+ this._setData('disabled', true);
+ },
+
+ _trigger: function(type, event, data) {
+ var callback = this.options[type],
+ eventName = (type == this.widgetEventPrefix
+ ? type : this.widgetEventPrefix + type);
+
+ event = $.Event(event);
+ event.type = eventName;
+
+ // copy original event properties over to the new event
+ // this would happen if we could call $.event.fix instead of $.Event
+ // but we don't have a way to force an event to be fixed multiple times
+ if (event.originalEvent) {
+ for (var i = $.event.props.length, prop; i;) {
+ prop = $.event.props[--i];
+ event[prop] = event.originalEvent[prop];
+ }
+ }
+
+ this.element.trigger(event, data);
+
+ return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
+ || event.isDefaultPrevented());
+ }
+};
+
+$.widget.defaults = {
+ disabled: false
+};
+
+
+/** Mouse Interaction Plugin **/
+
+$.ui.mouse = {
+ _mouseInit: function() {
+ var self = this;
+
+ this.element
+ .bind('mousedown.'+this.widgetName, function(event) {
+ return self._mouseDown(event);
+ })
+ .bind('click.'+this.widgetName, function(event) {
+ if(self._preventClickEvent) {
+ self._preventClickEvent = false;
+ event.stopImmediatePropagation();
+ return false;
+ }
+ });
+
+ // Prevent text selection in IE
+ if ($.browser.msie) {
+ this._mouseUnselectable = this.element.attr('unselectable');
+ this.element.attr('unselectable', 'on');
+ }
+
+ this.started = false;
+ },
+
+ // TODO: make sure destroying one instance of mouse doesn't mess with
+ // other instances of mouse
+ _mouseDestroy: function() {
+ this.element.unbind('.'+this.widgetName);
+
+ // Restore text selection in IE
+ ($.browser.msie
+ && this.element.attr('unselectable', this._mouseUnselectable));
+ },
+
+ _mouseDown: function(event) {
+ // don't let more than one widget handle mouseStart
+ // TODO: figure out why we have to use originalEvent
+ event.originalEvent = event.originalEvent || {};
+ if (event.originalEvent.mouseHandled) { return; }
+
+ // we may have missed mouseup (out of window)
+ (this._mouseStarted && this._mouseUp(event));
+
+ this._mouseDownEvent = event;
+
+ var self = this,
+ btnIsLeft = (event.which == 1),
+ elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
+ if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
+ return true;
+ }
+
+ this.mouseDelayMet = !this.options.delay;
+ if (!this.mouseDelayMet) {
+ this._mouseDelayTimer = setTimeout(function() {
+ self.mouseDelayMet = true;
+ }, this.options.delay);
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted = (this._mouseStart(event) !== false);
+ if (!this._mouseStarted) {
+ event.preventDefault();
+ return true;
+ }
+ }
+
+ // these delegates are required to keep context
+ this._mouseMoveDelegate = function(event) {
+ return self._mouseMove(event);
+ };
+ this._mouseUpDelegate = function(event) {
+ return self._mouseUp(event);
+ };
+ $(document)
+ .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ // preventDefault() is used to prevent the selection of text here -
+ // however, in Safari, this causes select boxes not to be selectable
+ // anymore, so this fix is needed
+ ($.browser.safari || event.preventDefault());
+
+ event.originalEvent.mouseHandled = true;
+ return true;
+ },
+
+ _mouseMove: function(event) {
+ // IE mouseup check - mouseup happened when mouse was out of window
+ if ($.browser.msie && !event.button) {
+ return this._mouseUp(event);
+ }
+
+ if (this._mouseStarted) {
+ this._mouseDrag(event);
+ return event.preventDefault();
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted =
+ (this._mouseStart(this._mouseDownEvent, event) !== false);
+ (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
+ }
+
+ return !this._mouseStarted;
+ },
+
+ _mouseUp: function(event) {
+ $(document)
+ .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ if (this._mouseStarted) {
+ this._mouseStarted = false;
+ this._preventClickEvent = (event.target == this._mouseDownEvent.target);
+ this._mouseStop(event);
+ }
+
+ return false;
+ },
+
+ _mouseDistanceMet: function(event) {
+ return (Math.max(
+ Math.abs(this._mouseDownEvent.pageX - event.pageX),
+ Math.abs(this._mouseDownEvent.pageY - event.pageY)
+ ) >= this.options.distance
+ );
+ },
+
+ _mouseDelayMet: function(event) {
+ return this.mouseDelayMet;
+ },
+
+ // These are placeholder methods, to be overriden by extending plugin
+ _mouseStart: function(event) {},
+ _mouseDrag: function(event) {},
+ _mouseStop: function(event) {},
+ _mouseCapture: function(event) { return true; }
+};
+
+$.ui.mouse.defaults = {
+ cancel: null,
+ distance: 1,
+ delay: 0
+};
+
+})(jQuery);
--- /dev/null
+++ b/static/scripts/jquery.cookie.js
@@ -0,0 +1,97 @@
+/**
+ * Cookie plugin
+ *
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/**
+ * Create a cookie with the given name and value and other optional parameters.
+ *
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Set the value of a cookie.
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
+ * @desc Create a cookie with all available options.
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Create a session cookie.
+ * @example $.cookie('the_cookie', null);
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
+ * used when the cookie was set.
+ *
+ * @param String name The name of the cookie.
+ * @param String value The value of the cookie.
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
+ * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
+ * If set to null or omitted, the cookie will be a session cookie and will not be retained
+ * when the the browser exits.
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
+ * require a secure protocol (like HTTPS).
+ * @type undefined
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl(a)stilbuero.de
+ */
+
+/**
+ * Get the value of a cookie with the given name.
+ *
+ * @example $.cookie('the_cookie');
+ * @desc Get the value of a cookie.
+ *
+ * @param String name The name of the cookie.
+ * @return The value of the cookie.
+ * @type String
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl(a)stilbuero.de
+ */
+jQuery.cookie = function(name, value, options) {
+ if (typeof value != 'undefined') { // name and value given, set cookie
+ options = options || {};
+ if (value === null) {
+ value = '';
+ options = $.extend({}, options); // clone object since it's unexpected behavior if the expired property were changed
+ options.expires = -1;
+ }
+ var expires = '';
+ if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
+ var date;
+ if (typeof options.expires == 'number') {
+ date = new Date();
+ date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
+ } else {
+ date = options.expires;
+ }
+ expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
+ }
+ // NOTE Needed to parenthesize options.path and options.domain
+ // in the following expressions, otherwise they evaluate to undefined
+ // in the packed version for some reason...
+ var path = options.path ? '; path=' + (options.path) : '';
+ var domain = options.domain ? '; domain=' + (options.domain) : '';
+ var secure = options.secure ? '; secure' : '';
+ document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
+ } else { // only name given, get cookie
+ var cookieValue = null;
+ if (document.cookie && document.cookie != '') {
+ var cookies = document.cookie.split(';');
+ for (var i = 0; i < cookies.length; i++) {
+ var cookie = jQuery.trim(cookies[i]);
+ // Does this cookie string begin with the name we want?
+ if (cookie.substring(0, name.length + 1) == (name + '=')) {
+ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
+ break;
+ }
+ }
+ }
+ return cookieValue;
+ }
+};
Binary file static/june_2007_style/blue/dynatree_skin/ltM_ne.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltD_nes.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltFld_o.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltM_nes.gif has changed
--- /dev/null
+++ b/static/scripts/packed/jquery.dynatree.js
@@ -0,0 +1,1 @@
+var _canLog=true;function _log(g,f){if(!_canLog){return}var b=Array.prototype.slice.apply(arguments,[1]);var c=new Date();var a=c.getHours()+":"+c.getMinutes()+":"+c.getSeconds()+"."+c.getMilliseconds();b[0]=a+" - "+b[0];try{switch(g){case"info":window.console.info.apply(window.console,b);break;case"warn":window.console.warn.apply(window.console,b);break;default:window.console.log.apply(window.console,b)}}catch(d){if(!window.console){_canLog=false}}}function logMsg(a){Array.prototype.unshift.apply(arguments,["debug"]);_log.apply(this,arguments)}var getDynaTreePersistData=undefined;var DTNodeStatus_Error=-1;var DTNodeStatus_Loading=1;var DTNodeStatus_Ok=0;(function($){var Class={create:function(){return function(){this.initialize.apply(this,arguments)}}};var DynaTreeNode=Class.create();DynaTreeNode.prototype={initialize:function(parent,tree,data){this.parent=parent;this.tree=tree;if(typeof data=="string"){data={title:data}}if(data.key==undefined){data.key="_"+tree._nodeCount+
+}this.data=$.extend({},$.ui.dynatree.nodedatadefaults,data);this.div=null;this.span=null;this.childList=null;this.isLoading=false;this.hasSubSel=false},toString:function(){return"dtnode<"+this.data.key+">: '"+this.data.title+"'"},toDict:function(recursive,callback){var dict=$.extend({},this.data);dict.activate=(this.tree.activeNode===this);dict.focus=(this.tree.focusNode===this);dict.expand=this.bExpanded;dict.select=this.bSelected;if(callback){callback(dict)}if(recursive&&this.childList){dict.children=[];for(var i=0;i<this.childList.length;i++){dict.children.push(this.childList[i].toDict(true,callback))}}else{delete dict.children}return dict},_getInnerHtml:function(){var opts=this.tree.options;var cache=this.tree.cache;var rootParent=opts.rootVisible?null:this.tree.tnRoot;var bHideFirstExpander=(opts.rootVisible&&opts.minExpandLevel>0)||opts.minExpandLevel>1;var bHideFirstConnector=opts.rootVisible||opts.minExpandLevel>0;var res="";var p=this.parent;while(p){if(bHideFirstC
onnector&&p==rootParent){break}res=(p.isLastSibling()?cache.tagEmpty:cache.tagVline)+res;p=p.parent}if(bHideFirstExpander&&this.parent==rootParent){}else{if(this.childList||this.data.isLazy){res+=cache.tagExpander}else{res+=cache.tagConnector}}if(opts.checkbox&&this.data.hideCheckbox!=true&&!this.data.isStatusNode){res+=cache.tagCheckbox}if(this.data.icon){res+="<img src='"+opts.imagePath+this.data.icon+"' alt='' />"}else{if(this.data.icon==false){}else{res+=cache.tagNodeIcon}}var tooltip=(this.data&&typeof this.data.tooltip=="string")?" title='"+this.data.tooltip+"'":"";res+="<a href='#' class='"+opts.classNames.title+"'"+tooltip+">"+this.data.title+"</a>";return res},_fixOrder:function(){var cl=this.childList;if(!cl){return}var childDiv=this.div.firstChild.nextSibling;for(var i=0;i<cl.length-1;i++){var childNode1=cl[i];var childNode2=childDiv.firstChild.dtnode;if(childNode1!==childNode2){this.tree.logDebug("_fixOrder: mismatch at index "+i+": "+childNode1+" != "+childNode2
);this.div.insertBefore(childNode1.div,childNode2.div)}else{childDiv=childDiv.nextSibling}}},render:function(bDeep,bHidden){var opts=this.tree.options;var cn=opts.classNames;var isLastSib=this.isLastSibling();if(!this.div){this.span=document.createElement("span");this.span.dtnode=this;if(this.data.key){this.span.id=this.tree.options.idPrefix+this.data.key}this.div=document.createElement("div");this.div.appendChild(this.span);if(this.parent){this.parent.div.appendChild(this.div)}if(this.parent==null&&!this.tree.options.rootVisible){this.span.style.display="none"}}this.span.innerHTML=this._getInnerHtml();this.div.style.display=(this.parent==null||this.parent.bExpanded?"":"none");var cnList=[];cnList.push((this.data.isFolder)?cn.folder:cn.document);if(this.bExpanded){cnList.push(cn.expanded)}if(this.childList!=null){cnList.push(cn.hasChildren)}if(this.data.isLazy&&this.childList==null){cnList.push(cn.lazy)}if(isLastSib){cnList.push(cn.lastsib)}if(this.bSelected){cnList.push(cn.
selected)}if(this.hasSubSel){cnList.push(cn.partsel)}if(this.tree.activeNode===this){cnList.push(cn.active)}if(this.data.addClass){cnList.push(this.data.addClass)}cnList.push(cn.combinedExpanderPrefix+(this.bExpanded?"e":"c")+(this.data.isLazy&&this.childList==null?"d":"")+(isLastSib?"l":""));cnList.push(cn.combinedIconPrefix+(this.bExpanded?"e":"c")+(this.data.isFolder?"f":""));this.span.className=cnList.join(" ");if(bDeep&&this.childList&&(bHidden||this.bExpanded)){for(var i=0;i<this.childList.length;i++){this.childList[i].render(bDeep,bHidden)}this._fixOrder()}},hasChildren:function(){return this.childList!=null},isLastSibling:function(){var p=this.parent;if(!p){return true}return p.childList[p.childList.length-1]===this},prevSibling:function(){if(!this.parent){return null}var ac=this.parent.childList;for(var i=1;i<ac.length;i++){if(ac[i]===this){return ac[i-1]}}return null},nextSibling:function(){if(!this.parent){return null}var ac=this.parent.childList;for(var i=0;i<ac.
length-1;i++){if(ac[i]===this){return ac[i+1]}}return null},_setStatusNode:function(data){var firstChild=(this.childList?this.childList[0]:null);if(!data){if(firstChild){this.div.removeChild(firstChild.div);if(this.childList.length==1){this.childList=null}else{this.childList.shift()}}}else{if(firstChild){data.isStatusNode=true;firstChild.data=data;firstChild.render(false,false)}else{data.isStatusNode=true;firstChild=this.addChild(data)}}},setLazyNodeStatus:function(lts,opts){var tooltip=(opts&&opts.tooltip)?opts.tooltip:null;var info=(opts&&opts.info)?" ("+opts.info+")":"";switch(lts){case DTNodeStatus_Ok:this._setStatusNode(null);this.isLoading=false;this.render(false,false);if(this.tree.options.autoFocus){if(this===this.tree.tnRoot&&!this.tree.options.rootVisible&&this.childList){this.childList[0].focus()}else{this.focus()}}break;case DTNodeStatus_Loading:this.isLoading=true;this._setStatusNode({title:this.tree.options.strings.loading+info,tooltip:tooltip,addClass:this.tre
e.options.classNames.nodeWait});break;case DTNodeStatus_Error:this.isLoading=false;this._setStatusNode({title:this.tree.options.strings.loadError+info,tooltip:tooltip,addClass:this.tree.options.classNames.nodeError});break;default:throw"Bad LazyNodeStatus: '"+lts+"'."}},_parentList:function(includeRoot,includeSelf){var l=[];var dtn=includeSelf?this:this.parent;while(dtn){if(includeRoot||dtn.parent){l.unshift(dtn)}dtn=dtn.parent}return l},getLevel:function(){var level=0;var dtn=this.parent;while(dtn){level++;dtn=dtn.parent}return level},_getTypeForOuterNodeEvent:function(event){var cns=this.tree.options.classNames;var target=event.target;if(target.className.indexOf(cns.folder)<0&&target.className.indexOf(cns.document)<0){return null}var eventX=event.pageX-target.offsetLeft;var eventY=event.pageY-target.offsetTop;for(var i=0;i<target.childNodes.length;i++){var cn=target.childNodes[i];var x=cn.offsetLeft-target.offsetLeft;var y=cn.offsetTop-target.offsetTop;var nx=cn.clientWidt
h,ny=cn.clientHeight;if(eventX>=x&&eventX<=(x+nx)&&eventY>=y&&eventY<=(y+ny)){if(cn.className==cns.title){return"title"}else{if(cn.className==cns.expander){return"expander"}else{if(cn.className==cns.checkbox){return"checkbox"}else{if(cn.className==cns.nodeIcon){return"icon"}}}}}}return"prefix"},getEventTargetType:function(event){var tcn=event&&event.target?event.target.className:"";var cns=this.tree.options.classNames;if(tcn==cns.title){return"title"}else{if(tcn==cns.expander){return"expander"}else{if(tcn==cns.checkbox){return"checkbox"}else{if(tcn==cns.nodeIcon){return"icon"}else{if(tcn==cns.empty||tcn==cns.vline||tcn==cns.connector){return"prefix"}else{if(tcn.indexOf(cns.folder)>=0||tcn.indexOf(cns.document)>=0){return this._getTypeForOuterNodeEvent(event)}}}}}}return null},isVisible:function(){var parents=this._parentList(true,false);for(var i=0;i<parents.length;i++){if(!parents[i].bExpanded){return false}}return true},makeVisible:function(){var parents=this._parentList(t
rue,false);for(var i=0;i<parents.length;i++){parents[i]._expand(true)}},focus:function(){this.makeVisible();try{$(this.span).find(">a").focus()}catch(e){}},_activate:function(flag,fireEvents){this.tree.logDebug("dtnode._activate(%o, fireEvents=%o) - %o",flag,fireEvents,this);var opts=this.tree.options;if(this.data.isStatusNode){return}if(fireEvents&&opts.onQueryActivate&&opts.onQueryActivate.call(this.span,flag,this)==false){return}if(flag){if(this.tree.activeNode){if(this.tree.activeNode===this){return}this.tree.activeNode.deactivate()}if(opts.activeVisible){this.makeVisible()}this.tree.activeNode=this;if(opts.persist){$.cookie(opts.cookieId+"-active",this.data.key,opts.cookie)}this.tree.persistence.activeKey=this.data.key;$(this.span).addClass(opts.classNames.active);if(fireEvents&&opts.onActivate){opts.onActivate.call(this.span,this)}}else{if(this.tree.activeNode===this){var opts=this.tree.options;if(opts.onQueryActivate&&opts.onQueryActivate.call(this.span,false,this)==f
alse){return}$(this.span).removeClass(opts.classNames.active);if(opts.persist){$.cookie(opts.cookieId+"-active","",opts.cookie)}this.tree.persistence.activeKey=null;this.tree.activeNode=null;if(fireEvents&&opts.onDeactivate){opts.onDeactivate.call(this.span,this)}}}},activate:function(){this._activate(true,true)},deactivate:function(){this._activate(false,true)},isActive:function(){return(this.tree.activeNode===this)},_userActivate:function(){var activate=true;var expand=false;if(this.data.isFolder){switch(this.tree.options.clickFolderMode){case 2:activate=false;expand=true;break;case 3:activate=expand=true;break}}if(this.parent==null&&this.tree.options.minExpandLevel>0){expand=false}if(expand){this.toggleExpand();this.focus()}if(activate){this.activate()}},_setSubSel:function(hasSubSel){if(hasSubSel){this.hasSubSel=true;$(this.span).addClass(this.tree.options.classNames.partsel)}else{this.hasSubSel=false;$(this.span).removeClass(this.tree.options.classNames.partsel)}},_fixS
electionState:function(){if(this.bSelected){this.visit(function(dtnode){dtnode.parent._setSubSel(true);dtnode._select(true,false,false)});var p=this.parent;while(p){p._setSubSel(true);var allChildsSelected=true;for(var i=0;i<p.childList.length;i++){var n=p.childList[i];if(!n.bSelected&&!n.data.isStatusNode){allChildsSelected=false;break}}if(allChildsSelected){p._select(true,false,false)}p=p.parent}}else{this._setSubSel(false);this.visit(function(dtnode){dtnode._setSubSel(false);dtnode._select(false,false,false)});var p=this.parent;while(p){p._select(false,false,false);var isPartSel=false;for(var i=0;i<p.childList.length;i++){if(p.childList[i].bSelected||p.childList[i].hasSubSel){isPartSel=true;break}}p._setSubSel(isPartSel);p=p.parent}}},_select:function(sel,fireEvents,deep){var opts=this.tree.options;if(this.data.isStatusNode){return}if(this.bSelected==sel){return}if(fireEvents&&opts.onQuerySelect&&opts.onQuerySelect.call(this.span,sel,this)==false){return}if(opts.selectMod
e==1&&sel){this.tree.visit(function(dtnode){if(dtnode.bSelected){dtnode._select(false,false,false);return false}})}this.bSelected=sel;if(sel){if(opts.persist){this.tree.persistence.addSelect(this.data.key)}$(this.span).addClass(opts.classNames.selected);if(deep&&opts.selectMode==3){this._fixSelectionState()}if(fireEvents&&opts.onSelect){opts.onSelect.call(this.span,true,this)}}else{if(opts.persist){this.tree.persistence.clearSelect(this.data.key)}$(this.span).removeClass(opts.classNames.selected);if(deep&&opts.selectMode==3){this._fixSelectionState()}if(fireEvents&&opts.onSelect){opts.onSelect.call(this.span,false,this)}}},select:function(sel){if(this.data.unselectable){return this.bSelected}return this._select(sel!=false,true,true)},toggleSelect:function(){return this.select(!this.bSelected)},isSelected:function(){return this.bSelected},_loadContent:function(){try{var opts=this.tree.options;this.tree.logDebug("_loadContent: start - %o",this);this.setLazyNodeStatus(DTNodeSta
tus_Loading);if(true==opts.onLazyRead.call(this.span,this)){this.setLazyNodeStatus(DTNodeStatus_Ok);this.tree.logDebug("_loadContent: succeeded - %o",this)}}catch(e){this.setLazyNodeStatus(DTNodeStatus_Error);this.tree.logWarning("_loadContent: failed - %o",e)}},_expand:function(bExpand){if(this.bExpanded==bExpand){return}var opts=this.tree.options;if(!bExpand&&this.getLevel()<opts.minExpandLevel){this.tree.logDebug("dtnode._expand(%o) forced expand - %o",bExpand,this);return}if(opts.onQueryExpand&&opts.onQueryExpand.call(this.span,bExpand,this)==false){return}this.bExpanded=bExpand;if(opts.persist){if(bExpand){this.tree.persistence.addExpand(this.data.key)}else{this.tree.persistence.clearExpand(this.data.key)}}this.render(false);if(this.bExpanded&&this.parent&&opts.autoCollapse){var parents=this._parentList(false,true);for(var i=0;i<parents.length;i++){parents[i].collapseSiblings()}}if(opts.activeVisible&&this.tree.activeNode&&!this.tree.activeNode.isVisible()){this.tree.ac
tiveNode.deactivate()}if(bExpand&&this.data.isLazy&&this.childList==null&&!this.isLoading){this._loadContent();return}var fxDuration=opts.fx?(opts.fx.duration||200):0;if(this.childList){for(var i=0;i<this.childList.length;i++){var $child=$(this.childList[i].div);if(fxDuration){if(bExpand!=$child.is(":visible")){$child.animate(opts.fx,fxDuration)}}else{if(bExpand){$child.show()}else{$child.hide()}}}}if(opts.onExpand){opts.onExpand.call(this.span,bExpand,this)}},expand:function(flag){if(!this.childList&&!this.data.isLazy&&flag){return}if(this.parent==null&&this.tree.options.minExpandLevel>0&&!flag){return}this._expand(flag)},toggleExpand:function(){this.expand(!this.bExpanded)},collapseSiblings:function(){if(this.parent==null){return}var ac=this.parent.childList;for(var i=0;i<ac.length;i++){if(ac[i]!==this&&ac[i].bExpanded){ac[i]._expand(false)}}},onClick:function(event){var targetType=this.getEventTargetType(event);if(targetType=="expander"){this.toggleExpand();this.focus()}e
lse{if(targetType=="checkbox"){this.toggleSelect();this.focus()}else{this._userActivate();this.span.getElementsByTagName("a")[0].focus()}}return false},onDblClick:function(event){},onKeydown:function(event){var handled=true;switch(event.which){case 107:case 187:if(!this.bExpanded){this.toggleExpand()}break;case 109:case 189:if(this.bExpanded){this.toggleExpand()}break;case 32:this._userActivate();break;case 8:if(this.parent){this.parent.focus()}break;case 37:if(this.bExpanded){this.toggleExpand();this.focus()}else{if(this.parent&&(this.tree.options.rootVisible||this.parent.parent)){this.parent.focus()}}break;case 39:if(!this.bExpanded&&(this.childList||this.data.isLazy)){this.toggleExpand();this.focus()}else{if(this.childList){this.childList[0].focus()}}break;case 38:var sib=this.prevSibling();while(sib&&sib.bExpanded&&sib.childList){sib=sib.childList[sib.childList.length-1]}if(!sib&&this.parent&&(this.tree.options.rootVisible||this.parent.parent)){sib=this.parent}if(sib){si
b.focus()}break;case 40:var sib;if(this.bExpanded&&this.childList){sib=this.childList[0]}else{var parents=this._parentList(false,true);for(var i=parents.length-1;i>=0;i--){sib=parents[i].nextSibling();if(sib){break}}}if(sib){sib.focus()}break;default:handled=false}return !handled},onKeypress:function(event){},onFocus:function(event){var opts=this.tree.options;if(event.type=="blur"||event.type=="focusout"){if(opts.onBlur){opts.onBlur.call(this.span,this)}if(this.tree.tnFocused){$(this.tree.tnFocused.span).removeClass(opts.classNames.focused)}this.tree.tnFocused=null;if(opts.persist){$.cookie(opts.cookieId+"-focus","",opts.cookie)}}else{if(event.type=="focus"||event.type=="focusin"){if(this.tree.tnFocused&&this.tree.tnFocused!==this){this.tree.logDebug("dtnode.onFocus: out of sync: curFocus: %o",this.tree.tnFocused);$(this.tree.tnFocused.span).removeClass(opts.classNames.focused)}this.tree.tnFocused=this;if(opts.onFocus){opts.onFocus.call(this.span,this)}$(this.tree.tnFocused.
span).addClass(opts.classNames.focused);if(opts.persist){$.cookie(opts.cookieId+"-focus",this.data.key,opts.cookie)}}}},visit:function(fn,data,includeSelf){var n=0;if(includeSelf==true){if(fn(this,data)==false){return 1}n++}if(this.childList){for(var i=0;i<this.childList.length;i++){n+=this.childList[i].visit(fn,data,true)}}return n},remove:function(){if(this===this.tree.root){return false}return this.parent.removeChild(this)},removeChild:function(tn){var ac=this.childList;if(ac.length==1){if(tn!==ac[0]){throw"removeChild: invalid child"}return this.removeChildren()}if(tn===this.tree.activeNode){tn.deactivate()}if(this.tree.options.persist){if(tn.bSelected){this.tree.persistence.clearSelect(tn.data.key)}if(tn.bExpanded){this.tree.persistence.clearExpand(tn.data.key)}}tn.removeChildren(true);this.div.removeChild(tn.div);for(var i=0;i<ac.length;i++){if(ac[i]===tn){this.childList.splice(i,1);delete tn;break}}},removeChildren:function(isRecursiveCall,retainPersistence){var tree=
this.tree;var ac=this.childList;if(ac){for(var i=0;i<ac.length;i++){var tn=ac[i];if(tn===tree.activeNode&&!retainPersistence){tn.deactivate()}if(this.tree.options.persist&&!retainPersistence){if(tn.bSelected){this.tree.persistence.clearSelect(tn.data.key)}if(tn.bExpanded){this.tree.persistence.clearExpand(tn.data.key)}}tn.removeChildren(true,retainPersistence);this.div.removeChild(tn.div);delete tn}this.childList=null}if(!isRecursiveCall){this.isLoading=false;this.render(false,false)}},reload:function(force){if(this.parent==null){return this.tree.reload()}if(!this.data.isLazy){throw"node.reload() requires lazy nodes."}if(this.bExpanded){this.expand(false);this.removeChildren();this.expand(true)}else{this.removeChildren();if(force){this._loadContent()}}},_addChildNode:function(dtnode,beforeNode){var tree=this.tree;var opts=tree.options;var pers=tree.persistence;dtnode.parent=this;if(this.childList==null){this.childList=[]}else{if(!beforeNode){$(this.childList[this.childList.l
ength-1].span).removeClass(opts.classNames.lastsib)}}if(beforeNode){var iBefore=$.inArray(beforeNode,this.childList);if(iBefore<0){throw"<beforeNode> must be a child of <this>"}this.childList.splice(iBefore,0,dtnode)}else{this.childList.push(dtnode)}var isInitializing=tree.isInitializing();if(opts.persist&&pers.cookiesFound&&isInitializing){if(pers.activeKey==dtnode.data.key){tree.activeNode=dtnode}if(pers.focusedKey==dtnode.data.key){tree.focusNode=dtnode}dtnode.bExpanded=($.inArray(dtnode.data.key,pers.expandedKeyList)>=0);dtnode.bSelected=($.inArray(dtnode.data.key,pers.selectedKeyList)>=0)}else{if(dtnode.data.activate){tree.activeNode=dtnode;if(opts.persist){pers.activeKey=dtnode.data.key}}if(dtnode.data.focus){tree.focusNode=dtnode;if(opts.persist){pers.focusedKey=dtnode.data.key}}dtnode.bExpanded=(dtnode.data.expand==true);if(dtnode.bExpanded&&opts.persist){pers.addExpand(dtnode.data.key)}dtnode.bSelected=(dtnode.data.select==true);if(dtnode.bSelected&&opts.persist){pe
rs.addSelect(dtnode.data.key)}}if(opts.minExpandLevel>=dtnode.getLevel()){this.bExpanded=true}if(dtnode.bSelected&&opts.selectMode==3){var p=this;while(p){if(!p.hasSubSel){p._setSubSel(true)}p=p.parent}}if(tree.bEnableUpdate){this.render(true,true)}return dtnode},addChild:function(obj,beforeNode){if(!obj||obj.length==0){return}if(obj instanceof DynaTreeNode){return this._addChildNode(obj,beforeNode)}if(!obj.length){obj=[obj]}var prevFlag=this.tree.enableUpdate(false);var tnFirst=null;for(var i=0;i<obj.length;i++){var data=obj[i];var dtnode=this._addChildNode(new DynaTreeNode(this,this.tree,data),beforeNode);if(!tnFirst){tnFirst=dtnode}if(data.children){dtnode.addChild(data.children,null)}}this.tree.enableUpdate(prevFlag);return tnFirst},append:function(obj){this.tree.logWarning("node.append() is deprecated (use node.addChild() instead).");return this.addChild(obj,null)},appendAjax:function(ajaxOptions){this.removeChildren(false,true);this.setLazyNodeStatus(DTNodeStatus_Loadi
ng);var self=this;var orgSuccess=ajaxOptions.success;var orgError=ajaxOptions.error;var options=$.extend({},this.tree.options.ajaxDefaults,ajaxOptions,{success:function(data,textStatus){var prevPhase=self.tree.phase;self.tree.phase="init";self.addChild(data,null);self.tree.phase="postInit";self.setLazyNodeStatus(DTNodeStatus_Ok);if(orgSuccess){orgSuccess.call(options,self)}self.tree.phase=prevPhase},error:function(XMLHttpRequest,textStatus,errorThrown){self.tree.logWarning("appendAjax failed:",textStatus,":\n",XMLHttpRequest,"\n",errorThrown);self.setLazyNodeStatus(DTNodeStatus_Error,{info:textStatus,tooltip:""+errorThrown});if(orgError){orgError.call(options,self,XMLHttpRequest,textStatus,errorThrown)}}});$.ajax(options)},lastentry:undefined};var DynaTreeStatus=Class.create();DynaTreeStatus._getTreePersistData=function(cookieId,cookieOpts){var ts=new DynaTreeStatus(cookieId,cookieOpts);ts.read();return ts.toDict()};getDynaTreePersistData=DynaTreeStatus._getTreePersistData;D
ynaTreeStatus.prototype={initialize:function(cookieId,cookieOpts){this._log("DynaTreeStatus: initialize");if(cookieId===undefined){cookieId=$.ui.dynatree.defaults.cookieId}cookieOpts=$.extend({},$.ui.dynatree.defaults.cookie,cookieOpts);this.cookieId=cookieId;this.cookieOpts=cookieOpts;this.cookiesFound=undefined;this.activeKey=null;this.focusedKey=null;this.expandedKeyList=null;this.selectedKeyList=null},_log:function(msg){Array.prototype.unshift.apply(arguments,["debug"]);_log.apply(this,arguments)},read:function(){this._log("DynaTreeStatus: read");this.cookiesFound=false;var cookie=$.cookie(this.cookieId+"-active");this.activeKey=(cookie==null)?"":cookie;if(cookie!=null){this.cookiesFound=true}cookie=$.cookie(this.cookieId+"-focus");this.focusedKey=(cookie==null)?"":cookie;if(cookie!=null){this.cookiesFound=true}cookie=$.cookie(this.cookieId+"-expand");this.expandedKeyList=(cookie==null)?[]:cookie.split(",");if(cookie!=null){this.cookiesFound=true}cookie=$.cookie(this.coo
kieId+"-select");this.selectedKeyList=(cookie==null)?[]:cookie.split(",");if(cookie!=null){this.cookiesFound=true}},write:function(){this._log("DynaTreeStatus: write");$.cookie(this.cookieId+"-active",(this.activeKey==null)?"":this.activeKey,this.cookieOpts);$.cookie(this.cookieId+"-focus",(this.focusedKey==null)?"":this.focusedKey,this.cookieOpts);$.cookie(this.cookieId+"-expand",(this.expandedKeyList==null)?"":this.expandedKeyList.join(","),this.cookieOpts);$.cookie(this.cookieId+"-select",(this.selectedKeyList==null)?"":this.selectedKeyList.join(","),this.cookieOpts)},addExpand:function(key){this._log("addExpand(%o)",key);if($.inArray(key,this.expandedKeyList)<0){this.expandedKeyList.push(key);$.cookie(this.cookieId+"-expand",this.expandedKeyList.join(","),this.cookieOpts)}},clearExpand:function(key){this._log("clearExpand(%o)",key);var idx=$.inArray(key,this.expandedKeyList);if(idx>=0){this.expandedKeyList.splice(idx,1);$.cookie(this.cookieId+"-expand",this.expandedKeyLi
st.join(","),this.cookieOpts)}},addSelect:function(key){this._log("addSelect(%o)",key);if($.inArray(key,this.selectedKeyList)<0){this.selectedKeyList.push(key);$.cookie(this.cookieId+"-select",this.selectedKeyList.join(","),this.cookieOpts)}},clearSelect:function(key){this._log("clearSelect(%o)",key);var idx=$.inArray(key,this.selectedKeyList);if(idx>=0){this.selectedKeyList.splice(idx,1);$.cookie(this.cookieId+"-select",this.selectedKeyList.join(","),this.cookieOpts)}},isReloading:function(){return this.cookiesFound==true},toDict:function(){return{cookiesFound:this.cookiesFound,activeKey:this.activeKey,focusedKey:this.activeKey,expandedKeyList:this.expandedKeyList,selectedKeyList:this.selectedKeyList}},lastentry:undefined};var DynaTree=Class.create();DynaTree.version="$Version: 0.5.4$";DynaTree.prototype={initialize:function($widget){this.phase="init";this.$widget=$widget;this.options=$widget.options;this.$tree=$widget.element;this.divTree=this.$tree.get(0)},_load:function(
){var $widget=this.$widget;var opts=this.options;this.bEnableUpdate=true;this._nodeCount=1;this.activeNode=null;this.focusNode=null;if(opts.classNames!==$.ui.dynatree.defaults.classNames){opts.classNames=$.extend({},$.ui.dynatree.defaults.classNames,opts.classNames)}if(!opts.imagePath){$("script").each(function(){if(this.src.search(_rexDtLibName)>=0){if(this.src.indexOf("/")>=0){opts.imagePath=this.src.slice(0,this.src.lastIndexOf("/"))+"/skin/"}else{opts.imagePath="skin/"}return false}})}this.persistence=new DynaTreeStatus(opts.cookieId,opts.cookie);if(opts.persist){if(!$.cookie){_log("warn","Please include jquery.cookie.js to use persistence.")}this.persistence.read()}this.logDebug("DynaTree.persistence: %o",this.persistence.toDict());this.cache={tagEmpty:"<span class='"+opts.classNames.empty+"'></span>",tagVline:"<span class='"+opts.classNames.vline+"'></span>",tagExpander:"<span class='"+opts.classNames.expander+"'></span>",tagConnector:"<span class='"+opts.classNames.co
nnector+"'></span>",tagNodeIcon:"<span class='"+opts.classNames.nodeIcon+"'></span>",tagCheckbox:"<span class='"+opts.classNames.checkbox+"'></span>",lastentry:undefined};if(opts.children||(opts.initAjax&&opts.initAjax.url)||opts.initId){$(this.divTree).empty()}else{if(this.divRoot){$(this.divRoot).remove()}}this.tnRoot=new DynaTreeNode(null,this,{title:opts.title,key:"root"});this.tnRoot.data.isFolder=true;this.tnRoot.render(false,false);this.divRoot=this.tnRoot.div;this.divRoot.className=opts.classNames.container;this.divTree.appendChild(this.divRoot);var root=this.tnRoot;var isReloading=(opts.persist&&this.persistence.isReloading());var isLazy=false;var prevFlag=this.enableUpdate(false);this.logDebug("Dynatree._load(): read tree structure...");if(opts.children){root.addChild(opts.children)}else{if(opts.initAjax&&opts.initAjax.url){isLazy=true;root.data.isLazy=true;this._reloadAjax()}else{if(opts.initId){this._createFromTag(root,$("#"+opts.initId))}else{var $ul=this.$tree.
find(">ul").hide();this._createFromTag(root,$ul);$ul.remove()}}}this._checkConsistency();this.logDebug("Dynatree._load(): render nodes...");this.enableUpdate(prevFlag);this.logDebug("Dynatree._load(): bind events...");this.$widget.bind();this.logDebug("Dynatree._load(): postInit...");this.phase="postInit";if(opts.persist){this.persistence.write()}if(this.focusNode&&this.focusNode.isVisible()){this.logDebug("Focus on init: %o",this.focusNode);this.focusNode.focus()}if(!isLazy&&opts.onPostInit){opts.onPostInit.call(this,isReloading,false)}this.phase="idle"},_reloadAjax:function(){var opts=this.options;if(!opts.initAjax||!opts.initAjax.url){throw"tree.reload() requires 'initAjax' mode."}var pers=this.persistence;var ajaxOpts=$.extend({},opts.initAjax);if(ajaxOpts.addActiveKey){ajaxOpts.data.activeKey=pers.activeKey}if(ajaxOpts.addFocusedKey){ajaxOpts.data.focusedKey=pers.focusedKey}if(ajaxOpts.addExpandedKeyList){ajaxOpts.data.expandedKeyList=pers.expandedKeyList.join(",")}if(a
jaxOpts.addSelectedKeyList){ajaxOpts.data.selectedKeyList=pers.selectedKeyList.join(",")}if(opts.onPostInit){if(ajaxOpts.success){this.logWarning("initAjax: success callback is ignored when onPostInit was specified.")}if(ajaxOpts.error){this.logWarning("initAjax: error callback is ignored when onPostInit was specified.")}var isReloading=pers.isReloading();ajaxOpts.success=function(dtnode){opts.onPostInit.call(dtnode.tree,isReloading,false)};ajaxOpts.error=function(dtnode){opts.onPostInit.call(dtnode.tree,isReloading,true)}}this.logDebug("Dynatree._init(): send Ajax request...");this.tnRoot.appendAjax(ajaxOpts)},toString:function(){return"DynaTree '"+this.options.title+"'"},toDict:function(){return this.tnRoot.toDict(true)},getPersistData:function(){return this.persistence.toDict()},logDebug:function(msg){if(this.options.debugLevel>=2){Array.prototype.unshift.apply(arguments,["debug"]);_log.apply(this,arguments)}},logInfo:function(msg){if(this.options.debugLevel>=1){Array.pro
totype.unshift.apply(arguments,["info"]);_log.apply(this,arguments)}},logWarning:function(msg){Array.prototype.unshift.apply(arguments,["warn"]);_log.apply(this,arguments)},isInitializing:function(){return(this.phase=="init"||this.phase=="postInit")},isReloading:function(){return(this.phase=="init"||this.phase=="postInit")&&this.options.persist&&this.persistence.cookiesFound},isUserEvent:function(){return(this.phase=="userEvent")},redraw:function(){this.logDebug("dynatree.redraw()...");this.tnRoot.render(true,true);this.logDebug("dynatree.redraw() done.")},reloadAjax:function(){this.logWarning("tree.reloadAjax() is deprecated since v0.5.2 (use reload() instead).")},reload:function(){this._load()},getRoot:function(){return this.tnRoot},getNodeByKey:function(key){var el=document.getElementById(this.options.idPrefix+key);return(el&&el.dtnode)?el.dtnode:null},getActiveNode:function(){return this.activeNode},reactivate:function(setFocus){var node=this.activeNode;if(node){this.act
iveNode=null;node.activate();if(setFocus){node.focus()}}},getSelectedNodes:function(stopOnParents){var nodeList=[];this.tnRoot.visit(function(dtnode){if(dtnode.bSelected){nodeList.push(dtnode);if(stopOnParents==true){return false}}});return nodeList},activateKey:function(key){var dtnode=(key===null)?null:this.getNodeByKey(key);if(!dtnode){if(this.activeNode){this.activeNode.deactivate()}this.activeNode=null;return null}dtnode.focus();dtnode.activate();return dtnode},selectKey:function(key,select){var dtnode=this.getNodeByKey(key);if(!dtnode){return null}dtnode.select(select);return dtnode},enableUpdate:function(bEnable){if(this.bEnableUpdate==bEnable){return bEnable}this.bEnableUpdate=bEnable;if(bEnable){this.redraw()}return !bEnable},visit:function(fn,data,includeRoot){return this.tnRoot.visit(fn,data,includeRoot)},_createFromTag:function(parentTreeNode,$ulParent){var self=this;$ulParent.find(">li").each(function(){var $li=$(this);var $liSpan=$li.find(">span:first");var tit
le;if($liSpan.length){title=$liSpan.html()}else{title=$li.html();var iPos=title.search(/<ul/i);if(iPos>=0){title=$.trim(title.substring(0,iPos))}else{title=$.trim(title)}}var data={title:title,isFolder:$li.hasClass("folder"),isLazy:$li.hasClass("lazy"),expand:$li.hasClass("expanded"),select:$li.hasClass("selected"),activate:$li.hasClass("active"),focus:$li.hasClass("focused")};if($li.attr("title")){data.tooltip=$li.attr("title")}if($li.attr("id")){data.key=$li.attr("id")}if($li.attr("data")){var dataAttr=$.trim($li.attr("data"));if(dataAttr){if(dataAttr.charAt(0)!="{"){dataAttr="{"+dataAttr+"}"}try{$.extend(data,eval("("+dataAttr+")"))}catch(e){throw ("Error parsing node data: "+e+"\ndata:\n'"+dataAttr+"'")}}}childNode=parentTreeNode.addChild(data);var $ul=$li.find(">ul:first");if($ul.length){self._createFromTag(childNode,$ul)}})},_checkConsistency:function(){},lastentry:undefined};$.widget("ui.dynatree",{init:function(){_log("warn","ui.dynatree.init() was called; you should
upgrade to ui.core.js v1.6 or higher.");return this._init()},_init:function(){if(parseFloat($.ui.version)<1.8){_log("info","ui.dynatree._init() was called; consider upgrading to jquery.ui.core.js v1.8 or higher.");return this._create()}_log("debug","ui.dynatree._init() was called; no current default functionality.")},_create:function(){if(parseFloat($.ui.version)>=1.8){this.options=$.extend(true,{},$[this.namespace][this.widgetName].defaults,this.options)}logMsg("Dynatree._create(): version='%s', debugLevel=%o.",DynaTree.version,this.options.debugLevel);var opts=this.options;this.options.event+=".dynatree";var divTree=this.element.get(0);this.tree=new DynaTree(this);this.tree._load();this.tree.logDebug("Dynatree._create(): done.")},bind:function(){var $this=this.element;var o=this.options;this.unbind();function __getNodeFromElement(el){var iMax=5;while(el&&iMax--){if(el.dtnode){return el.dtnode}el=el.parentNode}return null}var eventNames="click.dynatree dblclick.dynatree";i
f(o.keyboard){eventNames+=" keypress.dynatree keydown.dynatree"}$this.bind(eventNames,function(event){var dtnode=__getNodeFromElement(event.target);if(!dtnode){return true}var prevPhase=dtnode.tree.phase;dtnode.tree.phase="userEvent";try{dtnode.tree.logDebug("bind(%o): dtnode: %o",event,dtnode);switch(event.type){case"click":return(o.onClick&&o.onClick(dtnode,event)===false)?false:dtnode.onClick(event);case"dblclick":return(o.onDblClick&&o.onDblClick(dtnode,event)===false)?false:dtnode.onDblClick(event);case"keydown":return(o.onKeydown&&o.onKeydown(dtnode,event)===false)?false:dtnode.onKeydown(event);case"keypress":return(o.onKeypress&&o.onKeypress(dtnode,event)===false)?false:dtnode.onKeypress(event)}}catch(e){var _=null}finally{dtnode.tree.phase=prevPhase}});function __focusHandler(event){event=arguments[0]=$.event.fix(event||window.event);var dtnode=__getNodeFromElement(event.target);return dtnode?dtnode.onFocus(event):false}var div=this.tree.divTree;if(div.addEventListen
er){div.addEventListener("focus",__focusHandler,true);div.addEventListener("blur",__focusHandler,true)}else{div.onfocusin=div.onfocusout=__focusHandler}},unbind:function(){this.element.unbind(".dynatree")},enable:function(){this.bind();$.widget.prototype.enable.apply(this,arguments)},disable:function(){this.unbind();$.widget.prototype.disable.apply(this,arguments)},getTree:function(){return this.tree},getRoot:function(){return this.tree.getRoot()},getActiveNode:function(){return this.tree.getActiveNode()},getSelectedNodes:function(){return this.tree.getSelectedNodes()},lastentry:undefined});$.ui.dynatree.getter="getTree getRoot getActiveNode getSelectedNodes";$.ui.dynatree.defaults={title:"Dynatree root",rootVisible:false,minExpandLevel:1,imagePath:null,children:null,initId:null,initAjax:null,autoFocus:true,keyboard:true,persist:false,autoCollapse:false,clickFolderMode:3,activeVisible:true,checkbox:false,selectMode:2,fx:null,onClick:null,onDblClick:null,onKeydown:null,onKeyp
ress:null,onFocus:null,onBlur:null,onQueryActivate:null,onQuerySelect:null,onQueryExpand:null,onPostInit:null,onActivate:null,onDeactivate:null,onSelect:null,onExpand:null,onLazyRead:null,ajaxDefaults:{cache:false,dataType:"json"},strings:{loading:"Loading…",loadError:"Load error!"},idPrefix:"ui-dynatree-id-",cookieId:"dynatree",cookie:{expires:null},classNames:{container:"ui-dynatree-container",folder:"ui-dynatree-folder",document:"ui-dynatree-document",empty:"ui-dynatree-empty",vline:"ui-dynatree-vline",expander:"ui-dynatree-expander",connector:"ui-dynatree-connector",checkbox:"ui-dynatree-checkbox",nodeIcon:"ui-dynatree-icon",title:"ui-dynatree-title",nodeError:"ui-dynatree-statusnode-error",nodeWait:"ui-dynatree-statusnode-wait",hidden:"ui-dynatree-hidden",combinedExpanderPrefix:"ui-dynatree-exp-",combinedIconPrefix:"ui-dynatree-ico-",hasChildren:"ui-dynatree-has-children",active:"ui-dynatree-active",selected:"ui-dynatree-selected",expanded:"ui-dynatree-expanded",l
azy:"ui-dynatree-lazy",focused:"ui-dynatree-focused",partsel:"ui-dynatree-partsel",lastsib:"ui-dynatree-lastsib"},debugLevel:1,lastentry:undefined};$.ui.dynatree.nodedatadefaults={title:null,key:null,isFolder:false,isLazy:false,tooltip:null,icon:null,addClass:null,activate:false,focus:false,expand:false,select:false,hideCheckbox:false,unselectable:false,children:null,lastentry:undefined}})(jQuery);var _rexDtLibName=/.*dynatree[^/]*\.js$/i;
Binary file static/june_2007_style/blue/dynatree_skin/rbChecked.gif has changed
--- /dev/null
+++ b/static/scripts/jquery.dynatree.js
@@ -0,0 +1,2034 @@
+/*************************************************************************
+ jquery.dynatree.js
+ Dynamic tree view control, with support for lazy loading of branches.
+
+ Copyright (c) 2008-2010, Martin Wendt (http://wwWendt.de)
+ Dual licensed under the MIT or GPL Version 2 licenses.
+ http://code.google.com/p/dynatree/wiki/LicenseInfo
+
+ A current version and some documentation is available at
+ http://dynatree.googlecode.com/
+
+ $Version: 0.5.4$
+ $Revision: 329, 2010-05-05 08:04:39$
+
+ @depends: jquery.js
+ @depends: ui.core.js
+ @depends: jquery.cookie.js
+*************************************************************************/
+
+
+/*************************************************************************
+ * Debug functions
+ */
+
+var _canLog = true;
+
+function _log(mode, msg) {
+ /**
+ * Usage: logMsg("%o was toggled", this);
+ */
+ if( !_canLog )
+ return;
+ // Remove first argument
+ var args = Array.prototype.slice.apply(arguments, [1]);
+ // Prepend timestamp
+ var dt = new Date();
+ var tag = dt.getHours()+":"+dt.getMinutes()+":"+dt.getSeconds()+"."+dt.getMilliseconds();
+ args[0] = tag + " - " + args[0];
+
+ try {
+ switch( mode ) {
+ case "info":
+ window.console.info.apply(window.console, args);
+ break;
+ case "warn":
+ window.console.warn.apply(window.console, args);
+ break;
+ default:
+ window.console.log.apply(window.console, args);
+ }
+ } catch(e) {
+ if( !window.console )
+ _canLog = false; // Permanently disable, when logging is not supported by the browser
+ }
+}
+
+function logMsg(msg) {
+ Array.prototype.unshift.apply(arguments, ["debug"]);
+ _log.apply(this, arguments);
+}
+
+
+// Forward declaration
+var getDynaTreePersistData = undefined;
+
+
+
+/*************************************************************************
+ * Constants
+ */
+var DTNodeStatus_Error = -1;
+var DTNodeStatus_Loading = 1;
+var DTNodeStatus_Ok = 0;
+
+
+// Start of local namespace
+;(function($) {
+
+/*************************************************************************
+ * Common tool functions.
+ */
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+/*************************************************************************
+ * Class DynaTreeNode
+ */
+var DynaTreeNode = Class.create();
+
+DynaTreeNode.prototype = {
+ initialize: function(parent, tree, data) {
+ /**
+ * @constructor
+ */
+ this.parent = parent;
+ this.tree = tree;
+ if ( typeof data == "string" )
+ data = { title: data };
+ if( data.key == undefined )
+ data.key = "_" + tree._nodeCount++;
+ this.data = $.extend({}, $.ui.dynatree.nodedatadefaults, data);
+ this.div = null; // not yet created
+ this.span = null; // not yet created
+ this.childList = null; // no subnodes yet
+// this.isRead = false; // Lazy content not yet read
+ this.isLoading = false; // Lazy content is being loaded
+ this.hasSubSel = false;
+ },
+
+ toString: function() {
+ return "dtnode<" + this.data.key + ">: '" + this.data.title + "'";
+ },
+
+ toDict: function(recursive, callback) {
+ var dict = $.extend({}, this.data);
+ dict.activate = ( this.tree.activeNode === this );
+ dict.focus = ( this.tree.focusNode === this );
+ dict.expand = this.bExpanded;
+ dict.select = this.bSelected;
+ if( callback )
+ callback(dict);
+ if( recursive && this.childList ) {
+ dict.children = [];
+ for(var i=0; i<this.childList.length; i++ )
+ dict.children.push(this.childList[i].toDict(true, callback));
+ } else {
+ delete dict.children;
+ }
+ return dict;
+ },
+
+ _getInnerHtml: function() {
+ var opts = this.tree.options;
+ var cache = this.tree.cache;
+ // parent connectors
+ var rootParent = opts.rootVisible ? null : this.tree.tnRoot;
+ var bHideFirstExpander = (opts.rootVisible && opts.minExpandLevel>0) || opts.minExpandLevel>1;
+ var bHideFirstConnector = opts.rootVisible || opts.minExpandLevel>0;
+
+ var res = "";
+ var p = this.parent;
+ while( p ) {
+ // Suppress first connector column, if visible top level is always expanded
+ if ( bHideFirstConnector && p==rootParent )
+ break;
+ res = ( p.isLastSibling() ? cache.tagEmpty : cache.tagVline) + res;
+ p = p.parent;
+ }
+
+ // connector (expanded, expandable or simple)
+ if( bHideFirstExpander && this.parent==rootParent ) {
+ // skip connector
+ } else if ( this.childList || this.data.isLazy ) {
+ res += cache.tagExpander;
+ } else {
+ res += cache.tagConnector;
+ }
+
+ // Checkbox mode
+ if( opts.checkbox && this.data.hideCheckbox!=true && !this.data.isStatusNode ) {
+ res += cache.tagCheckbox;
+ }
+
+ // folder or doctype icon
+ if ( this.data.icon ) {
+ res += "<img src='" + opts.imagePath + this.data.icon + "' alt='' />";
+ } else if ( this.data.icon == false ) {
+ // icon == false means 'no icon'
+ } else {
+ // icon == null means 'default icon'
+ res += cache.tagNodeIcon;
+ }
+
+ // node name
+ var tooltip = ( this.data && typeof this.data.tooltip == "string" ) ? " title='" + this.data.tooltip + "'" : "";
+ res += "<a href='#' class='" + opts.classNames.title + "'" + tooltip + ">" + this.data.title + "</a>";
+ return res;
+ },
+
+ _fixOrder: function() {
+ /**
+ * Make sure, that <div> order matches childList order.
+ */
+ var cl = this.childList;
+ if( !cl )
+ return;
+ var childDiv = this.div.firstChild.nextSibling;
+ for(var i=0; i<cl.length-1; i++) {
+ var childNode1 = cl[i];
+ var childNode2 = childDiv.firstChild.dtnode;
+ if( childNode1 !== childNode2 ) {
+ this.tree.logDebug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2);
+ this.div.insertBefore(childNode1.div, childNode2.div);
+ } else {
+ childDiv = childDiv.nextSibling;
+ }
+ }
+ },
+
+ render: function(bDeep, bHidden) {
+ /**
+ * Create HTML markup for this node.
+ *
+ * <div> // This div contains the node's span and list of child div's.
+ * <span id='key'>S S S A</span> // Span contains graphic spans and title <a> tag
+ * <div>child1</div>
+ * <div>child2</div>
+ * </div>
+ */
+// this.tree.logDebug("%o.render()", this);
+ var opts = this.tree.options;
+ var cn = opts.classNames;
+ var isLastSib = this.isLastSibling();
+ // ---
+ if( ! this.div ) {
+ this.span = document.createElement("span");
+ this.span.dtnode = this;
+ if( this.data.key )
+ this.span.id = this.tree.options.idPrefix + this.data.key;
+ this.div = document.createElement("div");
+ this.div.appendChild(this.span);
+
+ if ( this.parent ) {
+ this.parent.div.appendChild(this.div);
+ }
+
+ if( this.parent==null && !this.tree.options.rootVisible )
+ this.span.style.display = "none";
+ }
+ // set node connector images, links and text
+ this.span.innerHTML = this._getInnerHtml();
+
+ // hide this node, if parent is collapsed
+ this.div.style.display = ( this.parent==null || this.parent.bExpanded ? "" : "none");
+
+ // Set classes for current status
+ var cnList = [];
+ cnList.push( ( this.data.isFolder ) ? cn.folder : cn.document );
+ if( this.bExpanded )
+ cnList.push(cn.expanded);
+ if( this.childList != null )
+ cnList.push(cn.hasChildren);
+ if( this.data.isLazy && this.childList==null )
+ cnList.push(cn.lazy);
+ if( isLastSib )
+ cnList.push(cn.lastsib);
+ if( this.bSelected )
+ cnList.push(cn.selected);
+ if( this.hasSubSel )
+ cnList.push(cn.partsel);
+ if( this.tree.activeNode === this )
+ cnList.push(cn.active);
+ if( this.data.addClass )
+ cnList.push(this.data.addClass);
+ // IE6 doesn't correctly evaluate multiple class names,
+ // so we create combined class names that can be used in the CSS
+ cnList.push(cn.combinedExpanderPrefix
+ + (this.bExpanded ? "e" : "c")
+ + (this.data.isLazy && this.childList==null ? "d" : "")
+ + (isLastSib ? "l" : "")
+ );
+ cnList.push(cn.combinedIconPrefix
+ + (this.bExpanded ? "e" : "c")
+ + (this.data.isFolder ? "f" : "")
+ );
+ this.span.className = cnList.join(" ");
+
+ if( bDeep && this.childList && (bHidden || this.bExpanded) ) {
+ for(var i=0; i<this.childList.length; i++) {
+ this.childList[i].render(bDeep, bHidden)
+ }
+ this._fixOrder();
+ }
+ },
+
+ hasChildren: function() {
+ return this.childList != null;
+ },
+
+ isLastSibling: function() {
+ var p = this.parent;
+ if ( !p ) return true;
+ return p.childList[p.childList.length-1] === this;
+ },
+
+ prevSibling: function() {
+ if( !this.parent ) return null;
+ var ac = this.parent.childList;
+ for(var i=1; i<ac.length; i++) // start with 1, so prev(first) = null
+ if( ac[i] === this )
+ return ac[i-1];
+ return null;
+ },
+
+ nextSibling: function() {
+ if( !this.parent ) return null;
+ var ac = this.parent.childList;
+ for(var i=0; i<ac.length-1; i++) // up to length-2, so next(last) = null
+ if( ac[i] === this )
+ return ac[i+1];
+ return null;
+ },
+
+ _setStatusNode: function(data) {
+ // Create, modify or remove the status child node (pass 'null', to remove it).
+ var firstChild = ( this.childList ? this.childList[0] : null );
+ if( !data ) {
+ if ( firstChild ) {
+ this.div.removeChild(firstChild.div);
+ if( this.childList.length == 1 )
+ this.childList = null;
+ else
+ this.childList.shift();
+ }
+ } else if ( firstChild ) {
+ data.isStatusNode = true;
+ firstChild.data = data;
+ firstChild.render(false, false);
+ } else {
+ data.isStatusNode = true;
+ firstChild = this.addChild(data);
+ }
+ },
+
+ setLazyNodeStatus: function(lts, opts) {
+ var tooltip = (opts && opts.tooltip) ? opts.tooltip : null;
+ var info = (opts && opts.info) ? " (" + opts.info + ")" : "";
+ switch( lts ) {
+ case DTNodeStatus_Ok:
+ this._setStatusNode(null);
+// this.isRead = true;
+ this.isLoading = false;
+ this.render(false, false);
+ if( this.tree.options.autoFocus ) {
+ if( this === this.tree.tnRoot && !this.tree.options.rootVisible && this.childList ) {
+ // special case: using ajaxInit
+ this.childList[0].focus();
+ } else {
+ this.focus();
+ }
+ }
+ break;
+ case DTNodeStatus_Loading:
+ this.isLoading = true;
+ this._setStatusNode({
+ title: this.tree.options.strings.loading + info,
+ tooltip: tooltip,
+ addClass: this.tree.options.classNames.nodeWait
+ });
+ break;
+ case DTNodeStatus_Error:
+ this.isLoading = false;
+ this._setStatusNode({
+ title: this.tree.options.strings.loadError + info,
+ tooltip: tooltip,
+ addClass: this.tree.options.classNames.nodeError
+ });
+ break;
+ default:
+ throw "Bad LazyNodeStatus: '" + lts + "'.";
+ }
+ },
+
+ _parentList: function(includeRoot, includeSelf) {
+ var l = [];
+ var dtn = includeSelf ? this : this.parent;
+ while( dtn ) {
+ if( includeRoot || dtn.parent )
+ l.unshift(dtn);
+ dtn = dtn.parent;
+ };
+ return l;
+ },
+
+ getLevel: function() {
+ var level = 0;
+ var dtn = this.parent;
+ while( dtn ) {
+ level++;
+ dtn = dtn.parent;
+ };
+ return level;
+ },
+
+ _getTypeForOuterNodeEvent: function(event) {
+ /** Return the inner node span (title, checkbox or expander) if
+ * event.target points to the outer span.
+ * This function should fix issue #93:
+ * FF2 ignores empty spans, when generating events (returning the parent instead).
+ */
+ var cns = this.tree.options.classNames;
+ var target = event.target;
+ // Only process clicks on an outer node span (probably due to a FF2 event handling bug)
+ if( target.className.indexOf(cns.folder)<0
+ && target.className.indexOf(cns.document)<0 ) {
+ return null
+ }
+ // Event coordinates, relative to outer node span:
+ var eventX = event.pageX - target.offsetLeft;
+ var eventY = event.pageY - target.offsetTop;
+
+ for(var i=0; i<target.childNodes.length; i++) {
+ var cn = target.childNodes[i];
+ var x = cn.offsetLeft - target.offsetLeft;
+ var y = cn.offsetTop - target.offsetTop;
+ var nx = cn.clientWidth, ny = cn.clientHeight;
+// alert (cn.className + ": " + x + ", " + y + ", s:" + nx + ", " + ny);
+ if( eventX>=x && eventX<=(x+nx) && eventY>=y && eventY<=(y+ny) ) {
+// alert("HIT "+ cn.className);
+ if( cn.className==cns.title )
+ return "title";
+ else if( cn.className==cns.expander )
+ return "expander";
+ else if( cn.className==cns.checkbox )
+ return "checkbox";
+ else if( cn.className==cns.nodeIcon )
+ return "icon";
+ }
+ }
+ return "prefix";
+ },
+
+ getEventTargetType: function(event) {
+ // Return the part of a node, that a click event occured on.
+ // Note: there is no check, if the was fired on TIHS node.
+ var tcn = event && event.target ? event.target.className : "";
+ var cns = this.tree.options.classNames;
+
+ if( tcn == cns.title )
+ return "title";
+ else if( tcn==cns.expander )
+ return "expander";
+ else if( tcn==cns.checkbox )
+ return "checkbox";
+ else if( tcn==cns.nodeIcon )
+ return "icon";
+ else if( tcn==cns.empty || tcn==cns.vline || tcn==cns.connector )
+ return "prefix";
+ else if( tcn.indexOf(cns.folder)>=0 || tcn.indexOf(cns.document)>=0 )
+ // FIX issue #93
+ return this._getTypeForOuterNodeEvent(event);
+ return null;
+ },
+
+ isVisible: function() {
+ // Return true, if all parents are expanded.
+ var parents = this._parentList(true, false);
+ for(var i=0; i<parents.length; i++)
+ if( ! parents[i].bExpanded ) return false;
+ return true;
+ },
+
+ makeVisible: function() {
+ // Make sure, all parents are expanded
+ var parents = this._parentList(true, false);
+ for(var i=0; i<parents.length; i++)
+ parents[i]._expand(true);
+ },
+
+ focus: function() {
+ // TODO: check, if we already have focus
+// this.tree.logDebug("dtnode.focus(): %o", this);
+ this.makeVisible();
+ try {
+ $(this.span).find(">a").focus();
+ } catch(e) { }
+ },
+
+ _activate: function(flag, fireEvents) {
+ // (De)Activate - but not focus - this node.
+ this.tree.logDebug("dtnode._activate(%o, fireEvents=%o) - %o", flag, fireEvents, this);
+ var opts = this.tree.options;
+ if( this.data.isStatusNode )
+ return;
+ if ( fireEvents && opts.onQueryActivate && opts.onQueryActivate.call(this.span, flag, this) == false )
+ return; // Callback returned false
+
+ if( flag ) {
+ // Activate
+ if( this.tree.activeNode ) {
+ if( this.tree.activeNode === this )
+ return;
+ this.tree.activeNode.deactivate();
+ }
+ if( opts.activeVisible )
+ this.makeVisible();
+ this.tree.activeNode = this;
+ if( opts.persist )
+ $.cookie(opts.cookieId+"-active", this.data.key, opts.cookie);
+ this.tree.persistence.activeKey = this.data.key;
+ $(this.span).addClass(opts.classNames.active);
+ if ( fireEvents && opts.onActivate ) // Pass element as 'this' (jQuery convention)
+ opts.onActivate.call(this.span, this);
+ } else {
+ // Deactivate
+ if( this.tree.activeNode === this ) {
+ var opts = this.tree.options;
+ if ( opts.onQueryActivate && opts.onQueryActivate.call(this.span, false, this) == false )
+ return; // Callback returned false
+ $(this.span).removeClass(opts.classNames.active);
+ if( opts.persist ) {
+ // Note: we don't pass null, but ''. So the cookie is not deleted.
+ // If we pass null, we also have to pass a COPY of opts, because $cookie will override opts.expires (issue 84)
+ $.cookie(opts.cookieId+"-active", "", opts.cookie);
+ }
+ this.tree.persistence.activeKey = null;
+ this.tree.activeNode = null;
+ if ( fireEvents && opts.onDeactivate )
+ opts.onDeactivate.call(this.span, this);
+ }
+ }
+ },
+
+ activate: function() {
+ // Select - but not focus - this node.
+// this.tree.logDebug("dtnode.activate(): %o", this);
+ this._activate(true, true);
+ },
+
+ deactivate: function() {
+// this.tree.logDebug("dtnode.deactivate(): %o", this);
+ this._activate(false, true);
+ },
+
+ isActive: function() {
+ return (this.tree.activeNode === this);
+ },
+
+ _userActivate: function() {
+ // Handle user click / [space] / [enter], according to clickFolderMode.
+ var activate = true;
+ var expand = false;
+ if ( this.data.isFolder ) {
+ switch( this.tree.options.clickFolderMode ) {
+ case 2:
+ activate = false;
+ expand = true;
+ break;
+ case 3:
+ activate = expand = true;
+ break;
+ }
+ }
+ if( this.parent == null && this.tree.options.minExpandLevel>0 ) {
+ expand = false;
+ }
+ if( expand ) {
+ this.toggleExpand();
+ this.focus();
+ }
+ if( activate ) {
+ this.activate();
+ }
+ },
+
+ _setSubSel: function(hasSubSel) {
+ if( hasSubSel ) {
+ this.hasSubSel = true;
+ $(this.span).addClass(this.tree.options.classNames.partsel);
+ } else {
+ this.hasSubSel = false;
+ $(this.span).removeClass(this.tree.options.classNames.partsel);
+ }
+ },
+
+ _fixSelectionState: function() {
+ // fix selection status, for multi-hier mode
+// this.tree.logDebug("_fixSelectionState(%o) - %o", this.bSelected, this);
+ if( this.bSelected ) {
+ // Select all children
+ this.visit(function(dtnode){
+ dtnode.parent._setSubSel(true);
+ dtnode._select(true, false, false);
+ });
+ // Select parents, if all children are selected
+ var p = this.parent;
+ while( p ) {
+ p._setSubSel(true);
+ var allChildsSelected = true;
+ for(var i=0; i<p.childList.length; i++) {
+ var n = p.childList[i];
+ if( !n.bSelected && !n.data.isStatusNode ) {
+ allChildsSelected = false;
+ break;
+ }
+ }
+ if( allChildsSelected )
+ p._select(true, false, false);
+ p = p.parent;
+ }
+ } else {
+ // Deselect all children
+ this._setSubSel(false);
+ this.visit(function(dtnode){
+ dtnode._setSubSel(false);
+ dtnode._select(false, false, false);
+ });
+ // Deselect parents, and recalc hasSubSel
+ var p = this.parent;
+ while( p ) {
+ p._select(false, false, false);
+ var isPartSel = false;
+ for(var i=0; i<p.childList.length; i++) {
+ if( p.childList[i].bSelected || p.childList[i].hasSubSel ) {
+ isPartSel = true;
+ break;
+ }
+ }
+ p._setSubSel(isPartSel);
+ p = p.parent;
+ }
+ }
+ },
+
+ _select: function(sel, fireEvents, deep) {
+ // Select - but not focus - this node.
+// this.tree.logDebug("dtnode._select(%o) - %o", sel, this);
+ var opts = this.tree.options;
+ if( this.data.isStatusNode )
+ return;
+ //
+ if( this.bSelected == sel ) {
+// this.tree.logDebug("dtnode._select(%o) IGNORED - %o", sel, this);
+ return;
+ }
+ // Allow event listener to abort selection
+ if ( fireEvents && opts.onQuerySelect && opts.onQuerySelect.call(this.span, sel, this) == false )
+ return; // Callback returned false
+
+ // Force single-selection
+ if( opts.selectMode==1 && sel ) {
+ this.tree.visit(function(dtnode){
+ if( dtnode.bSelected ) {
+ // Deselect; assuming that in selectMode:1 there's max. one other selected node
+ dtnode._select(false, false, false);
+ return false;
+ }
+ });
+ }
+
+ this.bSelected = sel;
+// this.tree._changeNodeList("select", this, sel);
+
+ if( sel ) {
+ if( opts.persist )
+ this.tree.persistence.addSelect(this.data.key);
+
+ $(this.span).addClass(opts.classNames.selected);
+
+ if( deep && opts.selectMode==3 )
+ this._fixSelectionState();
+
+ if ( fireEvents && opts.onSelect )
+ opts.onSelect.call(this.span, true, this);
+
+ } else {
+ if( opts.persist )
+ this.tree.persistence.clearSelect(this.data.key);
+
+ $(this.span).removeClass(opts.classNames.selected);
+
+ if( deep && opts.selectMode==3 )
+ this._fixSelectionState();
+
+ if ( fireEvents && opts.onSelect )
+ opts.onSelect.call(this.span, false, this);
+ }
+ },
+
+ select: function(sel) {
+ // Select - but not focus - this node.
+// this.tree.logDebug("dtnode.select(%o) - %o", sel, this);
+ if( this.data.unselectable )
+ return this.bSelected;
+ return this._select(sel!=false, true, true);
+ },
+
+ toggleSelect: function() {
+// this.tree.logDebug("dtnode.toggleSelect() - %o", this);
+ return this.select(!this.bSelected);
+ },
+
+ isSelected: function() {
+ return this.bSelected;
+ },
+
+ _loadContent: function() {
+ try {
+ var opts = this.tree.options;
+ this.tree.logDebug("_loadContent: start - %o", this);
+ this.setLazyNodeStatus(DTNodeStatus_Loading);
+ if( true == opts.onLazyRead.call(this.span, this) ) {
+ // If function returns 'true', we assume that the loading is done:
+ this.setLazyNodeStatus(DTNodeStatus_Ok);
+ // Otherwise (i.e. if the loading was started as an asynchronous process)
+ // the onLazyRead(dtnode) handler is expected to call dtnode.setLazyNodeStatus(DTNodeStatus_Ok/_Error) when done.
+ this.tree.logDebug("_loadContent: succeeded - %o", this);
+ }
+ } catch(e) {
+// alert(e);
+ this.setLazyNodeStatus(DTNodeStatus_Error);
+ this.tree.logWarning("_loadContent: failed - %o", e);
+ }
+ },
+
+ _expand: function(bExpand) {
+// this.tree.logDebug("dtnode._expand(%o) - %o", bExpand, this);
+ if( this.bExpanded == bExpand ) {
+// this.tree.logDebug("dtnode._expand(%o) IGNORED - %o", bExpand, this);
+ return;
+ }
+ var opts = this.tree.options;
+ if( !bExpand && this.getLevel()<opts.minExpandLevel ) {
+ this.tree.logDebug("dtnode._expand(%o) forced expand - %o", bExpand, this);
+ return;
+ }
+ if ( opts.onQueryExpand && opts.onQueryExpand.call(this.span, bExpand, this) == false )
+ return; // Callback returned false
+ this.bExpanded = bExpand;
+
+ // Persist expand state
+ if( opts.persist ) {
+ if( bExpand )
+ this.tree.persistence.addExpand(this.data.key);
+ else
+ this.tree.persistence.clearExpand(this.data.key);
+ }
+
+ this.render(false);
+
+ // Auto-collapse mode: collapse all siblings
+ if( this.bExpanded && this.parent && opts.autoCollapse ) {
+ var parents = this._parentList(false, true);
+ for(var i=0; i<parents.length; i++)
+ parents[i].collapseSiblings();
+ }
+
+ // If the currently active node is now hidden, deactivate it
+ if( opts.activeVisible && this.tree.activeNode && ! this.tree.activeNode.isVisible() ) {
+ this.tree.activeNode.deactivate();
+ }
+ // Expanding a lazy node: set 'loading...' and call callback
+ if( bExpand && this.data.isLazy && this.childList==null && !this.isLoading ) {
+ this._loadContent();
+ return;
+ }
+// this.tree.logDebug("_expand: start div toggle - %o", this);
+
+ var fxDuration = opts.fx ? (opts.fx.duration || 200) : 0;
+ if( this.childList ) {
+ for(var i=0; i<this.childList.length; i++ ) {
+ var $child = $(this.childList[i].div);
+ if( fxDuration ) {
+ // This is a toggle, so only do it, if not already rendered (in)visible (issue 98)
+ if( bExpand != $child.is(':visible') )
+ $child.animate(opts.fx, fxDuration);
+ } else {
+ if( bExpand )
+ $child.show();
+ else
+ $child.hide(); // TODO: this seems to be slow, when called the first time for an element
+ }
+ }
+ }
+
+/* issue 109: using selector filter is really SLOW.
+ // issue 98: only toggle, if render hasn't set visibility already:
+ var filter = ">DIV" + (bExpand ? ":hidden" : ":visible");
+
+ if( opts.fx ) {
+ var duration = opts.fx.duration || 200;
+// $(">DIV", this.div).animate(opts.fx, duration);
+ $(filter, this.div).animate(opts.fx, duration);
+ } else {
+ $(filter, this.div).toggle();
+// var $d = $(">DIV", this.div);
+// this.tree.logDebug("_expand: got div, start toggle - %o", this);
+// $d.toggle();
+ }
+//*/
+// this.tree.logDebug("_expand: end div toggle - %o", this);
+
+ if ( opts.onExpand )
+ opts.onExpand.call(this.span, bExpand, this);
+ },
+
+ expand: function(flag) {
+ if( !this.childList && !this.data.isLazy && flag )
+ return; // Prevent expanding empty nodes
+ if( this.parent == null && this.tree.options.minExpandLevel>0 && !flag )
+ return; // Prevent collapsing the root
+ this._expand(flag);
+ },
+
+ toggleExpand: function() {
+ this.expand(!this.bExpanded);
+ },
+
+ collapseSiblings: function() {
+ if( this.parent == null )
+ return;
+ var ac = this.parent.childList;
+ for (var i=0; i<ac.length; i++) {
+ if ( ac[i] !== this && ac[i].bExpanded )
+ ac[i]._expand(false);
+ }
+ },
+
+ onClick: function(event) {
+// this.tree.logDebug("dtnode.onClick(" + event.type + "): dtnode:" + this + ", button:" + event.button + ", which: " + event.which);
+ var targetType = this.getEventTargetType(event);
+ if( targetType == "expander" ) {
+ // Clicking the expander icon always expands/collapses
+ this.toggleExpand();
+ this.focus(); // issue 95
+ } else if( targetType == "checkbox" ) {
+ // Clicking the checkbox always (de)selects
+ this.toggleSelect();
+ this.focus(); // issue 95
+ } else {
+ this._userActivate();
+ // Chrome and Safari don't focus the a-tag on click
+ this.span.getElementsByTagName("a")[0].focus();
+ }
+ // Make sure that clicks stop, otherwise <a href='#'> jumps to the top
+ return false;
+ },
+
+ onDblClick: function(event) {
+// this.tree.logDebug("dtnode.onDblClick(" + event.type + "): dtnode:" + this + ", button:" + event.button + ", which: " + event.which);
+ },
+
+ onKeydown: function(event) {
+// this.tree.logDebug("dtnode.onKeydown(" + event.type + "): dtnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+ var handled = true;
+// alert("keyDown" + event.which);
+
+ switch( event.which ) {
+ // charCodes:
+// case 43: // '+'
+ case 107: // '+'
+ case 187: // '+' @ Chrome, Safari
+ if( !this.bExpanded ) this.toggleExpand();
+ break;
+// case 45: // '-'
+ case 109: // '-'
+ case 189: // '+' @ Chrome, Safari
+ if( this.bExpanded ) this.toggleExpand();
+ break;
+ //~ case 42: // '*'
+ //~ break;
+ //~ case 47: // '/'
+ //~ break;
+ // case 13: // <enter>
+ // <enter> on a focused <a> tag seems to generate a click-event.
+ // this._userActivate();
+ // break;
+ case 32: // <space>
+ this._userActivate();
+ break;
+ case 8: // <backspace>
+ if( this.parent )
+ this.parent.focus();
+ break;
+ case 37: // <left>
+ if( this.bExpanded ) {
+ this.toggleExpand();
+ this.focus();
+ } else if( this.parent && (this.tree.options.rootVisible || this.parent.parent) ) {
+ this.parent.focus();
+ }
+ break;
+ case 39: // <right>
+ if( !this.bExpanded && (this.childList || this.data.isLazy) ) {
+ this.toggleExpand();
+ this.focus();
+ } else if( this.childList ) {
+ this.childList[0].focus();
+ }
+ break;
+ case 38: // <up>
+ var sib = this.prevSibling();
+ while( sib && sib.bExpanded && sib.childList )
+ sib = sib.childList[sib.childList.length-1];
+ if( !sib && this.parent && (this.tree.options.rootVisible || this.parent.parent) )
+ sib = this.parent;
+ if( sib ) sib.focus();
+ break;
+ case 40: // <down>
+ var sib;
+ if( this.bExpanded && this.childList ) {
+ sib = this.childList[0];
+ } else {
+ var parents = this._parentList(false, true);
+ for(var i=parents.length-1; i>=0; i--) {
+ sib = parents[i].nextSibling();
+ if( sib ) break;
+ }
+ }
+ if( sib ) sib.focus();
+ break;
+ default:
+ handled = false;
+ }
+ // Return false, if handled, to prevent default processing
+ return !handled;
+ },
+
+ onKeypress: function(event) {
+ // onKeypress is only hooked to allow user callbacks.
+ // We don't process it, because IE and Safari don't fire keypress for cursor keys.
+// this.tree.logDebug("dtnode.onKeypress(" + event.type + "): dtnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+ },
+
+ onFocus: function(event) {
+ // Handles blur and focus events.
+// this.tree.logDebug("dtnode.onFocus(%o): %o", event, this);
+ var opts = this.tree.options;
+ if ( event.type=="blur" || event.type=="focusout" ) {
+ if ( opts.onBlur ) // Pass element as 'this' (jQuery convention)
+ opts.onBlur.call(this.span, this);
+ if( this.tree.tnFocused )
+ $(this.tree.tnFocused.span).removeClass(opts.classNames.focused);
+ this.tree.tnFocused = null;
+ if( opts.persist )
+ $.cookie(opts.cookieId+"-focus", "", opts.cookie);
+ } else if ( event.type=="focus" || event.type=="focusin") {
+ // Fix: sometimes the blur event is not generated
+ if( this.tree.tnFocused && this.tree.tnFocused !== this ) {
+ this.tree.logDebug("dtnode.onFocus: out of sync: curFocus: %o", this.tree.tnFocused);
+ $(this.tree.tnFocused.span).removeClass(opts.classNames.focused);
+ }
+ this.tree.tnFocused = this;
+ if ( opts.onFocus ) // Pass element as 'this' (jQuery convention)
+ opts.onFocus.call(this.span, this);
+ $(this.tree.tnFocused.span).addClass(opts.classNames.focused);
+ if( opts.persist )
+ $.cookie(opts.cookieId+"-focus", this.data.key, opts.cookie);
+ }
+ // TODO: return anything?
+// return false;
+ },
+
+ visit: function(fn, data, includeSelf) {
+ // Call fn(dtnode, data) for all child nodes. Stop iteration, if fn() returns false.
+ var n = 0;
+ if( includeSelf == true ) {
+ if( fn(this, data) == false )
+ return 1;
+ n++;
+ }
+ if ( this.childList )
+ for (var i=0; i<this.childList.length; i++)
+ n += this.childList[i].visit(fn, data, true);
+ return n;
+ },
+
+ remove: function() {
+ // Remove this node
+// this.tree.logDebug ("%o.remove()", this);
+ if ( this === this.tree.root )
+ return false;
+ return this.parent.removeChild(this);
+ },
+
+ removeChild: function(tn) {
+ // Remove tn from list of direct children.
+ var ac = this.childList;
+ if( ac.length == 1 ) {
+ if( tn !== ac[0] )
+ throw "removeChild: invalid child";
+ return this.removeChildren();
+ }
+ if( tn === this.tree.activeNode )
+ tn.deactivate();
+ if( this.tree.options.persist ) {
+ if( tn.bSelected )
+ this.tree.persistence.clearSelect(tn.data.key);
+ if ( tn.bExpanded )
+ this.tree.persistence.clearExpand(tn.data.key);
+ }
+ tn.removeChildren(true);
+ this.div.removeChild(tn.div);
+ for(var i=0; i<ac.length; i++) {
+ if( ac[i] === tn ) {
+ this.childList.splice(i, 1);
+ delete tn;
+ break;
+ }
+ }
+ },
+
+ removeChildren: function(isRecursiveCall, retainPersistence) {
+ // Remove all child nodes (more efficiently than recursive remove())
+// this.tree.logDebug ("%o.removeChildren(%o)", this, isRecursiveCall);
+ var tree = this.tree;
+ var ac = this.childList;
+ if( ac ) {
+ for(var i=0; i<ac.length; i++) {
+ var tn=ac[i];
+// this.tree.logDebug ("del %o", tn);
+ if ( tn === tree.activeNode && !retainPersistence )
+ tn.deactivate();
+ if( this.tree.options.persist && !retainPersistence ) {
+ if( tn.bSelected )
+ this.tree.persistence.clearSelect(tn.data.key);
+ if ( tn.bExpanded )
+ this.tree.persistence.clearExpand(tn.data.key);
+ }
+ tn.removeChildren(true, retainPersistence);
+ this.div.removeChild(tn.div);
+ delete tn;
+ }
+ this.childList = null;
+ }
+ if( ! isRecursiveCall ) {
+// this._expand(false);
+// this.isRead = false;
+ this.isLoading = false;
+ this.render(false, false);
+ }
+ },
+
+ reload: function(force) {
+ // Discard lazy content (and reload, if node was expanded).
+ if( this.parent == null )
+ return this.tree.reload();
+
+ if( ! this.data.isLazy )
+ throw "node.reload() requires lazy nodes.";
+ if( this.bExpanded ) {
+ this.expand(false);
+ this.removeChildren();
+ this.expand(true);
+ } else {
+ this.removeChildren();
+ if( force )
+ this._loadContent();
+ }
+ },
+
+ _addChildNode: function(dtnode, beforeNode) {
+ /**
+ * Internal function to add one single DynatreeNode as a child.
+ *
+ */
+ var tree = this.tree;
+ var opts = tree.options;
+ var pers = tree.persistence;
+
+// tree.logDebug("%o._addChildNode(%o)", this, dtnode);
+
+ // --- Update and fix dtnode attributes if necessary
+ dtnode.parent = this;
+// if( beforeNode && (beforeNode.parent !== this || beforeNode === dtnode ) )
+// throw "<beforeNode> must be another child of <this>";
+
+ // --- Add dtnode as a child
+ if ( this.childList==null ) {
+ this.childList = [];
+ } else if( ! beforeNode ) {
+ // Fix 'lastsib'
+ $(this.childList[this.childList.length-1].span).removeClass(opts.classNames.lastsib);
+ }
+ if( beforeNode ) {
+ var iBefore = $.inArray(beforeNode, this.childList);
+ if( iBefore < 0 )
+ throw "<beforeNode> must be a child of <this>";
+ this.childList.splice(iBefore, 0, dtnode);
+// alert(this.childList);
+ } else {
+ // Append node
+ this.childList.push(dtnode);
+ }
+
+ // --- Handle persistence
+ // Initial status is read from cookies, if persistence is active and
+ // cookies are already present.
+ // Otherwise the status is read from the data attributes and then persisted.
+ var isInitializing = tree.isInitializing();
+ if( opts.persist && pers.cookiesFound && isInitializing ) {
+ // Init status from cookies
+// tree.logDebug("init from cookie, pa=%o, dk=%o", pers.activeKey, dtnode.data.key);
+ if( pers.activeKey == dtnode.data.key )
+ tree.activeNode = dtnode;
+ if( pers.focusedKey == dtnode.data.key )
+ tree.focusNode = dtnode;
+ dtnode.bExpanded = ($.inArray(dtnode.data.key, pers.expandedKeyList) >= 0);
+ dtnode.bSelected = ($.inArray(dtnode.data.key, pers.selectedKeyList) >= 0);
+// tree.logDebug(" key=%o, bSelected=%o", dtnode.data.key, dtnode.bSelected);
+ } else {
+ // Init status from data (Note: we write the cookies after the init phase)
+// tree.logDebug("init from data");
+ if( dtnode.data.activate ) {
+ tree.activeNode = dtnode;
+ if( opts.persist )
+ pers.activeKey = dtnode.data.key;
+ }
+ if( dtnode.data.focus ) {
+ tree.focusNode = dtnode;
+ if( opts.persist )
+ pers.focusedKey = dtnode.data.key;
+ }
+ dtnode.bExpanded = ( dtnode.data.expand == true ); // Collapsed by default
+ if( dtnode.bExpanded && opts.persist )
+ pers.addExpand(dtnode.data.key);
+ dtnode.bSelected = ( dtnode.data.select == true ); // Deselected by default
+/*
+ Doesn't work, cause pers.selectedKeyList may be null
+ if( dtnode.bSelected && opts.selectMode==1
+ && pers.selectedKeyList && pers.selectedKeyList.length>0 ) {
+ tree.logWarning("Ignored multi-selection in single-mode for %o", dtnode);
+ dtnode.bSelected = false; // Fixing bad input data (multi selection for mode:1)
+ }
+*/
+ if( dtnode.bSelected && opts.persist )
+ pers.addSelect(dtnode.data.key);
+ }
+
+ // Always expand, if it's below minExpandLevel
+// tree.logDebug ("%o._addChildNode(%o), l=%o", this, dtnode, dtnode.getLevel());
+ if ( opts.minExpandLevel >= dtnode.getLevel() ) {
+// tree.logDebug ("Force expand for %o", dtnode);
+ this.bExpanded = true;
+ }
+
+ // In multi-hier mode, update the parents selection state
+ // issue #82: only if not initializing, because the children may not exist yet
+// if( !dtnode.data.isStatusNode && opts.selectMode==3 && !isInitializing )
+// dtnode._fixSelectionState();
+
+ // In multi-hier mode, update the parents selection state
+ if( dtnode.bSelected && opts.selectMode==3 ) {
+ var p = this;
+ while( p ) {
+ if( !p.hasSubSel )
+ p._setSubSel(true);
+ p = p.parent;
+ }
+ }
+ // render this node and the new child
+ if ( tree.bEnableUpdate )
+ this.render(true, true);
+
+ return dtnode;
+ },
+
+ addChild: function(obj, beforeNode) {
+ /**
+ * Add a node object as child.
+ *
+ * This should be the only place, where a DynaTreeNode is constructed!
+ * (Except for the root node creation in the tree constructor)
+ *
+ * @param obj A JS object (may be recursive) or an array of those.
+ * @param {DynaTreeNode} beforeNode (optional) sibling node.
+ *
+ * Data format: array of node objects, with optional 'children' attributes.
+ * [
+ * { title: "t1", isFolder: true, ... }
+ * { title: "t2", isFolder: true, ...,
+ * children: [
+ * {title: "t2.1", ..},
+ * {..}
+ * ]
+ * }
+ * ]
+ * A simple object is also accepted instead of an array.
+ *
+ */
+// this.tree.logDebug("%o.addChild(%o, %o)", this, obj, beforeNode);
+ if( !obj || obj.length==0 ) // Passed null or undefined or empty array
+ return;
+ if( obj instanceof DynaTreeNode )
+ return this._addChildNode(obj, beforeNode);
+ if( !obj.length ) // Passed a single data object
+ obj = [ obj ];
+
+ var prevFlag = this.tree.enableUpdate(false);
+
+ var tnFirst = null;
+ for (var i=0; i<obj.length; i++) {
+ var data = obj[i];
+ var dtnode = this._addChildNode(new DynaTreeNode(this, this.tree, data), beforeNode);
+ if( !tnFirst ) tnFirst = dtnode;
+ // Add child nodes recursively
+ if( data.children )
+ dtnode.addChild(data.children, null);
+ }
+ this.tree.enableUpdate(prevFlag);
+ return tnFirst;
+ },
+
+ append: function(obj) {
+ this.tree.logWarning("node.append() is deprecated (use node.addChild() instead).");
+ return this.addChild(obj, null);
+ },
+
+ appendAjax: function(ajaxOptions) {
+ this.removeChildren(false, true);
+ this.setLazyNodeStatus(DTNodeStatus_Loading);
+ // Ajax option inheritance: $.ajaxSetup < $.ui.dynatree.defaults.ajaxDefaults < tree.options.ajaxDefaults < ajaxOptions
+ var self = this;
+ var orgSuccess = ajaxOptions.success;
+ var orgError = ajaxOptions.error;
+ var options = $.extend({}, this.tree.options.ajaxDefaults, ajaxOptions, {
+/*
+ complete: function(req, textStatus){
+ alert("ajax complete");
+ },
+ timeout: 5000, // 5 sec
+*/
+ success: function(data, textStatus){
+ // <this> is the request options
+// self.tree.logDebug("appendAjax().success");
+ var prevPhase = self.tree.phase;
+ self.tree.phase = "init";
+// self.append(data);
+ self.addChild(data, null);
+ self.tree.phase = "postInit";
+ self.setLazyNodeStatus(DTNodeStatus_Ok);
+ if( orgSuccess )
+ orgSuccess.call(options, self);
+ self.tree.phase = prevPhase;
+ },
+ error: function(XMLHttpRequest, textStatus, errorThrown){
+ // <this> is the request options
+// self.tree.logWarning("appendAjax failed: %o:\n%o\n%o", textStatus, XMLHttpRequest, errorThrown);
+ self.tree.logWarning("appendAjax failed:", textStatus, ":\n", XMLHttpRequest, "\n", errorThrown);
+ self.setLazyNodeStatus(DTNodeStatus_Error, {info: textStatus, tooltip: ""+errorThrown});
+ if( orgError )
+ orgError.call(options, self, XMLHttpRequest, textStatus, errorThrown);
+ }
+ });
+ $.ajax(options);
+ },
+ // --- end of class
+ lastentry: undefined
+}
+
+/*************************************************************************
+ * class DynaTreeStatus
+ */
+
+var DynaTreeStatus = Class.create();
+
+
+DynaTreeStatus._getTreePersistData = function(cookieId, cookieOpts) {
+ // Static member: Return persistence information from cookies
+ var ts = new DynaTreeStatus(cookieId, cookieOpts);
+ ts.read();
+ return ts.toDict();
+}
+// Make available in global scope
+getDynaTreePersistData = DynaTreeStatus._getTreePersistData;
+
+
+DynaTreeStatus.prototype = {
+ // Constructor
+ initialize: function(cookieId, cookieOpts) {
+ this._log("DynaTreeStatus: initialize");
+ if( cookieId === undefined )
+ cookieId = $.ui.dynatree.defaults.cookieId;
+ cookieOpts = $.extend({}, $.ui.dynatree.defaults.cookie, cookieOpts);
+
+ this.cookieId = cookieId;
+ this.cookieOpts = cookieOpts;
+ this.cookiesFound = undefined;
+ this.activeKey = null;
+ this.focusedKey = null;
+ this.expandedKeyList = null;
+ this.selectedKeyList = null;
+ },
+ // member functions
+ _log: function(msg) {
+ // this.logDebug("_changeNodeList(%o): nodeList:%o, idx:%o", mode, nodeList, idx);
+ Array.prototype.unshift.apply(arguments, ["debug"]);
+ _log.apply(this, arguments);
+ },
+ read: function() {
+ this._log("DynaTreeStatus: read");
+ // Read or init cookies.
+ this.cookiesFound = false;
+
+ var cookie = $.cookie(this.cookieId + "-active");
+ this.activeKey = ( cookie == null ) ? "" : cookie;
+ if( cookie != null ) this.cookiesFound = true;
+
+ cookie = $.cookie(this.cookieId + "-focus");
+ this.focusedKey = ( cookie == null ) ? "" : cookie;
+ if( cookie != null ) this.cookiesFound = true;
+
+ cookie = $.cookie(this.cookieId + "-expand");
+ this.expandedKeyList = ( cookie == null ) ? [] : cookie.split(",");
+ if( cookie != null ) this.cookiesFound = true;
+
+ cookie = $.cookie(this.cookieId + "-select");
+ this.selectedKeyList = ( cookie == null ) ? [] : cookie.split(",");
+ if( cookie != null ) this.cookiesFound = true;
+ },
+ write: function() {
+ this._log("DynaTreeStatus: write");
+ $.cookie(this.cookieId + "-active", ( this.activeKey == null ) ? "" : this.activeKey, this.cookieOpts);
+ $.cookie(this.cookieId + "-focus", ( this.focusedKey == null ) ? "" : this.focusedKey, this.cookieOpts);
+ $.cookie(this.cookieId + "-expand", ( this.expandedKeyList == null ) ? "" : this.expandedKeyList.join(","), this.cookieOpts);
+ $.cookie(this.cookieId + "-select", ( this.selectedKeyList == null ) ? "" : this.selectedKeyList.join(","), this.cookieOpts);
+ },
+ addExpand: function(key) {
+ this._log("addExpand(%o)", key);
+ if( $.inArray(key, this.expandedKeyList) < 0 ) {
+ this.expandedKeyList.push(key);
+ $.cookie(this.cookieId + "-expand", this.expandedKeyList.join(","), this.cookieOpts);
+ }
+ },
+ clearExpand: function(key) {
+ this._log("clearExpand(%o)", key);
+ var idx = $.inArray(key, this.expandedKeyList);
+ if( idx >= 0 ) {
+ this.expandedKeyList.splice(idx, 1);
+ $.cookie(this.cookieId + "-expand", this.expandedKeyList.join(","), this.cookieOpts);
+ }
+ },
+ addSelect: function(key) {
+ this._log("addSelect(%o)", key);
+ if( $.inArray(key, this.selectedKeyList) < 0 ) {
+ this.selectedKeyList.push(key);
+ $.cookie(this.cookieId + "-select", this.selectedKeyList.join(","), this.cookieOpts);
+ }
+ },
+ clearSelect: function(key) {
+ this._log("clearSelect(%o)", key);
+ var idx = $.inArray(key, this.selectedKeyList);
+ if( idx >= 0 ) {
+ this.selectedKeyList.splice(idx, 1);
+ $.cookie(this.cookieId + "-select", this.selectedKeyList.join(","), this.cookieOpts);
+ }
+ },
+ isReloading: function() {
+ return this.cookiesFound == true;
+ },
+ toDict: function() {
+ return {
+ cookiesFound: this.cookiesFound,
+ activeKey: this.activeKey,
+ focusedKey: this.activeKey,
+ expandedKeyList: this.expandedKeyList,
+ selectedKeyList: this.selectedKeyList
+ };
+ },
+ // --- end of class
+ lastentry: undefined
+};
+
+
+/*************************************************************************
+ * class DynaTree
+ */
+
+var DynaTree = Class.create();
+
+// --- Static members ----------------------------------------------------------
+
+DynaTree.version = "$Version: 0.5.4$";
+/*
+DynaTree._initTree = function() {
+};
+
+DynaTree._bind = function() {
+};
+*/
+//--- Class members ------------------------------------------------------------
+
+DynaTree.prototype = {
+ // Constructor
+// initialize: function(divContainer, options) {
+ initialize: function($widget) {
+ // instance members
+ this.phase = "init";
+ this.$widget = $widget;
+ this.options = $widget.options;
+ this.$tree = $widget.element;
+ // find container element
+ this.divTree = this.$tree.get(0);
+ },
+
+ // member functions
+
+ _load: function() {
+ var $widget = this.$widget;
+ var opts = this.options;
+ this.bEnableUpdate = true;
+ this._nodeCount = 1;
+ this.activeNode = null;
+ this.focusNode = null;
+
+ // If a 'options.classNames' dictionary was passed, still use defaults
+ // for undefined classes:
+ if( opts.classNames !== $.ui.dynatree.defaults.classNames ) {
+ opts.classNames = $.extend({}, $.ui.dynatree.defaults.classNames, opts.classNames);
+ }
+ // Guess skin path, if not specified
+ if(!opts.imagePath) {
+ $("script").each( function () {
+ // Eclipse syntax parser breaks on this expression, so put it at the bottom:
+ if( this.src.search(_rexDtLibName) >= 0 ) {
+ if( this.src.indexOf("/")>=0 ) // issue #47
+ opts.imagePath = this.src.slice(0, this.src.lastIndexOf("/")) + "/skin/";
+ else
+ opts.imagePath = "skin/";
+// logMsg("Guessing imagePath from '%s': '%s'", this.src, opts.imagePath);
+ return false; // first match
+ }
+ });
+ }
+
+ this.persistence = new DynaTreeStatus(opts.cookieId, opts.cookie);
+ if( opts.persist ) {
+ if( !$.cookie )
+ _log("warn", "Please include jquery.cookie.js to use persistence.");
+ this.persistence.read();
+ }
+ this.logDebug("DynaTree.persistence: %o", this.persistence.toDict());
+
+ // Cached tag strings
+ this.cache = {
+ tagEmpty: "<span class='" + opts.classNames.empty + "'></span>",
+ tagVline: "<span class='" + opts.classNames.vline + "'></span>",
+ tagExpander: "<span class='" + opts.classNames.expander + "'></span>",
+ tagConnector: "<span class='" + opts.classNames.connector + "'></span>",
+ tagNodeIcon: "<span class='" + opts.classNames.nodeIcon + "'></span>",
+ tagCheckbox: "<span class='" + opts.classNames.checkbox + "'></span>",
+ lastentry: undefined
+ };
+
+ // Clear container, in case it contained some 'waiting' or 'error' text
+ // for clients that don't support JS.
+ // We don't do this however, if we try to load from an embedded UL element.
+ if( opts.children || (opts.initAjax && opts.initAjax.url) || opts.initId )
+ $(this.divTree).empty();
+ else if( this.divRoot )
+ $(this.divRoot).remove();
+
+ // create the root element
+ this.tnRoot = new DynaTreeNode(null, this, {title: opts.title, key: "root"});
+ this.tnRoot.data.isFolder = true;
+ this.tnRoot.render(false, false);
+ this.divRoot = this.tnRoot.div;
+ this.divRoot.className = opts.classNames.container;
+ // add root to container
+ // TODO: this should be delayed until all children have been created for performance reasons
+ this.divTree.appendChild(this.divRoot);
+
+ var root = this.tnRoot;
+ var isReloading = ( opts.persist && this.persistence.isReloading() );
+ var isLazy = false;
+ var prevFlag = this.enableUpdate(false);
+
+ this.logDebug("Dynatree._load(): read tree structure...");
+
+ // Init tree structure
+ if( opts.children ) {
+ // Read structure from node array
+ root.addChild(opts.children);
+
+ } else if( opts.initAjax && opts.initAjax.url ) {
+ // Init tree from AJAX request
+ isLazy = true;
+ root.data.isLazy = true;
+ this._reloadAjax();
+
+ } else if( opts.initId ) {
+ // Init tree from another UL element
+ this._createFromTag(root, $("#"+opts.initId));
+
+ } else {
+ // Init tree from the first UL element inside the container <div>
+ var $ul = this.$tree.find(">ul").hide();
+ this._createFromTag(root, $ul);
+ $ul.remove();
+ }
+
+ this._checkConsistency();
+ // Render html markup
+ this.logDebug("Dynatree._load(): render nodes...");
+ this.enableUpdate(prevFlag);
+
+ // bind event handlers
+ this.logDebug("Dynatree._load(): bind events...");
+ this.$widget.bind();
+
+ // --- Post-load processing
+ this.logDebug("Dynatree._load(): postInit...");
+ this.phase = "postInit";
+
+ // In persist mode, make sure that cookies are written, even if they are empty
+ if( opts.persist ) {
+ this.persistence.write();
+ }
+
+ // Set focus, if possible (this will also fire an event and write a cookie)
+ if( this.focusNode && this.focusNode.isVisible() ) {
+ this.logDebug("Focus on init: %o", this.focusNode);
+ this.focusNode.focus();
+ }
+
+ if( !isLazy && opts.onPostInit ) {
+ opts.onPostInit.call(this, isReloading, false);
+ }
+
+ this.phase = "idle";
+ },
+
+ _reloadAjax: function() {
+ // Reload
+ var opts = this.options;
+ if( ! opts.initAjax || ! opts.initAjax.url )
+ throw "tree.reload() requires 'initAjax' mode.";
+ var pers = this.persistence;
+ var ajaxOpts = $.extend({}, opts.initAjax);
+ // Append cookie info to the request
+// this.logDebug("reloadAjax: key=%o, an.key:%o", pers.activeKey, this.activeNode?this.activeNode.data.key:"?");
+ if( ajaxOpts.addActiveKey )
+ ajaxOpts.data.activeKey = pers.activeKey;
+ if( ajaxOpts.addFocusedKey )
+ ajaxOpts.data.focusedKey = pers.focusedKey;
+ if( ajaxOpts.addExpandedKeyList )
+ ajaxOpts.data.expandedKeyList = pers.expandedKeyList.join(",");
+ if( ajaxOpts.addSelectedKeyList )
+ ajaxOpts.data.selectedKeyList = pers.selectedKeyList.join(",");
+
+ // Set up onPostInit callback to be called when Ajax returns
+ if( opts.onPostInit ) {
+ if( ajaxOpts.success )
+ this.logWarning("initAjax: success callback is ignored when onPostInit was specified.");
+ if( ajaxOpts.error )
+ this.logWarning("initAjax: error callback is ignored when onPostInit was specified.");
+ var isReloading = pers.isReloading();
+ ajaxOpts["success"] = function(dtnode) { opts.onPostInit.call(dtnode.tree, isReloading, false); };
+ ajaxOpts["error"] = function(dtnode) { opts.onPostInit.call(dtnode.tree, isReloading, true); };
+ }
+ this.logDebug("Dynatree._init(): send Ajax request...");
+ this.tnRoot.appendAjax(ajaxOpts);
+ },
+
+ toString: function() {
+ return "DynaTree '" + this.options.title + "'";
+ },
+
+ toDict: function() {
+ return this.tnRoot.toDict(true);
+ },
+
+ getPersistData: function() {
+ return this.persistence.toDict();
+ },
+
+ logDebug: function(msg) {
+ if( this.options.debugLevel >= 2 ) {
+ Array.prototype.unshift.apply(arguments, ["debug"]);
+ _log.apply(this, arguments);
+ }
+ },
+
+ logInfo: function(msg) {
+ if( this.options.debugLevel >= 1 ) {
+ Array.prototype.unshift.apply(arguments, ["info"]);
+ _log.apply(this, arguments);
+ }
+ },
+
+ logWarning: function(msg) {
+ Array.prototype.unshift.apply(arguments, ["warn"]);
+ _log.apply(this, arguments);
+ },
+
+ isInitializing: function() {
+ return ( this.phase=="init" || this.phase=="postInit" );
+ },
+ isReloading: function() {
+ return ( this.phase=="init" || this.phase=="postInit" ) && this.options.persist && this.persistence.cookiesFound;
+ },
+ isUserEvent: function() {
+ return ( this.phase=="userEvent" );
+ },
+
+ redraw: function() {
+ this.logDebug("dynatree.redraw()...");
+ this.tnRoot.render(true, true);
+ this.logDebug("dynatree.redraw() done.");
+ },
+
+ reloadAjax: function() {
+ this.logWarning("tree.reloadAjax() is deprecated since v0.5.2 (use reload() instead).");
+ },
+
+ reload: function() {
+ this._load();
+ },
+
+ getRoot: function() {
+ return this.tnRoot;
+ },
+
+ getNodeByKey: function(key) {
+ // $("#...") has problems, if the key contains '.', so we use getElementById()
+// return $("#" + this.options.idPrefix + key).attr("dtnode");
+ var el = document.getElementById(this.options.idPrefix + key);
+ return ( el && el.dtnode ) ? el.dtnode : null;
+ },
+
+ getActiveNode: function() {
+ return this.activeNode;
+ },
+
+ reactivate: function(setFocus) {
+ // Re-fire onQueryActivate and onActivate events.
+ var node = this.activeNode;
+// this.logDebug("reactivate %o", node);
+ if( node ) {
+ this.activeNode = null; // Force re-activating
+ node.activate();
+ if( setFocus )
+ node.focus();
+ }
+ },
+
+ getSelectedNodes: function(stopOnParents) {
+ var nodeList = [];
+ this.tnRoot.visit(function(dtnode){
+ if( dtnode.bSelected ) {
+ nodeList.push(dtnode);
+ if( stopOnParents == true )
+ return false; // stop processing this branch
+ }
+ });
+ return nodeList;
+ },
+
+ activateKey: function(key) {
+ var dtnode = (key === null) ? null : this.getNodeByKey(key);
+ if( !dtnode ) {
+ if( this.activeNode )
+ this.activeNode.deactivate();
+ this.activeNode = null;
+ return null;
+ }
+ dtnode.focus();
+ dtnode.activate();
+ return dtnode;
+ },
+
+ selectKey: function(key, select) {
+ var dtnode = this.getNodeByKey(key);
+ if( !dtnode )
+ return null;
+ dtnode.select(select);
+ return dtnode;
+ },
+
+ enableUpdate: function(bEnable) {
+ if ( this.bEnableUpdate==bEnable )
+ return bEnable;
+ this.bEnableUpdate = bEnable;
+ if ( bEnable )
+ this.redraw();
+ return !bEnable; // return previous value
+ },
+
+ visit: function(fn, data, includeRoot) {
+ return this.tnRoot.visit(fn, data, includeRoot);
+ },
+
+ _createFromTag: function(parentTreeNode, $ulParent) {
+ // Convert a <UL>...</UL> list into children of the parent tree node.
+ var self = this;
+/*
+TODO: better?
+ this.$lis = $("li:has(a[href])", this.element);
+ this.$tabs = this.$lis.map(function() { return $("a", this)[0]; });
+ */
+ $ulParent.find(">li").each(function() {
+ var $li = $(this);
+ var $liSpan = $li.find(">span:first");
+ var title;
+ if( $liSpan.length ) {
+ // If a <li><span> tag is specified, use it literally.
+ title = $liSpan.html();
+ } else {
+ // If only a <li> tag is specified, use the trimmed string up to the next child <ul> tag.
+ title = $li.html();
+ var iPos = title.search(/<ul/i);
+ if( iPos>=0 )
+ title = $.trim(title.substring(0, iPos));
+ else
+ title = $.trim(title);
+// self.logDebug("%o", title);
+ }
+ // Parse node options from ID, title and class attributes
+ var data = {
+ title: title,
+ isFolder: $li.hasClass("folder"),
+ isLazy: $li.hasClass("lazy"),
+ expand: $li.hasClass("expanded"),
+ select: $li.hasClass("selected"),
+ activate: $li.hasClass("active"),
+ focus: $li.hasClass("focused")
+ };
+ if( $li.attr("title") )
+ data.tooltip = $li.attr("title");
+ if( $li.attr("id") )
+ data.key = $li.attr("id");
+ // If a data attribute is present, evaluate as a JavaScript object
+ if( $li.attr("data") ) {
+ var dataAttr = $.trim($li.attr("data"));
+ if( dataAttr ) {
+ if( dataAttr.charAt(0) != "{" )
+ dataAttr = "{" + dataAttr + "}"
+ try {
+ $.extend(data, eval("(" + dataAttr + ")"));
+ } catch(e) {
+ throw ("Error parsing node data: " + e + "\ndata:\n'" + dataAttr + "'");
+ }
+ }
+ }
+ childNode = parentTreeNode.addChild(data);
+ // Recursive reading of child nodes, if LI tag contains an UL tag
+ var $ul = $li.find(">ul:first");
+ if( $ul.length ) {
+ self._createFromTag(childNode, $ul); // must use 'self', because 'this' is the each() context
+ }
+ });
+ },
+
+ _checkConsistency: function() {
+// this.logDebug("tree._checkConsistency() NOT IMPLEMENTED - %o", this);
+ },
+
+ // --- end of class
+ lastentry: undefined
+};
+
+/*************************************************************************
+ * widget $(..).dynatree
+ */
+
+$.widget("ui.dynatree", {
+ init: function() {
+ // ui.core 1.6 renamed init() to _init(): this stub assures backward compatibility
+ _log("warn", "ui.dynatree.init() was called; you should upgrade to ui.core.js v1.6 or higher.");
+ return this._init();
+ },
+
+ _init: function() {
+ if( parseFloat($.ui.version) < 1.8 ) {
+ // jquery.ui.core 1.8 renamed _init() to _create(): this stub assures backward compatibility
+ _log("info", "ui.dynatree._init() was called; consider upgrading to jquery.ui.core.js v1.8 or higher.");
+ return this._create();
+ }
+ // jquery.ui.core 1.8 still uses _init() to perform "default functionality"
+ _log("debug", "ui.dynatree._init() was called; no current default functionality.");
+ },
+
+ _create: function() {
+ if( parseFloat($.ui.version) >= 1.8 ) {
+ this.options = $.extend(true, {}, $[this.namespace][this.widgetName].defaults, this.options);
+ }
+ logMsg("Dynatree._create(): version='%s', debugLevel=%o.", DynaTree.version, this.options.debugLevel);
+ var opts = this.options;
+ // The widget framework supplies this.element and this.options.
+ this.options.event += ".dynatree"; // namespace event
+
+ var divTree = this.element.get(0);
+/* // Clear container, in case it contained some 'waiting' or 'error' text
+ // for clients that don't support JS
+ if( opts.children || (opts.initAjax && opts.initAjax.url) || opts.initId )
+ $(divTree).empty();
+*/
+ // Create the DynaTree object
+ this.tree = new DynaTree(this);
+ this.tree._load();
+ this.tree.logDebug("Dynatree._create(): done.");
+ },
+
+ bind: function() {
+ var $this = this.element;
+ var o = this.options;
+
+ // Prevent duplicate binding
+ this.unbind();
+
+ // Tool function to get dtnode from the event target:
+ function __getNodeFromElement(el) {
+ var iMax = 5;
+ while( el && iMax-- ) {
+ if( el.dtnode ) return el.dtnode;
+ el = el.parentNode;
+ };
+ return null;
+ }
+
+ var eventNames = "click.dynatree dblclick.dynatree";
+ if( o.keyboard ) // Note: leading ' '!
+ eventNames += " keypress.dynatree keydown.dynatree";
+ $this.bind(eventNames, function(event){
+ var dtnode = __getNodeFromElement(event.target);
+ if( !dtnode )
+ return true; // Allow bubbling of other events
+ var prevPhase = dtnode.tree.phase;
+ dtnode.tree.phase = "userEvent";
+ try {
+ dtnode.tree.logDebug("bind(%o): dtnode: %o", event, dtnode);
+
+ switch(event.type) {
+ case "click":
+ return ( o.onClick && o.onClick(dtnode, event)===false ) ? false : dtnode.onClick(event);
+ case "dblclick":
+ return ( o.onDblClick && o.onDblClick(dtnode, event)===false ) ? false : dtnode.onDblClick(event);
+ case "keydown":
+ return ( o.onKeydown && o.onKeydown(dtnode, event)===false ) ? false : dtnode.onKeydown(event);
+ case "keypress":
+ return ( o.onKeypress && o.onKeypress(dtnode, event)===false ) ? false : dtnode.onKeypress(event);
+ };
+ } catch(e) {
+ var _ = null; // issue 117
+// dtnode.tree.logError("bind(%o): dtnode: %o", event, dtnode);
+ } finally {
+ dtnode.tree.phase = prevPhase;
+ }
+ });
+
+ // focus/blur don't bubble, i.e. are not delegated to parent <div> tags,
+ // so we use the addEventListener capturing phase.
+ // See http://www.howtocreate.co.uk/tutorials/javascript/domevents
+ function __focusHandler(event) {
+ // Handles blur and focus.
+ // Fix event for IE:
+ event = arguments[0] = $.event.fix( event || window.event );
+ var dtnode = __getNodeFromElement(event.target);
+ return dtnode ? dtnode.onFocus(event) : false;
+ }
+ var div = this.tree.divTree;
+ if( div.addEventListener ) {
+ div.addEventListener("focus", __focusHandler, true);
+ div.addEventListener("blur", __focusHandler, true);
+ } else {
+ div.onfocusin = div.onfocusout = __focusHandler;
+ }
+ // EVENTS
+ // disable click if event is configured to something else
+// if (!(/^click/).test(o.event))
+// this.$tabs.bind("click.tabs", function() { return false; });
+
+ },
+
+ unbind: function() {
+ this.element.unbind(".dynatree");
+ },
+
+/* TODO: we could handle option changes during runtime here (maybe to re-render, ...)
+ setData: function(key, value) {
+ this.tree.logDebug("dynatree.setData('" + key + "', '" + value + "')");
+ },
+*/
+ enable: function() {
+ this.bind();
+ // Call default disable(): remove -disabled from css:
+ $.widget.prototype.enable.apply(this, arguments);
+ },
+
+ disable: function() {
+ this.unbind();
+ // Call default disable(): add -disabled to css:
+ $.widget.prototype.disable.apply(this, arguments);
+ },
+
+ // --- getter methods (i.e. NOT returning a reference to $)
+ getTree: function() {
+ return this.tree;
+ },
+
+ getRoot: function() {
+ return this.tree.getRoot();
+ },
+
+ getActiveNode: function() {
+ return this.tree.getActiveNode();
+ },
+
+ getSelectedNodes: function() {
+ return this.tree.getSelectedNodes();
+ },
+
+ // ------------------------------------------------------------------------
+ lastentry: undefined
+});
+
+
+// The following methods return a value (thus breaking the jQuery call chain):
+
+$.ui.dynatree.getter = "getTree getRoot getActiveNode getSelectedNodes";
+
+
+// Plugin default options:
+
+$.ui.dynatree.defaults = {
+ title: "Dynatree root", // Name of the root node.
+ rootVisible: false, // Set to true, to make the root node visible.
+ minExpandLevel: 1, // 1: root node is not collapsible
+ imagePath: null, // Path to a folder containing icons. Defaults to 'skin/' subdirectory.
+ children: null, // Init tree structure from this object array.
+ initId: null, // Init tree structure from a <ul> element with this ID.
+ initAjax: null, // Ajax options used to initialize the tree strucuture.
+ autoFocus: true, // Set focus to first child, when expanding or lazy-loading.
+ keyboard: true, // Support keyboard navigation.
+ persist: false, // Persist expand-status to a cookie
+ autoCollapse: false, // Automatically collapse all siblings, when a node is expanded.
+ clickFolderMode: 3, // 1:activate, 2:expand, 3:activate and expand
+ activeVisible: true, // Make sure, active nodes are visible (expanded).
+ checkbox: false, // Show checkboxes.
+ selectMode: 2, // 1:single, 2:multi, 3:multi-hier
+ fx: null, // Animations, e.g. null or { height: "toggle", duration: 200 }
+
+ // Low level event handlers: onEvent(dtnode, event): return false, to stop default processing
+ onClick: null, // null: generate focus, expand, activate, select events.
+ onDblClick: null, // (No default actions.)
+ onKeydown: null, // null: generate keyboard navigation (focus, expand, activate).
+ onKeypress: null, // (No default actions.)
+ onFocus: null, // null: set focus to node.
+ onBlur: null, // null: remove focus from node.
+
+ // Pre-event handlers onQueryEvent(flag, dtnode): return false, to stop processing
+ onQueryActivate: null, // Callback(flag, dtnode) before a node is (de)activated.
+ onQuerySelect: null, // Callback(flag, dtnode) before a node is (de)selected.
+ onQueryExpand: null, // Callback(flag, dtnode) before a node is expanded/collpsed.
+
+ // High level event handlers
+ onPostInit: null, // Callback(isReloading, isError) when tree was (re)loaded.
+ onActivate: null, // Callback(dtnode) when a node is activated.
+ onDeactivate: null, // Callback(dtnode) when a node is deactivated.
+ onSelect: null, // Callback(flag, dtnode) when a node is (de)selected.
+ onExpand: null, // Callback(dtnode) when a node is expanded/collapsed.
+ onLazyRead: null, // Callback(dtnode) when a lazy node is expanded for the first time.
+
+ ajaxDefaults: { // Used by initAjax option
+ cache: false, // false: Append random '_' argument to the request url to prevent caching.
+ dataType: "json" // Expect json format and pass json object to callbacks.
+ },
+ strings: {
+ loading: "Loading…",
+ loadError: "Load error!"
+ },
+ idPrefix: "ui-dynatree-id-", // Used to generate node id's like <span id="ui-dynatree-id-<key>">.
+// cookieId: "ui-dynatree-cookie", // Choose a more unique name, to allow multiple trees.
+ cookieId: "dynatree", // Choose a more unique name, to allow multiple trees.
+ cookie: {
+ expires: null //7, // Days or Date; null: session cookie
+// path: "/", // Defaults to current page
+// domain: "jquery.com",
+// secure: true
+ },
+ // Class names used, when rendering the HTML markup.
+ // Note: if only single entries are passed for options.classNames, all other
+ // values are still set to default.
+ classNames: {
+ container: "ui-dynatree-container",
+ folder: "ui-dynatree-folder",
+ document: "ui-dynatree-document",
+
+ empty: "ui-dynatree-empty",
+ vline: "ui-dynatree-vline",
+ expander: "ui-dynatree-expander",
+ connector: "ui-dynatree-connector",
+ checkbox: "ui-dynatree-checkbox",
+ nodeIcon: "ui-dynatree-icon",
+ title: "ui-dynatree-title",
+
+ nodeError: "ui-dynatree-statusnode-error",
+ nodeWait: "ui-dynatree-statusnode-wait",
+ hidden: "ui-dynatree-hidden",
+ combinedExpanderPrefix: "ui-dynatree-exp-",
+ combinedIconPrefix: "ui-dynatree-ico-",
+// disabled: "ui-dynatree-disabled",
+ hasChildren: "ui-dynatree-has-children",
+ active: "ui-dynatree-active",
+ selected: "ui-dynatree-selected",
+ expanded: "ui-dynatree-expanded",
+ lazy: "ui-dynatree-lazy",
+ focused: "ui-dynatree-focused",
+ partsel: "ui-dynatree-partsel",
+ lastsib: "ui-dynatree-lastsib"
+ },
+ debugLevel: 1,
+
+ // ------------------------------------------------------------------------
+ lastentry: undefined
+};
+
+/**
+ * Reserved data attributes for a tree node.
+ */
+$.ui.dynatree.nodedatadefaults = {
+ title: null, // (required) Displayed name of the node (html is allowed here)
+ key: null, // May be used with activate(), select(), find(), ...
+ isFolder: false, // Use a folder icon. Also the node is expandable but not selectable.
+ isLazy: false, // Call onLazyRead(), when the node is expanded for the first time to allow for delayed creation of children.
+ tooltip: null, // Show this popup text.
+ icon: null, // Use a custom image (filename relative to tree.options.imagePath). 'null' for default icon, 'false' for no icon.
+ addClass: null, // Class name added to the node's span tag.
+ activate: false, // Initial active status.
+ focus: false, // Initial focused status.
+ expand: false, // Initial expanded status.
+ select: false, // Initial selected status.
+ hideCheckbox: false, // Suppress checkbox display for this node.
+ unselectable: false, // Prevent selection.
+// disabled: false,
+ // The following attributes are only valid if passed to some functions:
+ children: null, // Array of child nodes.
+ // NOTE: we can also add custom attributes here.
+ // This may then also be used in the onActivate(), onSelect() or onLazyTree() callbacks.
+ // ------------------------------------------------------------------------
+ lastentry: undefined
+};
+
+// ---------------------------------------------------------------------------
+})(jQuery);
+
+// Eclipse syntax parser breaks on this expression, so we put it at the bottom.
+var _rexDtLibName = /.*dynatree[^/]*\.js$/i;
Binary file static/june_2007_style/blue/dynatree_skin/customFolder1.gif has changed
--- /dev/null
+++ b/static/june_2007_style/blue/dynatree_skin/ui.dynatree.css
@@ -0,0 +1,295 @@
+/*******************************************************************************
+ * Tree container
+ */
+div.ui-dynatree-container
+{
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt; /* font size should not be too big */
+ white-space: nowrap;
+ padding: 3px;
+
+ background-color: white;
+ border: none;
+}
+
+/* Style, when control is disabled */
+.ui-dynatree-disabled div.ui-dynatree-container
+{
+ opacity: 0.5;
+/* filter: alpha(opacity=50); /* Yields a css warning */
+ background-color: silver;
+}
+
+
+/*******************************************************************************
+ * Vertical line image
+ */
+div.ui-dynatree-container img
+{
+ width: 16px;
+ height: 16px;
+ margin-left: 3px;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*******************************************************************************
+ * Common icon definitions
+ */
+span.ui-dynatree-empty,
+span.ui-dynatree-vline,
+span.ui-dynatree-connector,
+span.ui-dynatree-expander,
+span.ui-dynatree-icon,
+span.ui-dynatree-checkbox,
+span.ui-dynatree-radio
+{
+ width: 16px;
+ height: 16px;
+ display: -moz-inline-box; /* @ FF 1+2 */
+ display: inline-block; /* Required to make a span sizeable */
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-position: left;
+}
+
+/*******************************************************************************
+ * Lines and connectors
+ */
+span.ui-dynatree-empty
+{
+}
+span.ui-dynatree-vline
+{
+ background-image: url("ltL_ns.gif");
+}
+span.ui-dynatree-connector
+{
+ background-image: url("ltL_nes.gif");
+}
+.ui-dynatree-lastsib span.ui-dynatree-connector
+{
+ background-image: url("ltL_ne.gif");
+}
+
+/*******************************************************************************
+ * Expander icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: ui-dynatree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ */
+
+span.ui-dynatree-expander
+{
+ background-image: url("ltP_nes.gif");
+ cursor: pointer;
+}
+.ui-dynatree-exp-cl span.ui-dynatree-expander /* Collapsed, not delayed, last sibling */
+{
+ background-image: url("ltP_ne.gif");
+}
+.ui-dynatree-exp-cd span.ui-dynatree-expander /* Collapsed, delayed, not last sibling */
+{
+ background-image: url("ltD_nes.gif");
+}
+.ui-dynatree-exp-cdl span.ui-dynatree-expander /* Collapsed, delayed, last sibling */
+{
+ background-image: url("ltD_ne.gif");
+}
+.ui-dynatree-exp-e span.ui-dynatree-expander, /* Expanded, not delayed, not last sibling */
+.ui-dynatree-exp-ed span.ui-dynatree-expander /* Expanded, delayed, not last sibling */
+{
+ background-image: url("ltM_nes.gif");
+}
+.ui-dynatree-exp-el span.ui-dynatree-expander, /* Expanded, not delayed, last sibling */
+.ui-dynatree-exp-edl span.ui-dynatree-expander /* Expanded, delayed, last sibling */
+{
+ background-image: url("ltM_ne.gif");
+}
+
+
+/*******************************************************************************
+ * Checkbox icon
+ */
+span.ui-dynatree-checkbox
+{
+ margin-left: 3px;
+ background-image: url("cbUnchecked.gif");
+}
+span.ui-dynatree-checkbox:hover
+{
+ background-image: url("cbUnchecked_hover.gif");
+}
+
+.ui-dynatree-partsel span.ui-dynatree-checkbox
+{
+ background-image: url("cbIntermediate.gif");
+}
+.ui-dynatree-partsel span.ui-dynatree-checkbox:hover
+{
+ background-image: url("cbIntermediate_hover.gif");
+}
+
+.ui-dynatree-selected span.ui-dynatree-checkbox
+{
+ background-image: url("cbChecked.gif");
+}
+.ui-dynatree-selected span.ui-dynatree-checkbox:hover
+{
+ background-image: url("cbChecked_hover.gif");
+}
+
+/*******************************************************************************
+ * Radiobutton icon
+ * This is a customization, that may be activated by overriding the 'checkbox'
+ * class name as 'ui-dynatree-radio' in the tree options.
+ */
+span.ui-dynatree-radio
+{
+ margin-left: 3px;
+ background-image: url("rbUnchecked.gif");
+}
+span.ui-dynatree-radio:hover
+{
+ background-image: url("rbUnchecked_hover.gif");
+}
+
+.ui-dynatree-partsel span.ui-dynatree-radio
+{
+ background-image: url("rbIntermediate.gif");
+}
+.ui-dynatree-partsel span.ui-dynatree-radio:hover
+{
+ background-image: url("rbIntermediate_hover.gif");
+}
+
+.ui-dynatree-selected span.ui-dynatree-radio
+{
+ background-image: url("rbChecked.gif");
+}
+.ui-dynatree-selected span.ui-dynatree-radio:hover
+{
+ background-image: url("rbChecked_hover.gif");
+}
+
+/*******************************************************************************
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: ui-dynatree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ */
+
+span.ui-dynatree-icon /* Default icon */
+{
+ margin-left: 3px;
+ background-image: url("ltDoc.gif");
+}
+
+.ui-dynatree-ico-cf span.ui-dynatree-icon /* Collapsed Folder */
+{
+ background-image: url("ltFld.gif");
+}
+
+.ui-dynatree-ico-ef span.ui-dynatree-icon /* Expanded Folder */
+{
+ background-image: url("ltFld_o.gif");
+}
+
+/* Status node icons */
+
+.ui-dynatree-statusnode-wait span.ui-dynatree-icon
+{
+ background-image: url("ltWait.gif");
+}
+
+.ui-dynatree-statusnode-error span.ui-dynatree-icon
+{
+ background-image: url("ltError.gif");
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+
+ /* @Chrome: fix broken hit area of node titles (issue 133) */
+span.ui-dynatree-document,
+span.ui-dynatree-folder
+{
+ display: -moz-inline-box; /* @ FF 1+2 */
+ display: inline-block; /* Required to make a span sizeable */
+}
+
+/* Remove blue color and underline from title links */
+div.ui-dynatree-container a
+/*, div.ui-dynatree-container a:visited*/
+{
+ color: black; /* inherit doesn't work on IE */
+ text-decoration: none;
+ vertical-align: top;
+ margin: 0px;
+ margin-left: 3px;
+/* outline: 0; /* @ Firefox, prevent dotted border after click */
+}
+
+div.ui-dynatree-container a:hover
+{
+ text-decoration: underline;
+}
+
+span.ui-dynatree-document a,
+span.ui-dynatree-folder a
+{
+ display: inline-block; /* Better alignment, when title contains <br> */
+/* vertical-align: top;*/
+ padding-left: 3px;
+ padding-right: 3px; /* Otherwise italic font will be outside bounds */
+ /* line-height: 16px; /* should be the same as img height, in case 16 px */
+}
+span.ui-dynatree-folder a
+{
+ font-weight: normal;
+}
+
+div.ui-dynatree-container a:focus,
+span.ui-dynatree-focused a:link /* @IE */
+{
+ background-color: #EFEBDE; /* gray */
+}
+
+
+span.ui-dynatree-has-children a
+{
+}
+
+span.ui-dynatree-expanded a
+{
+}
+
+span.ui-dynatree-selected a
+{
+ color: black;
+ font-style: italic;
+}
+
+span.ui-dynatree-active a
+{
+ background-color: #3169C6 !important;
+ color: white !important; /* @ IE6 */
+}
+
+/*******************************************************************************
+ * Custom node classes (sample)
+ */
+
+span.custom1 a
+{
+ background-color: maroon;
+ color: yellow;
+}
--- /dev/null
+++ b/static/scripts/packed/jquery.cookie.js
@@ -0,0 +1,1 @@
+jQuery.cookie=function(b,j,m){if(typeof j!="undefined"){m=m||{};if(j===null){j="";m=$.extend({},m);m.expires=-1}var e="";if(m.expires&&(typeof m.expires=="number"||m.expires.toUTCString)){var f;if(typeof m.expires=="number"){f=new Date();f.setTime(f.getTime()+(m.expires*24*60*60*1000))}else{f=m.expires}e="; expires="+f.toUTCString()}var l=m.path?"; path="+(m.path):"";var g=m.domain?"; domain="+(m.domain):"";var a=m.secure?"; secure":"";document.cookie=[b,"=",encodeURIComponent(j),e,l,g,a].join("")}else{var d=null;if(document.cookie&&document.cookie!=""){var k=document.cookie.split(";");for(var h=0;h<k.length;h++){var c=jQuery.trim(k[h]);if(c.substring(0,b.length+1)==(b+"=")){d=decodeURIComponent(c.substring(b.length+1));break}}}return d}};
Binary file static/june_2007_style/blue/dynatree_skin/ltL_nes.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltL_ns.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltL_ne.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltD_ne.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/rbIntermediate_hover.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/cbUnchecked.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/cbUnchecked_hover.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/ltL_.gif has changed
Binary file static/june_2007_style/blue/dynatree_skin/rbChecked_hover.gif has changed
1
0
galaxy-dist commit 569483091092: Keep the sample's bar code incormation when editn the sample row in the non-admin user view.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Greg Von Kuster <greg(a)bx.psu.edu>
# Date 1288731289 14400
# Node ID 56948309109207f932a113e464409432c7a38df7
# Parent 27c152bb441a0136720dbbc0c7cb293e581b8f5f
Keep the sample's bar code incormation when editn the sample row in the non-admin user view.
--- a/templates/requests/common/common.mako
+++ b/templates/requests/common/common.mako
@@ -153,6 +153,7 @@
<input type="text" name="sample_${current_sample_index}_barcode" value="${current_sample['barcode']}" size="10"/>
%else:
${current_sample['barcode']}
+ <input type="hidden" name="sample_${current_sample_index}_barcode" value="${current_sample['barcode']}"/>
%endif
</td>
%endif
@@ -261,7 +262,7 @@
%elif sample:
<tr><td>${current_sample_name}</td>
- %if is_submitted or is_complete:
+ %if display_bar_code:
<td>${current_sample_barcode}</td>
%endif
%if is_unsubmitted:
1
0
galaxy-dist commit 37477f7d10e7: Data Libraries: Pre-generate and cache variables so that expensive functions like jQuery.siblings, jQuery.filter and jQuery.find only have to be called a minimum amount of times. Provides significant speedup to loading of large data libraries.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1288749068 14400
# Node ID 37477f7d10e7407186bd189fdec9e114e4b8f3d2
# Parent 4053c425b536b9878f6f8bdfac75453adec7bdf3
Data Libraries: Pre-generate and cache variables so that expensive functions like jQuery.siblings, jQuery.filter and jQuery.find only have to be called a minimum amount of times. Provides significant speedup to loading of large data libraries.
--- a/templates/library/common/browse_library.mako
+++ b/templates/library/common/browse_library.mako
@@ -68,7 +68,7 @@
}
}
};
-
+
var save_folder_state = function() {
var state = {};
$("tr.folderRow").each( function() {
@@ -79,12 +79,17 @@
};
$("#library-grid").each(function() {
- // Recursively fill in children and descendents of each row
- var process_row = function(q, parents) {
+
+ var child_of_parent_cache = {};
+ // Recursively fill in children and descendents of each row
+ var process_row = function(q, parents) {
// Find my index
- var index = q.parent().children().index(q);
+ var parent = q.parent(),
+ this_level = child_of_parent_cache[parent] || (child_of_parent_cache[parent] = parent.children());
+
+ var index = this_level.index(q);
// Find my immediate children
- var children = q.siblings().filter("[parent='" + index + "']");
+ var children = $(par_child_dict[index]);
// Recursively handle them
var descendents = children;
children.each( function() {
@@ -103,8 +108,7 @@
}
save_folder_state();
};
- $(q).find("span.expandLink").click(expand_fn);
- $(q).find("span.expandLink a").click(expand_fn);
+ $("." + q.attr("id") + "-click").click(expand_fn);
// Check/uncheck boxes in subfolders.
q.children("td").children("input[type=checkbox]").click( function() {
if ( $(this).is(":checked") ) {
@@ -112,15 +116,32 @@
} else {
descendents.find("input[type=checkbox]").attr("checked", false);
// If you uncheck a lower level checkbox, uncheck the boxes above it
- // (since deselecting a child means the parent is not fully selected any
- // more).
+ // (since deselecting a child means the parent is not fully selected any more).
parents.children("td").children("input[type=checkbox]").attr("checked", false);
}
});
// return descendents for use by parent
return descendents;
- }
- $(this).find("tbody tr").not("[parent]").each( function() {
+ }
+
+ // Initialize dict[parent_id] = rows_which_have_that_parent_id_as_parent_attr
+ var par_child_dict = {},
+ no_parent = [];
+
+ $(this).find("tbody tr").each( function() {
+ if (this.hasAttribute("parent")) {
+ var parent = this.getAttribute("parent");
+ if (par_child_dict[parent] !== undefined) {
+ par_child_dict[parent].push(this);
+ } else {
+ par_child_dict[parent] = [this];
+ }
+ } else {
+ no_parent.push(this);
+ }
+ });
+
+ $(no_parent).each( function() {
descendents = process_row( $(this), $([]) );
descendents.hide();
});
@@ -338,7 +359,8 @@
info_association, inherited = folder.get_info_association( restrict=True )
%>
%if not root_folder and ( not folder.deleted or show_deleted ):
- <tr id="folder-${trans.security.encode_id(folder.id)}" class="folderRow libraryOrFolderRow"
+ <% encoded_id = trans.security.encode_id(folder.id) %>
+ <tr id="folder-${encoded_id}" class="folderRow libraryOrFolderRow"
%if parent is not None:
parent="${parent}"
style="display: none;"
@@ -349,9 +371,9 @@
%if folder.deleted:
<span class="libraryItem-error">
%endif
- <span class="expandLink"><span class="rowIcon"></span>
+ <span class="expandLink folder-${encoded_id}-click"><span class="rowIcon"></span><div style="float: left; margin-left: 2px;" class="menubutton split popup" id="folder_img-${folder.id}-popup">
- <a href="javascript:void(0);">${folder.name}</a>
+ <a class="folder-${encoded_id}-click" href="javascript:void(0);">${folder.name}</a></div>
%if folder.deleted:
</span>
1
0
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Dannon Baker <dannonbaker(a)me.com>
# Date 1288646507 14400
# Node ID 9285b39ae2f3dfd5017808b4d9b657094fec802b
# Parent 695c89309bcb2f5d31bfb8b9d8b0124ff3abf90f
Packing editor.
Tweak to reload.
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js
@@ -1,1 +1,1 @@
-function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.act
ion_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){if(f[b]=="input"||issubtype(f[b],this.datatypes[c])){return true}}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(t
his.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind
("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal)).redraw()}).bind("hover",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img/>").attr("src",image_path+"/delete_icon.png").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){workflow.check_changes_in_active_form();v
ar i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClass("input-terminal-active");return i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:fun
ction(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(h){var g=this.element;if(h.type){this.type=h.type}this.name=h.name;this.form_html=h.form_html;this.tool_state=h.tool_state;this.tool_errors=h.tool_errors;this.tooltip=h.tooltip?h.tooltip:"";this.annotation=h.annotation;this.post_job_actions=h.post_job_actions;if(h.workflow_outputs){this.workflow_outputs=h.workflow_outputs}else{this.workflow_outputs=[]}if(this.tool_errors){g.addClass("tool-node-error")}else{g.removeClass("tool-node-error")}var d=this;var c=Math.max(150,g.width());var a=g.find(".toolFormBody");a.find("div").remove();var i=$("<div class='inputs'></div
>").appendTo(a);$.each(h.data_inputs,function(k,f){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,f.name,f.extensions);var b=$("<div class='form-row dataRow input-data-row' name='"+f.name+"'>"+f.label+"</div>");b.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(b);c=Math.max(c,b.outerWidth());b.css({position:"",left:"",top:"",display:""});$("body").remove(b);i.append(b.prepend(j))});if((h.data_inputs.length>0)&&(h.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(h.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");d.enable_output_terminal(j,b.name,b.extensions);var f=b.name;if(b.extensions.indexOf("input")<0){f=f+" ("+b.extensions.join(", ")+")"}var m=$("<div class='form-row dataRow'>"+f+"</div>");if(d.type=="tool"){var l=$("<div class='callout'></div>").css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",image_path+"/
fugue/asterisk-small-outline.png").click(function(){if($.inArray(b.name,d.workflow_outputs)!=-1){d.workflow_outputs.splice($.inArray(b.name,d.workflow_outputs),1);l.find("img").attr("src",image_path+"/fugue/asterisk-small-outline.png")}else{d.workflow_outputs.push(b.name);l.find("img").attr("src",image_path+"/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tipsy({delayIn:500,fallback:"Flag this as a workflow output. All non-flagged outputs will be hidden."});l.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});l.show();m.append(l);if($.inArray(b.name,d.workflow_outputs)==-1){l.find("img").attr("src",image_path+"/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",image_path+"/fugue/asterisk-small.png")}m.bind("hover",function(){l.find("img").attr("src",image_path+"/fugue/asterisk-small-yellow.png")});m.bind("mouseleave",function(){l.find("img").attr("src",image_path+"/fugue/asterisk-small.png");if($.inArray(b.name,d.workf
low_outputs)==-1){l.find("img").attr("src",image_path+"/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",image_path+"/fugue/asterisk-small.png")}})}m.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(m);c=Math.max(c,m.outerWidth()+17);m.css({position:"",left:"",top:"",display:""});$("body").remove(m);a.append(m.append(j))});g.css("width",Math.min(250,Math.max(g.width(),c)));workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;this.annotation=f.annotation;this.post_job_actions=$.parseJSON(f.post_job_actions);if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.n
ame,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].terminal.connectors[0]=i;i.handle2=j[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);th
is.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(h,i){g[i.name]=null;$.each(i.connectors,function(j,k){g[i.name]={id:k.handle1.node.id,output_name:k.handle1.name}})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={job_id:h.id,action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job
_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_no
de!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30
;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math
.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+image_path+"/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<img/>").attr("src",image_path+"/delete_icon.png").c
lick(function(b){g.destroy()}).hover(function(){$(this).attr("src",image_path+"/delete_icon_dark.png")},function(){$(this).attr("src",image_path+"/delete_icon.png")}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];retur
n(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){thi
s.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes
();b.draw_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(f){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("hei
ght",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
+function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.act
ion_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){if(f[b]=="input"||issubtype(f[b],this.datatypes[c])){return true}}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(t
his.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind
("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal)).redraw()}).bind("hover",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img/>").attr("src",image_path+"/delete_icon.png").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){workflow.check_changes_in_active_form();v
ar i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClass("input-terminal-active");return i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:fun
ction(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(h){var g=this.element;if(h.type){this.type=h.type}this.name=h.name;this.form_html=h.form_html;this.tool_state=h.tool_state;this.tool_errors=h.tool_errors;this.tooltip=h.tooltip?h.tooltip:"";this.annotation=h.annotation;this.post_job_actions=h.post_job_actions;if(h.workflow_outputs){this.workflow_outputs=h.workflow_outputs}else{this.workflow_outputs=[]}if(this.tool_errors){g.addClass("tool-node-error")}else{g.removeClass("tool-node-error")}var d=this;var c=Math.max(150,g.width());var a=g.find(".toolFormBody");a.find("div").remove();var i=$("<div class='inputs'></div
>").appendTo(a);$.each(h.data_inputs,function(k,f){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,f.name,f.extensions);var b=$("<div class='form-row dataRow input-data-row' name='"+f.name+"'>"+f.label+"</div>");b.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(b);c=Math.max(c,b.outerWidth());b.css({position:"",left:"",top:"",display:""});$("body").remove(b);i.append(b.prepend(j))});if((h.data_inputs.length>0)&&(h.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(h.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");d.enable_output_terminal(j,b.name,b.extensions);var f=b.name;if(b.extensions.indexOf("input")<0){f=f+" ("+b.extensions.join(", ")+")"}var m=$("<div class='form-row dataRow'>"+f+"</div>");if(d.type=="tool"){var l=$("<div class='callout'></div>").css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",image_path+"/
fugue/asterisk-small-outline.png").click(function(){if($.inArray(b.name,d.workflow_outputs)!=-1){d.workflow_outputs.splice($.inArray(b.name,d.workflow_outputs),1);l.find("img").attr("src",image_path+"/fugue/asterisk-small-outline.png")}else{d.workflow_outputs.push(b.name);l.find("img").attr("src",image_path+"/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tipsy({delayIn:500,fallback:"Flag this as a workflow output. All non-flagged outputs will be hidden."});l.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});l.show();m.append(l);if($.inArray(b.name,d.workflow_outputs)==-1){l.find("img").attr("src",image_path+"/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",image_path+"/fugue/asterisk-small.png")}m.bind("hover",function(){l.find("img").attr("src",image_path+"/fugue/asterisk-small-yellow.png")});m.bind("mouseleave",function(){l.find("img").attr("src",image_path+"/fugue/asterisk-small.png");if($.inArray(b.name,d.workf
low_outputs)==-1){l.find("img").attr("src",image_path+"/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",image_path+"/fugue/asterisk-small.png")}})}m.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(m);c=Math.max(c,m.outerWidth()+17);m.css({position:"",left:"",top:"",display:""});$("body").remove(m);a.append(m.append(j))});g.css("width",Math.min(250,Math.max(g.width(),c)));workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;this.annotation=f.annotation;this.post_job_actions=$.parseJSON(f.post_job_actions);if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.n
ame,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].terminal.connectors[0]=i;i.handle2=j[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);th
is.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var a=false;$.each(this.nodes,function(b,c){if(c.workflow_outputs&&c.workflow_outputs.length>0){a=true}});if(a==false){return true}wf=this;$.each(this.nodes,function(b,f){if(f.type=="tool"){var d=false;if(f.post_job_actions==null){f.post_job_actions={}}var c=[];$.each(f.post_job_actions,function(h,g){if(g.action_type=="HideDatasetAction"){c.push(h)}});if(c.length>0&&f==workflow.active_node){$.each(c,function(g,h){d=true;delete f.post_job_actions[h]})}$.each(f.output_terminals,function(h,i){var g=true;$.each(f.workflow_outputs,function(k,l){if(i.name==l){g=false}});if(g==true){d=true;var j={action_type:"HideDatasetAction",output_name:i.name,action_arguments
:{}};f.post_job_actions["HideDatasetAction"+i.name]=null;f.post_job_actions["HideDatasetAction"+i.name]=j}});if(wf.active_node==f&&d==true){wf.reload_active_node()}}})},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(h,i){g[i.name]=null;$.each(i.connectors,function(j,k){g[i.name]={id:k.handle1.node.id,output_name:k.handle1.name}})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(a){wf=this;var b=
0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){th
is.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;
$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g
+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+image_path+"/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<img/>").attr("src",image_path+"/delete_icon.png").click(func
tion(b){g.destroy()}).hover(function(){$(this).attr("src",image_path+"/delete_icon_dark.png")},function(){$(this).attr("src",image_path+"/delete_icon.png")}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to
_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;th
is.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw
_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(f){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$
.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -614,8 +614,11 @@ function Workflow( canvas_container ) {
}
},
reload_active_node : function() {
- this.clear_active_node();
- this.activate_node(node);
+ if (this.active_node){
+ var node = this.active_node;
+ this.clear_active_node();
+ this.activate_node(node);
+ }
},
clear_active_node : function() {
if ( this.active_node ) {
1
0