galaxy-dev
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- 10008 discussions

28 Oct '09
details: http://www.bx.psu.edu/hg/galaxy/rev/ea29f33390d3
changeset: 2894:ea29f33390d3
user: Nate Coraor <nate(a)bx.psu.edu>
date: Tue Oct 20 10:39:30 2009 -0400
description:
Fix setting the peek when a line is already unicode (when does this happen?)
1 file(s) affected in this change:
lib/galaxy/datatypes/data.py
diffs (15 lines):
diff -r 55d479c8d592 -r ea29f33390d3 lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py Mon Oct 19 12:05:19 2009 -0400
+++ b/lib/galaxy/datatypes/data.py Tue Oct 20 10:39:30 2009 -0400
@@ -136,7 +136,10 @@
line = line.strip()
if not line:
continue
- out.append( '<tr><td>%s</td></tr>' % escape( unicode( line, 'utf-8' ) ) )
+ if type( line ) is unicode:
+ out.append( '<tr><td>%s</td></tr>' % escape( line ) )
+ else:
+ out.append( '<tr><td>%s</td></tr>' % escape( unicode( line, 'utf-8' ) ) )
out.append( '</table>' )
out = "".join( out )
except Exception, exc:
1
0

28 Oct '09
details: http://www.bx.psu.edu/hg/galaxy/rev/61684a4d6b9e
changeset: 2895:61684a4d6b9e
user: Kanwei Li <kanwei(a)gmail.com>
date: Tue Oct 20 15:34:47 2009 -0400
description:
Show encoded URL, while still allowing unencoded ids for backward compatibility. Revert to "display" displaying whole file.
6 file(s) affected in this change:
lib/galaxy/web/buildapp.py
lib/galaxy/web/controllers/dataset.py
lib/galaxy/web/controllers/root.py
templates/dataset/large_file.mako
templates/root/history_common.mako
test/base/twilltestcase.py
diffs (213 lines):
diff -r ea29f33390d3 -r 61684a4d6b9e lib/galaxy/web/buildapp.py
--- a/lib/galaxy/web/buildapp.py Tue Oct 20 10:39:30 2009 -0400
+++ b/lib/galaxy/web/buildapp.py Tue Oct 20 15:34:47 2009 -0400
@@ -77,7 +77,7 @@
webapp.add_route( '/async/:tool_id/:data_id/:data_secret', controller='async', action='index', tool_id=None, data_id=None, data_secret=None )
webapp.add_route( '/:controller/:action', action='index' )
webapp.add_route( '/:action', controller='root', action='index' )
- webapp.add_route( '/datasets/:dataset_id/:action/:filename', controller='dataset', action='index', dataset_id=None, filename=None)
+ webapp.add_route( '/datasets/:encoded_id/:action/:filename', controller='dataset', action='index', encoded_id=None, filename=None)
webapp.add_route( '/u/:username/p/:slug', controller='page', action='display_by_username_and_slug' )
webapp.finalize_config()
# Wrap the webapp in some useful middleware
diff -r ea29f33390d3 -r 61684a4d6b9e lib/galaxy/web/controllers/dataset.py
--- a/lib/galaxy/web/controllers/dataset.py Tue Oct 20 10:39:30 2009 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Tue Oct 20 15:34:47 2009 -0400
@@ -199,8 +199,14 @@
return 'This link may not be followed from within Galaxy.'
@web.expose
- def display(self, trans, dataset_id=None, filename=None, show_all=False, **kwd):
+ def display(self, trans, encoded_id=None, preview=False, filename=None, to_ext=None, **kwd):
"""Catches the dataset id and displays file contents as directed"""
+
+ # DEPRECATION: We still support unencoded ids for backward compatibility
+ try:
+ dataset_id = int( encoded_id )
+ except ValueError:
+ dataset_id = trans.security.decode_id( encoded_id )
data = trans.app.model.HistoryDatasetAssociation.get( dataset_id )
if not data:
raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
@@ -208,30 +214,47 @@
if trans.app.security_agent.can_access_dataset( roles, data.dataset ):
if data.state == trans.model.Dataset.states.UPLOAD:
return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to view it." )
- if filename is None or filename.lower() == "index":
- file_path = data.file_name
- mime = trans.app.datatypes_registry.get_mimetype_by_extension( data.extension.lower() )
- trans.response.set_content_type(mime)
- trans.log_event( "Display dataset id: %s" % str( dataset_id ) )
-
- else:
+
+ if filename and filename != "index":
file_path = os.path.join( data.extra_files_path, filename )
- mime, encoding = mimetypes.guess_type( file_path )
- if mime is None:
- mime = trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( file_path )[-1] )
- trans.response.set_content_type( mime )
+ if os.path.exists( file_path ):
+ mime, encoding = mimetypes.guess_type( file_path )
+ if not mime:
+ try:
+ mime = trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( file_path )[-1] )
+ except:
+ mime = "txt"
- if os.path.exists( file_path ):
- max_peek_size = 1000000 # 1 MB
- if show_all or os.stat( file_path ).st_size < max_peek_size:
+ trans.response.set_content_type( mime )
return open( file_path )
else:
+ return "Could not find '%s' on the extra files path." % filename
+
+ mime = trans.app.datatypes_registry.get_mimetype_by_extension( data.extension.lower() )
+ trans.response.set_content_type(mime)
+ trans.log_event( "Display dataset id: %s" % str( dataset_id ) )
+
+ if to_ext: # Saving the file
+ trans.response.headers['Content-Length'] = int( os.stat( data.file_name ).st_size )
+ if to_ext[0] != ".":
+ to_ext = "." + to_ext
+ valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ fname = data.name
+ fname = ''.join(c in valid_chars and c or '_' for c in fname)[0:150]
+ trans.response.headers["Content-Disposition"] = "attachment; filename=GalaxyHistoryItem-%s-[%s]%s" % (data.hid, fname, to_ext)
+ return open( data.file_name )
+
+ if os.path.exists( data.file_name ):
+ max_peek_size = 1000000 # 1 MB
+ if preview and os.stat( data.file_name ).st_size > max_peek_size:
trans.response.set_content_type( "text/html" )
- return trans.fill_template( "/dataset/large_file.mako",
- truncated_data = open( file_path ).read(max_peek_size),
+ return trans.stream_template_mako( "/dataset/large_file.mako",
+ truncated_data = open( data.file_name ).read(max_peek_size),
data = data )
+ else:
+ return open( data.file_name )
else:
- raise paste.httpexceptions.HTTPNotFound( "File Not Found (%s)." % ( filename ) )
+ raise paste.httpexceptions.HTTPNotFound( "File Not Found (%s)." % data.file_name )
else:
return trans.show_error_message( "You are not allowed to access this dataset" )
diff -r ea29f33390d3 -r 61684a4d6b9e lib/galaxy/web/controllers/root.py
--- a/lib/galaxy/web/controllers/root.py Tue Oct 20 10:39:30 2009 -0400
+++ b/lib/galaxy/web/controllers/root.py Tue Oct 20 15:34:47 2009 -0400
@@ -139,49 +139,13 @@
@web.expose
def display( self, trans, id=None, hid=None, tofile=None, toext=".txt", **kwd ):
"""
- Returns data directly into the browser.
- Sets the mime-type according to the extension
+ Backward compatibility.
"""
- if hid is not None:
- try:
- hid = int( hid )
- except:
- return "hid '%s' is invalid" %str( hid )
- history = trans.get_history()
- for dataset in history.datasets:
- if dataset.hid == hid:
- data = dataset
- break
- else:
- raise Exception( "No dataset with hid '%d'" % hid )
+ if tofile:
+ to_ext = toext
else:
- try:
- data = self.app.model.HistoryDatasetAssociation.get( id )
- except:
- return "Dataset id '%s' is invalid" %str( id )
- if data:
- user, roles = trans.get_user_and_roles()
- if trans.app.security_agent.can_access_dataset( roles, data.dataset ):
- mime = trans.app.datatypes_registry.get_mimetype_by_extension( data.extension.lower() )
- trans.response.set_content_type(mime)
- if tofile:
- fStat = os.stat(data.file_name)
- trans.response.headers['Content-Length'] = int(fStat.st_size)
- if toext[0:1] != ".":
- toext = "." + toext
- valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
- fname = data.name
- fname = ''.join(c in valid_chars and c or '_' for c in fname)[0:150]
- trans.response.headers["Content-Disposition"] = "attachment; filename=GalaxyHistoryItem-%s-[%s]%s" % (data.hid, fname, toext)
- trans.log_event( "Display dataset id: %s" % str(id) )
- try:
- return open( data.file_name )
- except:
- return "This dataset contains no content"
- else:
- return "You are not allowed to access this dataset"
- else:
- return "No dataset with id '%s'" % str( id )
+ to_ext = None
+ return trans.webapp.controllers['dataset'].display( trans, encoded_id=id, to_ext=to_ext )
@web.expose
def display_child(self, trans, parent_id=None, designation=None, tofile=None, toext=".txt"):
diff -r ea29f33390d3 -r 61684a4d6b9e templates/dataset/large_file.mako
--- a/templates/dataset/large_file.mako Tue Oct 20 10:39:30 2009 -0400
+++ b/templates/dataset/large_file.mako Tue Oct 20 15:34:47 2009 -0400
@@ -2,8 +2,8 @@
<div class="warningmessagelarge">
This dataset is large and only the first megabyte is shown below.<br />
- <a href="${h.url_for( controller='dataset', action='display', dataset_id=data.id, show_all=True )}">Show all</a> |
- <a href="${h.url_for( controller='root', action='display', id=data.id, tofile='yes', toext=data.ext )}">Save</a>
+ <a href="${h.url_for( controller='dataset', action='display', encoded_id=trans.security.encode_id( data.id ), filename='' )}">Show all</a> |
+ <a href="${h.url_for( controller='dataset', action='display', encoded_id=trans.security.encode_id( data.id ), to_ext=data.ext )}">Save</a>
</div>
<pre>
diff -r ea29f33390d3 -r 61684a4d6b9e templates/root/history_common.mako
--- a/templates/root/history_common.mako Tue Oct 20 10:39:30 2009 -0400
+++ b/templates/root/history_common.mako Tue Oct 20 15:34:47 2009 -0400
@@ -33,7 +33,7 @@
<img src="${h.url_for('/static/images/pencil_icon_grey.png')}" width='16' height='16' alt='edit attributes' title='edit attributes' class='button edit' border='0'>
%endif
%else:
- <a class="icon-button display" title="display data" href="${h.url_for( controller='dataset', dataset_id=data.id, action='display', filename='index')}" target="galaxy_main"></a>
+ <a class="icon-button display" title="display data" href="${h.url_for( controller='dataset', action='display', encoded_id=trans.security.encode_id( data.id ), preview=True, filename='' )}" target="galaxy_main"></a>
%if user_owns_dataset:
<a class="icon-button edit" title="edit attributes" href="${h.url_for( controller='root', action='edit', id=data.id )}" target="galaxy_main"></a>
%endif
@@ -87,7 +87,7 @@
<div class="info">${_('Info: ')}${data.display_info()}</div>
<div>
%if data.has_data:
- <a href="${h.url_for( controller='root', action='display', id=data.id, tofile='yes', toext=data.ext )}" target="_blank">save</a>
+ <a href="${h.url_for( controller='dataset', action='display', encoded_id=trans.security.encode_id( data.id ), to_ext=data.ext )}">save</a>
%if user_owns_dataset:
| <a href="${h.url_for( controller='tool_runner', action='rerun', id=data.id )}" target="galaxy_main">rerun</a>
%endif
diff -r ea29f33390d3 -r 61684a4d6b9e test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Tue Oct 20 10:39:30 2009 -0400
+++ b/test/base/twilltestcase.py Tue Oct 20 15:34:47 2009 -0400
@@ -419,9 +419,9 @@
self.visit_url( "%s/dataset/undelete?id=%s" % ( self.url, hda_id ) )
if check_str:
self.check_page_for_string( check_str )
- def display_history_item( self, id, check_str='' ):
+ def display_history_item( self, hda_id, check_str='' ):
"""Displays a history item - simulates eye icon click"""
- self.visit_url( '%s/datasets/%s/display/index' % ( self.url, id ) )
+ self.visit_url( '%s/datasets/%s/display/' % ( self.url, self.security.encode_id( hda_id ) ) )
if check_str:
self.check_page_for_string( check_str )
self.home()
@@ -554,7 +554,7 @@
def verify_composite_datatype_file_content( self, file_name, hda_id ):
local_name = self.get_filename( file_name )
temp_name = self.get_filename( 'temp_%s' % file_name )
- self.visit_url( "%s/datasets/%s/display/%s" % ( self.url, hda_id, file_name ) )
+ self.visit_url( "%s/datasets/%s/display/%s" % ( self.url, self.security.encode_id( hda_id ), file_name ) )
data = self.last_page()
file( temp_name, 'wb' ).write( data )
try:
1
0
Hi Nate,
I tried to run the tool with a small input file. Then that case also the
test fails and returns the same error message.
FAIL: mGenePredict ( mgenepredict ) > Test-1
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/galaxy/galaxy-2.1.2009/test/functional/test_toolbox.py", line
114, in test_tool
self.do_it()
File "/home/galaxy/galaxy-2.1.2009/test/functional/test_toolbox.py", line
54, in do_it
self.verify_dataset_correctness( file )
File "/home/galaxy/galaxy-2.1.2009/test/base/twilltestcase.py", line 323,
in verify_dataset_correctness
if wait: self.wait() #wait for job to finish
File "/home/galaxy/galaxy-2.1.2009/test/base/twilltestcase.py", line 617,
in wait
self.assertNotEqual(count, maxiter)
AssertionError: 20 == 20
Also I can find that the job is not finished even though I got the fail
message. I confirmed the same, when I run the test again it produces an
error message stating that the Galaxy port is already in use.
I hope my assumption is true, if not please let me know.
Many thanks,
Vipin T S
2
3
Hi all,
I wrote a functional test for my tool. Here is the test code.
<tests>
<test>
<param name="source" value="history" />
<param name="fasta_input" value="tair9_chr4_10000.fas"
ftype="fasta" />
<param name="source" value="pretrained" />
<param name="organism" value="arabidopsis" />
<output name="output" file="tair9_chr4_output.gff3" />
</test>
</tests>
While running the test I am getting an error message like the following.
ERROR: test module functional in /home/galaxy/galaxy-2.1.2009/test
----------------------------------------------------------------------
Traceback (most recent call last):
File
"/home/galaxy/galaxy-2.1.2009/eggs/py2.5-noplatform/nose-0.9.1.dev_r101-py2.5.egg/nose/suite.py",
line 46, in run
self.setUp()
File
"/home/galaxy/galaxy-2.1.2009/eggs/py2.5-noplatform/nose-0.9.1.dev_r101-py2.5.egg/nose/suite.py",
line 200, in setUp
try_run(self.module, names)
File
"/home/galaxy/galaxy-2.1.2009/eggs/py2.5-noplatform/nose-0.9.1.dev_r101-py2.5.egg/nose/util.py",
line 200, in try_run
return func()
File "/home/galaxy/galaxy-2.1.2009/test/functional/__init__.py", line
88, in setup
server = httpserver.serve( webapp, host=galaxy_test_host,
port=galaxy_test_port, start_loop=False )
File
"/home/galaxy/galaxy-2.1.2009/eggs/py2.5-noplatform/Paste-1.5.1-py2.5.egg/paste/httpserver.py",
line 1257, in serve
threadpool_options=threadpool_options)
File
"/home/galaxy/galaxy-2.1.2009/eggs/py2.5-noplatform/Paste-1.5.1-py2.5.egg/paste/httpserver.py",
line 1107, in __init__
RequestHandlerClass, ssl_context)
File
"/home/galaxy/galaxy-2.1.2009/eggs/py2.5-noplatform/Paste-1.5.1-py2.5.egg/paste/httpserver.py",
line 1087, in __init__
RequestHandlerClass, ssl_context)
File
"/home/galaxy/galaxy-2.1.2009/eggs/py2.5-noplatform/Paste-1.5.1-py2.5.egg/paste/httpserver.py",
line 328, in __init__
HTTPServer.__init__(self, server_address, RequestHandlerClass)
File "/usr/lib/python2.5/SocketServer.py", line 330, in __init__
self.server_bind()
File "/usr/lib/python2.5/BaseHTTPServer.py", line 101, in server_bind
SocketServer.TCPServer.server_bind(self)
File "/usr/lib/python2.5/SocketServer.py", line 341, in server_bind
self.socket.bind(self.server_address)
File "<string>", line 1, in bind
error: (98, 'Address already in use')
************************************************************
It will be great if you can give me a suggestion.
Thanks in advance,
Vipin T S
4
6
details: http://www.bx.psu.edu/hg/galaxy/rev/2f249afc66ea
changeset: 2892:2f249afc66ea
user: rc
date: Mon Oct 19 09:53:04 2009 -0400
description:
Fixed a form definition editing bug
3 file(s) affected in this change:
lib/galaxy/web/controllers/forms.py
templates/admin/forms/manage_forms.mako
templates/admin/forms/show_form_read_only.mako
diffs (69 lines):
diff -r 38bbf36f70e8 -r 2f249afc66ea lib/galaxy/web/controllers/forms.py
--- a/lib/galaxy/web/controllers/forms.py Sun Oct 18 18:19:12 2009 -0400
+++ b/lib/galaxy/web/controllers/forms.py Mon Oct 19 09:53:04 2009 -0400
@@ -313,10 +313,10 @@
ctr=0
sb_options = []
while True:
- option = params.get( 'field_'+str(index)+'_option_'+str(ctr), None )
- ctr = ctr+1
- if option:
+ if kwd.has_key( 'field_'+str(index)+'_option_'+str(ctr) ):
+ option = params.get( 'field_'+str(index)+'_option_'+str(ctr), None )
sb_options.append(util.restore_text(option))
+ ctr = ctr+1
else:
return sb_options
def __get_saved_form(self, fd):
@@ -342,8 +342,8 @@
layout = []
index = 0
while True:
- grid_name = util.restore_text( params.get( 'grid_layout%i' % index, '' ) )
- if grid_name:
+ if kwd.has_key( 'grid_layout%i' % index ):
+ grid_name = util.restore_text( params.get( 'grid_layout%i' % index, '' ) )
layout.append( grid_name )
index = index + 1
else:
@@ -355,7 +355,7 @@
# get the user entered fields
index = 0
while True:
- if params.get( 'field_name_%i' % index, False ):
+ if kwd.has_key( 'field_name_%i' % index ):
fields.append( self.__get_field( index, **kwd ) )
index = index + 1
else:
diff -r 38bbf36f70e8 -r 2f249afc66ea templates/admin/forms/manage_forms.mako
--- a/templates/admin/forms/manage_forms.mako Sun Oct 18 18:19:12 2009 -0400
+++ b/templates/admin/forms/manage_forms.mako Mon Oct 19 09:53:04 2009 -0400
@@ -23,7 +23,7 @@
</div>
%else:
<div popupmenu="form-${form.id}-popup">
- <a class="action-button" href="${h.url_for( action='edit', form_id=form.id, show_form=True )}">Edit form definition</a>
+ <a class="action-button" href="${h.url_for( action='edit', form_id=form.id, show_form=True )}">Edit</a>
<a class="action-button" confirm="Click OK to delete the form ${form.name}." href="${h.url_for( action='delete', form_id=form.id )}">Delete</a>
</div>
%endif
diff -r 38bbf36f70e8 -r 2f249afc66ea templates/admin/forms/show_form_read_only.mako
--- a/templates/admin/forms/show_form_read_only.mako Sun Oct 18 18:19:12 2009 -0400
+++ b/templates/admin/forms/show_form_read_only.mako Mon Oct 19 09:53:04 2009 -0400
@@ -63,14 +63,14 @@
<div class="toolForm">
%if form.desc:
- <div class="toolFormTitle">${form.name} - <i>${form.desc}</i>
+ <div class="toolFormTitle">${form.name} - <i> ${form.desc}</i> (${form.type})
<a id="form-${form.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="form-${form.id}-popup">
<a class="action-button" href="${h.url_for( action='edit', form_id=form.id, show_form=True )}">Edit</a>
</div>
</div>
%else:
- <div class="toolFormTitle">${form.name}
+ <div class="toolFormTitle">${form.name} (${form.type})
<a id="form-${form.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="form-${form.id}-popup">
<a class="action-button" href="${h.url_for( action='edit', form_id=form.id, show_form=True )}">Edit</a>
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/55d479c8d592
changeset: 2893:55d479c8d592
user: Ross Lazarus <ross.lazarus(a)gmail.com>
date: Mon Oct 19 12:05:19 2009 -0400
description:
removed bogus unit tests from new gg/gff
1 file(s) affected in this change:
lib/galaxy/datatypes/genetics.py
diffs (55 lines):
diff -r 2f249afc66ea -r 55d479c8d592 lib/galaxy/datatypes/genetics.py
--- a/lib/galaxy/datatypes/genetics.py Mon Oct 19 09:53:04 2009 -0400
+++ b/lib/galaxy/datatypes/genetics.py Mon Oct 19 12:05:19 2009 -0400
@@ -28,26 +28,6 @@
gal_Log = logging.getLogger(__name__)
verbose = False
-
-
-"""
-Want to make some wig tracks from each analysis
-Best n -log10(p). Make top hit the window.
-
-
-from ucsc wig docs
-ll options are placed in a single line separated by spaces:
-
- track type=wiggle_0 name=track_label description=center_label \
- visibility=display_mode color=r,g,b altColor=r,g,b \
- priority=priority autoScale=on|off \
- gridDefault=on|off maxHeightPixels=max:default:min \
- graphType=bar|points viewLimits=lower:upper \
- yLineMark=real-value yLineOnOff=on|off \
- windowingFunction=maximum|mean|minimum smoothingWindow=off|2-16
-
-The track type with version is REQUIRED, and it currently must be wiggle_0:
-"""
class GenomeGraphs(Interval):
@@ -131,7 +111,7 @@
else:
# We've spanned a chromosome
break
- if i > 10:
+ if i > 10: # span 10 features
break
except:
seqid, start, stop = ( '', '', '' )
@@ -189,15 +169,6 @@
Determines whether the file is in gff format
GFF lines have nine required fields that must be tab-separated.
-
- For complete details see http://genome.ucsc.edu/FAQ/FAQformat#format3
-
- >>> fname = get_test_fname( 'gff_version_3.gff' )
- >>> Gff().sniff( fname )
- False
- >>> fname = get_test_fname( 'test.gff' )
- >>> Gff().sniff( fname )
- True
"""
f = open(filename,'r')
headers = f.readline().split
1
0

20 Oct '09
details: http://www.bx.psu.edu/hg/galaxy/rev/38bbf36f70e8
changeset: 2891:38bbf36f70e8
user: Ross Lazarus <ross.lazarus(a)gmail.com>
date: Sun Oct 18 18:19:12 2009 -0400
description:
Remove Genome Graphs and replace with topTable (eg 1000 best p values) as a ucsc compatible gff
1 file(s) affected in this change:
lib/galaxy/datatypes/genetics.py
diffs (321 lines):
diff -r 16a0c13c94cc -r 38bbf36f70e8 lib/galaxy/datatypes/genetics.py
--- a/lib/galaxy/datatypes/genetics.py Fri Oct 16 15:54:43 2009 -0400
+++ b/lib/galaxy/datatypes/genetics.py Sun Oct 18 18:19:12 2009 -0400
@@ -16,126 +16,222 @@
import data
from galaxy import util
from cgi import escape
-import urllib
+import urllib, binascii
from galaxy.web import url_for
from galaxy.datatypes import metadata
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes.data import Text
from galaxy.datatypes.tabular import Tabular
from galaxy.datatypes.images import Html
+from galaxy.datatypes.interval import Interval
+from galaxy.util.hash_util import *
gal_Log = logging.getLogger(__name__)
verbose = False
-class GenomeGraphs( Tabular ):
- """Tab delimited data containing a marker id and any number of numeric values"""
+
+"""
+Want to make some wig tracks from each analysis
+Best n -log10(p). Make top hit the window.
+
+
+from ucsc wig docs
+ll options are placed in a single line separated by spaces:
+
+ track type=wiggle_0 name=track_label description=center_label \
+ visibility=display_mode color=r,g,b altColor=r,g,b \
+ priority=priority autoScale=on|off \
+ gridDefault=on|off maxHeightPixels=max:default:min \
+ graphType=bar|points viewLimits=lower:upper \
+ yLineMark=real-value yLineOnOff=on|off \
+ windowingFunction=maximum|mean|minimum smoothingWindow=off|2-16
+
+The track type with version is REQUIRED, and it currently must be wiggle_0:
+"""
+
+class GenomeGraphs(Interval):
+
+ """gg version viewable at ucsc of Gff format"""
+ file_ext = "gg"
+ column_names = [ 'Seqname', 'Source', 'Feature', 'Start', 'End', 'Score', 'Strand', 'Frame', 'Group' ]
"""Add metadata elements"""
- MetadataElement( name="markerCol", default=1, desc="Marker ID column", param=metadata.ColumnParameter )
- MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True )
- MetadataElement( name="column_types", default=[], desc="Column types", readonly=True, visible=False )
- file_ext = 'gg'
+ MetadataElement( name="columns", default=9, desc="Number of columns", readonly=True, visible=False )
+ MetadataElement( name="column_types", default=['str','str','str','int','int','int','str','str','str'], param=metadata.ColumnTypesParameter, desc="Column types", readonly=True, visible=False )
+ MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
+ MetadataElement( name="startCol", default=4, desc="Start column", param=metadata.ColumnParameter )
+ MetadataElement( name="endCol", default=5, desc="End column", param=metadata.ColumnParameter )
+ MetadataElement( name="strandCol", desc="Strand column (click box & select)", param=metadata.ColumnParameter, optional=True, no_value=0 )
+ ###do we need to repeat these? they are the same as should be inherited from interval type
+
+ def __init__(self, **kwd):
+ """Initialize datatype, by adding GBrowse display app"""
+ Interval.__init__(self, **kwd)
+ self.add_display_app ( 'ucsc', 'display at UCSC', 'as_ucsc_display_file', 'ucsc_links' )
- def __init__(self, **kwd):
- """Initialize gg datatype, by adding UCSC display apps"""
- Tabular.__init__(self, **kwd)
- self.add_display_app ( 'ucsc', 'Genome Graph', 'as_ucsc_display_file', 'ucsc_links' )
-
- def set_peek( self, dataset ):
- """Set the peek and blurb text"""
- if not dataset.dataset.purged:
- dataset.peek = data.get_file_peek( dataset.file_name )
- dataset.blurb = util.commaify( str( data.get_line_count( dataset.file_name ) ) ) + " rows"
- else:
- dataset.peek = 'file does not exist'
- dataset.blurb = 'file purged from disk'
+ def as_ucsc_display_file( self, dataset, **kwd ):
+ return open( dataset.file_name )
- def get_mime(self):
- """Returns the mime type of the datatype"""
- return 'application/vnd.msexcel'
+ def set_meta( self, dataset, overwrite = True, **kwd ):
+ i = 0
+ for i, line in enumerate( file ( dataset.file_name ) ):
+ line = line.rstrip('\r\n')
+ if line and not line.startswith( '#' ):
+ elems = line.split( '\t' )
+ if len(elems) == 9:
+ try:
+ int( elems[3] )
+ int( elems[4] )
+ break
+ except:
+ pass
+ Interval.set_meta( self, dataset, overwrite = overwrite, skip = i )
+
+ def make_html_table( self, dataset, skipchars=[] ):
+ """Create HTML table, used for displaying peek"""
+ out = ['<table cellspacing="0" cellpadding="3">']
+ comments = []
+ try:
+ # Generate column header
+ out.append( '<tr>' )
+ for i, name in enumerate( self.column_names ):
+ out.append( '<th>%s.%s</th>' % ( str( i+1 ), name ) )
+ out.append( self.make_html_peek_rows( dataset, skipchars=skipchars ) )
+ out.append( '</table>' )
+ out = "".join( out )
+ except Exception, exc:
+ out = "Can't create peek %s" % exc
+ return out
def get_estimated_display_viewport( self, dataset ):
- """Return a chrom, start, stop tuple for viewing a file."""
- raise notImplemented
-
- def as_ucsc_display_file( self, dataset, **kwd ):
- """Returns file"""
- return file(dataset.file_name,'r')
-
+ """
+ Return a chrom, start, stop tuple for viewing a file. There are slight differences between gff 2 and gff 3
+ formats. This function should correctly handle both...
+ """
+ if True or (dataset.has_data() and dataset.state == dataset.states.OK):
+ try:
+ seqid = ''
+ start = 2147483647 # Maximum value of a signed 32 bit integer ( 2**31 - 1 )
+ stop = 0
+ for i, line in enumerate( file( dataset.file_name ) ):
+ if i == 0: # track stuff there
+ continue
+ line = line.rstrip( '\r\n' )
+ if not line:
+ continue
+ if not line.startswith( '#' ):
+ elems = line.split( '\t' )
+ if not seqid:
+ # We can only set the viewport for a single chromosome
+ seqid = elems[0]
+ if seqid == elems[0]:
+ # Make sure we have not spanned chromosomes
+ start = min( start, int( elems[3] ) )
+ stop = max( stop, int( elems[4] ) )
+ else:
+ # We've spanned a chromosome
+ break
+ if i > 10:
+ break
+ except:
+ seqid, start, stop = ( '', '', '' )
+ return ( seqid, str( start ), str( stop ) )
+ else:
+ return ( '', '', '' )
+
+ def gbrowse_links( self, dataset, type, app, base_url ):
+ ret_val = []
+ if dataset.has_data:
+ viewport_tuple = self.get_estimated_display_viewport( dataset )
+ seqid = viewport_tuple[0]
+ start = viewport_tuple[1]
+ stop = viewport_tuple[2]
+ if seqid and start and stop:
+ for site_name, site_url in util.get_gbrowse_sites_by_build( dataset.dbkey ):
+ if site_name in app.config.gbrowse_display_sites:
+ link = "%s?start=%s&stop=%s&ref=%s&dbkey=%s" % ( site_url, start, stop, seqid, dataset.dbkey )
+ ret_val.append( ( site_name, link ) )
+ return ret_val
+
def ucsc_links( self, dataset, type, app, base_url ):
- """ from the ever-helpful angie hinrichs angie(a)soe.ucsc.edu
- a genome graphs call looks like this
- http://genome.ucsc.edu/cgi-bin/hgGenome?clade=mammal&org=Human&db=hg18&hgGe…
- &hgGenome_dataSetDescription=test&hgGenome_formatType=best%20guess&hgGenome_markerType=best%20guess
- &hgGenome_columnLabels=best%20guess&hgGenome_maxVal=&hgGenome_labelVals=
- &hgGenome_maxGapToFill=25000000&hgGenome_uploadFile=http://galaxy.esphealth.org/datasets/333/display/index
- &hgGenome_doSubmitUpload=submit
- Galaxy gives this for an interval file
- http://genome.ucsc.edu/cgi-bin/hgTracks?db=hg18&position=chr1:1-1000&hgt.cu…
- http%3A%2F%2Fgalaxy.esphealth.org%2Fdisplay_as%3Fid%3D339%26display_app%3Ducsc
- """
ret_val = []
- ggtail = '&hgGenome_doSubmitUpload=submit'
- if not dataset.dbkey:
- dataset.dbkey = 'hg18' # punt!
- ret_val = []
- ggtail = '&hgGenome_doSubmitUpload=submit'
- if not dataset.dbkey:
- dataset.dbkey = 'hg18' # punt!
- if dataset.has_data:
- for site_name, site_url in util.get_ucsc_by_build(dataset.dbkey):
+ if dataset.has_data:
+ viewport_tuple = self.get_estimated_display_viewport(dataset)
+ if viewport_tuple:
+ chrom = viewport_tuple[0]
+ start = viewport_tuple[1]
+ stop = viewport_tuple[2]
+ if start == '' or int(start) < 1:
+ start='1'
+ if stop == '' or int(stop) <= start:
+ stop = '%d' % (int(start) + 10000)
+ for site_name, site_url in util.get_ucsc_by_build(dataset.dbkey):
if site_name in app.config.ucsc_display_sites:
- site_url = site_url.replace('/hgTracks?','/hgGenome?') # for genome graphs
- display_url = urllib.quote_plus( "%s/display_as?id=%i&display_app=%s" % (base_url, dataset.id, type) )
- sl = ["%sdb=%s" % (site_url,dataset.dbkey ),]
- sl.append("&hgGenome_dataSetName=%s&hgGenome_dataSetDescription=%s" % (dataset.name, 'GalaxyGG_data'))
- sl.append("&hgGenome_formatType=best%20guess&hgGenome_markerType=best%20guess")
- sl.append("&hgGenome_columnLabels=first%20row&hgGenome_maxVal=&hgGenome_labelVals=")
- sl.append("&hgGenome_maxGapToFill=25000000&hgGenome_uploadFile=")
- s = urllib.quote_plus( ''.join(sl) )
- link = "%s%s%s" % (s, display_url, ggtail )
+ # HACK: UCSC doesn't support https, so force http even
+ # if our URL scheme is https. Making this work
+ # requires additional hackery in your upstream proxy.
+ # If UCSC ever supports https, remove this hack.
+ internal_url = "%s" % url_for( controller='dataset',
+ dataset_id=dataset.id, action='display_at', filename='ucsc_' + site_name )
+ if base_url.startswith( 'https://' ):
+ base_url = base_url.replace( 'https', 'http', 1 )
+ display_url = urllib.quote_plus( "%s%s/display_as?id=%i&display_app=%s&authz_method=display_at" % (base_url, url_for( controller='root' ), dataset.id, type) )
+ redirect_url = urllib.quote_plus( "%sdb=%s&position=%s:%s-%s&hgt.customText=%%s" % (site_url, dataset.dbkey, chrom, start, stop) )
+ link = '%s?redirect_url=%s&display_url=%s' % ( internal_url, redirect_url, display_url )
ret_val.append( (site_name, link) )
+ else:
+ gal_Log.debug('@@@ gg ucsc_links - no viewport_tuple')
return ret_val
- def validate( self, dataset ):
- """Validate a gg file - all numeric after header row"""
- errors = list()
- infile = open(dataset.file_name, "r")
- for i,row in enumerate(infile): #drop header
- badvals = []
- if i > 0:
- ll = row.strip().split('\t')
- for j,x in enumerate(ll):
- try:
- x = float(x)
- except:
- badval.append('col%d:%s' % (j+1,x))
- if len(badvals) > 0:
- errors.append('row %d, %s' % (' '.join(badvals)))
- return errors
+ def sniff( self, filename ):
+ """
+ Determines whether the file is in gff format
- def repair_methods( self, dataset ):
- """Return options for removing errors along with a description"""
- return [("lines","Remove erroneous lines")]
+ GFF lines have nine required fields that must be tab-separated.
+
+ For complete details see http://genome.ucsc.edu/FAQ/FAQformat#format3
+
+ >>> fname = get_test_fname( 'gff_version_3.gff' )
+ >>> Gff().sniff( fname )
+ False
+ >>> fname = get_test_fname( 'test.gff' )
+ >>> Gff().sniff( fname )
+ True
+ """
+ f = open(filename,'r')
+ headers = f.readline().split
+ if headers[0].lower() == 'track':
+ headers = f.readline.split()
+ #headers = get_headers( filename, '\t' )
+ try:
+ if len(headers) < 2:
+ return False
+ for hdr in headers:
+ if hdr and hdr[0].startswith( '##gff-version' ) and hdr[0].find( '2' ) < 0:
+ return False
+ if hdr and hdr[0] and not hdr[0].startswith( '#' ):
+ if len(hdr) != 9:
+ return False
+ try:
+ int( hdr[3] )
+ int( hdr[4] )
+ except:
+ return False
+ if hdr[5] != '.':
+ try:
+ score = int(hdr[5])
+ except:
+ return False
+ if (score < 0 or score > 1000):
+ return False
+ if hdr[6] not in data.valid_strand:
+ return False
+ return True
+ except:
+ return False
+
- def sniff(self,filename):
- """
- """
- infile = open(dataset.file_name, "r")
- header= infile.next() # header
- badvals = []
- for i,row in enumerate(infile[:10]): # sample first 10 rows
- ll = row.strip().split('\t')
- for j,x in enumerate(ll[1:]): # ignore first identifier col
- try:
- x = float(x)
- except:
- badval.append('col%d:%s' % (j+1,x))
- if len(badvals) > 0:
- return False
- else:
- return True
class rgTabList(Tabular):
""" for sampleid and for featureid lists of exclusions or inclusions in the clean tool
1
0

20 Oct '09
details: http://www.bx.psu.edu/hg/galaxy/rev/e945dcdfd578
changeset: 2888:e945dcdfd578
user: Ross Lazarus <ross.lazarus(a)gmail.com>
date: Thu Oct 15 19:01:07 2009 -0400
description:
moved the rgGRR svg scripts to static/scripts/tools/rgenetics and decreased chattiness in genetics.py
8 file(s) affected in this change:
lib/galaxy/datatypes/genetics.py
scripts/check_eggs.py
static/scripts/checkbox_and_radiobutton.js
static/scripts/helper_functions.js
static/scripts/timer.js
static/scripts/tools/rgenetics/checkbox_and_radiobutton.js
static/scripts/tools/rgenetics/helper_functions.js
static/scripts/tools/rgenetics/timer.js
diffs (1353 lines):
diff -r cbe28b41fb9d -r e945dcdfd578 lib/galaxy/datatypes/genetics.py
--- a/lib/galaxy/datatypes/genetics.py Thu Oct 15 10:48:38 2009 -0400
+++ b/lib/galaxy/datatypes/genetics.py Thu Oct 15 19:01:07 2009 -0400
@@ -25,6 +25,7 @@
from galaxy.datatypes.images import Html
gal_Log = logging.getLogger(__name__)
+verbose = False
class GenomeGraphs( Tabular ):
"""Tab delimited data containing a marker id and any number of numeric values"""
@@ -247,7 +248,8 @@
head,rest = os.path.split(old)
newpath = os.path.join(head,newbase)
newpath = '%s%s' % (newpath,e)
- shutil.move(oldpath,newpath)
+ if oldpath <> newpath:
+ shutil.move(oldpath,newpath)
return newpath
bn = dataset.metadata.base_name
efp = dataset.extra_files_path
@@ -266,20 +268,32 @@
def set_meta( self, dataset, **kwd ):
- """
- NOTE we apply the tabular machinary to the phenodata extracted
- from a BioC eSet or affybatch.
+ """for lped/pbed eg
"""
+ if kwd.get('overwrite') == False:
+ if verbose:
+ gal_Log.debug('@@@ rgenetics set_meta called with overwrite = False')
+ return True
try:
- flist = os.listdir(dataset.extra_files_path)
- except:
- gal_Log.debug('@@@rgenetics set_meta failed - no dataset?')
- return
+ efp = dataset.extra_files_path
+ except:
+ if verbose:
+ gal_Log.debug('@@@rgenetics set_meta failed %s - dataset %s has no efp ?' % (sys.exc_info()[0], dataset.name))
+ return False
+ try:
+ flist = os.listdir(efp)
+ except:
+ if verbose: gal_Log.debug('@@@rgenetics set_meta failed %s - dataset %s has no efp ?' % (sys.exc_info()[0],dataset.name))
+ return False
+ if len(flist) == 0:
+ if verbose:
+ gal_Log.debug('@@@rgenetics set_meta failed - %s efp %s is empty?' % (dataset.name,efp))
+ return False
bn = None
for f in flist:
- n = os.path.splitext(f)[0]
- if not bn:
+ n,e = os.path.splitext(f)[0]
+ if (not bn) and e in ('.ped','.map','.bim','.fam'):
bn = n
dataset.metadata.base_name = bn
if not bn:
@@ -607,8 +621,9 @@
try:
flist = os.listdir(dataset.extra_files_path)
except:
- gal_Log.debug('@@@rexpression set_meta failed - no dataset?')
- return
+ if verbose:
+ gal_Log.debug('@@@rexpression set_meta failed - no dataset?')
+ return False
bn = None
for f in flist:
n = os.path.splitext(f)[0]
diff -r cbe28b41fb9d -r e945dcdfd578 scripts/check_eggs.py
--- a/scripts/check_eggs.py Thu Oct 15 10:48:38 2009 -0400
+++ b/scripts/check_eggs.py Thu Oct 15 19:01:07 2009 -0400
@@ -1,3 +1,4 @@
+#! /usr/bin/python
"""
usage: check_eggs.py
"""
diff -r cbe28b41fb9d -r e945dcdfd578 static/scripts/checkbox_and_radiobutton.js
--- a/static/scripts/checkbox_and_radiobutton.js Thu Oct 15 10:48:38 2009 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,347 +0,0 @@
-/*
-Scripts to create interactive checkboxes and radio buttons in SVG using ECMA script
-Copyright (C) <2007> <Andreas Neumann>
-Version 1.1.3, 2007-08-09
-neumann(a)karto.baug.ethz.ch
-http://www.carto.net/
-http://www.carto.net/neumann/
-
-Credits:
-* Guy Morton for providing a fix to let users toggle checkboxes by clicking on text labels
-* Bruce Rindahl for providing the bugfix described in version 1.1.2
-* Simon Shutter for providing a fix for the ASV in IE crash when reloading the SVG file after calling the .remove() method on a checkbox
-
-----
-
-Documentation: http://www.carto.net/papers/svg/gui/checkbox_and_radiobutton/
-
-----
-
-current version: 1.1.3
-
-version history:
-1.0 (2006-03-13)
-initial version
-
-1.1 (2006-07-11)
-text labels are now clickable (thanks to Guy Morton)
-added method .moveTo() to move checkbox to a different location
-introduced new constructor parameter labelYOffset to allow more flexible placement of the text label
-
-1.1.1 (2007-02-06)
-added cursor pointer to the text label and use element representing the checkBox
-
-1.1.2 (2007-04-19)
-bug fix: this.selectedIndex was not correctly initialized in method addCheckBox of the radioButtonGroup object
-
-1.1.3 (2007-08-09)
-bug fix: the method .remove() was slightly modified (using removeEventListener) for avoiding a crash related to the method after reloading the SVG file
-
--------
-
-
-This ECMA script library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library (lesser_gpl.txt); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-----
-
-original document site: http://www.carto.net/papers/svg/gui/checkbox_and_radiobutton/
-Please contact the author in case you want to use code or ideas commercially.
-If you use this code, please include this copyright header, the included full
-LGPL 2.1 text and read the terms provided in the LGPL 2.1 license
-(http://www.gnu.org/copyleft/lesser.txt)
-
--------------------------------
-
-Please report bugs and send improvements to neumann(a)karto.baug.ethz.ch
-If you use this control, please link to the original (http://www.carto.net/papers/svg/gui/checkbox_and_radiobutton/)
-somewhere in the source-code-comment or the "about" of your project and give credits, thanks!
-
-*/
-
-function checkBox(id,parentNode,x,y,checkboxId,checkcrossId,checkedStatus,labelText,textStyles,labelDistance,labelYOffset,radioButtonGroup,functionToCall) {
- var nrArguments = 13;
- var createCheckbox= true;
- if (arguments.length == nrArguments) {
- this.id = id; //an internal id, this id is not used in the SVG Dom tree
- this.parentNode = parentNode; //the parentNode, string or nodeReference
- this.x = x; //the center of the checkBox
- this.y = y; //the center of the checkBox
- this.checkboxId = checkboxId; //the id of the checkbox symbol (background)
- this.checkcrossId = checkcrossId; //the id of the checkbox symbol (foreground), pointer-events should be set to "none"
- this.checkedStatus = checkedStatus; //a status variable (true|false), indicates if checkbox is on or off
- this.labelText = labelText; //the text of the checkbox label to be displayed, use undefined or empty string if you don't need a label text
- this.textStyles = textStyles; //an array of literals containing the text settings
- if (!this.textStyles["font-size"]) {
- this.textStyles["font-size"] = 12;
- }
- this.labelDistance = labelDistance; //a distance defined from the center of the checkbox to the left of the text of the label
- this.labelYOffset = labelYOffset; //a y offset value for the text label in relation to the checkbox symbol center
- this.radioButtonGroup = radioButtonGroup; //a reference to a radio button group, if this is a standalone checkBox, just use the parameter undefined
- this.functionToCall = functionToCall; //the function to call after triggering checkBox
- this.exists = true; //status that indicates if checkbox exists or not, is set to false after method .remove() was called
- this.label = undefined; //later a reference to the label text node
- }
- else {
- createCheckbox = false;
- alert("Error in checkbox ("+id+"): wrong nr of arguments! You have to pass over "+nrArguments+" parameters.");
- }
- if (createCheckbox) {
- //timer stuff
- this.timer = new Timer(this); //a Timer instance for calling the functionToCall
- if (this.radioButtonGroup) {
- this.timerMs = 0;
- }
- else {
- this.timerMs = 200; //a constant of this object that is used in conjunction with the timer - functionToCall is called after 200 ms
- }
- //create checkbox
- this.createCheckBox();
- }
- else {
- alert("Could not create checkbox with id '"+id+"' due to errors in the constructor parameters");
- }
-}
-
-//this method creates all necessary checkbox geometry
-checkBox.prototype.createCheckBox = function() {
- if (typeof(this.parentNode) == "string") {
- this.parentNode = document.getElementById(this.parentNode);
- }
- //create checkbox
- this.checkBox = document.createElementNS(svgNS,"use");
- this.checkBox.setAttributeNS(null,"x",this.x);
- this.checkBox.setAttributeNS(null,"y",this.y);
- this.checkBox.setAttributeNS(xlinkNS,"href","#"+this.checkboxId);
- this.checkBox.addEventListener("click",this,false);
- this.checkBox.setAttributeNS(null,"cursor","pointer");
- this.parentNode.appendChild(this.checkBox);
- //create checkcross
- this.checkCross = document.createElementNS(svgNS,"use");
- this.checkCross.setAttributeNS(null,"x",this.x);
- this.checkCross.setAttributeNS(null,"y",this.y);
- this.checkCross.setAttributeNS(xlinkNS,"href","#"+this.checkcrossId);
- this.parentNode.appendChild(this.checkCross);
- if (this.checkedStatus == false) {
- this.checkCross.setAttributeNS(null,"display","none");
- }
- //create label, if any
- if (this.labelText) {
- if (this.labelText.length > 0) {
- this.label = document.createElementNS(svgNS,"text");
- for (var attrib in this.textStyles) {
- var value = this.textStyles[attrib];
- if (attrib == "font-size") {
- value += "px";
- }
- this.label.setAttributeNS(null,attrib,value);
- }
- this.label.setAttributeNS(null,"x",(this.x + this.labelDistance));
- this.label.setAttributeNS(null,"y",(this.y + this.labelYOffset));
- this.label.setAttributeNS(null,"cursor","pointer");
- var labelTextNode = document.createTextNode(this.labelText);
- this.label.appendChild(labelTextNode);
- this.label.setAttributeNS(null,"pointer-events","all");
- this.label.addEventListener("click",this,false);
- this.parentNode.appendChild(this.label);
- }
- }
- if (this.radioButtonGroup) {
- this.radioButtonGroup.addCheckBox(this);
- }
-}
-
-checkBox.prototype.handleEvent = function(evt) {
- if (evt.type == "click") {
- if (this.checkedStatus == true) {
- this.checkCross.setAttributeNS(null,"display","none");
- this.checkedStatus = false;
- }
- else {
- this.checkCross.setAttributeNS(null,"display","inline");
- this.checkedStatus = true;
- }
- }
- this.timer.setTimeout("fireFunction",this.timerMs);
-}
-
-checkBox.prototype.fireFunction = function() {
- if (this.radioButtonGroup) {
- this.radioButtonGroup.selectById(this.id,true);
- }
- else {
- if (typeof(this.functionToCall) == "function") {
- this.functionToCall(this.id,this.checkedStatus,this.labelText);
- }
- if (typeof(this.functionToCall) == "object") {
- this.functionToCall.checkBoxChanged(this.id,this.checkedStatus,this.labelText);
- }
- if (typeof(this.functionToCall) == undefined) {
- return;
- }
- }
-}
-
-checkBox.prototype.check = function(FireFunction) {
- this.checkCross.setAttributeNS(null,"display","inherit");
- this.checkedStatus = true;
- if (FireFunction) {
- this.timer.setTimeout("fireFunction",this.timerMs);
- }
-}
-
-checkBox.prototype.uncheck = function(FireFunction) {
- this.checkCross.setAttributeNS(null,"display","none");
- this.checkedStatus = false;
- if (FireFunction) {
- this.timer.setTimeout("fireFunction",this.timerMs);
- }
-}
-
-//move checkbox to a different position
-checkBox.prototype.moveTo = function(moveX,moveY) {
- this.x = moveX;
- this.y = moveY;
- //move checkbox
- this.checkBox.setAttributeNS(null,"x",this.x);
- this.checkBox.setAttributeNS(null,"y",this.y);
- //move checkcross
- this.checkCross.setAttributeNS(null,"x",this.x);
- this.checkCross.setAttributeNS(null,"y",this.y);
- //move text label
- if (this.labelText) {
- this.label.setAttributeNS(null,"x",(this.x + this.labelDistance));
- this.label.setAttributeNS(null,"y",(this.y + this.labelYOffset));
- }
-}
-
-checkBox.prototype.remove = function(FireFunction) {
- this.checkBox.removeEventListener("click",this,false);
- this.parentNode.removeChild(this.checkBox);
- this.parentNode.removeChild(this.checkCross);
- if (this.label) {
- this.parentNode.removeChild(this.label);
- }
- this.exists = false;
-}
-
-checkBox.prototype.setLabelText = function(labelText) {
- this.labelText = labelText
- if (this.label) {
- this.label.firstChild.nodeValue = labelText;
- }
- else {
- if (this.labelText.length > 0) {
- this.label = document.createElementNS(svgNS,"text");
- for (var attrib in this.textStyles) {
- value = this.textStyles[attrib];
- if (attrib == "font-size") {
- value += "px";
- }
- this.label.setAttributeNS(null,attrib,value);
- }
- this.label.setAttributeNS(null,"x",(this.x + this.labelDistance));
- this.label.setAttributeNS(null,"y",(this.y + this.textStyles["font-size"] * 0.3));
- var labelTextNode = document.createTextNode(this.labelText);
- this.label.appendChild(labelTextNode);
- this.parentNode.appendChild(this.label);
- }
- }
-}
-
-/* start of the radioButtonGroup object */
-
-function radioButtonGroup(id,functionToCall) {
- var nrArguments = 2;
- if (arguments.length == nrArguments) {
- this.id = id;
- if (typeof(functionToCall) == "function" || typeof(functionToCall) == "object" || typeof(functionToCall) == undefined) {
- this.functionToCall = functionToCall;
- }
- else {
- alert("Error in radiobutton with ("+id+"): argument functionToCall is not of type 'function', 'object' or undefined!");
- }
- this.checkBoxes = new Array(); //this array will hold checkbox objects
- this.selectedId = undefined; //holds the id of the active radio button
- this.selectedIndex = undefined; //holds the index of the active radio button
- //timer stuff
- this.timer = new Timer(this); //a Timer instance for calling the functionToCall
- this.timerMs = 200; //a constant of this object that is used in conjunction with the timer - functionToCall is called after 200 ms
- }
- else {
- alert("Error in radiobutton with ("+id+"): wrong nr of arguments! You have to pass over "+nrArguments+" parameters.");
- }
-}
-
-radioButtonGroup.prototype.addCheckBox = function(checkBoxObj) {
- this.checkBoxes.push(checkBoxObj);
- if (checkBoxObj.checkedStatus) {
- this.selectedId = checkBoxObj.id;
- this.selectedIndex = this.checkBoxes.length - 1;
- }
-}
-
-//change radio button selection by id
-radioButtonGroup.prototype.selectById = function(cbId,fireFunction) {
- var found = false;
- for (var i=0;i<this.checkBoxes.length;i++) {
- if (this.checkBoxes[i].id == cbId) {
- this.selectedId = cbId;
- this.selectedIndex = i;
- if (this.checkBoxes[i].checkedStatus == false) {
- this.checkBoxes[i].check(false);
- }
- found = true;
- }
- else {
- this.checkBoxes[i].uncheck(false);
- }
- }
- if (found) {
- if (fireFunction) {
- this.timer.setTimeout("fireFunction",this.timerMs);
- }
- }
- else {
- alert("Error in radiobutton with ("+this.id+"): could not find checkbox with id '"+cbId+"'");
- }
-}
-
-//change radio button selection by label name
-radioButtonGroup.prototype.selectByLabelname = function(labelName,fireFunction) {
- var id = -1;
- for (var i=0;i<this.checkBoxes.length;i++) {
- if (this.checkBoxes[i].labelText == labelName) {
- id = this.checkBoxes[i].id;
- }
- }
- if (id == -1) {
- alert("Error in radiobutton with ("+this.id+"): could not find checkbox with label '"+labelName+"'");
- }
- else {
- this.selectById(id,fireFunction);
- }
-}
-
-radioButtonGroup.prototype.fireFunction = function() {
- if (typeof(this.functionToCall) == "function") {
- this.functionToCall(this.id,this.selectedId,this.checkBoxes[this.selectedIndex].labelText);
- }
- if (typeof(this.functionToCall) == "object") {
- this.functionToCall.radioButtonChanged(this.id,this.selectedId,this.checkBoxes[this.selectedIndex].labelText);
- }
- if (typeof(this.functionToCall) == undefined) {
- return;
- }
-}
\ No newline at end of file
diff -r cbe28b41fb9d -r e945dcdfd578 static/scripts/helper_functions.js
--- a/static/scripts/helper_functions.js Thu Oct 15 10:48:38 2009 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,817 +0,0 @@
-/**
- * @fileoverview
- *
- * ECMAScript <a href="http://www.carto.net/papers/svg/resources/helper_functions.html">helper functions</a>, main purpose is to serve in SVG mapping or other SVG based web applications
- *
- * This ECMA script library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library (http://www.carto.net/papers/svg/resources/lesser_gpl.txt) if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Please report bugs and send improvements to neumann(a)karto.baug.ethz.ch
- * If you use these scripts, please link to the original (http://www.carto.net/papers/svg/resources/helper_functions.html)
- * somewhere in the source-code-comment or the "about" of your project and give credits, thanks!
- *
- * See <a href="js_docs_out/overview-summary-helper_functions.js.html">documentation</a>.
- *
- * @author Andreas Neumann a.neumann(a)carto.net
- * @copyright LGPL 2.1 <a href="http://www.gnu.org/copyleft/lesser.txt">Gnu LGPL 2.1</a>
- * @credits Bruce Rindahl, numerous people on svgdevelopers(a)yahoogroups.com
- */
-
-//global variables necessary to create elements in these namespaces, do not delete them!!!!
-
-/**
- * This variable is a shortcut to the full URL of the SVG namespace
- * @final
- * @type String
- */
-var svgNS = "http://www.w3.org/2000/svg";
-
-/**
- * This variable is a shortcut to the full URL of the XLink namespace
- * @final
- * @type String
- */
-var xlinkNS = "http://www.w3.org/1999/xlink";
-
-/**
- * This variable is a shortcut to the full URL of the attrib namespace
- * @final
- * @type String
- */
-var cartoNS = "http://www.carto.net/attrib";
-
-/**
- * This variable is a alias to the full URL of the attrib namespace
- * @final
- * @type String
- */
-var attribNS = "http://www.carto.net/attrib";
-
-/**
- * This variable is a alias to the full URL of the Batik extension namespace
- * @final
- * @type String
- */
-var batikNS = "http://xml.apache.org/batik/ext";
-
-/**
- * Returns the polar direction from a given vector
- * @param {Number} xdiff the x-part of the vector
- * @param {Number} ydiff the y-part of the vector
- * @return direction the direction in radians
- * @type Number
- * @version 1.0 (2007-04-30)
- * @see #toPolarDist
- * @see #toRectX
- * @see #toRectY
- */
-function toPolarDir(xdiff,ydiff) {
- var direction = (Math.atan2(ydiff,xdiff));
- return(direction);
-}
-
-/**
- * Returns the polar distance from a given vector
- * @param {Number} xdiff the x-part of the vector
- * @param {Number} ydiff the y-part of the vector
- * @return distance the distance
- * @type Number
- * @version 1.0 (2007-04-30)
- * @see #toPolarDir
- * @see #toRectX
- * @see #toRectY
- */
-function toPolarDist(xdiff,ydiff) {
- var distance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
- return(distance);
-}
-
-/**
- * Returns the x-part of a vector from a given direction and distance
- * @param {Number} direction the direction (in radians)
- * @param {Number} distance the distance
- * @return x the x-part of the vector
- * @type Number
- * @version 1.0 (2007-04-30)
- * @see #toPolarDist
- * @see #toPolarDir
- * @see #toRectY
- */
-function toRectX(direction,distance) {
- var x = distance * Math.cos(direction);
- return(x);
-}
-
-/**
- * Returns the y-part of the vector from a given direction and distance
- * @param {Number} direction the direction (in radians)
- * @param {Number} distance the distance
- * @return y the y-part of the vector
- * @type Number
- * @version 1.0 (2007-04-30)
- * @see #toPolarDist
- * @see #toPolarDir
- * @see #toRectX
- */
-function toRectY(direction,distance) {
- y = distance * Math.sin(direction);
- return(y);
-}
-
-/**
- * Converts degrees to radians
- * @param {Number} deg the degree value
- * @return rad the radians value
- * @type Number
- * @version 1.0 (2007-04-30)
- * @see #RadToDeg
- */
-function DegToRad(deg) {
- return (deg / 180.0 * Math.PI);
-}
-
-/**
- * Converts radians to degrees
- * @param {Number} rad the radians value
- * @return deg the degree value
- * @type Number
- * @version 1.0 (2007-04-30)
- * @see #DegToRad
- */
-function RadToDeg(rad) {
- return (rad / Math.PI * 180.0);
-}
-
-/**
- * Converts decimal degrees to degrees, minutes, seconds
- * @param {Number} dd the decimal degree value
- * @return degrees the degree values in the following notation: {deg:degrees,min:minutes,sec:seconds}
- * @type literal
- * @version 1.0 (2007-04-30)
- * @see #dms2dd
- */
-function dd2dms(dd) {
- var minutes = (Math.abs(dd) - Math.floor(Math.abs(dd))) * 60;
- var seconds = (minutes - Math.floor(minutes)) * 60;
- var minutes = Math.floor(minutes);
- if (dd >= 0) {
- var degrees = Math.floor(dd);
- }
- else {
- var degrees = Math.ceil(dd);
- }
- return {deg:degrees,min:minutes,sec:seconds};
-}
-
-/**
- * Converts degrees, minutes and seconds to decimal degrees
- * @param {Number} deg the degree value
- * @param {Number} min the minute value
- * @param {Number} sec the second value
- * @return deg the decimal degree values
- * @type Number
- * @version 1.0 (2007-04-30)
- * @see #dd2dms
- */
-function dms2dd(deg,min,sec) {
- if (deg < 0) {
- return deg - (min / 60) - (sec / 3600);
- }
- else {
- return deg + (min / 60) + (sec / 3600);
- }
-}
-
-/**
- * log function, missing in the standard Math object
- * @param {Number} x the value where the log function should be applied to
- * @param {Number} b the base value for the log function
- * @return logResult the result of the log function
- * @type Number
- * @version 1.0 (2007-04-30)
- */
-function log(x,b) {
- if(b==null) b=Math.E;
- return Math.log(x)/Math.log(b);
-}
-
-/**
- * interpolates a value (e.g. elevation) bilinearly based on the position within a cell with 4 corner values
- * @param {Number} za the value at the upper left corner of the cell
- * @param {Number} zb the value at the upper right corner of the cell
- * @param {Number} zc the value at the lower right corner of the cell
- * @param {Number} zd the value at the lower left corner of the cell
- * @param {Number} xpos the x position of the point where a new value should be interpolated
- * @param {Number} ypos the y position of the point where a new value should be interpolated
- * @param {Number} ax the x position of the lower left corner of the cell
- * @param {Number} ay the y position of the lower left corner of the cell
- * @param {Number} cellsize the size of the cell
- * @return interpol_value the result of the bilinear interpolation function
- * @type Number
- * @version 1.0 (2007-04-30)
- */
-function intBilinear(za,zb,zc,zd,xpos,ypos,ax,ay,cellsize) { //bilinear interpolation function
- var e = (xpos - ax) / cellsize;
- var f = (ypos - ay) / cellsize;
-
- //calculation of weights
- var wa = (1 - e) * (1 - f);
- var wb = e * (1 - f);
- var wc = e * f;
- var wd = f * (1 - e);
-
- var interpol_value = wa * zc + wb * zd + wc * za + wd * zb;
- return interpol_value;
-}
-
-/**
- * tests if a given point is left or right of a given line
- * @param {Number} pointx the x position of the given point
- * @param {Number} pointy the y position of the given point
- * @param {Number} linex1 the x position of line's start point
- * @param {Number} liney1 the y position of line's start point
- * @param {Number} linex2 the x position of line's end point
- * @param {Number} liney2 the y position of line's end point
- * @return leftof the result of the leftOfTest, 1 means leftOf, 0 means rightOf
- * @type Number (integer, 0|1)
- * @version 1.0 (2007-04-30)
- */
-function leftOfTest(pointx,pointy,linex1,liney1,linex2,liney2) {
- var result = (liney1 - pointy) * (linex2 - linex1) - (linex1 - pointx) * (liney2 - liney1);
- if (result < 0) {
- var leftof = 1; //case left of
- }
- else {
- var leftof = 0; //case left of
- }
- return leftof;
-}
-
-/**
- * calculates the distance between a given point and a given line
- * @param {Number} pointx the x position of the given point
- * @param {Number} pointy the y position of the given point
- * @param {Number} linex1 the x position of line's start point
- * @param {Number} liney1 the y position of line's start point
- * @param {Number} linex2 the x position of line's end point
- * @param {Number} liney2 the y position of line's end point
- * @return distance the result of the leftOfTest, 1 means leftOf, 0 means rightOf
- * @type Number
- * @version 1.0 (2007-04-30)
- */
-function distFromLine(xpoint,ypoint,linex1,liney1,linex2,liney2) {
- var dx = linex2 - linex1;
- var dy = liney2 - liney1;
- var distance = (dy * (xpoint - linex1) - dx * (ypoint - liney1)) / Math.sqrt(Math.pow(dx,2) + Math.pow(dy,2));
- return distance;
-}
-
-/**
- * calculates the angle between two vectors (lines)
- * @param {Number} ax the x part of vector a
- * @param {Number} ay the y part of vector a
- * @param {Number} bx the x part of vector b
- * @param {Number} by the y part of vector b
- * @return angle the angle in radians
- * @type Number
- * @version 1.0 (2007-04-30)
- * @credits <a href="http://www.mathe-online.at/mathint/vect2/i.html#Winkel">Mathe Online (Winkel)</a>
- */
-function angleBetwTwoLines(ax,ay,bx,by) {
- var angle = Math.acos((ax * bx + ay * by) / (Math.sqrt(Math.pow(ax,2) + Math.pow(ay,2)) * Math.sqrt(Math.pow(bx,2) + Math.pow(by,2))));
- return angle;
-}
-
-/**
- * calculates the bisector vector for two given vectors
- * @param {Number} ax the x part of vector a
- * @param {Number} ay the y part of vector a
- * @param {Number} bx the x part of vector b
- * @param {Number} by the y part of vector b
- * @return c the resulting vector as an Array, c[0] is the x part of the vector, c[1] is the y part
- * @type Array
- * @version 1.0 (2007-04-30)
- * @credits <a href="http://www.mathe-online.at/mathint/vect1/i.html#Winkelsymmetrale">Mathe Online (Winkelsymmetrale)</a>
- * see #calcBisectorAngle
- * */
-function calcBisectorVector(ax,ay,bx,by) {
- var betraga = Math.sqrt(Math.pow(ax,2) + Math.pow(ay,2));
- var betragb = Math.sqrt(Math.pow(bx,2) + Math.pow(by,2));
- var c = new Array();
- c[0] = ax / betraga + bx / betragb;
- c[1] = ay / betraga + by / betragb;
- return c;
-}
-
-/**
- * calculates the bisector angle for two given vectors
- * @param {Number} ax the x part of vector a
- * @param {Number} ay the y part of vector a
- * @param {Number} bx the x part of vector b
- * @param {Number} by the y part of vector b
- * @return angle the bisector angle in radians
- * @type Number
- * @version 1.0 (2007-04-30)
- * @credits <a href="http://www.mathe-online.at/mathint/vect1/i.html#Winkelsymmetrale">Mathe Online (Winkelsymmetrale)</a>
- * see #calcBisectorVector
- * */
-function calcBisectorAngle(ax,ay,bx,by) {
- var betraga = Math.sqrt(Math.pow(ax,2) + Math.pow(ay,2));
- var betragb = Math.sqrt(Math.pow(bx,2) + Math.pow(by,2));
- var c1 = ax / betraga + bx / betragb;
- var c2 = ay / betraga + by / betragb;
- var angle = toPolarDir(c1,c2);
- return angle;
-}
-
-/**
- * calculates the intersection point of two given lines
- * @param {Number} line1x1 the x the start point of line 1
- * @param {Number} line1y1 the y the start point of line 1
- * @param {Number} line1x2 the x the end point of line 1
- * @param {Number} line1y2 the y the end point of line 1
- * @return interSectPoint the intersection point, interSectPoint.x contains x-part, interSectPoint.y the y-part of the resulting coordinate
- * @type Object
- * @version 1.0 (2007-04-30)
- * @credits <a href="http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/">P. Bourke</a>
- */
-function intersect2lines(line1x1,line1y1,line1x2,line1y2,line2x1,line2y1,line2x2,line2y2) {
- var interSectPoint = new Object();
- var denominator = (line2y2 - line2y1)*(line1x2 - line1x1) - (line2x2 - line2x1)*(line1y2 - line1y1);
- if (denominator == 0) {
- alert("lines are parallel");
- }
- else {
- var ua = ((line2x2 - line2x1)*(line1y1 - line2y1) - (line2y2 - line2y1)*(line1x1 - line2x1)) / denominator;
- var ub = ((line1x2 - line1x1)*(line1y1 - line2y1) - (line1y2 - line1y1)*(line1x1 - line2x1)) / denominator;
- }
- interSectPoint["x"] = line1x1 + ua * (line1x2 - line1x1);
- interSectPoint["y"] = line1y1 + ua * (line1y2 - line1y1);
- return interSectPoint;
-}
-
-/**
- * reformats a given number to a string by adding separators at every third digit
- * @param {String|Number} inputNumber the input number, can be of type number or string
- * @param {String} separator the separator, e.g. ' or ,
- * @return newString the intersection point, interSectPoint.x contains x-part, interSectPoint.y the y-part of the resulting coordinate
- * @type String
- * @version 1.0 (2007-04-30)
- */
-function formatNumberString(inputNumber,separator) {
- //check if of type string, if number, convert it to string
- if (typeof(inputNumber) == "Number") {
- var myTempString = inputNumber.toString();
- }
- else {
- var myTempString = inputNumber;
- }
- var newString="";
- //if it contains a comma, it will be split
- var splitResults = myTempString.split(".");
- var myCounter = splitResults[0].length;
- if (myCounter > 3) {
- while(myCounter > 0) {
- if (myCounter > 3) {
- newString = separator + splitResults[0].substr(myCounter - 3,3) + newString;
- }
- else {
- newString = splitResults[0].substr(0,myCounter) + newString;
- }
- myCounter -= 3;
- }
- }
- else {
- newString = splitResults[0];
- }
- //concatenate if it contains a comma
- if (splitResults[1]) {
- newString = newString + "." + splitResults[1];
- }
- return newString;
-}
-
-/**
- * writes a status text message out to a SVG text element's first child
- * @param {String} statusText the text message to be displayed
- * @version 1.0 (2007-04-30)
- */
- function statusChange(statusText) {
- document.getElementById("statusText").firstChild.nodeValue = "Statusbar: " + statusText;
-}
-
-/**
- * scales an SVG element, requires that the element has an x and y attribute (e.g. circle, ellipse, use element, etc.)
- * @param {dom::Event} evt the evt object that triggered the scaling
- * @param {Number} factor the scaling factor
- * @version 1.0 (2007-04-30)
- */
-function scaleObject(evt,factor) {
- //reference to the currently selected object
- var element = evt.currentTarget;
- var myX = element.getAttributeNS(null,"x");
- var myY = element.getAttributeNS(null,"y");
- var newtransform = "scale(" + factor + ") translate(" + (myX * 1 / factor - myX) + " " + (myY * 1 / factor - myY) +")";
- element.setAttributeNS(null,'transform', newtransform);
-}
-
-/**
- * returns the transformation matrix (ctm) for the given node up to the root element
- * the basic use case is to provide a wrapper function for the missing SVGLocatable.getTransformToElement method (missing in ASV3)
- * @param {svg::SVGTransformable} node the node reference for the SVGElement the ctm is queried
- * @return CTM the current transformation matrix from the given node to the root element
- * @type svg::SVGMatrix
- * @version 1.0 (2007-05-01)
- * @credits <a href="http://www.kevlindev.com/tutorials/basics/transformations/toUserSpace/index…">Kevin Lindsey (toUserSpace)</a>
- * @see #getTransformToElement
- */
-function getTransformToRootElement(node) {
- try {
- //this part is for fully conformant players (like Opera, Batik, Firefox, Safari ...)
- var CTM = node.getTransformToElement(document.documentElement);
- }
- catch (ex) {
- //this part is for ASV3 or other non-conformant players
- // Initialize our CTM the node's Current Transformation Matrix
- var CTM = node.getCTM();
- // Work our way through the ancestor nodes stopping at the SVG Document
- while ( ( node = node.parentNode ) != document ) {
- // Multiply the new CTM to the one with what we have accumulated so far
- CTM = node.getCTM().multiply(CTM);
- }
- }
- return CTM;
-}
-
-/**
- * returns the transformation matrix (ctm) for the given dom::Node up to a different dom::Node
- * the basic use case is to provide a wrapper function for the missing SVGLocatable.getTransformToElement method (missing in ASV3)
- * @param {svg::SVGTransformable} node the node reference for the element the where the ctm should be calculated from
- * @param {svg::SVGTransformable} targetNode the target node reference for the element the ctm should be calculated to
- * @return CTM the current transformation matrix from the given node to the target element
- * @type svg::SVGMatrix
- * @version 1.0 (2007-05-01)
- * @credits <a href="http://www.kevlindev.com/tutorials/basics/transformations/toUserSpace/index…">Kevin Lindsey (toUserSpace)</a>
- * @see #getTransformToRootElement
- */
-function getTransformToElement(node,targetNode) {
- try {
- //this part is for fully conformant players
- var CTM = node.getTransformToElement(targetNode);
- }
- catch (ex) {
- //this part is for ASV3 or other non-conformant players
- // Initialize our CTM the node's Current Transformation Matrix
- var CTM = node.getCTM();
- // Work our way through the ancestor nodes stopping at the SVG Document
- while ( ( node = node.parentNode ) != targetNode ) {
- // Multiply the new CTM to the one with what we have accumulated so far
- CTM = node.getCTM().multiply(CTM);
- }
- }
- return CTM;
-}
-
-/**
- * converts HSV to RGB values
- * @param {Number} hue the hue value (between 0 and 360)
- * @param {Number} sat the saturation value (between 0 and 1)
- * @param {Number} val the value value (between 0 and 1)
- * @return rgbArr the rgb values (associative array or object, the keys are: red,green,blue), all values are scaled between 0 and 255
- * @type Object
- * @version 1.0 (2007-05-01)
- * @see #rgb2hsv
- */
-function hsv2rgb(hue,sat,val) {
- var rgbArr = new Object();
- if ( sat == 0) {
- rgbArr["red"] = Math.round(val * 255);
- rgbArr["green"] = Math.round(val * 255);
- rgbArr["blue"] = Math.round(val * 255);
- }
- else {
- var h = hue / 60;
- var i = Math.floor(h);
- var f = h - i;
- if (i % 2 == 0) {
- f = 1 - f;
- }
- var m = val * (1 - sat);
- var n = val * (1 - sat * f);
- switch(i) {
- case 0:
- rgbArr["red"] = val;
- rgbArr["green"] = n;
- rgbArr["blue"] = m;
- break;
- case 1:
- rgbArr["red"] = n;
- rgbArr["green"] = val;
- rgbArr["blue"] = m;
- break;
- case 2:
- rgbArr["red"] = m;
- rgbArr["green"] = val;
- rgbArr["blue"] = n;
- break;
- case 3:
- rgbArr["red"] = m;
- rgbArr["green"] = n;
- rgbArr["blue"] = val;
- break;
- case 4:
- rgbArr["red"] = n;
- rgbArr["green"] = m;
- rgbArr["blue"] = val;
- break;
- case 5:
- rgbArr["red"] = val;
- rgbArr["green"] = m;
- rgbArr["blue"] = n;
- break;
- case 6:
- rgbArr["red"] = val;
- rgbArr["green"] = n;
- rgbArr["blue"] = m;
- break;
- }
- rgbArr["red"] = Math.round(rgbArr["red"] * 255);
- rgbArr["green"] = Math.round(rgbArr["green"] * 255);
- rgbArr["blue"] = Math.round(rgbArr["blue"] * 255);
- }
- return rgbArr;
-}
-
-/**
- * converts RGB to HSV values
- * @param {Number} red the hue value (between 0 and 255)
- * @param {Number} green the saturation value (between 0 and 255)
- * @param {Number} blue the value value (between 0 and 255)
- * @return hsvArr the hsv values (associative array or object, the keys are: hue (0-360),sat (0-1),val (0-1))
- * @type Object
- * @version 1.0 (2007-05-01)
- * @see #hsv2rgb
- */
-function rgb2hsv(red,green,blue) {
- var hsvArr = new Object();
- red = red / 255;
- green = green / 255;
- blue = blue / 255;
- myMax = Math.max(red, Math.max(green,blue));
- myMin = Math.min(red, Math.min(green,blue));
- v = myMax;
- if (myMax > 0) {
- s = (myMax - myMin) / myMax;
- }
- else {
- s = 0;
- }
- if (s > 0) {
- myDiff = myMax - myMin;
- rc = (myMax - red) / myDiff;
- gc = (myMax - green) / myDiff;
- bc = (myMax - blue) / myDiff;
- if (red == myMax) {
- h = (bc - gc) / 6;
- }
- if (green == myMax) {
- h = (2 + rc - bc) / 6;
- }
- if (blue == myMax) {
- h = (4 + gc - rc) / 6;
- }
- }
- else {
- h = 0;
- }
- if (h < 0) {
- h += 1;
- }
- hsvArr["hue"] = Math.round(h * 360);
- hsvArr["sat"] = s;
- hsvArr["val"] = v;
- return hsvArr;
-}
-
-/**
- * populates an array such that it can be addressed by both a key or an index nr,
- * note that both Arrays need to be of the same length
- * @param {Array} arrayKeys the array containing the keys
- * @param {Array} arrayValues the array containing the values
- * @return returnArray the resulting array containing both associative values and also a regular indexed array
- * @type Array
- * @version 1.0 (2007-05-01)
- */
-function arrayPopulate(arrayKeys,arrayValues) {
- var returnArray = new Array();
- if (arrayKeys.length != arrayValues.length) {
- alert("error: arrays do not have the same length!");
- }
- else {
- for (i=0;i<arrayKeys.length;i++) {
- returnArray[arrayKeys[i]] = arrayValues[i];
- }
- }
- return returnArray;
-}
-
-/**
- * Wrapper object for network requests, uses getURL or XMLHttpRequest depending on availability
- * The callBackFunction receives a XML or text node representing the rootElement
- * of the fragment received or the return text, depending on the returnFormat.
- * See also the following <a href="http://www.carto.net/papers/svg/network_requests/">documentation</a>.
- * @class this is a wrapper object to provide network request functionality (get|post)
- * @param {String} url the URL/IRI of the network resource to be called
- * @param {Function|Object} callBackFunction the callBack function or object that is called after the data was received, in case of an object, the method 'receiveData' is called; both the function and the object's 'receiveData' method get 2 return parameters: 'node.firstChild'|text (the root element of the XML or text resource), this.additionalParams (if defined)
- * @param {String} returnFormat the return format, either 'xml' or 'json' (or text)
- * @param {String} method the method of the network request, either 'get' or 'post'
- * @param {String|Undefined} postText the String containing the post text (optional) or Undefined (if not a 'post' request)
- * @param {Object|Array|String|Number|Undefined} additionalParams additional parameters that will be passed to the callBackFunction or object (optional) or Undefined
- * @return a new getData instance
- * @type getData
- * @constructor
- * @version 1.0 (2007-02-23)
- */
-function getData(url,callBackFunction,returnFormat,method,postText,additionalParams) {
- this.url = url;
- this.callBackFunction = callBackFunction;
- this.returnFormat = returnFormat;
- this.method = method;
- this.additionalParams = additionalParams;
- if (method != "get" && method != "post") {
- alert("Error in network request: parameter 'method' must be 'get' or 'post'");
- }
- this.postText = postText;
- this.xmlRequest = null; //@private reference to the XMLHttpRequest object
-}
-
-/**
- * triggers the network request defined in the constructor
- */
-getData.prototype.getData = function() {
- //call getURL() if available
- if (window.getURL) {
- if (this.method == "get") {
- getURL(this.url,this);
- }
- if (this.method == "post") {
- postURL(this.url,this.postText,this);
- }
- }
- //or call XMLHttpRequest() if available
- else if (window.XMLHttpRequest) {
- var _this = this;
- this.xmlRequest = new XMLHttpRequest();
- if (this.method == "get") {
- if (this.returnFormat == "xml") {
- this.xmlRequest.overrideMimeType("text/xml");
- }
- this.xmlRequest.open("GET",this.url,true);
- }
- if (this.method == "post") {
- this.xmlRequest.open("POST",this.url,true);
- }
- this.xmlRequest.onreadystatechange = function() {_this.handleEvent()};
- if (this.method == "get") {
- this.xmlRequest.send(null);
- }
- if (this.method == "post") {
- //test if postText exists and is of type string
- var reallyPost = true;
- if (!this.postText) {
- reallyPost = false;
- alert("Error in network post request: missing parameter 'postText'!");
- }
- if (typeof(this.postText) != "string") {
- reallyPost = false;
- alert("Error in network post request: parameter 'postText' has to be of type 'string')");
- }
- if (reallyPost) {
- this.xmlRequest.send(this.postText);
- }
- }
- }
- //write an error message if neither method is available
- else {
- alert("your browser/svg viewer neither supports window.getURL nor window.XMLHttpRequest!");
- }
-}
-
-/**
- * this is the callback method for the getURL() or postURL() case
- * @private
- */
-getData.prototype.operationComplete = function(data) {
- //check if data has a success property
- if (data.success) {
- //parse content of the XML format to the variable "node"
- if (this.returnFormat == "xml") {
- //convert the text information to an XML node and get the first child
- var node = parseXML(data.content,document);
- //distinguish between a callback function and an object
- if (typeof(this.callBackFunction) == "function") {
- this.callBackFunction(node.firstChild,this.additionalParams);
- }
- if (typeof(this.callBackFunction) == "object") {
- this.callBackFunction.receiveData(node.firstChild,this.additionalParams);
- }
- }
- if (this.returnFormat == "json") {
- if (typeof(this.callBackFunction) == "function") {
- this.callBackFunction(data.content,this.additionalParams);
- }
- if (typeof(this.callBackFunction) == "object") {
- this.callBackFunction.receiveData(data.content,this.additionalParams);
- }
- }
- }
- else {
- alert("something went wrong with dynamic loading of geometry!");
- }
-}
-
-/**
- * this is the callback method for the XMLHttpRequest case
- * @private
- */
-getData.prototype.handleEvent = function() {
- if (this.xmlRequest.readyState == 4) {
- if (this.returnFormat == "xml") {
- //we need to import the XML node first
- var importedNode = document.importNode(this.xmlRequest.responseXML.documentElement,true);
- if (typeof(this.callBackFunction) == "function") {
- this.callBackFunction(importedNode,this.additionalParams);
- }
- if (typeof(this.callBackFunction) == "object") {
- this.callBackFunction.receiveData(importedNode,this.additionalParams);
- }
- }
- if (this.returnFormat == "json") {
- if (typeof(this.callBackFunction) == "function") {
- this.callBackFunction(this.xmlRequest.responseText,this.additionalParams);
- }
- if (typeof(this.callBackFunction) == "object") {
- this.callBackFunction.receiveData(this.xmlRequest.responseText,this.additionalParams);
- }
- }
- }
-}
-
-/**
- * Serializes an XML node and returns a string representation. Wrapper function to hide implementation differences.
- * This can be used for debugging purposes or to post data to a server or network resource.
- * @param {dom::Node} node the DOM node reference
- * @return textRepresentation the String representation of the XML node
- * @type String
- * @version 1.0 (2007-05-01)
- * @see getData
- */
-function serializeNode(node) {
- if (typeof XMLSerializer != 'undefined') {
- return new XMLSerializer().serializeToString(node);
- }
- else if (typeof node.xml != 'undefined') {
- return node.xml;
- }
- else if (typeof printNode != 'undefined') {
- return printNode(node);
- }
- else if (typeof Packages != 'undefined') {
- try {
- var stringWriter = new java.io.StringWriter();
- Packages.org.apache.batik.dom.util.DOMUtilities.writeNode(node,stringWriter);
- return stringWriter.toString();
- }
- catch (e) {
- alert("Sorry, your SVG viewer does not support the printNode/serialize function.");
- return '';
- }
- }
- else {
- alert("Sorry, your SVG viewer does not support the printNode/serialize function.");
- return '';
- }
-}
-
-/**
- * Starts a SMIL animation element with the given id by triggering the '.beginElement()' method.
- * This is a convenience (shortcut) function.
- * @param {String} id a valid id of a valid SMIL animation element
- * @version 1.0 (2007-05-01)
- */
-//starts an animtion with the given id
-//this function is useful in combination with window.setTimeout()
-function startAnimation(id) {
- document.getElementById(id).beginElement();
-}
diff -r cbe28b41fb9d -r e945dcdfd578 static/scripts/timer.js
--- a/static/scripts/timer.js Thu Oct 15 10:48:38 2009 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-// source/credits: "Algorithm": http://www.codingforums.com/showthread.php?s=&threadid=10531
-// The constructor should be called with
-// the parent object (optional, defaults to window).
-
-function Timer(){
- this.obj = (arguments.length)?arguments[0]:window;
- return this;
-}
-
-// The set functions should be called with:
-// - The name of the object method (as a string) (required)
-// - The millisecond delay (required)
-// - Any number of extra arguments, which will all be
-// passed to the method when it is evaluated.
-
-Timer.prototype.setInterval = function(func, msec){
- var i = Timer.getNew();
- var t = Timer.buildCall(this.obj, i, arguments);
- Timer.set[i].timer = window.setInterval(t,msec);
- return i;
-}
-Timer.prototype.setTimeout = function(func, msec){
- var i = Timer.getNew();
- Timer.buildCall(this.obj, i, arguments);
- Timer.set[i].timer = window.setTimeout("Timer.callOnce("+i+");",msec);
- return i;
-}
-
-// The clear functions should be called with
-// the return value from the equivalent set function.
-
-Timer.prototype.clearInterval = function(i){
- if(!Timer.set[i]) return;
- window.clearInterval(Timer.set[i].timer);
- Timer.set[i] = null;
-}
-Timer.prototype.clearTimeout = function(i){
- if(!Timer.set[i]) return;
- window.clearTimeout(Timer.set[i].timer);
- Timer.set[i] = null;
-}
-
-// Private data
-
-Timer.set = new Array();
-Timer.buildCall = function(obj, i, args){
- var t = "";
- Timer.set[i] = new Array();
- if(obj != window){
- Timer.set[i].obj = obj;
- t = "Timer.set["+i+"].obj.";
- }
- t += args[0]+"(";
- if(args.length > 2){
- Timer.set[i][0] = args[2];
- t += "Timer.set["+i+"][0]";
- for(var j=1; (j+2)<args.length; j++){
- Timer.set[i][j] = args[j+2];
- t += ", Timer.set["+i+"]["+j+"]";
- }}
- t += ");";
- Timer.set[i].call = t;
- return t;
-}
-Timer.callOnce = function(i){
- if(!Timer.set[i]) return;
- eval(Timer.set[i].call);
- Timer.set[i] = null;
-}
-Timer.getNew = function(){
- var i = 0;
- while(Timer.set[i]) i++;
- return i;
-}
\ No newline at end of file
diff -r cbe28b41fb9d -r e945dcdfd578 static/scripts/tools/rgenetics/checkbox_and_radiobutton.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/tools/rgenetics/checkbox_and_radiobutton.js Thu Oct 15 19:01:07 2009 -0400
@@ -0,0 +1,1 @@
+function checkBox(d,g,m,j,n,l,c,f,k,b,h,o,a){var e=13;var i=true;if(arguments.length==e){this.id=d;this.parentNode=g;this.x=m;this.y=j;this.checkboxId=n;this.checkcrossId=l;this.checkedStatus=c;this.labelText=f;this.textStyles=k;if(!this.textStyles["font-size"]){this.textStyles["font-size"]=12}this.labelDistance=b;this.labelYOffset=h;this.radioButtonGroup=o;this.functionToCall=a;this.exists=true;this.label=undefined}else{i=false;alert("Error in checkbox ("+d+"): wrong nr of arguments! You have to pass over "+e+" parameters.")}if(i){this.timer=new Timer(this);if(this.radioButtonGroup){this.timerMs=0}else{this.timerMs=200}this.createCheckBox()}else{alert("Could not create checkbox with id '"+d+"' due to errors in the constructor parameters")}}checkBox.prototype.createCheckBox=function(){if(typeof(this.parentNode)=="string"){this.parentNode=document.getElementById(this.parentNode)}this.checkBox=document.createElementNS(svgNS,"use");this.checkBox.setAttributeNS(null,"x",this.x);
this.checkBox.setAttributeNS(null,"y",this.y);this.checkBox.setAttributeNS(xlinkNS,"href","#"+this.checkboxId);this.checkBox.addEventListener("click",this,false);this.checkBox.setAttributeNS(null,"cursor","pointer");this.parentNode.appendChild(this.checkBox);this.checkCross=document.createElementNS(svgNS,"use");this.checkCross.setAttributeNS(null,"x",this.x);this.checkCross.setAttributeNS(null,"y",this.y);this.checkCross.setAttributeNS(xlinkNS,"href","#"+this.checkcrossId);this.parentNode.appendChild(this.checkCross);if(this.checkedStatus==false){this.checkCross.setAttributeNS(null,"display","none")}if(this.labelText){if(this.labelText.length>0){this.label=document.createElementNS(svgNS,"text");for(var b in this.textStyles){var a=this.textStyles[b];if(b=="font-size"){a+="px"}this.label.setAttributeNS(null,b,a)}this.label.setAttributeNS(null,"x",(this.x+this.labelDistance));this.label.setAttributeNS(null,"y",(this.y+this.labelYOffset));this.label.setAttributeNS(null,"cursor",
"pointer");var c=document.createTextNode(this.labelText);this.label.appendChild(c);this.label.setAttributeNS(null,"pointer-events","all");this.label.addEventListener("click",this,false);this.parentNode.appendChild(this.label)}}if(this.radioButtonGroup){this.radioButtonGroup.addCheckBox(this)}};checkBox.prototype.handleEvent=function(a){if(a.type=="click"){if(this.checkedStatus==true){this.checkCross.setAttributeNS(null,"display","none");this.checkedStatus=false}else{this.checkCross.setAttributeNS(null,"display","inline");this.checkedStatus=true}}this.timer.setTimeout("fireFunction",this.timerMs)};checkBox.prototype.fireFunction=function(){if(this.radioButtonGroup){this.radioButtonGroup.selectById(this.id,true)}else{if(typeof(this.functionToCall)=="function"){this.functionToCall(this.id,this.checkedStatus,this.labelText)}if(typeof(this.functionToCall)=="object"){this.functionToCall.checkBoxChanged(this.id,this.checkedStatus,this.labelText)}if(typeof(this.functionToCall)==unde
fined){return}}};checkBox.prototype.check=function(a){this.checkCross.setAttributeNS(null,"display","inherit");this.checkedStatus=true;if(a){this.timer.setTimeout("fireFunction",this.timerMs)}};checkBox.prototype.uncheck=function(a){this.checkCross.setAttributeNS(null,"display","none");this.checkedStatus=false;if(a){this.timer.setTimeout("fireFunction",this.timerMs)}};checkBox.prototype.moveTo=function(b,a){this.x=b;this.y=a;this.checkBox.setAttributeNS(null,"x",this.x);this.checkBox.setAttributeNS(null,"y",this.y);this.checkCross.setAttributeNS(null,"x",this.x);this.checkCross.setAttributeNS(null,"y",this.y);if(this.labelText){this.label.setAttributeNS(null,"x",(this.x+this.labelDistance));this.label.setAttributeNS(null,"y",(this.y+this.labelYOffset))}};checkBox.prototype.remove=function(a){this.checkBox.removeEventListener("click",this,false);this.parentNode.removeChild(this.checkBox);this.parentNode.removeChild(this.checkCross);if(this.label){this.parentNode.removeChild(t
his.label)}this.exists=false};checkBox.prototype.setLabelText=function(a){this.labelText=a;if(this.label){this.label.firstChild.nodeValue=a}else{if(this.labelText.length>0){this.label=document.createElementNS(svgNS,"text");for(var b in this.textStyles){value=this.textStyles[b];if(b=="font-size"){value+="px"}this.label.setAttributeNS(null,b,value)}this.label.setAttributeNS(null,"x",(this.x+this.labelDistance));this.label.setAttributeNS(null,"y",(this.y+this.textStyles["font-size"]*0.3));var c=document.createTextNode(this.labelText);this.label.appendChild(c);this.parentNode.appendChild(this.label)}}};function radioButtonGroup(c,a){var b=2;if(arguments.length==b){this.id=c;if(typeof(a)=="function"||typeof(a)=="object"||typeof(a)==undefined){this.functionToCall=a}else{alert("Error in radiobutton with ("+c+"): argument functionToCall is not of type 'function', 'object' or undefined!")}this.checkBoxes=new Array();this.selectedId=undefined;this.selectedIndex=undefined;this.timer=ne
w Timer(this);this.timerMs=200}else{alert("Error in radiobutton with ("+c+"): wrong nr of arguments! You have to pass over "+b+" parameters.")}}radioButtonGroup.prototype.addCheckBox=function(a){this.checkBoxes.push(a);if(a.checkedStatus){this.selectedId=a.id;this.selectedIndex=this.checkBoxes.length-1}};radioButtonGroup.prototype.selectById=function(c,a){var d=false;for(var b=0;b<this.checkBoxes.length;b++){if(this.checkBoxes[b].id==c){this.selectedId=c;this.selectedIndex=b;if(this.checkBoxes[b].checkedStatus==false){this.checkBoxes[b].check(false)}d=true}else{this.checkBoxes[b].uncheck(false)}}if(d){if(a){this.timer.setTimeout("fireFunction",this.timerMs)}}else{alert("Error in radiobutton with ("+this.id+"): could not find checkbox with id '"+c+"'")}};radioButtonGroup.prototype.selectByLabelname=function(a,b){var d=-1;for(var c=0;c<this.checkBoxes.length;c++){if(this.checkBoxes[c].labelText==a){d=this.checkBoxes[c].id}}if(d==-1){alert("Error in radiobutton with ("+this.id+
"): could not find checkbox with label '"+a+"'")}else{this.selectById(d,b)}};radioButtonGroup.prototype.fireFunction=function(){if(typeof(this.functionToCall)=="function"){this.functionToCall(this.id,this.selectedId,this.checkBoxes[this.selectedIndex].labelText)}if(typeof(this.functionToCall)=="object"){this.functionToCall.radioButtonChanged(this.id,this.selectedId,this.checkBoxes[this.selectedIndex].labelText)}if(typeof(this.functionToCall)==undefined){return}};
\ No newline at end of file
diff -r cbe28b41fb9d -r e945dcdfd578 static/scripts/tools/rgenetics/helper_functions.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/tools/rgenetics/helper_functions.js Thu Oct 15 19:01:07 2009 -0400
@@ -0,0 +1,1 @@
+var svgNS="http://www.w3.org/2000/svg";var xlinkNS="http://www.w3.org/1999/xlink";var cartoNS="http://www.carto.net/attrib";var attribNS="http://www.carto.net/attrib";var batikNS="http://xml.apache.org/batik/ext";function toPolarDir(a,c){var b=(Math.atan2(c,a));return(b)}function toPolarDist(a,b){var c=Math.sqrt(a*a+b*b);return(c)}function toRectX(b,c){var a=c*Math.cos(b);return(a)}function toRectY(a,b){y=b*Math.sin(a);return(y)}function DegToRad(a){return(a/180*Math.PI)}function RadToDeg(a){return(a/Math.PI*180)}function dd2dms(a){var b=(Math.abs(a)-Math.floor(Math.abs(a)))*60;var d=(b-Math.floor(b))*60;var b=Math.floor(b);if(a>=0){var c=Math.floor(a)}else{var c=Math.ceil(a)}return{deg:c,min:b,sec:d}}function dms2dd(c,a,b){if(c<0){return c-(a/60)-(b/3600)}else{return c+(a/60)+(b/3600)}}function log(c,a){if(a==null){a=Math.E}return Math.log(c)/Math.log(a)}function intBilinear(m,k,g,c,o,b,a,u,t){var q=(o-a)/t;var p=(b-u)/t;var n=(1-q)*(1-p);var l=q*(1-p);var j=q*p;var d=p*(1-
q);var r=n*g+l*c+j*m+d*k;return r}function leftOfTest(b,j,d,g,c,f){var a=(g-j)*(c-d)-(d-b)*(f-g);if(a<0){var e=1}else{var e=0}return e}function distFromLine(e,f,d,a,c,j){var k=c-d;var g=j-a;var b=(g*(e-d)-k*(f-a))/Math.sqrt(Math.pow(k,2)+Math.pow(g,2));return b}function angleBetwTwoLines(b,a,e,c){var d=Math.acos((b*e+a*c)/(Math.sqrt(Math.pow(b,2)+Math.pow(a,2))*Math.sqrt(Math.pow(e,2)+Math.pow(c,2))));return d}function calcBisectorVector(b,a,g,e){var f=Math.sqrt(Math.pow(b,2)+Math.pow(a,2));var d=Math.sqrt(Math.pow(g,2)+Math.pow(e,2));var j=new Array();j[0]=b/f+g/d;j[1]=a/f+e/d;return j}function calcBisectorAngle(a,k,j,g){var c=Math.sqrt(Math.pow(a,2)+Math.pow(k,2));var b=Math.sqrt(Math.pow(j,2)+Math.pow(g,2));var f=a/c+j/b;var e=k/c+g/b;var d=toPolarDir(f,e);return d}function intersect2lines(l,f,k,e,n,j,m,g){var c=new Object();var d=(g-j)*(k-l)-(m-n)*(e-f);if(d==0){alert("lines are parallel")}else{var b=((m-n)*(f-j)-(g-j)*(l-n))/d;var a=((k-l)*(f-j)-(e-f)*(l-n))/d}c.x=l+b*(
k-l);c.y=f+b*(e-f);return c}function formatNumberString(a,e){if(typeof(a)=="Number"){var c=a.toString()}else{var c=a}var b="";var d=c.split(".");var f=d[0].length;if(f>3){while(f>0){if(f>3){b=e+d[0].substr(f-3,3)+b}else{b=d[0].substr(0,f)+b}f-=3}}else{b=d[0]}if(d[1]){b=b+"."+d[1]}return b}function statusChange(a){document.getElementById("statusText").firstChild.nodeValue="Statusbar: "+a}function scaleObject(a,e){var d=a.currentTarget;var c=d.getAttributeNS(null,"x");var b=d.getAttributeNS(null,"y");var f="scale("+e+") translate("+(c*1/e-c)+" "+(b*1/e-b)+")";d.setAttributeNS(null,"transform",f)}function getTransformToRootElement(b){try{var c=b.getTransformToElement(document.documentElement)}catch(a){var c=b.getCTM();while((b=b.parentNode)!=document){c=b.getCTM().multiply(c)}}return c}function getTransformToElement(b,c){try{var d=b.getTransformToElement(c)}catch(a){var d=b.getCTM();while((b=b.parentNode)!=c){d=b.getCTM().multiply(d)}}return d}function hsv2rgb(j,c,b){var l=new
Object();if(c==0){l.red=Math.round(b*255);l.green=Math.round(b*255);l.blue=Math.round(b*255)}else{var g=j/60;var e=Math.floor(g);var k=g-e;if(e%2==0){k=1-k}var d=b*(1-c);var a=b*(1-c*k);switch(e){case 0:l.red=b;l.green=a;l.blue=d;break;case 1:l.red=a;l.green=b;l.blue=d;break;case 2:l.red=d;l.green=b;l.blue=a;break;case 3:l.red=d;l.green=a;l.blue=b;break;case 4:l.red=a;l.green=d;l.blue=b;break;case 5:l.red=b;l.green=d;l.blue=a;break;case 6:l.red=b;l.green=a;l.blue=d;break}l.red=Math.round(l.red*255);l.green=Math.round(l.green*255);l.blue=Math.round(l.blue*255)}return l}function rgb2hsv(c,b,a){var d=new Object();c=c/255;b=b/255;a=a/255;myMax=Math.max(c,Math.max(b,a));myMin=Math.min(c,Math.min(b,a));v=myMax;if(myMax>0){s=(myMax-myMin)/myMax}else{s=0}if(s>0){myDiff=myMax-myMin;rc=(myMax-c)/myDiff;gc=(myMax-b)/myDiff;bc=(myMax-a)/myDiff;if(c==myMax){h=(bc-gc)/6}if(b==myMax){h=(2+rc-bc)/6}if(a==myMax){h=(4+gc-rc)/6}}else{h=0}if(h<0){h+=1}d.hue=Math.round(h*360);d.sat=s;d.val=v;ret
urn d}function arrayPopulate(a,b){var c=new Array();if(a.length!=b.length){alert("error: arrays do not have the same length!")}else{for(i=0;i<a.length;i++){c[a[i]]=b[i]}}return c}function getData(d,c,e,f,b,a){this.url=d;this.callBackFunction=c;this.returnFormat=e;this.method=f;this.additionalParams=a;if(f!="get"&&f!="post"){alert("Error in network request: parameter 'method' must be 'get' or 'post'")}this.postText=b;this.xmlRequest=null}getData.prototype.getData=function(){if(window.getURL){if(this.method=="get"){getURL(this.url,this)}if(this.method=="post"){postURL(this.url,this.postText,this)}}else{if(window.XMLHttpRequest){var b=this;this.xmlRequest=new XMLHttpRequest();if(this.method=="get"){if(this.returnFormat=="xml"){this.xmlRequest.overrideMimeType("text/xml")}this.xmlRequest.open("GET",this.url,true)}if(this.method=="post"){this.xmlRequest.open("POST",this.url,true)}this.xmlRequest.onreadystatechange=function(){b.handleEvent()};if(this.method=="get"){this.xmlRequest
.send(null)}if(this.method=="post"){var a=true;if(!this.postText){a=false;alert("Error in network post request: missing parameter 'postText'!")}if(typeof(this.postText)!="string"){a=false;alert("Error in network post request: parameter 'postText' has to be of type 'string')")}if(a){this.xmlRequest.send(this.postText)}}}else{alert("your browser/svg viewer neither supports window.getURL nor window.XMLHttpRequest!")}}};getData.prototype.operationComplete=function(b){if(b.success){if(this.returnFormat=="xml"){var a=parseXML(b.content,document);if(typeof(this.callBackFunction)=="function"){this.callBackFunction(a.firstChild,this.additionalParams)}if(typeof(this.callBackFunction)=="object"){this.callBackFunction.receiveData(a.firstChild,this.additionalParams)}}if(this.returnFormat=="json"){if(typeof(this.callBackFunction)=="function"){this.callBackFunction(b.content,this.additionalParams)}if(typeof(this.callBackFunction)=="object"){this.callBackFunction.receiveData(b.content,this.
additionalParams)}}}else{alert("something went wrong with dynamic loading of geometry!")}};getData.prototype.handleEvent=function(){if(this.xmlRequest.readyState==4){if(this.returnFormat=="xml"){var a=document.importNode(this.xmlRequest.responseXML.documentElement,true);if(typeof(this.callBackFunction)=="function"){this.callBackFunction(a,this.additionalParams)}if(typeof(this.callBackFunction)=="object"){this.callBackFunction.receiveData(a,this.additionalParams)}}if(this.returnFormat=="json"){if(typeof(this.callBackFunction)=="function"){this.callBackFunction(this.xmlRequest.responseText,this.additionalParams)}if(typeof(this.callBackFunction)=="object"){this.callBackFunction.receiveData(this.xmlRequest.responseText,this.additionalParams)}}}};function serializeNode(b){if(typeof XMLSerializer!="undefined"){return new XMLSerializer().serializeToString(b)}else{if(typeof b.xml!="undefined"){return b.xml}else{if(typeof printNode!="undefined"){return printNode(b)}else{if(typeof Pac
kages!="undefined"){try{var a=new java.io.StringWriter();Packages.org.apache.batik.dom.util.DOMUtilities.writeNode(b,a);return a.toString()}catch(c){alert("Sorry, your SVG viewer does not support the printNode/serialize function.");return""}}else{alert("Sorry, your SVG viewer does not support the printNode/serialize function.");return""}}}}}function startAnimation(a){document.getElementById(a).beginElement()};
\ No newline at end of file
diff -r cbe28b41fb9d -r e945dcdfd578 static/scripts/tools/rgenetics/timer.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/tools/rgenetics/timer.js Thu Oct 15 19:01:07 2009 -0400
@@ -0,0 +1,1 @@
+function Timer(){this.obj=(arguments.length)?arguments[0]:window;return this}Timer.prototype.setInterval=function(c,d){var b=Timer.getNew();var a=Timer.buildCall(this.obj,b,arguments);Timer.set[b].timer=window.setInterval(a,d);return b};Timer.prototype.setTimeout=function(b,c){var a=Timer.getNew();Timer.buildCall(this.obj,a,arguments);Timer.set[a].timer=window.setTimeout("Timer.callOnce("+a+");",c);return a};Timer.prototype.clearInterval=function(a){if(!Timer.set[a]){return}window.clearInterval(Timer.set[a].timer);Timer.set[a]=null};Timer.prototype.clearTimeout=function(a){if(!Timer.set[a]){return}window.clearTimeout(Timer.set[a].timer);Timer.set[a]=null};Timer.set=new Array();Timer.buildCall=function(e,d,b){var c="";Timer.set[d]=new Array();if(e!=window){Timer.set[d].obj=e;c="Timer.set["+d+"].obj."}c+=b[0]+"(";if(b.length>2){Timer.set[d][0]=b[2];c+="Timer.set["+d+"][0]";for(var a=1;(a+2)<b.length;a++){Timer.set[d][a]=b[a+2];c+=", Timer.set["+d+"]["+a+"]"}}c+=");";Timer.set[
d].call=c;return c};Timer.callOnce=function(i){if(!Timer.set[i]){return}eval(Timer.set[i].call);Timer.set[i]=null};Timer.getNew=function(){var a=0;while(Timer.set[a]){a++}return a};
\ No newline at end of file
1
0

20 Oct '09
details: http://www.bx.psu.edu/hg/galaxy/rev/15756ebb2b11
changeset: 2889:15756ebb2b11
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Thu Oct 15 20:10:32 2009 -0400
description:
Fixes and new functional tests for uploading multi-byte character files and fixes for displaying multi-byte character dataset peek.
8 file(s) affected in this change:
lib/galaxy/datatypes/data.py
lib/galaxy/jobs/__init__.py
lib/galaxy/model/__init__.py
lib/galaxy/tools/actions/upload_common.py
lib/galaxy/tools/parameters/grouping.py
test-data/asian_chars_1.txt
test/functional/test_get_data.py
tools/data_source/upload.py
diffs (269 lines):
diff -r e945dcdfd578 -r 15756ebb2b11 lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py Thu Oct 15 19:01:07 2009 -0400
+++ b/lib/galaxy/datatypes/data.py Thu Oct 15 20:10:32 2009 -0400
@@ -136,7 +136,7 @@
line = line.strip()
if not line:
continue
- out.append( '<tr><td>%s</td></tr>' % escape( unicode( line ) ) )
+ out.append( '<tr><td>%s</td></tr>' % escape( unicode( line, 'utf-8' ) ) )
out.append( '</table>' )
out = "".join( out )
except Exception, exc:
@@ -437,8 +437,8 @@
temp.close()
if file_type in [ 'gzipped', 'binary' ]:
text = "%s file" % file_type
- else:
- text = unicode( '\n'.join( lines ), 'utf-8' )
+ else:
+ text = unicode( '\n'.join( lines ), 'utf-8' )
return text
def get_line_count(file_name):
diff -r e945dcdfd578 -r 15756ebb2b11 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py Thu Oct 15 19:01:07 2009 -0400
+++ b/lib/galaxy/jobs/__init__.py Thu Oct 15 20:10:32 2009 -0400
@@ -535,12 +535,12 @@
dataset.metadata.from_JSON_dict( self.external_output_metadata.get_output_filenames_by_dataset( dataset ).filename_out )
try:
assert context.get( 'line_count', None ) is not None
- if self.tool.is_multi_byte:
+ if ( not dataset.datatype.composite_type and dataset.dataset.is_multi_byte() ) or self.tool.is_multi_byte:
dataset.set_multi_byte_peek( line_count=context['line_count'] )
else:
dataset.set_peek( line_count=context['line_count'] )
except:
- if self.tool.is_multi_byte:
+ if ( not dataset.datatype.composite_type and dataset.dataset.is_multi_byte() ) or self.tool.is_multi_byte:
dataset.set_multi_byte_peek()
else:
dataset.set_peek()
diff -r e945dcdfd578 -r 15756ebb2b11 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Thu Oct 15 19:01:07 2009 -0400
+++ b/lib/galaxy/model/__init__.py Thu Oct 15 20:10:32 2009 -0400
@@ -5,7 +5,7 @@
the relationship cardinalities are obvious (e.g. prefer Dataset to Data)
"""
-import os.path, os, errno, sys
+import os.path, os, errno, sys, codecs
import galaxy.datatypes
from galaxy.util.bunch import Bunch
from galaxy import util
@@ -418,7 +418,13 @@
return self.get_size() > 0
def mark_deleted( self, include_children=True ):
self.deleted = True
-
+ def is_multi_byte( self ):
+ if not self.has_data():
+ return False
+ try:
+ return util.is_multi_byte( codecs.open( self.file_name, 'r', 'utf-8' ).read( 100 ) )
+ except UnicodeDecodeError, e:
+ return False
# FIXME: sqlalchemy will replace this
def _delete(self):
"""Remove the file that corresponds to this data"""
@@ -433,7 +439,7 @@
permitted_actions = Dataset.permitted_actions
def __init__( self, id=None, hid=None, name=None, info=None, blurb=None, peek=None, extension=None,
dbkey=None, metadata=None, history=None, dataset=None, deleted=False, designation=None,
- parent_id=None, validation_errors=None, visible=True, create_dataset = False ):
+ parent_id=None, validation_errors=None, visible=True, create_dataset=False ):
self.name = name or "Unnamed dataset"
self.id = id
self.info = info
@@ -519,6 +525,9 @@
def get_mime( self ):
"""Returns the mime type of the data"""
return datatypes_registry.get_mimetype_by_extension( self.extension.lower() )
+ def is_multi_byte( self ):
+ """Data consists of multi-byte characters"""
+ return self.dataset.is_multi_byte()
def set_peek( self ):
return self.datatype.set_peek( self )
def set_multi_byte_peek( self ):
@@ -556,7 +565,7 @@
def get_converter_types(self):
return self.datatype.get_converter_types( self, datatypes_registry)
def find_conversion_destination( self, accepted_formats, **kwd ):
- """Returns ( target_ext, exisiting converted dataset )"""
+ """Returns ( target_ext, existing converted dataset )"""
return self.datatype.find_conversion_destination( self, accepted_formats, datatypes_registry, **kwd )
def add_validation_error( self, validation_error ):
self.validation_errors.append( validation_error )
diff -r e945dcdfd578 -r 15756ebb2b11 lib/galaxy/tools/actions/upload_common.py
--- a/lib/galaxy/tools/actions/upload_common.py Thu Oct 15 19:01:07 2009 -0400
+++ b/lib/galaxy/tools/actions/upload_common.py Thu Oct 15 20:10:32 2009 -0400
@@ -27,7 +27,7 @@
elif type( f ) == dict and 'filename' and 'local_filename' not in f:
raise Exception( 'Uploaded file was encoded in a way not understood by Galaxy.' )
if upload_dataset['url_paste'].strip() != '':
- upload_dataset['url_paste'] = datatypes.sniff.stream_to_file( StringIO.StringIO( upload_dataset['url_paste'] ), prefix="strio_url_paste_" )[0]
+ upload_dataset['url_paste'], is_multi_byte = datatypes.sniff.stream_to_file( StringIO.StringIO( upload_dataset['url_paste'] ), prefix="strio_url_paste_" )
else:
upload_dataset['url_paste'] = None
new_files.append( upload_dataset )
@@ -135,7 +135,6 @@
folder.refresh()
matches = filter( lambda x: x.name == name, active_folders( trans, folder ) )
if matches:
- log.debug( 'DEBUGDEBUG: In %s, found a folder name match: %s:%s' % ( folder.name, matches[0].id, matches[0].name ) )
folder = matches[0]
else:
new_folder = trans.app.model.LibraryFolder( name=name, description='Automatically created by upload tool' )
@@ -143,7 +142,6 @@
folder.add_folder( new_folder )
new_folder.flush()
trans.app.security_agent.copy_library_permissions( folder, new_folder )
- log.debug( 'DEBUGDEBUG: In %s, created a new folder: %s:%s' % ( folder.name, new_folder.id, new_folder.name ) )
folder = new_folder
if library_bunch.replace_dataset:
ld = library_bunch.replace_dataset
diff -r e945dcdfd578 -r 15756ebb2b11 lib/galaxy/tools/parameters/grouping.py
--- a/lib/galaxy/tools/parameters/grouping.py Thu Oct 15 19:01:07 2009 -0400
+++ b/lib/galaxy/tools/parameters/grouping.py Thu Oct 15 20:10:32 2009 -0400
@@ -240,7 +240,7 @@
url_paste = context['url_paste']
name = context.get( 'NAME', None )
info = context.get( 'INFO', None )
- space_to_tab = False
+ space_to_tab = False
if context.get( 'space_to_tab', None ) not in ["None", None]:
space_to_tab = True
warnings = []
@@ -248,7 +248,6 @@
if file_bunch.path:
file_bunch.space_to_tab = space_to_tab
rval.append( file_bunch )
- #rval.append( ( type, temp_name, precreated_name, space_to_tab, dataset_name, dataset_info ) )
for file_bunch in get_url_paste_urls_or_filename( context, override_name = name, override_info = info ):
if file_bunch.path:
file_bunch.space_to_tab = space_to_tab
@@ -266,11 +265,6 @@
if d_type.composite_type is not None:
#handle uploading of composite datatypes
#Only one Dataset can be created
-
- '''
- dataset = UploadedDataset()
- dataset.datatype = d_type
- '''
dataset = Bunch()
dataset.type = 'composite'
dataset.file_type = file_type
@@ -279,14 +273,12 @@
dataset.warnings = []
dataset.metadata = {}
dataset.composite_files = {}
-
#load metadata
files_metadata = context.get( self.metadata_ref, {} )
for meta_name, meta_spec in d_type.metadata_spec.iteritems():
if meta_spec.set_in_upload:
if meta_name in files_metadata:
dataset.metadata[ meta_name ] = files_metadata[ meta_name ]
-
dataset_name = None
dataset_info = None
if dataset.datatype.composite_type == 'auto_primary_file':
diff -r e945dcdfd578 -r 15756ebb2b11 test-data/asian_chars_1.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/asian_chars_1.txt Thu Oct 15 20:10:32 2009 -0400
@@ -0,0 +1,1 @@
+蛋白質核酸酵素:制癌性物質の化学修飾による効果の向上.
\ No newline at end of file
diff -r e945dcdfd578 -r 15756ebb2b11 test/functional/test_get_data.py
--- a/test/functional/test_get_data.py Thu Oct 15 19:01:07 2009 -0400
+++ b/test/functional/test_get_data.py Thu Oct 15 20:10:32 2009 -0400
@@ -93,3 +93,17 @@
self.verify_composite_datatype_file_content( 'rgenetics.bed', str( hda1.id ) )
self.verify_composite_datatype_file_content( 'rgenetics.fam', str( hda1.id ) )
self.delete_history( id=self.security.encode_id( history4.id ) )
+ def test_020_upload_multibyte_character_file( self ):
+ """Test uploading multi-byte character file"""
+ # Logged in as admin_user
+ self.check_history_for_string( 'Your history is empty' )
+ history5 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
+ galaxy.model.History.table.c.user_id==admin_user.id ) ) \
+ .order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
+ self.upload_file( 'asian_chars_1.txt' )
+ hda1 = galaxy.model.HistoryDatasetAssociation.query() \
+ .order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first()
+ assert hda1 is not None, "Problem retrieving hda1 from database"
+ self.verify_dataset_correctness( 'asian_chars_1.txt', hid=str( hda1.hid ) )
+ self.check_history_for_string( 'uploaded multi-byte char file' )
+ self.delete_history( id=self.security.encode_id( history5.id ) )
diff -r e945dcdfd578 -r 15756ebb2b11 tools/data_source/upload.py
--- a/tools/data_source/upload.py Thu Oct 15 19:01:07 2009 -0400
+++ b/tools/data_source/upload.py Thu Oct 15 20:10:32 2009 -0400
@@ -4,7 +4,7 @@
# WARNING: Changes in this tool (particularly as related to parsing) may need
# to be reflected in galaxy.web.controllers.tool_runner and galaxy.tools
-import urllib, sys, os, gzip, tempfile, shutil, re, gzip, zipfile
+import urllib, sys, os, gzip, tempfile, shutil, re, gzip, zipfile, codecs
from galaxy import eggs
# need to import model before sniff to resolve a circular import dependency
import galaxy.model
@@ -129,13 +129,11 @@
if dataset.type == 'url':
try:
- temp_name, is_multi_byte = sniff.stream_to_file( urllib.urlopen( dataset.path ), prefix='url_paste' )
+ temp_name, dataset.is_multi_byte = sniff.stream_to_file( urllib.urlopen( dataset.path ), prefix='url_paste' )
except Exception, e:
file_err( 'Unable to fetch %s\n%s' % ( dataset.path, str( e ) ), dataset, json_file )
return
dataset.path = temp_name
- dataset.is_multi_byte = is_multi_byte
-
# See if we have an empty file
if not os.path.exists( dataset.path ):
file_err( 'Uploaded temporary file (%s) does not exist.' % dataset.path, dataset, json_file )
@@ -143,11 +141,15 @@
if not os.path.getsize( dataset.path ) > 0:
file_err( 'The uploaded file is empty', dataset, json_file )
return
- if 'is_multi_byte' not in dir( dataset ):
- dataset.is_multi_byte = util.is_multi_byte( open( dataset.path, 'r' ).read( 1024 ) )
+ if not dataset.type == 'url':
+ # Already set is_multi_byte above if type == 'url'
+ try:
+ dataset.is_multi_byte = util.is_multi_byte( codecs.open( dataset.path, 'r', 'utf-8' ).read( 100 ) )
+ except UnicodeDecodeError, e:
+ dataset.is_multi_byte = False
if dataset.is_multi_byte:
+ data_type = 'multi-byte char'
ext = sniff.guess_ext( dataset.path, is_multi_byte=True )
- data_type = ext
else:
# See if we have a gzipped file, which, if it passes our restrictions, we'll uncompress
is_gzipped, is_valid = check_gzip( dataset.path )
@@ -283,24 +285,19 @@
sys.exit( 1 )
output_paths = parse_outputs( sys.argv[2:] )
-
json_file = open( 'galaxy.json', 'w' )
-
for line in open( sys.argv[1], 'r' ):
dataset = from_json_string( line )
dataset = util.bunch.Bunch( **safe_dict( dataset ) )
-
try:
output_path = output_paths[int( dataset.dataset_id )]
except:
print >>sys.stderr, 'Output path for dataset %s not found on command line' % dataset.dataset_id
sys.exit( 1 )
-
if dataset.type == 'composite':
add_composite_file( dataset, json_file, output_path )
else:
add_file( dataset, json_file, output_path )
-
# clean up paramfile
try:
os.remove( sys.argv[1] )
1
0

20 Oct '09
details: http://www.bx.psu.edu/hg/galaxy/rev/16a0c13c94cc
changeset: 2890:16a0c13c94cc
user: jeremy goecks <jeremy.goecks at emory.edu>
date: Fri Oct 16 15:54:43 2009 -0400
description:
Added anchors--identified by encoded id--to datasets in a history so that HDAs can be directly referenced. Clicking on a dataset in the datasets (HDAs) grid now goes to the dataset within the history.
4 file(s) affected in this change:
lib/galaxy/web/controllers/root.py
templates/dataset/grid.mako
templates/root/history.mako
templates/root/history_common.mako
diffs (59 lines):
diff -r 15756ebb2b11 -r 16a0c13c94cc lib/galaxy/web/controllers/root.py
--- a/lib/galaxy/web/controllers/root.py Thu Oct 15 20:10:32 2009 -0400
+++ b/lib/galaxy/web/controllers/root.py Fri Oct 16 15:54:43 2009 -0400
@@ -55,7 +55,7 @@
return trans.fill_template_mako( "/my_data.mako" )
@web.expose
- def history( self, trans, as_xml=False, show_deleted=False ):
+ def history( self, trans, as_xml=False, show_deleted=False, hda_id=None ):
"""
Display the current history, creating a new history if necessary.
NOTE: No longer accepts "id" or "template" options for security reasons.
@@ -78,6 +78,7 @@
return trans.stream_template_mako( "root/history.mako",
history = history,
datasets = query.all(),
+ hda_id = hda_id,
show_deleted = show_deleted )
@web.expose
diff -r 15756ebb2b11 -r 16a0c13c94cc templates/dataset/grid.mako
--- a/templates/dataset/grid.mako Thu Oct 15 20:10:32 2009 -0400
+++ b/templates/dataset/grid.mako Fri Oct 16 15:54:43 2009 -0400
@@ -110,7 +110,7 @@
%endif
%if 'history' in refresh_frames:
if ( parent.frames && parent.frames.galaxy_history ) {
- parent.frames.galaxy_history.location.href="${h.url_for( controller='root', action='history')}";
+ parent.frames.galaxy_history.location.href="${h.url_for( controller='root', action='history', hda_id=str(ids) )}";
if ( parent.force_right_panel ) {
parent.force_right_panel( 'show' );
}
diff -r 15756ebb2b11 -r 16a0c13c94cc templates/root/history.mako
--- a/templates/root/history.mako Thu Oct 15 20:10:32 2009 -0400
+++ b/templates/root/history.mako Fri Oct 16 15:54:43 2009 -0400
@@ -77,6 +77,10 @@
<% updateable = [data for data in reversed( datasets ) if data.visible and data.state not in [ "deleted", "empty", "error", "ok" ]] %>
${ ",".join( map(lambda data: "\"%s\" : \"%s\"" % (data.id, data.state), updateable) ) }
});
+ // Navigate to a dataset.
+ %if hda_id:
+ self.location = "#${hda_id}";
+ %endif
});
// Functionized so AJAX'd datasets can call them
function initShowHide() {
diff -r 15756ebb2b11 -r 16a0c13c94cc templates/root/history_common.mako
--- a/templates/root/history_common.mako Thu Oct 15 20:10:32 2009 -0400
+++ b/templates/root/history_common.mako Fri Oct 16 15:54:43 2009 -0400
@@ -20,7 +20,8 @@
</div>
%endif
- ## Header row for history items (name, state, action buttons)
+ ## Header row for history items (name, state, action buttons)
+ <a name="${trans.security.encode_id(data.id)}"></a>
<div style="overflow: hidden;" class="historyItemTitleBar">
<div class="historyItemButtons">
%if data_state == "upload":
1
0