galaxy-dev
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
April 2010
- 37 participants
- 148 discussions
15 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/0dc1fc63c945
changeset: 3632:0dc1fc63c945
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Tue Apr 13 10:22:27 2010 -0400
description:
Enable user to change dbkey from a known key back to unspecified. This is a hack, but there's no straightforward way to accomplish this without modifying the jquery autocomplete script.
diffstat:
static/scripts/galaxy.base.js | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diffs (30 lines):
diff -r 968161f35d50 -r 0dc1fc63c945 static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Tue Apr 13 10:16:46 2010 -0400
+++ b/static/scripts/galaxy.base.js Tue Apr 13 10:22:27 2010 -0400
@@ -149,10 +149,10 @@
var select_mapping = {};
select_elt.children('option').each( function() {
// Get text, value for option.
- var text = $(this).text();
+ var text = $(this).text();
var value = $(this).attr('value');
- // Ignore values that are '?'
+ // HACK: dbkey-specific: ignore values that are '?'
if (value == '?') {
return;
}
@@ -169,6 +169,13 @@
}
});
+ // HACK: dbkey-specific: add an unspecified option. We need to add this at the end b/c adding it first mucks
+ // up the autocomplete sorting for some reason. (I.e. All options that start with the first character of the
+ // first option are listed before the other, alphabetized options.)
+ select_options.push( "unspecified (?)" );
+ select_mapping[ "unspecified (?)" ] = "?";
+ select_mapping[ "?" ] = "?";
+
// Set initial text if it's empty.
if ( text_input_elt.attr('value') == '' ) {
text_input_elt.attr('value', 'Click to Search or Select');
1
0
15 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/968161f35d50
changeset: 3631:968161f35d50
user: rc
date: Tue Apr 13 10:16:46 2010 -0400
description:
fixed forms and user_info functional tests
removed a debugging print stmt
diffstat:
lib/galaxy/model/__init__.py | 2 +-
lib/galaxy/web/controllers/forms.py | 1 -
test/functional/test_forms_and_requests.py | 8 ++++----
test/functional/test_user_info.py | 2 +-
4 files changed, 6 insertions(+), 7 deletions(-)
diffs (74 lines):
diff -r fdf5c92e7fae -r 968161f35d50 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Mon Apr 12 19:11:36 2010 -0400
+++ b/lib/galaxy/model/__init__.py Tue Apr 13 10:16:46 2010 -0400
@@ -1326,7 +1326,7 @@
# the user had already filled out this field and the same form is re-rendered
# due to some reason like required fields have been left out.
if field[ 'type' ] == 'CheckboxField':
- value = CheckboxField.is_checked( util.restore_text( params.get( field_name, False ) ) )
+ value = CheckboxField.is_checked( params.get( field_name, False ) )
else:
value = util.restore_text( params.get( field_name, '' ) )
elif contents:
diff -r fdf5c92e7fae -r 968161f35d50 lib/galaxy/web/controllers/forms.py
--- a/lib/galaxy/web/controllers/forms.py Mon Apr 12 19:11:36 2010 -0400
+++ b/lib/galaxy/web/controllers/forms.py Tue Apr 13 10:16:46 2010 -0400
@@ -541,7 +541,6 @@
self.selectbox_options = []
# if the form is for defining samples, then use the sample field types
# which does not include TextArea & AddressField
- print >> sys.stderr, 'form_type', form_type
if form_type == trans.app.model.FormDefinition.types.SAMPLE:
for ft in BaseField.sample_field_types():
self.fieldtype.add_option(ft, ft)
diff -r fdf5c92e7fae -r 968161f35d50 test/functional/test_forms_and_requests.py
--- a/test/functional/test_forms_and_requests.py Mon Apr 12 19:11:36 2010 -0400
+++ b/test/functional/test_forms_and_requests.py Tue Apr 13 10:16:46 2010 -0400
@@ -106,7 +106,7 @@
"""Testing address & library creation"""
# first create a regular user
self.logout()
- self.login( email='test1(a)bx.psu.edu' )
+ self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
self.logout()
self.login( email='test(a)bx.psu.edu' )
# first create a library for the request so that it can be submitted later
@@ -191,7 +191,7 @@
self.check_page_for_string( name )
# create address
self.logout()
- self.login( email='test1(a)bx.psu.edu' )
+ self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
self.add_user_address( regular_user1.id, address1 )
global regular_user
regular_user = sa_session.query( galaxy.model.User ) \
@@ -206,7 +206,7 @@
"""Testing creating, editing and submitting a request as a regular user"""
# login as a regular user
self.logout()
- self.login( email='test1(a)bx.psu.edu' )
+ self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
# set field values
fields = ['option1', str(user_address.id), 'field three value']
# create the request
@@ -259,7 +259,7 @@
self.home()
sa_session.refresh( request_one )
self.logout()
- self.login( email='test1(a)bx.psu.edu' )
+ self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
# check if the request's state is now set to 'complete'
self.check_request_grid(state='Complete', request_name=request_one.name)
assert request_one.state is not request_one.states.COMPLETE, "The state of the request '%s' should be set to '%s'" \
diff -r fdf5c92e7fae -r 968161f35d50 test/functional/test_user_info.py
--- a/test/functional/test_user_info.py Mon Apr 12 19:11:36 2010 -0400
+++ b/test/functional/test_user_info.py Tue Apr 13 10:16:46 2010 -0400
@@ -162,7 +162,7 @@
# Test changing email and user name - first try an invalid user name
self.edit_login_info( new_email='test12_new(a)bx.psu.edu',
new_username='test12_new',
- check_str1='User name must contain only letters, numbers and' )
+ check_str1="User name must contain only lower-case letters, numbers and '-'" )
# Now try a valid user name
self.edit_login_info( new_email='test12_new(a)bx.psu.edu',
new_username='test12-new',
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/fdf5c92e7fae
changeset: 3630:fdf5c92e7fae
user: Kelly Vincent <kpvincent(a)bx.psu.edu>
date: Mon Apr 12 19:11:36 2010 -0400
description:
Fixed a bug in the new joiner tool
diffstat:
tools/new_operations/column_join.py | 97 +++++++++++++++++++++++------------
tools/new_operations/column_join.xml | 8 +-
2 files changed, 68 insertions(+), 37 deletions(-)
diffs (213 lines):
diff -r 6b93e705c8a4 -r fdf5c92e7fae tools/new_operations/column_join.py
--- a/tools/new_operations/column_join.py Mon Apr 12 17:24:17 2010 -0400
+++ b/tools/new_operations/column_join.py Mon Apr 12 19:11:36 2010 -0400
@@ -19,6 +19,32 @@
sys.stderr.write( msg )
sys.exit()
+def hinge_compare( hinge1, hinge2 ):
+ """
+ Compares items like 'chr10' and 'chrM' or 'scaffold2' and scaffold10' so that
+ first part handled as text but last part as number
+ """
+ pat = re.compile( '(?P<text>\D*)(?P<number>\d+)?' )
+ split_hinge1 = hinge1.split( '\t' )
+ split_hinge2 = hinge2.split( '\t' )
+ for i in range( len( split_hinge1 ) ):
+ if split_hinge1[ i ] == split_hinge2[ i ]:
+ continue
+ try:
+ if int( split_hinge1[ i ] ) > int( split_hinge2[ i ] ):
+ return 1
+ else:
+ return -1
+ except ValueError:
+ try:
+ if float( split_hinge1[ i ] ) > float( split_hinge2[ i ] ):
+ return 1
+ else:
+ return -1
+ except ValueError:
+ return ref_compare( split_hinge1[ i ], split_hinge2[ i ])
+ return 0
+
def ref_compare( ref1, ref2 ):
"""
Compares items like 'chr10' and 'chrM' or 'scaffold2' and scaffold10' so that
@@ -52,35 +78,31 @@
elif text1 < text2:
return -1
-def ref_pos_sort( infile, outfile ):
+def hinge_sort( infile, outfile, hinge ):
"""Given input file name, sorts logically (text vs. numeric) into provided output file name."""
- ref_locs = {}
+ hinge_locs = {}
bad_lines = []
fin = open( infile, 'rb' )
line = fin.readline()
while line.strip():
- if True:
+ try:
+ hinge_parts = line.split( '\t' )[ :hinge ]
try:
- ref_seq, ref_loc = line.split( '\t' )[:2]
- try:
- ref_locs[ ref_seq ][ long( ref_loc ) ] = fin.tell() - len( line.strip() ) - 1
- except KeyError:
- ref_locs[ ref_seq ] = { long( ref_loc ): fin.tell() - len( line.strip() ) - 1 }
- except ValueError:
- bad_lines.append( line )
- except ValueError:
- bad_line.append( line )
+ hinge_locs[ '\t'.join( hinge_parts ) ].append( fin.tell() - len( line.strip() ) - 1 )
+ except KeyError:
+ hinge_locs[ '\t'.join( hinge_parts ) ] = [ fin.tell() - len( line.strip() ) - 1 ]
+ except ValueError:
+ bad_line.append( line )
line = fin.readline()
fin.close()
- refs = ref_locs.keys()
- refs.sort( ref_compare )
fin = open( infile, 'rb' )
fout = open( outfile, 'wb' )
- for ref in refs:
- locs = ref_locs[ ref ].keys()
- locs.sort()
+ hinge_locs_sorted = hinge_locs.keys()
+ hinge_locs_sorted.sort( hinge_compare )
+ for hinge_loc in hinge_locs_sorted:
+ locs = hinge_locs[ hinge_loc ]
for loc in locs:
- fin.seek( ref_locs[ ref ][ loc ] )
+ fin.seek( loc )
fout.write( fin.readline() )
fout.close()
fin.close()
@@ -90,14 +112,17 @@
if len( chr_pos ) == 0 and ''.join( chr_pos ):
return ''
min_loc = len( chr_pos )
- min_ref_pos = []
+ min_hinge = []
loc = 0
for c_pos in chr_pos:
if c_pos.strip():
+ split_c = c_pos.split( '\t' )
+
+
ref, pos = c_pos.split( '\t' )[:2]
pos = int( pos )
- if not min_ref_pos:
- min_ref_pos = [ ref, pos ]
+ if not min_hinge:
+ min_hinge = split_c
min_loc = loc
else:
ref_comp = ref_compare( ref, min_ref_pos[0] )
@@ -126,25 +151,33 @@
tmp_file = tempfile.NamedTemporaryFile()
tmp_file_name = tmp_file.name
tmp_file.close()
- ref_pos_sort( in_file, tmp_file_name )
+ hinge_sort( in_file, tmp_file_name, hinge )
tmp_file = open( tmp_file_name, 'rb' )
tmp_input_files.append( tmp_file )
# cycle through files, getting smallest line of all files one at a time
# also have to keep track of vertical position of extra columns
fout = file( output, 'w' )
- old_current_chr_pos = ''
+ old_current = ''
first_line = True
current_lines = [ f.readline() for f in tmp_input_files ]
last_lines = ''.join( current_lines ).strip()
last_loc = -1
+ i = 0
while last_lines:
# get the "minimum" hinge, which should come first, and the file location in list
- current_chr_pos, loc = min_chr_pos( [ '\t'.join( line.split( '\t' )[ :hinge ] ) for line in current_lines ] )
+ hinges = [ '\t'.join( line.split( '\t' )[ :hinge ] ) for line in current_lines ]
+ hinge_dict = {}
+ for i in range( len( hinges ) ):
+ if not hinge_dict.has_key( hinges[ i ] ):
+ hinge_dict[ hinges[ i ] ] = i
+ hinges.sort( hinge_compare )
+ hinges = [ h for h in hinges if h ]
+ current, loc = hinges[0], hinge_dict[ hinges[0] ]
# first output empty columns for vertical alignment (account for "missing" files)
- if current_chr_pos != old_current_chr_pos:
+ if current != old_current:
last_loc = -1
if loc - last_loc > 1:
- current_data = [ '' for col in range( ( loc - last_loc - 1 ) * len( cols[ hinge: ] ) ) ]
+ current_data = [ '' for col in range( ( loc - last_loc - 1 ) * len( [ col for col in cols if col > hinge ] ) ) ]
else:
current_data = []
# now output actual data
@@ -154,22 +187,20 @@
if col > hinge:
current_data.append( split_line[ col - 1 ] )
current_lines[ loc ] = tmp_input_files[ loc ].readline()
- if current_chr_pos == old_current_chr_pos:
- fout.write( '\t%s' % '\t'.join( current_data ) )
+ if current == old_current:
+ if current_data:
+ fout.write( '\t%s' % '\t'.join( current_data ) )
else:
if not first_line:
fout.write( '\n' )
- fout.write( '%s\t%s' % ( current_chr_pos, '\t'.join( current_data ) ) )
+ fout.write( '%s\t%s' % ( current, '\t'.join( current_data ) ) )
first_line = False
- old_current_chr_pos = current_chr_pos
- if last_lines == ''.join( current_lines ).strip():
- break
+ old_current = current
last_lines = ''.join( current_lines ).strip()
last_loc = loc
fout.write( '\n' )
for f in tmp_input_files:
os.unlink( f.name )
fout.close()
-# sys.stderr.write('******************\n'+file(fout.name, 'r').read()+'\n******************\n')
if __name__ == "__main__" : __main__()
diff -r 6b93e705c8a4 -r fdf5c92e7fae tools/new_operations/column_join.xml
--- a/tools/new_operations/column_join.xml Mon Apr 12 17:24:17 2010 -0400
+++ b/tools/new_operations/column_join.xml Mon Apr 12 19:11:36 2010 -0400
@@ -21,7 +21,7 @@
</repeat>
</inputs>
<outputs>
- <data name="output" format="pileup" />
+ <data name="output" format="tabular" />
</outputs>
<tests>
<test>
@@ -30,7 +30,7 @@
<param name="hinge" value="1,2" />
<param name="input2" value="column_join_in2.pileup" ftype="pileup" />
<param name="input" value="column_join_in3.pileup" ftype="pileup" />
- <output name="output" file="column_join_out1.pileup" ftype="pileup" />
+ <output name="output" file="column_join_out1.pileup" ftype="tabular" />
</test>
<test>
<param name="input1" value="column_join_in4.pileup" ftype="pileup" />
@@ -38,7 +38,7 @@
<param name="hinge" value="1,2" />
<param name="input2" value="column_join_in5.pileup" ftype="pileup" />
<param name="input" value="column_join_in6.pileup" ftype="pileup" />
- <output name="output" file="column_join_out2.pileup" ftype="pileup" />
+ <output name="output" file="column_join_out2.pileup" ftype="tabular" />
</test>
<test>
<param name="input1" value="column_join_in7.pileup" ftype="pileup" />
@@ -46,7 +46,7 @@
<param name="hinge" value="1,2" />
<param name="input2" value="column_join_in8.pileup" ftype="pileup" />
<param name="input" value="column_join_in9.pileup" ftype="pileup" />
- <output name="output" file="column_join_out3.pileup" ftype="pileup" />
+ <output name="output" file="column_join_out3.pileup" ftype="tabular" />
</test>
</tests>
<help>
1
0
15 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/6b93e705c8a4
changeset: 3629:6b93e705c8a4
user: Nate Coraor <nate(a)bx.psu.edu>
date: Mon Apr 12 17:24:17 2010 -0400
description:
If a subdir of the library import dir is a symlink and we are linking instead of copying data on import, dereference that symlink
diffstat:
lib/galaxy/web/controllers/library_common.py | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)
diffs (25 lines):
diff -r c19605dca27d -r 6b93e705c8a4 lib/galaxy/web/controllers/library_common.py
--- a/lib/galaxy/web/controllers/library_common.py Mon Apr 12 15:56:13 2010 -0400
+++ b/lib/galaxy/web/controllers/library_common.py Mon Apr 12 17:24:17 2010 -0400
@@ -915,8 +915,19 @@
for entry in os.listdir( full_dir ):
# Only import regular files
path = os.path.join( full_dir, entry )
- if os.path.islink( path ) and os.path.isfile( path ) and params.get( 'link_data_only', False ):
- # If we're linking instead of copying, link the file the link points to, not the link itself.
+ if os.path.islink( full_dir ) and params.get( 'link_data_only', False ):
+ # If we're linking instead of copying and the
+ # sub-"directory" in the import dir is actually a symlink,
+ # dereference the symlink, but not any of its contents.
+ link_path = os.readlink( full_dir )
+ if os.path.isabs( link_path ):
+ path = os.path.join( link_path, entry )
+ else:
+ path = os.path.abspath( os.path.join( link_path, entry ) )
+ elif os.path.islink( path ) and os.path.isfile( path ) and params.get( 'link_data_only', False ):
+ # If we're linking instead of copying and the "file" in the
+ # sub-directory of the import dir is actually a symlink,
+ # dereference the symlink (one dereference only, Vasili).
link_path = os.readlink( path )
if os.path.isabs( link_path ):
path = link_path
1
0
15 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/c19605dca27d
changeset: 3628:c19605dca27d
user: Kelly Vincent <kpvincent(a)bx.psu.edu>
date: Mon Apr 12 15:56:13 2010 -0400
description:
Updated NGS tools' stderr handling to use file rather than pipe to allow for large stderr output
diffstat:
tools/metag_tools/megablast_wrapper.py | 13 +++++++++-
tools/samtools/sam_merge.py | 15 ++++++++++--
tools/samtools/sam_pileup.py | 18 ++++++++++++---
tools/samtools/sam_to_bam.py | 27 ++++++++++++++++++-----
tools/sr_mapping/bowtie_wrapper.py | 26 +++++++++++++++++-----
tools/sr_mapping/bowtie_wrapper.xml | 4 +-
tools/sr_mapping/bwa_wrapper.py | 38 +++++++++++++++++++++++++--------
7 files changed, 109 insertions(+), 32 deletions(-)
diffs (406 lines):
diff -r f32497f2e001 -r c19605dca27d tools/metag_tools/megablast_wrapper.py
--- a/tools/metag_tools/megablast_wrapper.py Mon Apr 12 10:30:25 2010 -0400
+++ b/tools/metag_tools/megablast_wrapper.py Mon Apr 12 15:56:13 2010 -0400
@@ -74,24 +74,33 @@
print megablast_command
+ tmp = tempfile.NamedTemporaryFile().name
try:
- proc = subprocess.Popen( args=megablast_command, shell=True, stderr=subprocess.PIPE )
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=megablast_command, shell=True, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
+ if os.path.exists( tmp ):
+ os.unlink( tmp )
except Exception, e:
if os.path.exists( mega_temp_output ):
os.unlink( mega_temp_output )
+ if os.path.exists( tmp ):
+ os.unlink( tmp )
stop_err( 'Error indexing reference sequence. ' + str( e ) )
output = open( output_filename, 'w' )
diff -r f32497f2e001 -r c19605dca27d tools/samtools/sam_merge.py
--- a/tools/samtools/sam_merge.py Mon Apr 12 10:30:25 2010 -0400
+++ b/tools/samtools/sam_merge.py Mon Apr 12 15:56:13 2010 -0400
@@ -9,7 +9,7 @@
[input3[,input4[,input5[,...]]]]
"""
-import os, subprocess, sys
+import os, subprocess, sys, tempfile
def stop_err( msg ):
sys.stderr.write( '%s\n' % msg )
@@ -22,22 +22,31 @@
stop_err( 'There are not enough files to merge' )
filenames = sys.argv[3:]
cmd = 'samtools merge %s %s %s' % ( outfile, infile, ' '.join( filenames ) )
+ tmp = tempfile.NamedTemporaryFile().name
try:
- proc = subprocess.Popen( args=cmd, shell=True, stderr=subprocess.PIPE )
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=cmd, shell=True, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
+ if os.path.exists( tmp ):
+ os.unlink( tmp )
except Exception, e:
+ if os.path.exists( tmp ):
+ os.unlink( tmp )
stop_err( 'Error running SAMtools merge tool\n' + str( e ) )
if os.path.getsize( outfile ) > 0:
sys.stdout.write( '%s files merged.' % ( len( sys.argv ) - 2 ) )
diff -r f32497f2e001 -r c19605dca27d tools/samtools/sam_pileup.py
--- a/tools/samtools/sam_pileup.py Mon Apr 12 10:30:25 2010 -0400
+++ b/tools/samtools/sam_pileup.py Mon Apr 12 15:56:13 2010 -0400
@@ -88,36 +88,46 @@
elif options.ref == 'history':
os.symlink( options.ownFile, tmpf1_name )
cmdIndex = 'samtools faidx %s' % ( tmpf1_name )
- proc = subprocess.Popen( args=cmdIndex, shell=True, cwd=tmpDir, stderr=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmpDir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=cmdIndex, shell=True, cwd=tmpDir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
#did index succeed?
if returncode != 0:
raise Exception, 'Error creating index file\n' + stderr
cmd = cmd % ( opts, tmpf1_name, tmpf0bam_name, options.output1 )
#perform pileup command
- proc = subprocess.Popen( args=cmd, shell=True, cwd=tmpDir, stderr=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmpDir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=cmd, shell=True, cwd=tmpDir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
#did it succeed?
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
except Exception, e:
diff -r f32497f2e001 -r c19605dca27d tools/samtools/sam_to_bam.py
--- a/tools/samtools/sam_to_bam.py Mon Apr 12 10:30:25 2010 -0400
+++ b/tools/samtools/sam_to_bam.py Mon Apr 12 15:56:13 2010 -0400
@@ -75,18 +75,23 @@
os.symlink( options.ref_file, fai_index_file_base )
fai_index_file_path = '%s.fai' % fai_index_file_base
command = 'samtools faidx %s' % fai_index_file_base
- proc = subprocess.Popen( args=command, shell=True, cwd=tmp_dir, stderr=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmp_dir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=command, shell=True, cwd=tmp_dir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
if len( open( fai_index_file_path ).read().strip() ) == 0:
@@ -104,18 +109,23 @@
# IMPORTANT NOTE: for some reason the samtools view command gzips the resulting bam file without warning,
# and the docs do not currently state that this occurs ( very bad ).
command = 'samtools view -bt %s -o %s %s' % ( fai_index_file_path, tmp_aligns_file_name, options.input1 )
- proc = subprocess.Popen( args=command, shell=True, cwd=tmp_dir, stderr=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmp_dir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=command, shell=True, cwd=tmp_dir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
if len( open( tmp_aligns_file_name ).read() ) == 0:
@@ -133,18 +143,23 @@
tmp_sorted_aligns_file_name = tmp_sorted_aligns_file.name
tmp_sorted_aligns_file.close()
command = 'samtools sort %s %s' % ( tmp_aligns_file_name, tmp_sorted_aligns_file_name )
- proc = subprocess.Popen( args=command, shell=True, cwd=tmp_dir, stderr=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmp_dir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=command, shell=True, cwd=tmp_dir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
except Exception, e:
diff -r f32497f2e001 -r c19605dca27d tools/sr_mapping/bowtie_wrapper.py
--- a/tools/sr_mapping/bowtie_wrapper.py Mon Apr 12 10:30:25 2010 -0400
+++ b/tools/sr_mapping/bowtie_wrapper.py Mon Apr 12 15:56:13 2010 -0400
@@ -186,25 +186,34 @@
( iautoB, ipacked, ibmax, ibmaxdivn, idcv, inodc,
inoref, options.ioffrate, iftab, intoa, iendian,
iseed, icutoff, colorspace )
- except ValueError:
- indexing_cmds = '%s' % colorspace
+ except ValueError, e:
+ # clean up temp dir
+ if os.path.exists( tmp_index_dir ):
+ shutil.rmtree( tmp_index_dir )
+ stop_err( 'Something is wrong with the indexing parameters and the indexing and alignment could not be run\n' + str( e ) )
ref_file = tempfile.NamedTemporaryFile( dir=tmp_index_dir )
ref_file_name = ref_file.name
ref_file.close()
os.symlink( options.ref, ref_file_name )
cmd1 = 'bowtie-build %s -f %s %s' % ( indexing_cmds, ref_file_name, ref_file_name )
try:
- proc = subprocess.Popen( args=cmd1, shell=True, cwd=tmp_index_dir, stderr=subprocess.PIPE, stdout=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmp_index_dir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=cmd1, shell=True, cwd=tmp_index_dir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
+ # get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
except Exception, e:
@@ -358,18 +367,23 @@
else:
cmd2 = 'bowtie %s %s %s > %s' % ( aligning_cmds, ref_file_name, options.input1, options.output )
# align
- proc = subprocess.Popen( args=cmd2, shell=True, cwd=tmp_index_dir, stderr=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmp_index_dir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=cmd2, shell=True, cwd=tmp_index_dir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
# check that there are results in the output file
diff -r f32497f2e001 -r c19605dca27d tools/sr_mapping/bowtie_wrapper.xml
--- a/tools/sr_mapping/bowtie_wrapper.xml Mon Apr 12 10:30:25 2010 -0400
+++ b/tools/sr_mapping/bowtie_wrapper.xml Mon Apr 12 15:56:13 2010 -0400
@@ -181,8 +181,8 @@
--maxAlignAttempt="None"
--forwardAlign="None"
--reverseAlign="None"
- #end if
- #end if
+ #end if
+ #end if
</command>
<inputs>
<conditional name="refGenomeSource">
diff -r f32497f2e001 -r c19605dca27d tools/sr_mapping/bwa_wrapper.py
--- a/tools/sr_mapping/bwa_wrapper.py Mon Apr 12 10:30:25 2010 -0400
+++ b/tools/sr_mapping/bwa_wrapper.py Mon Apr 12 15:56:13 2010 -0400
@@ -91,18 +91,23 @@
indexing_cmds = '-a %s' % indexingAlg
cmd1 = 'bwa index %s %s' % ( indexing_cmds, ref_file_name )
try:
- proc = subprocess.Popen( args=cmd1, shell=True, cwd=tmp_index_dir, stderr=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmp_index_dir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=cmd1, shell=True, cwd=tmp_index_dir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
buffsize = 1048576
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
except Exception, e:
@@ -166,52 +171,67 @@
try:
# align
try:
- proc = subprocess.Popen( args=cmd2, shell=True, cwd=tmp_dir, stderr=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmp_dir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=cmd2, shell=True, cwd=tmp_dir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
except Exception, e:
raise Exception, 'Error aligning sequence. ' + str( e )
# and again if paired data
try:
- if cmd2b:
- proc = subprocess.Popen( args=cmd2b, shell=True, cwd=tmp_dir, stderr=subprocess.PIPE )
+ if cmd2b:
+ tmp = tempfile.NamedTemporaryFile( dir=tmp_dir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=cmd2b, shell=True, cwd=tmp_dir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
except Exception, e:
raise Exception, 'Error aligning second sequence. ' + str( e )
# generate align
try:
- proc = subprocess.Popen( args=cmd3, shell=True, cwd=tmp_dir, stderr=subprocess.PIPE )
+ tmp = tempfile.NamedTemporaryFile( dir=tmp_dir ).name
+ tmp_stderr = open( tmp, 'wb' )
+ proc = subprocess.Popen( args=cmd3, shell=True, cwd=tmp_dir, stderr=tmp_stderr.fileno() )
returncode = proc.wait()
+ tmp_stderr.close()
# get stderr, allowing for case where it's very large
+ tmp_stderr = open( tmp, 'rb' )
stderr = ''
try:
while True:
- stderr += proc.stderr.read( buffsize )
+ stderr += tmp_stderr.read( buffsize )
if not stderr or len( stderr ) % buffsize != 0:
break
except OverflowError:
pass
+ tmp_stderr.close()
if returncode != 0:
raise Exception, stderr
except Exception, e:
1
0
15 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/f32497f2e001
changeset: 3627:f32497f2e001
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Mon Apr 12 10:30:25 2010 -0400
description:
Allow FASTQ parser to handle extra space padded decimal scores, e.g. '0 '
diffstat:
lib/galaxy_utils/sequence/fastq.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diffs (12 lines):
diff -r 5536d57237a3 -r f32497f2e001 lib/galaxy_utils/sequence/fastq.py
--- a/lib/galaxy_utils/sequence/fastq.py Fri Apr 09 18:09:54 2010 -0400
+++ b/lib/galaxy_utils/sequence/fastq.py Mon Apr 12 10:30:25 2010 -0400
@@ -60,7 +60,7 @@
else:
quality = self.quality.rstrip() #decimal scores should have a trailing space
if quality:
- return map( int, quality.split( ' ' ) )
+ return [ int( val ) for val in quality.split( ' ' ) if val.strip() ]
else:
return []
def convert_read_to_format( self, format, force_quality_encoding = None ):
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/5536d57237a3
changeset: 3626:5536d57237a3
user: Kanwei Li <kanwei(a)gmail.com>
date: Fri Apr 09 18:09:54 2010 -0400
description:
- Update jQuery.jStore, JSON2
- Fix issue with all local prefs being deleted on "collapse all"
- Refactored history display code into galaxy.base
diffstat:
static/jStore.Flash.html | 19 -
static/jStore.swf | 0
static/scripts/class.js | 80 +
static/scripts/galaxy.base.js | 87 +
static/scripts/jquery.jstore-all.js | 748 -----------
static/scripts/jquery.jstore.js | 1810 ++++++++++++++++++++++++++++
static/scripts/json2.js | 26 +-
static/scripts/packed/class.js | 7 +
static/scripts/packed/galaxy.base.js | 2 +-
static/scripts/packed/jquery.jstore-all.js | 1 -
static/scripts/packed/jquery.jstore.js | 17 +
static/scripts/packed/json2.js | 2 +-
templates/display_base.mako | 29 +-
templates/history/display.mako | 264 +---
templates/history/view.mako | 259 +---
templates/page/display.mako | 272 +---
templates/root/history.mako | 222 +--
templates/workflow/editor.mako | 42 +-
18 files changed, 2216 insertions(+), 1671 deletions(-)
diffs (truncated from 4199 to 3000 lines):
diff -r a9402fc7ce1b -r 5536d57237a3 static/jStore.Flash.html
--- a/static/jStore.Flash.html Fri Apr 09 13:02:15 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
- <head>
- <title>Flash External Object</title>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <script type="text/javascript">
- /**
- * This function captures the flash_ready event. We need to relay this
- * back to the parent so it knows flash is ready.
- */
- function flash_ready(){
- parent.flash_ready();
- }
- </script>
- </head>
- <body>
- <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#versi…" width="1" height="1" id="jStoreFlash"><param name="allowScriptAccess" value="always" /><param name="movie" value="jStore.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffcc00" /><embed src="jStore.swf" quality="high" bgcolor="#ffcc00" width="1" height="1" name="jStoreFlash" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /></object>
- </body>
-</html>
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/jStore.swf
Binary file static/jStore.swf has changed
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/class.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/class.js Fri Apr 09 18:09:54 2010 -0400
@@ -0,0 +1,80 @@
+/*!
+ * Class definition
+ *
+ * Copyright (c) 2008 John Resig (http://ejohn.org/blog/simple-javascript-inheritance/)
+ * Inspired by base2 and Prototype
+ */
+
+"use strict";
+
+(function () {
+
+ var initializing = false,
+
+ fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
+
+ // The base Class implementation (does nothing)
+ this.Class = function(){};
+
+ // Create a new Class that inherits from this class
+ Class.extend = function (prop)
+ {
+ var _super = this.prototype;
+
+ // Instantiate a base class (but only create the instance, don't run the init constructor)
+ initializing = true;
+
+ var prototype = new this();
+
+ initializing = false;
+
+ // Copy the properties over onto the new prototype
+ for (var name in prop)
+ {
+
+ // Check if we're overwriting an existing function
+ prototype[name] = (typeof prop[name] === "function" && typeof _super[name] === "function" && fnTest.test(prop[name]) ?
+
+ (function(name, fn)
+ {
+ return function()
+ {
+ var tmp = this._super;
+
+ // Add a new ._super() method that is the same method
+ // but on the super-class
+ this._super = _super[name];
+
+ // The method only need to be bound temporarily, so we
+ // remove it when we're done executing
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+
+ return ret;
+ };
+ }(name, prop[name])) : prop[name]);
+ }
+
+ // The dummy class constructor
+ function Class()
+ {
+ // All construction is actually done in the init method
+ if (!initializing && this.init)
+ {
+ this.init.apply(this, arguments);
+ }
+ }
+
+ // Populate our constructed prototype object
+ Class.prototype = prototype;
+
+ // Enforce the constructor to be what we expect
+ Class.constructor = Class;
+
+ // And make this class extendable
+ Class.extend = arguments.callee;
+
+ return Class;
+ };
+
+}());
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Fri Apr 09 13:02:15 2010 -0400
+++ b/static/scripts/galaxy.base.js Fri Apr 09 18:09:54 2010 -0400
@@ -275,6 +275,93 @@
});
}
+function init_history_items(historywrapper, noinit) {
+
+ var action = function() {
+ // Load saved state and show as necessary
+ try {
+ var stored = $.jStore.store("history_expand_state");
+ if (stored) {
+ for (var id in stored) {
+ $("#" + id + " div.historyItemBody" ).show();
+ }
+ }
+ } catch(err) {
+ // Something was wrong with values in storage, so clear storage
+ $.jStore.remove("history_expand_state");
+ }
+
+ // If Mozilla, hide scrollbars in hidden items since they cause animation bugs
+ if ( $.browser.mozilla ) {
+ $( "div.historyItemBody" ).each( function() {
+ if ( ! $(this).is( ":visible" ) ) $(this).find( "pre.peek" ).css( "overflow", "hidden" );
+ })
+ }
+
+ historywrapper.each( function() {
+ var id = this.id;
+ var body = $(this).children( "div.historyItemBody" );
+ var peek = body.find( "pre.peek" )
+ $(this).children( ".historyItemTitleBar" ).find( ".historyItemTitle" ).wrap( "<a href='#'></a>" ).click( function() {
+ if ( body.is(":visible") ) {
+ // Hiding stuff here
+ if ( $.browser.mozilla ) { peek.css( "overflow", "hidden" ) }
+ body.slideUp( "fast" );
+
+ if (!noinit) { // Ignore embedded item actions
+ // Save setting
+ var prefs = $.jStore.store("history_expand_state");
+ if (prefs) {
+ delete prefs[id];
+ $.jStore.store("history_expand_state", prefs);
+ }
+ }
+ } else {
+ // Showing stuff here
+ body.slideDown( "fast", function() {
+ if ( $.browser.mozilla ) { peek.css( "overflow", "auto" ); }
+ });
+
+ if (!noinit) {
+ // Save setting
+ var prefs = $.jStore.store("history_expand_state");
+ if (prefs === undefined) { prefs = {}; }
+ prefs[id] = true;
+ $.jStore.store("history_expand_state", prefs);
+ }
+ }
+ return false;
+ });
+ });
+
+ // Generate 'collapse all' link
+ $("#top-links > a.toggle").click( function() {
+ var prefs = $.jStore.store("history_expand_state");
+ if (prefs === undefined) { prefs = {}; }
+ $( "div.historyItemBody:visible" ).each( function() {
+ if ( $.browser.mozilla ) {
+ $(this).find( "pre.peek" ).css( "overflow", "hidden" );
+ }
+ $(this).slideUp( "fast" );
+ if (prefs) {
+ delete prefs[$(this).parent().attr("id")];
+ }
+ });
+ $.jStore.store("history_expand_state", prefs);
+ }).show();
+ }
+
+ if (noinit) {
+ action();
+ } else {
+ // Load jStore for local storage
+ $.jStore.init("galaxy"); // Auto-select best storage
+ $.jStore.engineReady(function() {
+ action();
+ });
+ }
+}
+
$(document).ready( function() {
// Links with confirmation
$( "a[confirm]" ).click( function() {
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/jquery.jstore-all.js
--- a/static/scripts/jquery.jstore-all.js Fri Apr 09 13:02:15 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,748 +0,0 @@
-/*
- * jStore - Persistent Client-Side Storage
- *
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- *
- * Dual licensed under:
- * MIT: http://www.opensource.org/licenses/mit-license.php
- * GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
- *//**
- * Javascript Class Framework
- *
- * Copyright (c) 2008 John Resig (http://ejohn.org/blog/simple-javascript-inheritance/)
- * Inspired by base2 and Prototype
- */
-(function(){
- var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
-
- // The base Class implementation (does nothing)
- this.Class = function(){};
-
- // Create a new Class that inherits from this class
- Class.extend = function(prop) {
- var _super = this.prototype;
-
- // Instantiate a base class (but only create the instance,
- // don't run the init constructor)
- initializing = true;
- var prototype = new this();
- initializing = false;
-
- // Copy the properties over onto the new prototype
- for (var name in prop) {
- // Check if we're overwriting an existing function
- prototype[name] = typeof prop[name] == "function" &&
- typeof _super[name] == "function" && fnTest.test(prop[name]) ?
- (function(name, fn){
- return function() {
- var tmp = this._super;
-
- // Add a new ._super() method that is the same method
- // but on the super-class
- this._super = _super[name];
-
- // The method only need to be bound temporarily, so we
- // remove it when we're done executing
- var ret = fn.apply(this, arguments);
- this._super = tmp;
-
- return ret;
- };
- })(name, prop[name]) :
- prop[name];
- }
-
- // The dummy class constructor
- function Class() {
- // All construction is actually done in the init method
- if ( !initializing && this.init )
- this.init.apply(this, arguments);
- }
-
- // Populate our constructed prototype object
- Class.prototype = prototype;
-
- // Enforce the constructor to be what we expect
- Class.constructor = Class;
-
- // And make this class extendable
- Class.extend = arguments.callee;
-
- return Class;
- };
-})();
-/*
- * jStore Delegate Framework
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- this.jStoreDelegate = Class.extend({
- init: function(parent){
- // The Object this delgate operates for
- this.parent = parent;
- // Container for callbacks to dispatch.
- // eventType => [ callback, callback, ... ]
- this.callbacks = {};
- },
- bind: function(event, callback){
- if ( !$.isFunction(callback) ) return this;
- if ( !this.callbacks[ event ] ) this.callbacks[ event ] = [];
-
- this.callbacks[ event ].push(callback);
-
- return this;
- },
- trigger: function(){
- var parent = this.parent,
- args = [].slice.call(arguments),
- event = args.shift(),
- handlers = this.callbacks[ event ];
-
- if ( !handlers ) return false;
-
- $.each(handlers, function(){ this.apply(parent, args) });
- return this;
- }
- });
-
-})(jQuery);/**
- * jStore-jQuery Interface
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Setup the jStore namespace in jQuery for options storage
- $.jStore = {};
-
- // Seed the options in
- $.extend($.jStore, {
- EngineOrder: [],
- // Engines should put their availability tests within jStore.Availability
- Availability: {},
- // Defined engines should enter themselves into the jStore.Engines
- Engines: {},
- // Instanciated engines should exist within jStore.Instances
- Instances: {},
- // The current engine to use for storage
- CurrentEngine: null,
- // Provide global settings for overwriting
- defaults: {
- project: null,
- engine: null,
- autoload: true,
- flash: 'jStore.Flash.html'
- },
- // Boolean for ready state handling
- isReady: false,
- // Boolean for flash ready state handling
- isFlashReady: false,
- // An event delegate
- delegate: new jStoreDelegate($.jStore)
- .bind('jStore-ready', function(engine){
- $.jStore.isReady = true;
- if ($.jStore.defaults.autoload) engine.connect();
- })
- .bind('flash-ready', function(){
- $.jStore.isFlashReady = true;
- })
- });
-
- // Enable ready callback for jStore
- $.jStore.ready = function(callback){
- if ($.jStore.isReady) callback.apply($.jStore, [$.jStore.CurrentEngine]);
- else $.jStore.delegate.bind('jStore-ready', callback);
- }
-
- // Enable failure callback registration for jStore
- $.jStore.fail = function(callback){
- $.jStore.delegate.bind('jStore-failure', callback);
- }
-
- // Enable ready callback for Flash
- $.jStore.flashReady = function(callback){
- if ($.jStore.isFlashReady) callback.apply($.jStore, [$.jStore.CurrentEngine]);
- else $.jStore.delegate.bind('flash-ready', callback);
- }
-
- // Enable and test an engine
- $.jStore.use = function(engine, project, identifier){
- project = project || $.jStore.defaults.project || location.hostname.replace(/\./g, '-') || 'unknown';
-
- var e = $.jStore.Engines[engine.toLowerCase()] || null,
- name = (identifier ? identifier + '.' : '') + project + '.' + engine;
-
- if ( !e ) throw 'JSTORE_ENGINE_UNDEFINED';
-
- // Instanciate the engine
- e = new e(project, name);
-
- // Prevent against naming conflicts
- if ($.jStore.Instances[name]) throw 'JSTORE_JRI_CONFLICT';
-
- // Test the engine
- if (e.isAvailable()){
- $.jStore.Instances[name] = e; // The Easy Way
- if (!$.jStore.CurrentEngine){
- $.jStore.CurrentEngine = e;
- }
- $.jStore.delegate.trigger('jStore-ready', e);
- } else {
- if (!e.autoload) // Not available
- throw 'JSTORE_ENGINE_UNAVILABLE';
- else { // The hard way
- e.included(function(){
- if (this.isAvailable()) { // Worked out
- $.jStore.Instances[name] = this;
- // If there is no current engine, use this one
- if (!$.jStore.CurrentEngine){
- $.jStore.CurrentEngine = this;
- }
- $.jStore.delegate.trigger('jStore-ready', this);
- }
- else $.jStore.delegate.trigger('jStore-failure', this);
- }).include();
- }
- }
- }
-
- // Set the current storage engine
- $.jStore.setCurrentEngine = function(name){
- if (!$.jStore.Instances.length ) // If no instances exist, attempt to load one
- return $.jStore.FindEngine();
-
- if (!name && $.jStore.Instances.length >= 1) { // If no name is specified, use the first engine
- $.jStore.delegate.trigger('jStore-ready', $.jStore.Instances[0]);
- return $.jStore.CurrentEngine = $.jStore.Instances[0];
- }
-
- if (name && $.jStore.Instances[name]) { // If a name is specified and exists, use it
- $.jStore.delegate.trigger('jStore-ready', $.jStore.Instances[name]);
- return $.jStore.CurrentEngine = $.jStore.Instances[name];
- }
-
- throw 'JSTORE_JRI_NO_MATCH';
- }
-
- // Test all possible engines for straightforward useability
- $.jStore.FindEngine = function(){
- $.each($.jStore.EngineOrder, function(k){
- if ($.jStore.Availability[this]()){ // Find the first, easiest option and use it.
- $.jStore.use(this, $.jStore.defaults.project, 'default');
- return false;
- }
- })
- }
-
- // Provide a simple interface for storing/getting values
- $.jStore.store = function(key, value){
- if (!$.jStore.CurrentEngine) return false;
-
- if ( !value ) // Executing a get command
- return $.jStore.CurrentEngine.get(key);
- // Executing a set command
- return $.jStore.CurrentEngine.set(key, value);
- }
- // Provide a simple interface for storing/getting values
- $.jStore.remove = function(key){
- if (!$.jStore.CurrentEngine) return false;
-
- return $.jStore.CurrentEngine.rem(key);
- }
-
- // Provide a chainable interface for storing values/getting a value at the end of a chain
- $.fn.store = function(key, value){
- if (!$.jStore.CurrentEngine) return this;
-
- var result = $.jStore.store(key, value);
-
- return !value ? result : this;
- }
-
- // Provide a chainable interface for removing values
- $.fn.removeStore = function(key){
- $.jStore.remove(key);
-
- return this;
- }
-
- // Provide a way for users to call for auto-loading
- $.jStore.load = function(){
- if ($.jStore.defaults.engine)
- return $.jStore.use($.jStore.defaults.engine, $.jStore.defaults.project, 'default');
-
- // Attempt to find a valid engine, and catch any exceptions if we can't
- try {
- $.jStore.FindEngine();
- } catch (e) {}
- }
-
-})(jQuery);
-/**
- * jStore Engine Core
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- this.StorageEngine = Class.extend({
- init: function(project, name){
- // Configure the project name
- this.project = project;
- // The JRI name given by the manager
- this.jri = name;
- // Cache the data so we can work synchronously
- this.data = {};
- // The maximum limit of the storage engine
- this.limit = -1;
- // Third party script includes
- this.includes = [];
- // Create an event delegate for users to subscribe to event triggers
- this.delegate = new jStoreDelegate(this)
- .bind('engine-ready', function(){
- this.isReady = true;
- })
- .bind('engine-included', function(){
- this.hasIncluded = true;
- });
- // If enabled, the manager will check availability, then run include(), then check again
- this.autoload = false; // This should be changed by the engines, if they have required includes
- // When set, we're ready to transact data
- this.isReady = false;
- // When the includer is finished, it will set this to true
- this.hasIncluded = false;
- },
- // Performs all necessary script includes
- include: function(){
- var self = this,
- total = this.includes.length,
- count = 0;
-
- $.each(this.includes, function(){
- $.ajax({type: 'get', url: this, dataType: 'script', cache: true,
- success: function(){
- count++;
- if (count == total) self.delegate.trigger('engine-included');
- }
- })
- });
- },
- // This should be overloaded with an actual functionality presence check
- isAvailable: function(){
- return false;
- },
- /** Event Subscription Shortcuts **/
- ready: function(callback){
- if (this.isReady) callback.apply(this);
- else this.delegate.bind('engine-ready', callback);
- return this;
- },
- included: function(callback){
- if (this.hasIncluded) callback.apply(this);
- else this.delegate.bind('engine-included', callback);
- return this;
- },
- /** Cache Data Access **/
- get: function(key){
- return this.data[key] || null;
- },
- set: function(key, value){
- this.data[key] = value;
- return value;
- },
- rem: function(key){
- var beforeDelete = this.data[key];
- this.data[key] = null;
- return beforeDelete;
- }
- });
-
-})(jQuery);
-/*
- * jStore DOM Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Set up a static test function for this instance
- var sessionAvailability = $.jStore.Availability.session = function(){
- return !!window.sessionStorage;
- },
- localAvailability = $.jStore.Availability.local = function(){
- return !!(window.localStorage || window.globalStorage);
- };
-
- this.jStoreDom = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'DOM';
-
- // Set the Database limit
- this.limit = 5 * 1024 * 1024;
- },
- connect: function(){
- // Fire our delegate to indicate we're ready for data transactions
- this.delegate.trigger('engine-ready');
- },
- get: function(key){
- var out = this.db.getItem(key);
- // Gecko's getItem returns {value: 'the value'}, WebKit returns 'the value'
- return out && out.value ? out.value : out
- },
- set: function(key, value){
- this.db.setItem(key,value);
- return value;
- },
- rem: function(key){
- var out = this.get(key);
- this.db.removeItem(key);
- return out
- }
- })
-
- this.jStoreLocal = jStoreDom.extend({
- connect: function(){
- // Gecko uses a non-standard globalStorage[ www.example.com ] DOM access object for persistant storage.
- this.db = !window.globalStorage ? window.localStorage : window.globalStorage[location.hostname];
- this._super();
- },
- isAvailable: localAvailability
- })
-
- this.jStoreSession = jStoreDom.extend({
- connect: function(){
- this.db = sessionStorage;
- this._super();
- },
- isAvailable: sessionAvailability
- })
-
- $.jStore.Engines.local = jStoreLocal;
- $.jStore.Engines.session = jStoreSession;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 1 ] = 'local';
-
-})(jQuery);
-/*
- * jStore Flash Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- * jStore.swf Copyright (c) 2008 Daniel Bulli (http://www.nuff-respec.com)
- */
-(function($){
-
- // Set up a static test function for this instance
- var avilability = $.jStore.Availability.flash = function(){
- return !!($.jStore.hasFlash('8.0.0'));
- }
-
- this.jStoreFlash = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'Flash';
-
- // Bind our flashReady function to the jStore Delegate
- var self = this;
- $.jStore.flashReady(function(){ self.flashReady() });
- },
- connect: function(){
- var name = 'jstore-flash-embed-' + this.project;
-
- // To make Flash Storage work on IE, we have to load up an iFrame
- // which contains an HTML page that embeds the object using an
- // object tag wrapping an embed tag. Of course, this is unnecessary for
- // all browsers except for IE, which, to my knowledge, is the only browser
- // in existance where you need to complicate your code to fix bugs. Goddamnit. :(
- $(document.body)
- .append('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" ' +
- 'id="jStoreFlashFrame" src="' +$.jStore.defaults.flash + '"></iframe>');
- },
- flashReady: function(e){
- var iFrame = $('#jStoreFlashFrame')[0];
-
- // IE
- if (iFrame.Document && $.isFunction(iFrame.Document['jStoreFlash'].f_get_cookie)) this.db = iFrame.Document['jStoreFlash'];
- // Safari && Firefox
- else if (iFrame.contentWindow && iFrame.contentWindow.document){
- var doc = iFrame.contentWindow.document;
- // Safari
- if ($.isFunction($('object', $(doc))[0].f_get_cookie)) this.db = $('object', $(doc))[0];
- // Firefox
- else if ($.isFunction($('embed', $(doc))[0].f_get_cookie)) this.db = $('embed', $(doc))[0];
- }
-
- // We're ready to process data
- if (this.db) this.delegate.trigger('engine-ready');
- },
- isAvailable: avilability,
- get: function(key){
- var out = this.db.f_get_cookie(key);
- return out == 'null' ? null : out;
- },
- set: function(key, value){
- this.db.f_set_cookie(key, value);
- return value;
- },
- rem: function(key){
- var beforeDelete = this.get(key);
- this.db.f_delete_cookie(key);
- return beforeDelete;
- }
- })
-
- $.jStore.Engines.flash = jStoreFlash;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 2 ] = 'flash';
-
- /**
- * Flash Detection functions copied from the jQuery Flash Plugin
- * Copyright (c) 2006 Luke Lutman (http://jquery.lukelutman.com/plugins/flash)
- * Dual licensed under the MIT and GPL licenses.
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.opensource.org/licenses/gpl-license.php
- */
- $.jStore.hasFlash = function(version){
- var pv = $.jStore.flashVersion().match(/\d+/g),
- rv = version.match(/\d+/g);
-
- for(var i = 0; i < 3; i++) {
- pv[i] = parseInt(pv[i] || 0);
- rv[i] = parseInt(rv[i] || 0);
- // player is less than required
- if(pv[i] < rv[i]) return false;
- // player is greater than required
- if(pv[i] > rv[i]) return true;
- }
- // major version, minor version and revision match exactly
- return true;
- }
-
- $.jStore.flashVersion = function(){
- // ie
- try {
- try {
- // avoid fp6 minor version lookup issues
- // see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet…
- var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
- try { axo.AllowScriptAccess = 'always'; }
- catch(e) { return '6,0,0'; }
- } catch(e) {}
- return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
- // other browsers
- } catch(e) {
- try {
- if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
- return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
- }
- } catch(e) {}
- }
- return '0,0,0';
- }
-
-})(jQuery);
-
-// Callback fired when ExternalInterface is established
-function flash_ready(){
- $.jStore.delegate.trigger('flash-ready');
-}
-/*
- * jStore Google Gears Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Set up a static test function for this instance
- var avilability = $.jStore.Availability.gears = function(){
- return !!(window.google && window.google.gears)
- }
-
- this.jStoreGears = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'Google Gears';
-
- // Add required third-party scripts
- this.includes.push('http://code.google.com/apis/gears/gears_init.js');
-
- // Allow Autoloading on fail
- this.autoload = true;
- },
- connect: function(){
- // Create our database connection
- var db = this.db = google.gears.factory.create('beta.database');
- db.open( 'jstore-' + this.project );
- db.execute( 'CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)' );
-
- // Cache the data from the table
- this.updateCache();
- },
- updateCache: function(){
- // Read the database into our cache object
- var result = this.db.execute( 'SELECT k,v FROM jstore' );
- while (result.isValidRow()){
- this.data[result.field(0)] = result.field(1);
- result.next();
- } result.close();
-
- // Fire our delegate to indicate we're ready for data transactions
- this.delegate.trigger('engine-ready');
- },
- isAvailable: avilability,
- set: function(key, value){
- // Update the database
- var db = this.db;
- db.execute( 'BEGIN' );
- db.execute( 'INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key,value] );
- db.execute( 'COMMIT' );
- return this._super(key, value);
- },
- rem: function(key){
- // Update the database
- var db = this.db;
- db.execute( 'BEGIN' );
- db.execute( 'DELETE FROM jstore WHERE k = ?', [key] );
- db.execute( 'COMMIT' );
- return this._super(key);
- }
- })
-
- $.jStore.Engines.gears = jStoreGears;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 3 ] = 'gears';
-
-})(jQuery);
-/*
- * jStore HTML5 Specification Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Set up a static test function for this instance
- var avilability = $.jStore.Availability.html5 = function(){
- return !!window.openDatabase
- }
-
- this.jStoreHtml5 = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'HTML5';
-
- // Set the Database limit
- this.limit = 1024 * 200;
- },
- connect: function(){
- // Create our database connection
- var db = this.db = openDatabase('jstore-' + this.project, '1.0', this.project, this.limit);
- if (!db) throw 'JSTORE_ENGINE_HTML5_NODB';
- db.transaction(function(db){
- db.executeSql( 'CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)' );
- });
-
- // Cache the data from the table
- this.updateCache();
- },
- updateCache: function(){
- var self = this;
- // Read the database into our cache object
- this.db.transaction(function(db){
- db.executeSql( 'SELECT k,v FROM jstore', [], function(db, result){
- var rows = result.rows, i = 0, row;
- for (; i < rows.length; ++i){
- row = rows.item(i);
- self.data[row.k] = row.v;
- }
-
- // Fire our delegate to indicate we're ready for data transactions
- self.delegate.trigger('engine-ready');
- });
- });
- },
- isAvailable: avilability,
- set: function(key, value){
- // Update the database
- this.db.transaction(function(db){
- db.executeSql( 'INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key,value]);
- });
- return this._super(key, value);
- },
- rem: function(key){
- // Update the database
- this.db.transaction(function(db){
- db.executeSql( 'DELETE FROM jstore WHERE k = ?', [key] )
- })
- return this._super(key);
- }
- })
-
- $.jStore.Engines.html5 = jStoreHtml5;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 0 ] = 'html5';
-
-})(jQuery);
-/*
- * jStore IE Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Set up a static test function for this instance
- var avilability = $.jStore.Availability.ie = function(){
- return !!window.ActiveXObject;
- }
-
- this.jStoreIE = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'IE';
-
- // Allow Autoloading on fail
- this.limit = 64 * 1024;
- },
- connect: function(){
- // Create a hidden div to store attributes in
- this.db = $('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-' + this.project + '"></div>')
- .appendTo(document.body).get(0);
- // Fire our delegate to indicate we're ready for data transactions
- this.delegate.trigger('engine-ready');
- },
- isAvailable: avilability,
- get: function(key){
- this.db.load(this.project);
- return this.db.getAttribute(key);
- },
- set: function(key, value){
- this.db.setAttribute(key, value);
- this.db.save(this.project);
- return value;
- },
- rem: function(key){
- var beforeDelete = this.get(key);
- this.db.removeAttribute(key);
- this.db.save(this.project);
- return beforeDelete;
- }
- })
-
- $.jStore.Engines.ie = jStoreIE;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 4 ] = 'ie';
-
-})(jQuery);
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/jquery.jstore.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/jquery.jstore.js Fri Apr 09 18:09:54 2010 -0400
@@ -0,0 +1,1810 @@
+/*!
+ * jStore 2.0 - Persistent Client Side Storage
+ *
+ * Copyright (c) 2010 Eric Garside (http://eric.garside.name/)
+ * Dual licensed under:
+ * MIT: http://www.opensource.org/licenses/mit-license.php
+ * GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
+ *
+ * ---------------------------
+ *
+ * jStore Flash Storage Component
+ *
+ * Copyright (c) 2006 Jeff Lerman (jeff(a)blip.tv)
+ * Licensed under the Creative Commons Attribution 3.0 United States License:
+ * http://creativecommons.org/licenses/by/3.0/us
+ */
+
+"use strict";
+
+/*global Class, window, jQuery, ActiveXObject, google */
+
+/*jslint white: true, browser: true, onevar: true, undef: true, eqeqeq: true, bitwise: true, regexp: false, strict: true, newcap: true, immed: true, maxerr: 50, indent: 4 */
+
+(function ($, window) {
+
+ //------------------------------
+ //
+ // Constants
+ //
+ //------------------------------
+
+ //------------------------------
+ // Exceptions
+ //------------------------------
+
+ /**
+ * An exception thrown by the StorageEngine class whenever its data accessor methods
+ * are called before the engine is ready to transact data.
+ */
+ var EX_UNSTABLE = 'JSTORE_ENGINE_UNSTABLE',
+
+ /**
+ * An exception thrown by jStore whenever an undefined storage engine is referenced for
+ * some task by an invalid JRI (jStore Resource Identifier).
+ */
+ EX_UNKNOWN = 'JSTORE_UNKNOWN_ENGINE_REQUESTED',
+
+ /**
+ * An exception thrown by jStore whenever a given flavor of storage is double defined.
+ */
+ EX_COLLISION = 'JSTORE_ENGINE_NAMESPACE_COLLISION',
+
+ /**
+ * An exception thrown by jStore whenever a jri is double applied to a resource.
+ */
+ EX_DUPLICATE = 'JSTORE_RESOURCE_NAMESPACE_COLLISION',
+
+ /**
+ * An exception thrown by jStore whenever a given flavor of storage has no defined engine.
+ */
+ EX_UNAVAILABLE = 'JSTORE_ENGINE_UNAVAILABLE',
+
+ /**
+ * An exception thrown by jStore whenever an invalid flavor type is used.
+ */
+ EX_INVALID = 'JSTORE_INVALID_FLAVOR',
+
+ //------------------------------
+ // Regular Expressions
+ //------------------------------
+
+ /**
+ * Regular expression to test property values for being JSON.
+ */
+ RX_JSON = (function ()
+ {
+ try
+ {
+ return new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$');
+ }
+ catch (e)
+ {
+ return (/^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/);
+ }
+ }()),
+
+ //------------------------------
+ // Storage Flavors
+ //------------------------------
+
+ /**
+ * The storage flavor identifier for HTML5 local storage.
+ */
+ FLAVOR_LOCAL = 'jstore-html5-local',
+
+ /**
+ * The storage flavor identifier for HTML5 database storage.
+ */
+ FLAVOR_SQL = 'jstore-html5-sql',
+
+ /**
+ * The storage flavor identifier for Adobe Flash SharedObject storage.
+ */
+ FLAVOR_FLASH = 'jstore-flash',
+
+ /**
+ * The storage flavor identifier for Google Gears storage.
+ */
+ FLAVOR_GEARS = 'jstore-google-gears',
+
+ /**
+ * The storage flavor identifier for Internet Explorer storage, available to IE7 and IE6.
+ */
+ FLAVOR_MSIE = 'jstore-msie',
+
+ //------------------------------
+ //
+ // Property Declaration
+ //
+ //------------------------------
+
+ /**
+ * The base StorageEngine class which each "storage flavor" will extend to meet the
+ * requirements for its specific implementation.
+ */
+ StorageEngine,
+
+ /**
+ * The jStore object. Internal to this closure, jStore is referenced by "_". It is
+ * exposed to jQuery below, and made publicly accessible through jQuery.jStore
+ */
+ _ = {},
+
+ /**
+ * The engines available to jStore for use. These are the class definitions for flavored
+ * storage engines.
+ *
+ * Signature:
+ * {
+ * <storageFlavor>: <flavoredStorageEngineDefinition>,
+ *
+ * ...
+ * }
+ */
+ definitions = {},
+
+ /**
+ * Active engines instantiated by jStore, indexed by their JRI.
+ *
+ * Signature:
+ * {
+ * <engineJRI>: <engineInstance>,
+ *
+ * ...
+ * }
+ */
+ engines = {},
+
+ /**
+ * If we are going to be using the flash storage engine, we want to postpone the jStore ready event until the jStore
+ * isFlashReady flag is also true. This property is set whenever flash is determined to be the storage engine.
+ */
+ waitForFlash = false,
+
+ /**
+ * Storage for listeners, indexed by content and event type.
+ *
+ * Signature:
+ * {
+ * <context>:
+ * {
+ * <eventType>: [<listener>, ...],
+ *
+ * ...
+ * },
+ *
+ * ...
+ * }
+ */
+ events = {},
+
+ /**
+ * The configuration for this implementation.
+ *
+ * Signature:
+ * {
+ * project: <defaultProjectName>,
+ *
+ * flash: <pathToFlashBootloader>,
+ *
+ * json: <pathToJSONFile>,
+ *
+ * errorCallback: <listenerToNotifyOnError>
+ * }
+ */
+ configurations =
+ {
+ project: undefined,
+
+ flash: 'jStore.Flash.html',
+
+ json: 'browser.json.js'
+ },
+
+ /**
+ * The active storage engine, being used to satisfy the get/set/remove functions on the jStore and jQuery
+ * objects.
+ */
+ active;
+
+ //------------------------------
+ //
+ // Internal Methods
+ //
+ //------------------------------
+
+ /**
+ * Determine if the given flavor is valid.
+ *
+ * @param flavor The flavor to test.
+ *
+ * @return True if the flavor is valid, false otherwise.
+ */
+ function validFlavor(flavor)
+ {
+ switch (flavor)
+ {
+
+ case FLAVOR_LOCAL:
+ case FLAVOR_SQL:
+ case FLAVOR_FLASH:
+ case FLAVOR_GEARS:
+ case FLAVOR_MSIE:
+ return true;
+
+ default:
+ return false;
+
+ }
+ }
+
+ /**
+ * Performs enhanced type comparison on an object. This is more reliable method
+ * of type checking a variable than a simple typeof comparison. The reason is that,
+ * typeof will reduce to the lowest common type.
+ *
+ * "typeof []" returns Object, and not Array.
+ * "typeof {}" returns Object as well.
+ *
+ * typecheck( [], 'Array' ) : returns true;
+ * typecheck( [], 'Object' ) : returns false;
+ *
+ * @param type The variable type to check.
+ *
+ * @param compare A string representing the literal type to check.
+ *
+ * @return True if the variable "type" matches the compare literal.
+ */
+ function typecheck(type, compare)
+ {
+ return !type ? false : type.constructor.toString().match(new RegExp(compare + '\\(\\)', 'i')) !== null;
+ }
+
+ /**
+ * If the provided listener is a valid function, it will be triggered with the provided context
+ * and parameters.
+ *
+ * @param listener The listener being triggered.
+ *
+ * @param context The context to provide to the listener.
+ *
+ * @param parameters The parameters to pass to the listener as arguments.
+ *
+ * @return The response of the notified listener.
+ */
+ function notify(listener, context, parameters)
+ {
+ if (typecheck(listener, 'Function'))
+ {
+ return listener.apply(context || _, typecheck(parameters, 'Array') ? parameters : [parameters]);
+ }
+ }
+
+ /**
+ * Load the given script.
+ *
+ * @param path The path to the file to include.
+ *
+ * @param listener The listener to notify when the file finishes loading.
+ */
+ function loadScript(path, listener)
+ {
+ $.ajax(
+ {
+ url: path,
+ complete: listener || $.noop(),
+ type: 'GET',
+ dataType: 'script',
+ cache: false
+ });
+ }
+
+ /**
+ * Checks the type of the value, and returns a value safe to persist in any client-side mechanism.
+ *
+ * @param value The value which should be prepared for storage.
+ *
+ * @return A value safe for storage.
+ */
+ function prepareForStorage(value)
+ {
+ if (value === undefined)
+ {
+ return '';
+ }
+
+ if (typecheck(value, 'Object') ||
+ typecheck(value, 'Array') ||
+ typecheck(value, 'Function'))
+ {
+ return JSON.stringify(value);
+ }
+
+ return value;
+ }
+
+ /**
+ * Checks the type of the value, and returns a value safe for access in any client-side mechanism.
+ *
+ * @param value The value which should be prepared for use.
+ *
+ * @return A value safe for use.
+ */
+ function prepareForRevival(value)
+ {
+ return RX_JSON.test(value) ? JSON.parse(value) : value;
+ }
+
+ /**
+ * Normalize a key before using it, to ensure it's valid.
+ *
+ * @param key The key to normalize.
+ *
+ * @return A normalized key, safe for storage.
+ */
+ function normalizeKey(key)
+ {
+ return key.replace(/^\s+|\s+$/g, "");
+ }
+
+ /**
+ * Define a flavored storage engine.
+ *
+ * @throws EX_COLLISION, EX_INVALID
+ *
+ * @param flavor The flavor of engine being defined.
+ *
+ * @param definition An object containing the new properties and methods for the engine extension.
+ *
+ * @param availability A function to invoke which must return a boolean value indicating the
+ * availability of the storage flavor on this browser.
+ */
+ function define(flavor, definition, availability)
+ {
+ if (!validFlavor(flavor))
+ {
+ throw EX_INVALID;
+ }
+
+ if (availability[flavor] !== undefined)
+ {
+ throw EX_COLLISION;
+ }
+
+ /**
+ * The logic here has been reworked so unavailable flavors are discarded, so we don't needlessly
+ * bloat the runtime size of jStore.
+ */
+ if (notify(availability) === true)
+ {
+ _.available[flavor] = true;
+
+ definition.flavor = flavor;
+
+ definitions[flavor] = StorageEngine.extend(definition);
+ }
+ else
+ {
+ _.available[flavor] = false;
+
+ // Filter the invalid flavor out of the priority list.
+ _.enginePriority = $.map(_.enginePriority, function (engine)
+ {
+ if (engine === flavor)
+ {
+ return null;
+ }
+ else
+ {
+ return engine;
+ }
+ });
+ }
+ }
+
+ /**
+ * Make the jStore library ready.
+ */
+ function makeReady()
+ {
+ if (_.isReady)
+ {
+ return;
+ }
+
+ if ((waitForFlash && _.isFlashReady) || !waitForFlash)
+ {
+ _.isReady = true;
+ _.trigger('jstore-ready', [engines[active]]);
+ }
+ }
+
+ /**
+ * Create a best-fit engine.
+ */
+ function createBestFitEngine()
+ {
+ _.create(_.enginePriority[0], undefined, 'best-fit');
+ }
+
+ /**
+ * Get the flash version currently supported in this browser.
+ *
+ * @return The flash version.
+ */
+ function flashVersion()
+ {
+ // MSIE
+ try
+ {
+ // avoid fp6 minor version lookup issues
+ // see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet…
+ var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
+
+ try
+ {
+ axo.AllowScriptAccess = 'always';
+ }
+ catch (axo_e)
+ {
+ return '6,0,0';
+ }
+
+ return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
+ }
+
+ // Real browsers
+ catch (e)
+ {
+ try
+ {
+ if (navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin)
+ {
+ return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
+ }
+ }
+ catch (flash_e)
+ {}
+ }
+
+ return '0,0,0';
+ }
+
+ /**
+ * Flash Detection functions copied from the jQuery Flash Plugin
+ *
+ * Copyright (c) 2006 Luke Lutman (http://jquery.lukelutman.com/plugins/flash)
+ *
+ * Dual licensed under the MIT and GPL licenses.
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/gpl-license.php
+ *
+ * @param version The version to compare to.
+ *
+ * @return True if the version is greater than or equal to the required version, false otherwise.
+ */
+ function hasFlashVersion(version)
+ {
+ var playerVersion = flashVersion().match(/\d+/g),
+ requiredVersion = version.match(/\d+/g),
+ index = 0,
+ player,
+ required;
+
+ for (; index < 3; index++)
+ {
+ player = parseInt(playerVersion[index], 10);
+ required = parseInt(requiredVersion[index], 10);
+
+ // Player version is less than what is required.
+ if (player < required)
+ {
+ return false;
+ }
+
+ // Player version is greater than what is required.
+ else if (player > required)
+ {
+ return true;
+ }
+ }
+
+ // Player and required version match exactly.
+ return true;
+ }
+
+ //------------------------------
+ //
+ // Plugin Definition
+ //
+ //------------------------------
+
+ //------------------------------
+ // Error Declaration
+ //------------------------------
+
+ //------------------------------
+ // Plugin Creation
+ //------------------------------
+
+ /**
+ * The jStore object. Manages a collection of StorageEngines for particular "storage flavors", or the types
+ * of storage solutions available to each browser.
+ *
+ * 2.0 Version Notes:
+ *
+ * - The user is now responsible for third-party script includes, with the exception of flash.
+ *
+ * - jStore has been given sole responsibility for testing engine availability.
+ *
+ * - For the sake of naming conventions, all property names now start with a lowercase, and are camel-cased.
+ *
+ * The following properties have been changed since the 1.2.x release:
+ *
+ * - EngineOrder: For the sake of naming conventions, renamed to enginePriority.
+ *
+ * The following properties and methods have been removed since the 1.2.x release:
+ *
+ * - Availability: jStore's engines would add their availability tests to this object, so jStore could test
+ * them. With the changes to how availability testing works, this property has been removed.
+ * A new property, "available" on jStore contains a set of available engines.
+ *
+ * - Engines: Formerly contained the definitions of storage engines. This property has been removed, and
+ * storage of these definitions has been moved internal to the closure.
+ *
+ * - Instances: Formerly contained instantiated storage engines. This property has been removed, and storage
+ * of instantiated engines has been moved internal to the closure.
+ *
+ * - CurrentEngine: Formerly contained the active storage engine being used for transacting data through the jStore
+ * and/or jQuery objects. This property has been removed, and storage of the current engine has
+ * been moved internal to the closure. A new method, "activeEngine" has been added to jQuery to
+ * get and set the active engine to use.
+ *
+ * - defaults: Formerly used to set the implementation options for jStore. This property has been removed and
+ * replaced with a new configuration metho on the jStore object.
+ *
+ * - delegate: The delegate class has been removed in favor of a much simpler bind/trigger accessor system, which
+ * is accessible contextually through storage engines, or generically through jStore.
+ *
+ * + fail: This registration class bound events on the delegate for jstore-fail events. Instead, use:
+ * jStore.bind('jstore-failure', listener);
+ *
+ * + flashReady: This registration class bound events on the delegate for flash-ready events. The jstore-ready method
+ * now accounts for waiting for flash readyness, if and only if the flash engine is being used. Simply
+ * call to jStore.ready().
+ *
+ * + load: Replaced with the init() method, which performs the same basic functions as the old load() method. Also,
+ * the init function is now domready safe, meaning it wraps itself in a domready listener, so the end user
+ * doesn't have to.
+ *
+ * + FindEngine: Removed entirely. The functionality provided by this method now implicitly occurs with the new define()
+ * system implemented for engine flavors.
+ *
+ * + setCurrentEngine: Replaced by activeEngine(). Set the current active engine by passing in the JRI.
+ *
+ * + safeStore: Replaced by a method internal to this closure, "prepareForStorage".
+ *
+ * + safeResurrect: Replaced by a method internal to this closure, "prepareForRevival".
+ *
+ * + use: Replaced by "create".
+ */
+ $.extend(_, {
+
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ /**
+ * The priority order in which engines should be tested for use. The lower their index in the array, the higher
+ * their priority for use.
+ *
+ * Be weary when reconfiguring the priority order of engines! jStore will use the first available engine it finds
+ * based on its priority when autoloading.
+ *
+ * This array is filtered out as engines are defined, with invalid engines being removed.
+ *
+ * Signature:
+ * [FLAVOR_<storageFlavor>, ...]
+ */
+ enginePriority: [FLAVOR_LOCAL, FLAVOR_SQL, FLAVOR_FLASH, FLAVOR_MSIE],
+
+ /**
+ * A collection of the availability states of engines, indexed by their flavor.
+ *
+ * Signature:
+ * {
+ * <storageFlavor>: true|false,
+ *
+ * ...
+ * }
+ */
+ available: {},
+
+ /**
+ * Flag to determine if the jStore library is ready. jStore becomes ready once the dom is ready and all necessary
+ * startup procedures required by jStore to function properly are completed.
+ */
+ isReady: false,
+
+ /**
+ * With the flash storage engine, we have to jump through a couple of hoops before the flash engine is ready to work.
+ * This flag tracks whether or not the flash storage is available.
+ */
+ isFlashReady: false,
+
+ /**
+ * The available engine flavors.
+ */
+ flavors:
+ {
+ local: FLAVOR_LOCAL,
+
+ sql: FLAVOR_SQL,
+
+ flash: FLAVOR_FLASH,
+
+ gears: FLAVOR_GEARS,
+
+ msie: FLAVOR_MSIE
+ },
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @throws EX_INVALID
+ *
+ * @param project The name of the jStore project. Used to generate a JRI for the engine we create.
+ *
+ * @param configuration Optionally, an object containing configuration options for this implementation.
+ *
+ * @param flavor Optionally, the flavor of storage to use. If not provided, jStore will pick the
+ * best flavor, based on the current browser.
+ *
+ * @return jStore
+ */
+ init: function (project, configuration, flavor)
+ {
+ // Extend our plugin configurations
+ $.extend(configurations, {project: project}, configuration);
+
+ $(function ()
+ {
+ // If JSON parsing isn't defined in this browser, include it.
+ if (window.JSON === undefined)
+ {
+ loadScript(configurations.json);
+ }
+
+ // If we have an explicit flavor to use, use it.
+ if (flavor !== undefined)
+ {
+ _.create(flavor, project, 'default');
+ }
+
+ // Otherwise, attempt to create a best-fit engine.
+ else
+ {
+ createBestFitEngine();
+ }
+ });
+
+ return _;
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ /**
+ * Create an instance of a flavored engine.
+ *
+ * @throws EX_INVALID, EX_UNAVAILABLE, EX_DUPLICATE
+ *
+ * @param flavor The flavor to create the engine with.
+ *
+ * @param project The project identifier for this instance.
+ *
+ * @param identifier Some arbitrary identifier for this project instance of the engine.
+ *
+ * @return The created instance.
+ */
+ create: function (flavor, project, identifier)
+ {
+ project = project || configurations.project || location.hostname.replace(/\./g, '-') || 'unknown';
+
+ if (!validFlavor(flavor))
+ {
+ throw EX_INVALID;
+ }
+
+ if (definitions[flavor] === undefined)
+ {
+ throw EX_UNAVAILABLE;
+ }
+
+ var jri = (identifier !== undefined ? identifier + '.' : '') + project + '.' + flavor,
+ engine;
+
+ if (engines[jri] !== undefined)
+ {
+ throw EX_DUPLICATE;
+ }
+
+ // Create our engine instance.
+ engine = engines[jri] = new definitions[flavor](project, jri);
+
+ // Set up a listener for our jstore-engine-ready event.
+ engine.ready(function ()
+ {
+ _.trigger('jstore-engine-ready', [engine]);
+ });
+
+ if (flavor === FLAVOR_FLASH && !_.isFlashReady)
+ {
+ if (active === undefined)
+ {
+ waitForFlash = true;
+ }
+
+ // Define a window-accessible function for flash to call via ExternalInterface
+ window.jstore_ready = function ()
+ {
+ _.isFlashReady = true;
+ _.trigger('flash-ready');
+
+ if (active === undefined)
+ {
+ makeReady();
+ }
+
+ // Remove the callback from the window scope, as it is no longer necessary
+ window.flash_ready = undefined;
+ };
+
+ window.jstore_error = function (message)
+ {
+ _.trigger('jstore-error', ['JSTORE_FLASH_EXCEPTION', null, message]);
+ };
+
+ $('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="' +
+ configurations.flash + '"></iframe>').appendTo('body');
+ }
+ else if (active === undefined)
+ {
+ active = jri;
+ makeReady();
+ }
+
+ return engine;
+ },
+
+ /**
+ * Fetch an engine by it's JRI.
+ *
+ * @param jri The JRI of the engine to retrieve.
+ *
+ * @return The requested engine.
+ */
+ engine: function (jri)
+ {
+ return engines[jri];
+ },
+
+ /**
+ * Returns the active storage engine being used. If a value is passed, sets that engine as the active engine.
+ *
+ * @throws EX_UNKNOWN
+ *
+ * @param jri Optionally, the JRI of the engine to make active, if it should be changed.
+ *
+ * @return The active storage engine.
+ */
+ activeEngine: function (jri)
+ {
+ if (jri !== undefined)
+ {
+ if (engines[jri] === undefined)
+ {
+ throw EX_UNKNOWN;
+ }
+ else
+ {
+ active = jri;
+ }
+ }
+
+ return engines[active];
+ },
+
+ /**
+ * Bind an event listener.
+ *
+ * @param event The event to bind a listener on.
+ *
+ * @param listener The listener to notify when the event occurs.
+ *
+ * @param context The context of the binding. A string representing the engine flavor
+ * binding the event, or undefined to indicate it's a jStore event.
+ *
+ * @return jStore
+ */
+ bind: function (event, listener, context)
+ {
+ context = context || 'jstore';
+
+ if (events[context] === undefined)
+ {
+ events[context] = {};
+ }
+
+ if (events[context][event] === undefined)
+ {
+ events[context][event] = [listener];
+ }
+ else
+ {
+ events[context][event].push(listener);
+ }
+
+ return _;
+ },
+
+ /**
+ * Trigger an event, notifying any bound listeners.
+ *
+ * @param event The event to trigger.
+ *
+ * @param parameters Any additional parameters to pass to the listeners being notified.
+ *
+ * @param context The context of the binding. A string representing the engine flavor
+ * binding the event, or undefined to indicate it's a jStore event.
+ *
+ * @return jStore
+ */
+ trigger: function (event, parameters, context)
+ {
+ context = context || 'jstore';
+
+ if (events[context] !== undefined)
+ {
+ if (events[context][event] !== undefined)
+ {
+ $.each(events[context][event], function ()
+ {
+ notify(this, _, parameters);
+ });
+ }
+ }
+
+ return _;
+ },
+
+ /**
+ * Bind a listener to be notified when jStore causes a non-fatal exception.
+ *
+ * @param listener The listener to notify when a failure occurs.
+ */
+ error: function (listener)
+ {
+ _.bind('jstore-error', listener);
+ },
+
+ /**
+ * Bind a listener to be notified when jStore is ready.
+ *
+ * @param listener The listener to notify when jStore is ready.
+ *
+ * @return jStore
+ */
+ ready: function (listener)
+ {
+ if (_.isReady)
+ {
+ notify(listener);
+ }
+ else
+ {
+ _.bind('jstore-ready', listener);
+ }
+
+ return _;
+ },
+
+ /**
+ * Bind a listener to be notified when jStore and the default engine are ready.
+ *
+ * @param listener The listener to notify when jStore and it's default engine are ready.
+ *
+ * @return jStore
+ */
+ engineReady: function (listener)
+ {
+ if (_.isReady)
+ {
+ notify(listener);
+ }
+ else
+ {
+ _.bind('jstore-engine-ready', listener);
+ }
+
+ return _;
+ },
+
+ /**
+ * A combined getter/setter for the active engine.
+ *
+ * @param key The key of the property to get, or set.
+ *
+ * @param value If a valid value is provided, sets the engine.
+ *
+ * @return The requested property value.
+ */
+ store: function (key, value)
+ {
+ return value === undefined ? _.get(key) : _.set(key, value);
+ },
+
+ /**
+ * Remove a property from the active engine.
+ *
+ * @param key The key of the property to remove.
+ *
+ * @return The value of the property before removal.
+ */
+ remove: function (key)
+ {
+ return _.activeEngine().remove(key);
+ },
+
+ /**
+ * Get a property from the active engine.
+ *
+ * @param key The key of the property to get.
+ *
+ * @return The value of the property.
+ */
+ get: function (key)
+ {
+ return _.activeEngine().get(key);
+ },
+
+ /**
+ * Set a property on the active engine.
+ *
+ * @param key The key of the property to set.
+ *
+ * @param value The value to set the property to.
+ *
+ * @return The new value of the property.
+ */
+ set: function (key, value)
+ {
+ return _.activeEngine().set(key, value);
+ }
+
+ });
+
+ //------------------------------
+ // Core Extension
+ //------------------------------
+
+ //------------------------------
+ //
+ // Class Definition
+ //
+ //------------------------------
+
+ /**
+ * The StorageEngine class is the unified API through which jStore accesses and manipulates
+ * the various storage flavors available.
+ *
+ * 2.0 Version Notes:
+ *
+ * - All third-party loading is now the responsibility of the developer.
+ *
+ * - The delegate class has been removed entirely. Engines have been given "bind" and "trigger" methods
+ * to interact directly with the delegate like-replacement that has been added to jStore.
+ *
+ * - Engine availability has been moved out of the engines themselves, and elevated to a jStore
+ * responsibility.
+ *
+ * The following methods have changed since the 1.2.x release:
+ *
+ * - get: When "get"ting a non-stored property, the get function will now return "undefined"
+ * instead of "null". "null" can now be used as a valid property value.
+ *
+ * - rem: Renamed to "remove". I always felt dirty about "rem" being vaguely explicit.
+ *
+ * The following properties have been removed since the 1.2.x release:
+ *
+ * - autoload: Part of the third-party loading logic.
+ *
+ * - hasIncluded: Part of the third-party loading logic.
+ *
+ * - includes: Part of the third-party loading logic.
+ *
+ * - isAvailable: Part of the availability logic elevated to jStore.
+ *
+ * @throws EX_UNSTABLE
+ */
+ StorageEngine = Class.extend({
+
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ /**
+ * The project which owns this storage engine.
+ */
+ project: undefined,
+
+ /**
+ * The JRI (jStore Resource Identifier) acts as a uuid for this specific instance
+ * of the storage engine.
+ */
+ jri: undefined,
+
+ /**
+ * The flavor of this engine.
+ */
+ flavor: undefined,
+
+ /**
+ * The actual database object which data is transacted through.
+ */
+ database: undefined,
+
+ /**
+ * A StorageEngine should always respond to fetch requests synchronously. However, some
+ * of the storage flavors require callback-based asynchronous access. To get around this,
+ * we simlpy require all engines to function off a primary data cache, to allow for
+ * synchronous access across all implementations.
+ *
+ * Signature:
+ * {
+ * <propertyKey>: <propertyValue>,
+ *
+ * ...
+ * }
+ */
+ data: undefined,
+
+ /**
+ * A number of storage engines enforce a size limit as to what they will persist for a given site.
+ * This limit is not monitored or computed by jStore currently, and this property will merely give
+ * a static indication of the total size alloted to the engine, as defined by the storage flavor.
+ */
+ limit: undefined,
+
+ /**
+ * Each storage flavor has a different process to go through before it's "ready" to transact data. This
+ * property stores the state of the engine's readyness, and uses it to notify listeners whenever jStore
+ * is ready to function.
+ */
+ isReady: undefined,
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param project The project which instantiated this engine.
+ *
+ * @param jri The uuid assigned to this instance by jStore.
+ */
+ init: function (project, jri)
+ {
+ this.project = project;
+ this.jri = jri;
+ this.data = {};
+ this.isReady = false;
+ this.updateCache();
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ /**
+ * Update the cache.
+ */
+ updateCache: function ()
+ {
+ this.isReady = true;
+ this.trigger('engine-ready', [this]);
+ },
+
+ /**
+ * Bind a listener to an event dispatched by this engine.
+ *
+ * @param event The event to bind on.
+ *
+ * @param listener The listener to notify when the event occurs.
+ */
+ bind: function (event, listener)
+ {
+ _.bind(event, listener, this.jri);
+ },
+
+ /**
+ * Trigger an event, notifying all bound listeners.
+ *
+ * @param event The event to trigger.
+ *
+ * @param parameters An optional Array of parameters to pass to the listeners.
+ */
+ trigger: function (event, parameters)
+ {
+ _.trigger(event, parameters, this.jri);
+ },
+
+ /**
+ * Bind a listener to the StorageEngine's ready event.
+ *
+ * @param listener The listener to notify whenever this engine is ready to transact data.
+ */
+ ready: function (listener)
+ {
+ if (this.isReady)
+ {
+ notify(listener, this);
+ }
+ else
+ {
+ this.bind('engine-ready', listener);
+ }
+ },
+
+ /**
+ * Get a property from the StorageEngine.
+ *
+ * @param key The property key of the data to retrieve.
+ *
+ * @return The property value, or "undefined" if the property isn't stored.
+ */
+ get: function (key)
+ {
+ this.__interruptAccess();
+
+ return this.data[key];
+ },
+
+ /**
+ * Sets a property in the StorageEngine.
+ *
+ * @param key The key of the property.
+ *
+ * @param value The value of the property.
+ *
+ * @return The new value of the property.
+ */
+ set: function (key, value)
+ {
+ this.__interruptAccess();
+
+ key = normalizeKey(key);
+
+ try
+ {
+ this.__set(key, value);
+ }
+ catch (e)
+ {
+ _.trigger('jstore-error', ['JSTORE_STORAGE_FAILURE', this.jri, e]);
+ }
+
+ this.data[key] = value;
+
+ return value;
+ },
+
+ /**
+ * Removes a property from the StorageEngine.
+ *
+ * @param key The property key of the data to remove.
+ *
+ * @return The value of the property, before it was removed.
+ */
+ remove: function (key)
+ {
+ this.__interruptAccess();
+
+ key = normalizeKey(key);
+
+ try
+ {
+ this.__remove(key);
+ }
+ catch (e)
+ {
+ _.trigger('jstore-error', ['JSTORE_REMOVE_FAILURE', this.jri, e]);
+ }
+
+ var buffer = this.data[key];
+
+ this.data[key] = undefined;
+
+ return buffer;
+ },
+
+ //------------------------------
+ // Internal Methods
+ //------------------------------
+
+ /**
+ * Ensures the engine is in a stable state for transacting data.
+ *
+ * @throws EX_UNSTABLE
+ */
+ __interruptAccess: function ()
+ {
+ if (!this.isReady)
+ {
+ throw EX_UNSTABLE;
+ }
+ },
+
+ /**
+ * Sets a property in the StorageEngine. This method should be overloaded to provide actual
+ * storage flavor integration.
+ *
+ * @param key The key of the property.
+ *
+ * @param value The value of the property.
+ *
+ * @return The new value of the property.
+ */
+ __set: function (key, value)
+ {
+ return;
+ },
+
+ /**
+ * Removes a property from the StorageEngine. This method should be overloaded to provide actual
+ * storage flavor integration.
+ *
+ * @param key The property key of the data to remove.
+ *
+ * @return The value of the property, before it was removed.
+ */
+ __remove: function (key)
+ {
+ return;
+ }
+
+ });
+
+ //------------------------------
+ //
+ // jQuery Hooks
+ //
+ //------------------------------
+
+ $.extend($.fn, {
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ /**
+ * A combined getter/setter for the active engine.
+ *
+ * @param key The key of the property to get, or set.
+ *
+ * @param value If a valid value is provided, sets the engine.
+ *
+ * @return jQuery
+ */
+ store: function (key, value)
+ {
+ if (value === undefined)
+ {
+ _.get(key);
+ }
+ else
+ {
+ _.set(key, value);
+ }
+
+ return this;
+ },
+
+ /**
+ * Remove a property from the active engine.
+ *
+ * @param key The key of the property to remove.
+ *
+ * @return jQuery
+ */
+ removeStore: function (key)
+ {
+ _.activeEngine().remove(key);
+
+ return this;
+ },
+
+ /**
+ * Get a property from the active engine.
+ *
+ * @param key The key of the property to get.
+ *
+ * @return The value of the property.
+ */
+ getStore: function (key)
+ {
+ return _.activeEngine().get(key);
+ },
+
+ /**
+ * Set a property on the active engine.
+ *
+ * @param key The key of the property to set.
+ *
+ * @param value The value to set the property to.
+ *
+ * @return jQuery
+ */
+ setStore: function (key, value)
+ {
+ _.activeEngine().set(key, value);
+
+ return this;
+ }
+
+ });
+
+ //------------------------------
+ //
+ // Event Bindings
+ //
+ //------------------------------
+
+ //------------------------------
+ //
+ // Startup Code
+ //
+ //------------------------------
+
+ //------------------------------
+ // Expose jStore through jQuery
+ //------------------------------
+
+ window.jStore = $.jStore = _;
+
+ //------------------------------
+ //
+ // Engine Definitions
+ //
+ //------------------------------
+
+ //------------------------------
+ // Local
+ //------------------------------
+
+ define(FLAVOR_LOCAL,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: parseInt(5e5, 16),
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ this.database = window.globalStorage === undefined ? window.localStorage : window.globalStorage[location.hostname];
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function ()
+ {
+ var key, value;
+
+ for (key in this.database)
+ {
+ var has_key = false;
+ if (this.database.hasOwnProperty) {
+ if (this.database.hasOwnProperty(key)) {
+ has_key = true;
+ }
+ } else { // IE 8
+ if (this.database.getItem(key) !== null) {
+ has_key = true;
+ }
+ }
+
+ if (has_key) {
+ value = this.database.getItem(key);
+
+ // Gecko's getItem returns {value: 'the value'}, WebKit returns 'the value'
+ this.data[key] = prepareForRevival(value && value.value ? value.value : value);
+ }
+ }
+
+ this._super();
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ this.database.setItem(key, prepareForStorage(value));
+ },
+
+ __remove: function (key)
+ {
+ this.database.removeItem(key);
+ }
+ },
+
+ function ()
+ {
+ return window.localStorage !== undefined || window.globalStorage !== undefined;
+ });
+
+ //------------------------------
+ // SQL
+ //------------------------------
+
+ define(FLAVOR_SQL,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: parseInt(32e3, 16),
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ this.database = window.openDatabase('jstore-' + project, '1.0', project, this.limit);
+
+ if (!this.database)
+ {
+ throw 'JSTORE_SQL_NO_DB';
+ }
+
+ this.database.transaction(function (database)
+ {
+ database.executeSql('CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)');
+ });
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function ()
+ {
+ var self = this,
+ _super = this._super;
+
+ this.database.transaction(function (database)
+ {
+ database.executeSql('SELECT k,v FROM jstore', [], function (database, result)
+ {
+ var rows = result.rows,
+ index = 0,
+ row;
+
+ for (; index < rows.length; ++index)
+ {
+ row = rows.item(index);
+ self.data[row.k] = prepareForRevival(row.v);
+ }
+
+ _super.apply(self);
+ });
+ });
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ this.database.transaction(function (database)
+ {
+ database.executeSql('INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key, prepareForStorage(value)]);
+ });
+ },
+
+ __remove: function (key)
+ {
+ this.database.transaction(function (database)
+ {
+ database.executeSql('DELETE FROM jstore WHERE k = ?', [key]);
+ });
+ }
+ },
+
+ function ()
+ {
+ return window.openDatabase !== undefined;
+ });
+
+ //------------------------------
+ // Flash
+ //------------------------------
+
+ define(FLAVOR_FLASH,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: -1,
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ var self = this;
+
+ _.bind('flash-ready', function ()
+ {
+ self.__flashReadyListener();
+ });
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function (enable)
+ {
+ /**
+ * The default call to updateCache passes no variable, so we can short circuit the
+ * ready state until we explictly call this after flash ready.
+ */
+ if (enable === true)
+ {
+ var key,
+ dataset = this.database.jstore_get_all();
+
+ for (key in dataset)
+ {
+ if (dataset.hasOwnProperty(key))
+ {
+ this.data[key] = prepareForRevival(this.database.jstore_get(key));
+ }
+ }
+
+ this._super();
+ }
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ if (!this.database.jstore_set(key, prepareForStorage(value)))
+ {
+ _.trigger('jstore-error', ['JSTORE_STORAGE_FAILURE', this.jri, 'Flash Exception']);
+ }
+ },
+
+ __remove: function (key)
+ {
+ this.database.jstore_remove(key);
+ },
+
+ /**
+ * Triggered whenever flash is ready.
+ */
+ __flashReadyListener: function ()
+ {
+ var iFrame = $('#jStoreFlashFrame')[0],
+ frameDocument;
+
+ // MSIE
+ if (iFrame.Document !== undefined && typecheck(iFrame.Document.jStoreFlash.jstore_get, 'Function'))
+ {
+ this.database = iFrame.Document.jStoreFlash;
+ }
+
+ // Real Browsers
+ else if (iFrame.contentWindow && iFrame.contentWindow.document)
+ {
+ frameDocument = $(iFrame.contentWindow.document);
+
+ // Webkit
+ if (typecheck($('object', frameDocument)[0].jstore_get, 'Function'))
+ {
+ this.database = $('object', frameDocument)[0];
+ }
+
+ // Gecko
+ else if (typecheck($('embed', frameDocument)[0].jstore_get, 'Function'))
+ {
+ this.database = $('embed', frameDocument)[0];
+ }
+ }
+
+ if (this.database === undefined)
+ {
+ throw 'JSTORE_FLASH_REFERENCE_ISSUE';
+ }
+ else
+ {
+ this.updateCache(true);
+ }
+ }
+ },
+
+ function ()
+ {
+ return hasFlashVersion('9.0.0');
+ });
+
+ //------------------------------
+ // Gears
+ //------------------------------
+
+ define(FLAVOR_GEARS,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: -1,
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ this.database = google.gears.factory.create('beta.database');
+ this.database.open('jstore-' + project);
+ this.database.execute('CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)');
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function ()
+ {
+ var result = this.database.execute('SELECT k,v FROM jstore');
+
+ while (result.isValidRow())
+ {
+ this.data[result.field(0)] = prepareForRevival(result.field(1));
+ result.next();
+ }
+
+ result.close();
+
+ this._super();
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ this.database.execute('BEGIN');
+ this.database.execute('INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key, prepareForStorage(value)]);
+ this.database.execute('COMMIT');
+ },
+
+ __remove: function (key)
+ {
+ this.database.execute('BEGIN');
+ this.database.execute('DELETE FROM jstore WHERE k = ?', [key]);
+ this.database.execute('COMMIT');
+ }
+ },
+
+ function ()
+ {
+ return window.google !== undefined && window.google.gears !== undefined;
+ });
+
+ //------------------------------
+ // MSIE
+ //------------------------------
+
+ define(FLAVOR_MSIE,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: parseInt(1e4, 16),
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ this.database = $('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-' + project + '"></div>')
+ .appendTo(document.body).get(0);
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function ()
+ {
+ this.database.load(this.project);
+
+ var node = document.getElementById('jstore-' + this.project),
+ xmlDoc = node.XMLDocument,
+ root,
+ index = 0;
+
+ if (xmlDoc && xmlDoc.documentElement && xmlDoc.documentElement.attributes)
+ {
+ root = xmlDoc.documentElement;
+
+ for (; index < root.attributes.length; ++index)
+ {
+ this.data[root.attributes.item(index).nodeName] = prepareForRevival(root.attributes.item(index).nodeValue);
+ }
+ }
+
+ this._super();
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ this.database.setAttribute(key, prepareForStorage(value));
+ this.database.save(this.project);
+ },
+
+ __remove: function (key)
+ {
+ this.database.removeAttribute(key);
+ this.database.save(this.project);
+ }
+ },
+
+ function ()
+ {
+ return window.ActiveXObject !== undefined;
+ });
+
+}(jQuery, window));
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/json2.js
--- a/static/scripts/json2.js Fri Apr 09 13:02:15 2010 -0400
+++ b/static/scripts/json2.js Fri Apr 09 18:09:54 2010 -0400
@@ -1,6 +1,6 @@
/*
http://www.JSON.org/json2.js
- 2009-06-29
+ 2010-03-20
Public Domain.
@@ -8,6 +8,14 @@
See http://www.JSON.org/js.html
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+
+
This file creates a global JSON object containing two methods: stringify
and parse.
@@ -33,7 +41,7 @@
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
- bound to the object holding the key.
+ bound to the value
For example, this would serialize Dates as ISO strings.
@@ -136,15 +144,9 @@
This is a reference implementation. You are free to copy, modify, or
redistribute.
-
- This code should be minified before deployment.
- See http://javascript.crockford.com/jsmin.html
-
- USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
- NOT CONTROL.
*/
-/*jslint evil: true */
+/*jslint evil: true, strict: false */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
@@ -153,10 +155,13 @@
test, toJSON, toString, valueOf
*/
+
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
-var JSON = JSON || {};
+if (!this.JSON) {
+ this.JSON = {};
+}
(function () {
@@ -428,6 +433,7 @@
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
+ text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/class.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/packed/class.js Fri Apr 09 18:09:54 2010 -0400
@@ -0,0 +1,7 @@
+/*
+ * Class definition
+ *
+ * Copyright (c) 2008 John Resig (http://ejohn.org/blog/simple-javascript-inheritance/)
+ * Inspired by base2 and Prototype
+ */
+"use strict";(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(g){var f=this.prototype;a=true;var e=new this();a=false;for(var d in g){e[d]=(typeof g[d]==="function"&&typeof f[d]==="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super;this._super=f[h];var j=i.apply(this,arguments);this._super=k;return j}}(d,g[d])):g[d])}function c(){if(!a&&this.init){this.init.apply(this,arguments)}}c.prototype=e;c.constructor=c;c.extend=arguments.callee;return c}}());
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/galaxy.base.js
--- a/static/scripts/packed/galaxy.base.js Fri Apr 09 13:02:15 2010 -0400
+++ b/static/scripts/packed/galaxy.base.js Fri Apr 09 18:09:54 2010 -0400
@@ -1,1 +1,1 @@
-$(document).ready(function(){replace_big_select_inputs()});$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}function make_popupmen!
u(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id")+"-menu'></ul>");$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d)}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function array_length(b){if(b.length){return b.length}var c=0;for(var a in b){c++}return c}function replace_big_select_inputs(){$("select[name=dbkey]").each(function(){var a=$(this);if(a!
.find("option").length<20){return}var b=a.attr("value");var c=$("<inpu
t type='text' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",a.attr("name"));c.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var f=[];var e={};a.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}f.push(h);e[h]=g;e[g]=g;if(g==b){c.attr("value",h)}});if(c.attr("value")==""){c.attr("value","Click to Search or Select")}var d={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};c.autocomplete(f,d);a.replaceWith(c);c.parents("form").submit(function(){var h=c.attr("value");var g=e[h];if(g!==null&&g!==undefined){c.attr("value",g)}else{if(b!=""){c.attr("value",b)}else{c.attr("value","?")}}})})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-activ!
e").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text(k)}else{j=$("<input type='text'></input>").attr({value:k,size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){l.text(o);if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}$(document).ready(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus()});
\ No newline at end of file
+$(document).ready(function(){replace_big_select_inputs()});$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}function make_popupmen!
u(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id")+"-menu'></ul>");$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d)}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function array_length(b){if(b.length){return b.length}var c=0;for(var a in b){c++}return c}function replace_big_select_inputs(){$("select[name=dbkey]").each(function(){var a=$(this);if(a!
.find("option").length<20){return}var b=a.attr("value");var c=$("<inpu
t type='text' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",a.attr("name"));c.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var f=[];var e={};a.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}f.push(h);e[h]=g;e[g]=g;if(g==b){c.attr("value",h)}});if(c.attr("value")==""){c.attr("value","Click to Search or Select")}var d={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};c.autocomplete(f,d);a.replaceWith(c);c.parents("form").submit(function(){var h=c.attr("value");var g=e[h];if(g!==null&&g!==undefined){c.attr("value",g)}else{if(b!=""){c.attr("value",b)}else{c.attr("value","?")}}})})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-activ!
e").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text(k)}else{j=$("<input type='text'></input>").attr({value:k,size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){l.text(o);if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(c,a){var b=function(){try{var d=$.jStore.store("history_expand_state");if(d){for(var f in d){$("#"+f+" div.historyItemBody").show()}}}catch(e){$.jStore.remove("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}c.each(function(){var i=this.i!
d;var g=$(this).children("div.historyItemBody");var h=g.find("pre.peek
");$(this).children(".historyItemTitleBar").find(".historyItemTitle").wrap("<a href='#'></a>").click(function(){if(g.is(":visible")){if($.browser.mozilla){h.css("overflow","hidden")}g.slideUp("fast");if(!a){var j=$.jStore.store("history_expand_state");if(j){delete j[i];$.jStore.store("history_expand_state",j)}}}else{g.slideDown("fast",function(){if($.browser.mozilla){h.css("overflow","auto")}});if(!a){var j=$.jStore.store("history_expand_state");if(j===undefined){j={}}j[i]=true;$.jStore.store("history_expand_state",j)}}return false})});$("#top-links > a.toggle").click(function(){var g=$.jStore.store("history_expand_state");if(g===undefined){g={}}$("div.historyItemBody:visible").each(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(g){delete g[$(this).parent().attr("id")]}});$.jStore.store("history_expand_state",g)}).show()};if(a){b()}else{$.jStore.init("galaxy");$.jStore.engineReady(function(){b()})}}$(document).re!
ady(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus()});
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/jquery.jstore-all.js
--- a/static/scripts/packed/jquery.jstore-all.js Fri Apr 09 13:02:15 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(g){var f=this.prototype;a=true;var e=new this();a=false;for(var d in g){e[d]=typeof g[d]=="function"&&typeof f[d]=="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super;this._super=f[h];var j=i.apply(this,arguments);this._super=k;return j}})(d,g[d]):g[d]}function c(){if(!a&&this.init){this.init.apply(this,arguments)}}c.prototype=e;c.constructor=c;c.extend=arguments.callee;return c}})();(function(a){this.jStoreDelegate=Class.extend({init:function(b){this.parent=b;this.callbacks={}},bind:function(b,c){if(!a.isFunction(c)){return this}if(!this.callbacks[b]){this.callbacks[b]=[]}this.callbacks[b].push(c);return this},trigger:function(){var d=this.parent,c=[].slice.call(arguments),e=c.shift(),b=this.callbacks[e];if(!b){return false}a.each(b,function(){this.apply(d,c)});return this}})})(jQuery);(function(a){a.jStore={};a.extend(a.jStore,{Engi!
neOrder:[],Availability:{},Engines:{},Instances:{},CurrentEngine:null,defaults:{project:null,engine:null,autoload:true,flash:"jStore.Flash.html"},isReady:false,isFlashReady:false,delegate:new jStoreDelegate(a.jStore).bind("jStore-ready",function(b){a.jStore.isReady=true;if(a.jStore.defaults.autoload){b.connect()}}).bind("flash-ready",function(){a.jStore.isFlashReady=true})});a.jStore.ready=function(b){if(a.jStore.isReady){b.apply(a.jStore,[a.jStore.CurrentEngine])}else{a.jStore.delegate.bind("jStore-ready",b)}};a.jStore.fail=function(b){a.jStore.delegate.bind("jStore-failure",b)};a.jStore.flashReady=function(b){if(a.jStore.isFlashReady){b.apply(a.jStore,[a.jStore.CurrentEngine])}else{a.jStore.delegate.bind("flash-ready",b)}};a.jStore.use=function(d,g,c){g=g||a.jStore.defaults.project||location.hostname.replace(/\./g,"-")||"unknown";var f=a.jStore.Engines[d.toLowerCase()]||null,b=(c?c+".":"")+g+"."+d;if(!f){throw"JSTORE_ENGINE_UNDEFINED"}f=new f(g,b);if(a.jStore.Instances[b]!
){throw"JSTORE_JRI_CONFLICT"}if(f.isAvailable()){a.jStore.Instances[b]
=f;if(!a.jStore.CurrentEngine){a.jStore.CurrentEngine=f}a.jStore.delegate.trigger("jStore-ready",f)}else{if(!f.autoload){throw"JSTORE_ENGINE_UNAVILABLE"}else{f.included(function(){if(this.isAvailable()){a.jStore.Instances[b]=this;if(!a.jStore.CurrentEngine){a.jStore.CurrentEngine=this}a.jStore.delegate.trigger("jStore-ready",this)}else{a.jStore.delegate.trigger("jStore-failure",this)}}).include()}}};a.jStore.setCurrentEngine=function(b){if(!a.jStore.Instances.length){return a.jStore.FindEngine()}if(!b&&a.jStore.Instances.length>=1){a.jStore.delegate.trigger("jStore-ready",a.jStore.Instances[0]);return a.jStore.CurrentEngine=a.jStore.Instances[0]}if(b&&a.jStore.Instances[b]){a.jStore.delegate.trigger("jStore-ready",a.jStore.Instances[b]);return a.jStore.CurrentEngine=a.jStore.Instances[b]}throw"JSTORE_JRI_NO_MATCH"};a.jStore.FindEngine=function(){a.each(a.jStore.EngineOrder,function(b){if(a.jStore.Availability[this]()){a.jStore.use(this,a.jStore.defaults.project,"default");re!
turn false}})};a.jStore.store=function(b,c){if(!a.jStore.CurrentEngine){return false}if(!c){return a.jStore.CurrentEngine.get(b)}return a.jStore.CurrentEngine.set(b,c)};a.jStore.remove=function(b){if(!a.jStore.CurrentEngine){return false}return a.jStore.CurrentEngine.rem(b)};a.fn.store=function(c,d){if(!a.jStore.CurrentEngine){return this}var b=a.jStore.store(c,d);return !d?b:this};a.fn.removeStore=function(b){a.jStore.remove(b);return this};a.jStore.load=function(){if(a.jStore.defaults.engine){return a.jStore.use(a.jStore.defaults.engine,a.jStore.defaults.project,"default")}try{a.jStore.FindEngine()}catch(b){}}})(jQuery);(function(a){this.StorageEngine=Class.extend({init:function(c,b){this.project=c;this.jri=b;this.data={};this.limit=-1;this.includes=[];this.delegate=new jStoreDelegate(this).bind("engine-ready",function(){this.isReady=true}).bind("engine-included",function(){this.hasIncluded=true});this.autoload=false;this.isReady=false;this.hasIncluded=false},include:func!
tion(){var b=this,d=this.includes.length,c=0;a.each(this.includes,func
tion(){a.ajax({type:"get",url:this,dataType:"script",cache:true,success:function(){c++;if(c==d){b.delegate.trigger("engine-included")}}})})},isAvailable:function(){return false},ready:function(b){if(this.isReady){b.apply(this)}else{this.delegate.bind("engine-ready",b)}return this},included:function(b){if(this.hasIncluded){b.apply(this)}else{this.delegate.bind("engine-included",b)}return this},get:function(b){return this.data[b]||null},set:function(b,c){this.data[b]=c;return c},rem:function(b){var c=this.data[b];this.data[b]=null;return c}})})(jQuery);(function(c){var b=c.jStore.Availability.session=function(){return !!window.sessionStorage},a=c.jStore.Availability.local=function(){return !!(window.localStorage||window.globalStorage)};this.jStoreDom=StorageEngine.extend({init:function(e,d){this._super(e,d);this.type="DOM";this.limit=5*1024*1024},connect:function(){this.delegate.trigger("engine-ready")},get:function(e){var d=this.db.getItem(e);return d&&d.value?d.value:d},set:!
function(d,e){this.db.setItem(d,e);return e},rem:function(e){var d=this.get(e);this.db.removeItem(e);return d}});this.jStoreLocal=jStoreDom.extend({connect:function(){this.db=!window.globalStorage?window.localStorage:window.globalStorage[location.hostname];this._super()},isAvailable:a});this.jStoreSession=jStoreDom.extend({connect:function(){this.db=sessionStorage;this._super()},isAvailable:b});c.jStore.Engines.local=jStoreLocal;c.jStore.Engines.session=jStoreSession;c.jStore.EngineOrder[1]="local"})(jQuery);(function(b){var a=b.jStore.Availability.flash=function(){return !!(b.jStore.hasFlash("8.0.0"))};this.jStoreFlash=StorageEngine.extend({init:function(e,d){this._super(e,d);this.type="Flash";var c=this;b.jStore.flashReady(function(){c.flashReady()})},connect:function(){var c="jstore-flash-embed-"+this.project;b(document.body).append('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="'+b.jStore.defaults.flas!
h+'"></iframe>')},flashReady:function(f){var c=b("#jStoreFlashFrame")[
0];if(c.Document&&b.isFunction(c.Document.jStoreFlash.f_get_cookie)){this.db=c.Document.jStoreFlash}else{if(c.contentWindow&&c.contentWindow.document){var d=c.contentWindow.document;if(b.isFunction(b("object",b(d))[0].f_get_cookie)){this.db=b("object",b(d))[0]}else{if(b.isFunction(b("embed",b(d))[0].f_get_cookie)){this.db=b("embed",b(d))[0]}}}}if(this.db){this.delegate.trigger("engine-ready")}},isAvailable:a,get:function(d){var c=this.db.f_get_cookie(d);return c=="null"?null:c},set:function(c,d){this.db.f_set_cookie(c,d);return d},rem:function(c){var d=this.get(c);this.db.f_delete_cookie(c);return d}});b.jStore.Engines.flash=jStoreFlash;b.jStore.EngineOrder[2]="flash";b.jStore.hasFlash=function(c){var e=b.jStore.flashVersion().match(/\d+/g),f=c.match(/\d+/g);for(var d=0;d<3;d++){e[d]=parseInt(e[d]||0);f[d]=parseInt(f[d]||0);if(e[d]<f[d]){return false}if(e[d]>f[d]){return true}}return true};b.jStore.flashVersion=function(){try{try{var c=new ActiveXObject("ShockwaveFlash.Shock!
waveFlash.6");try{c.AllowScriptAccess="always"}catch(d){return"6,0,0"}}catch(d){}return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(d){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){return(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(d){}}return"0,0,0"}})(jQuery);function flash_ready(){$.jStore.delegate.trigger("flash-ready")}(function(b){var a=b.jStore.Availability.gears=function(){return !!(window.google&&window.google.gears)};this.jStoreGears=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="Google Gears";this.includes.push("http://code.google.com/apis/gears/gears_init.js");this.autoload=true},connect:function(){var c=this.db=google.gears.factory.create("beta.database");c.open("jstore-"+this.project);c.execute("CREATE TABLE IF NOT EXISTS jstore (k TEX!
T UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)");this.updateCache()},
updateCache:function(){var c=this.db.execute("SELECT k,v FROM jstore");while(c.isValidRow()){this.data[c.field(0)]=c.field(1);c.next()}c.close();this.delegate.trigger("engine-ready")},isAvailable:a,set:function(d,e){var c=this.db;c.execute("BEGIN");c.execute("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[d,e]);c.execute("COMMIT");return this._super(d,e)},rem:function(d){var c=this.db;c.execute("BEGIN");c.execute("DELETE FROM jstore WHERE k = ?",[d]);c.execute("COMMIT");return this._super(d)}});b.jStore.Engines.gears=jStoreGears;b.jStore.EngineOrder[3]="gears"})(jQuery);(function(b){var a=b.jStore.Availability.html5=function(){return !!window.openDatabase};this.jStoreHtml5=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="HTML5";this.limit=1024*200},connect:function(){var c=this.db=openDatabase("jstore-"+this.project,"1.0",this.project,this.limit);if(!c){throw"JSTORE_ENGINE_HTML5_NODB"}c.transaction(function(d){d.executeSql("CREATE TABLE IF NOT EXISTS!
jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)")});this.updateCache()},updateCache:function(){var c=this;this.db.transaction(function(d){d.executeSql("SELECT k,v FROM jstore",[],function(f,e){var h=e.rows,g=0,j;for(;g<h.length;++g){j=h.item(g);c.data[j.k]=j.v}c.delegate.trigger("engine-ready")})})},isAvailable:a,set:function(c,d){this.db.transaction(function(e){e.executeSql("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[c,d])});return this._super(c,d)},rem:function(c){this.db.transaction(function(d){d.executeSql("DELETE FROM jstore WHERE k = ?",[c])});return this._super(c)}});b.jStore.Engines.html5=jStoreHtml5;b.jStore.EngineOrder[0]="html5"})(jQuery);(function(b){var a=b.jStore.Availability.ie=function(){return !!window.ActiveXObject};this.jStoreIE=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="IE";this.limit=64*1024},connect:function(){this.db=b('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-'+this.proj!
ect+'"></div>').appendTo(document.body).get(0);this.delegate.trigger("
engine-ready")},isAvailable:a,get:function(c){this.db.load(this.project);return this.db.getAttribute(c)},set:function(c,d){this.db.setAttribute(c,d);this.db.save(this.project);return d},rem:function(c){var d=this.get(c);this.db.removeAttribute(c);this.db.save(this.project);return d}});b.jStore.Engines.ie=jStoreIE;b.jStore.EngineOrder[4]="ie"})(jQuery);
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/jquery.jstore.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/packed/jquery.jstore.js Fri Apr 09 18:09:54 2010 -0400
@@ -0,0 +1,17 @@
+/*
+ * jStore 2.0 - Persistent Client Side Storage
+ *
+ * Copyright (c) 2010 Eric Garside (http://eric.garside.name/)
+ * Dual licensed under:
+ * MIT: http://www.opensource.org/licenses/mit-license.php
+ * GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
+ *
+ * ---------------------------
+ *
+ * jStore Flash Storage Component
+ *
+ * Copyright (c) 2006 Jeff Lerman (jeff(a)blip.tv)
+ * Licensed under the Creative Commons Attribution 3.0 United States License:
+ * http://creativecommons.org/licenses/by/3.0/us
+ */
+"use strict";(function(i,n){var h="JSTORE_ENGINE_UNSTABLE",t="JSTORE_UNKNOWN_ENGINE_REQUESTED",r="JSTORE_ENGINE_NAMESPACE_COLLISION",j="JSTORE_RESOURCE_NAMESPACE_COLLISION",m="JSTORE_ENGINE_UNAVAILABLE",o="JSTORE_INVALID_FLAVOR",f=(function(){try{return new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$')}catch(I){return(/^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/)}}()),b="jstore-html5-local",y="jstore-html5-sql",F="jstore-flash",G="jstore-google-gears",A="jstore-msie",u,E={},D={},C={},c=false,d={},q={project:undefined,flash:"jStore.Flash.html",json:"browser.json.js"},l;function z(I){switch(I){case b:case y:case F:case G:case A:return true;default:return false}}function g(I,J){return !I?false:I.constructor.toString().match(new RegExp(J+"\\(\\)","i"))!==null}function s(K,I,J){if(g(K,"Function")){return K.apply(I||E,g(J,"Array")?J:[J])}}function p(J,I){i.ajax({url:J,complete:I||i.noop(),type:"GET",dataType:"script",cache:false})}fun!
ction x(I){if(I===undefined){return""}if(g(I,"Object")||g(I,"Array")||g(I,"Function")){return JSON.stringify(I)}return I}function k(I){return f.test(I)?JSON.parse(I):I}function w(I){return I.replace(/^\s+|\s+$/g,"")}function e(I,J,K){if(!z(I)){throw o}if(K[I]!==undefined){throw r}if(s(K)===true){E.available[I]=true;J.flavor=I;D[I]=u.extend(J)}else{E.available[I]=false;E.enginePriority=i.map(E.enginePriority,function(L){if(L===I){return null}else{return L}})}}function v(){if(E.isReady){return}if((c&&E.isFlashReady)||!c){E.isReady=true;E.trigger("jstore-ready",[C[l]])}}function a(){E.create(E.enginePriority[0],undefined,"best-fit")}function H(){try{var J=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");try{J.AllowScriptAccess="always"}catch(L){return"6,0,0"}return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(K){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){return(na!
vigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave F
lash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(I){}}return"0,0,0"}function B(I){var N=H().match(/\d+/g),L=I.match(/\d+/g),J=0,K,M;for(;J<3;J++){K=parseInt(N[J],10);M=parseInt(L[J],10);if(K<M){return false}else{if(K>M){return true}}}return true}i.extend(E,{enginePriority:[b,y,F,A],available:{},isReady:false,isFlashReady:false,flavors:{local:b,sql:y,flash:F,gears:G,msie:A},init:function(J,K,I){i.extend(q,{project:J},K);i(function(){if(n.JSON===undefined){p(q.json)}if(I!==undefined){E.create(I,J,"default")}else{a()}});return E},create:function(I,M,J){M=M||q.project||location.hostname.replace(/\./g,"-")||"unknown";if(!z(I)){throw o}if(D[I]===undefined){throw m}var L=(J!==undefined?J+".":"")+M+"."+I,K;if(C[L]!==undefined){throw j}K=C[L]=new D[I](M,L);K.ready(function(){E.trigger("jstore-engine-ready",[K])});if(I===F&&!E.isFlashReady){if(l===undefined){c=true}n.jstore_ready=function(){E.isFlashReady=true;E.trigger("flash-ready");if(l===undefined){v()}n.flash!
_ready=undefined};n.jstore_error=function(N){E.trigger("jstore-error",["JSTORE_FLASH_EXCEPTION",null,N])};i('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="'+q.flash+'"></iframe>').appendTo("body")}else{if(l===undefined){l=L;v()}}return K},engine:function(I){return C[I]},activeEngine:function(I){if(I!==undefined){if(C[I]===undefined){throw t}else{l=I}}return C[l]},bind:function(J,K,I){I=I||"jstore";if(d[I]===undefined){d[I]={}}if(d[I][J]===undefined){d[I][J]=[K]}else{d[I][J].push(K)}return E},trigger:function(K,J,I){I=I||"jstore";if(d[I]!==undefined){if(d[I][K]!==undefined){i.each(d[I][K],function(){s(this,E,J)})}}return E},error:function(I){E.bind("jstore-error",I)},ready:function(I){if(E.isReady){s(I)}else{E.bind("jstore-ready",I)}return E},engineReady:function(I){if(E.isReady){s(I)}else{E.bind("jstore-engine-ready",I)}return E},store:function(I,J){return J===undefined?E.get(I):E.set(I,J)},remove:function!
(I){return E.activeEngine().remove(I)},get:function(I){return E.active
Engine().get(I)},set:function(I,J){return E.activeEngine().set(I,J)}});u=Class.extend({project:undefined,jri:undefined,flavor:undefined,database:undefined,data:undefined,limit:undefined,isReady:undefined,init:function(J,I){this.project=J;this.jri=I;this.data={};this.isReady=false;this.updateCache()},updateCache:function(){this.isReady=true;this.trigger("engine-ready",[this])},bind:function(I,J){E.bind(I,J,this.jri)},trigger:function(J,I){E.trigger(J,I,this.jri)},ready:function(I){if(this.isReady){s(I,this)}else{this.bind("engine-ready",I)}},get:function(I){this.__interruptAccess();return this.data[I]},set:function(I,J){this.__interruptAccess();I=w(I);try{this.__set(I,J)}catch(K){E.trigger("jstore-error",["JSTORE_STORAGE_FAILURE",this.jri,K])}this.data[I]=J;return J},remove:function(J){this.__interruptAccess();J=w(J);try{this.__remove(J)}catch(K){E.trigger("jstore-error",["JSTORE_REMOVE_FAILURE",this.jri,K])}var I=this.data[J];this.data[J]=undefined;return I},__interruptAcces!
s:function(){if(!this.isReady){throw h}},__set:function(I,J){return},__remove:function(I){return}});i.extend(i.fn,{store:function(I,J){if(J===undefined){E.get(I)}else{E.set(I,J)}return this},removeStore:function(I){E.activeEngine().remove(I);return this},getStore:function(I){return E.activeEngine().get(I)},setStore:function(I,J){E.activeEngine().set(I,J);return this}});n.jStore=i.jStore=E;e(b,{limit:parseInt(500000,16),init:function(J,I){this.database=n.globalStorage===undefined?n.localStorage:n.globalStorage[location.hostname];this._super(J,I)},updateCache:function(){var J,K;for(J in this.database){var I=false;if(this.database.hasOwnProperty){if(this.database.hasOwnProperty(J)){I=true}}else{if(this.database.getItem(J)!==null){I=true}}if(I){K=this.database.getItem(J);this.data[J]=k(K&&K.value?K.value:K)}}this._super()},__set:function(I,J){this.database.setItem(I,x(J))},__remove:function(I){this.database.removeItem(I)}},function(){return n.localStorage!==undefined||n.globalS!
torage!==undefined});e(y,{limit:parseInt(32000,16),init:function(J,I){
this.database=n.openDatabase("jstore-"+J,"1.0",J,this.limit);if(!this.database){throw"JSTORE_SQL_NO_DB"}this.database.transaction(function(K){K.executeSql("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)")});this._super(J,I)},updateCache:function(){var I=this,J=this._super;this.database.transaction(function(K){K.executeSql("SELECT k,v FROM jstore",[],function(O,L){var N=L.rows,M=0,P;for(;M<N.length;++M){P=N.item(M);I.data[P.k]=k(P.v)}J.apply(I)})})},__set:function(I,J){this.database.transaction(function(K){K.executeSql("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[I,x(J)])})},__remove:function(I){this.database.transaction(function(J){J.executeSql("DELETE FROM jstore WHERE k = ?",[I])})}},function(){return n.openDatabase!==undefined});e(F,{limit:-1,init:function(K,J){var I=this;E.bind("flash-ready",function(){I.__flashReadyListener()});this._super(K,J)},updateCache:function(I){if(I===true){var J,K=this.database.jstore_get_all();f!
or(J in K){if(K.hasOwnProperty(J)){this.data[J]=k(this.database.jstore_get(J))}}this._super()}},__set:function(I,J){if(!this.database.jstore_set(I,x(J))){E.trigger("jstore-error",["JSTORE_STORAGE_FAILURE",this.jri,"Flash Exception"])}},__remove:function(I){this.database.jstore_remove(I)},__flashReadyListener:function(){var I=i("#jStoreFlashFrame")[0],J;if(I.Document!==undefined&&g(I.Document.jStoreFlash.jstore_get,"Function")){this.database=I.Document.jStoreFlash}else{if(I.contentWindow&&I.contentWindow.document){J=i(I.contentWindow.document);if(g(i("object",J)[0].jstore_get,"Function")){this.database=i("object",J)[0]}else{if(g(i("embed",J)[0].jstore_get,"Function")){this.database=i("embed",J)[0]}}}}if(this.database===undefined){throw"JSTORE_FLASH_REFERENCE_ISSUE"}else{this.updateCache(true)}}},function(){return B("9.0.0")});e(G,{limit:-1,init:function(J,I){this.database=google.gears.factory.create("beta.database");this.database.open("jstore-"+J);this.database.execute("CREA!
TE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v T
EXT NOT NULL)");this._super(J,I)},updateCache:function(){var I=this.database.execute("SELECT k,v FROM jstore");while(I.isValidRow()){this.data[I.field(0)]=k(I.field(1));I.next()}I.close();this._super()},__set:function(I,J){this.database.execute("BEGIN");this.database.execute("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[I,x(J)]);this.database.execute("COMMIT")},__remove:function(I){this.database.execute("BEGIN");this.database.execute("DELETE FROM jstore WHERE k = ?",[I]);this.database.execute("COMMIT")}},function(){return n.google!==undefined&&n.google.gears!==undefined});e(A,{limit:parseInt(10000,16),init:function(J,I){this.database=i('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-'+J+'"></div>').appendTo(document.body).get(0);this._super(J,I)},updateCache:function(){this.database.load(this.project);var K=document.getElementById("jstore-"+this.project),L=K.XMLDocument,I,J=0;if(L&&L.documentElement&&L.documentElement.attributes){I=L.document!
Element;for(;J<I.attributes.length;++J){this.data[I.attributes.item(J).nodeName]=k(I.attributes.item(J).nodeValue)}}this._super()},__set:function(I,J){this.database.setAttribute(I,x(J));this.database.save(this.project)},__remove:function(I){this.database.removeAttribute(I);this.database.save(this.project)}},function(){return n.ActiveXObject!==undefined})}(jQuery,window));
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/json2.js
--- a/static/scripts/packed/json2.js Fri Apr 09 13:02:15 2010 -0400
+++ b/static/scripts/packed/json2.js Fri Apr 09 18:09:54 2010 -0400
@@ -1,1 +1,1 @@
-var JSON=JSON||{};(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0!
).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=st!
r(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.
length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test!
(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());
\ No newline at end of file
+if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.ch!
arCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(valu!
e,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}
v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-!
4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 templates/display_base.mako
--- a/templates/display_base.mako Fri Apr 09 13:02:15 2010 -0400
+++ b/templates/display_base.mako Fri Apr 09 18:09:54 2010 -0400
@@ -32,29 +32,25 @@
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "jquery", "jquery.tipsy", "galaxy.base", "json2", "jquery.autocomplete", "jquery.jstore-all", "autocomplete_tagging" )}
+ ${h.js( "jquery", "jquery.tipsy", "galaxy.base", "json2", "class", "jquery.jstore", "jquery.autocomplete", "autocomplete_tagging" )}
<script type="text/javascript">
- //
+
// Handle click on community tag.
- //
- function community_tag_click(tag_name, tag_value)
- {
+ function community_tag_click(tag_name, tag_value) {
<% controller_name = get_controller_name( item ) %>
var href = '${h.url_for ( controller='/' + controller_name , action='list_published')}';
href = href + "?f-tags=" + tag_name;
- if (tag_value != undefined && tag_value != "")
+ if (tag_value != undefined && tag_value != "") {
href = href + ":" + tag_value;
+ }
self.location = href;
}
- $(document).ready( function()
- {
+ $(function() {
// Set links to Galaxy screencasts to open in overlay.
- $(this).find("a[href^='http://screencast.g2.bx.psu.edu/']").each( function()
- {
- $(this).click( function()
- {
+ $(this).find("a[href^='http://screencast.g2.bx.psu.edu/']").each( function() {
+ $(this).click( function() {
var href = $(this).attr('href');
show_in_overlay(
{
@@ -67,7 +63,8 @@
return false;
});
});
-
+ // Init history boxes
+ init_history_items( $("div.historyItemWrapper") );
});
</script>
</%def>
@@ -76,14 +73,12 @@
${parent.stylesheets()}
${h.css( "autocomplete_tagging", "embed_item" )}
<style type="text/css">
- .page-body
- {
+ .page-body {
padding: 10px;
## float: left;
## width: 65%;
}
- .page-meta
- {
+ .page-meta {
float: right;
width: 27%;
padding: 0.5em;
diff -r a9402fc7ce1b -r 5536d57237a3 templates/history/display.mako
--- a/templates/history/display.mako Fri Apr 09 13:02:15 2010 -0400
+++ b/templates/history/display.mako Fri Apr 09 18:09:54 2010 -0400
@@ -1,207 +1,14 @@
<%inherit file="/display_base.mako"/>
<%namespace file="/root/history_common.mako" import="render_dataset" />
+## Set vars so that there's no need to change the code below.
+<%
+ history = published_item
+ datasets = published_item_data
+%>
+
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "jquery.jstore-all" )}
-
- ## Set vars so that there's no need to change the code below.
- <%
- history = published_item
- datasets = published_item_data
- %>
-
- <script type="text/javascript">
- $(function() {
- // Load jStore for local storage
- $.extend(jQuery.jStore.defaults, { project: 'galaxy', flash: '/static/jStore.Flash.html' })
- $.jStore.load(); // Auto-select best storage
1
0
15 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/a9402fc7ce1b
changeset: 3625:a9402fc7ce1b
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Apr 09 13:02:15 2010 -0400
description:
Rollback text + autocomplete for big selects. Only use text + autocomplete for dbkey.
diffstat:
static/scripts/galaxy.base.js | 5 ++---
static/scripts/packed/galaxy.base.js | 2 +-
2 files changed, 3 insertions(+), 4 deletions(-)
diffs (24 lines):
diff -r 58ba6fbe22b3 -r a9402fc7ce1b static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Fri Apr 09 11:35:02 2010 -0400
+++ b/static/scripts/galaxy.base.js Fri Apr 09 13:02:15 2010 -0400
@@ -120,10 +120,9 @@
}
// Replace any select box with 20+ options with a text input box + autocomplete.
-// TODO: make this work _well_ on pages with multiple forms; currently, value is reverted when any form is submitted -
-// value should be reverted when only the form that element is in is submitted.
+// TODO: make work with dynamic tool inputs and then can replace all big selects.
function replace_big_select_inputs() {
- $('select').each( function() {
+ $('select[name=dbkey]').each( function() {
var select_elt = $(this);
// Skip if there are < 20 options.
if (select_elt.find('option').length < 20)
diff -r 58ba6fbe22b3 -r a9402fc7ce1b static/scripts/packed/galaxy.base.js
--- a/static/scripts/packed/galaxy.base.js Fri Apr 09 11:35:02 2010 -0400
+++ b/static/scripts/packed/galaxy.base.js Fri Apr 09 13:02:15 2010 -0400
@@ -1,1 +1,1 @@
-$(document).ready(function(){replace_big_select_inputs()});$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}function make_popupmen!
u(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id")+"-menu'></ul>");$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d)}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function array_length(b){if(b.length){return b.length}var c=0;for(var a in b){c++}return c}function replace_big_select_inputs(){$("select").each(function(){var a=$(this);if(a.find("optio!
n").length<20){return}var b=a.attr("value");var c=$("<input type='text
' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",a.attr("name"));c.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var f=[];var e={};a.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}f.push(h);e[h]=g;e[g]=g;if(g==b){c.attr("value",h)}});if(c.attr("value")==""){c.attr("value","Click to Search or Select")}var d={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};c.autocomplete(f,d);a.replaceWith(c);c.parents("form").submit(function(){var h=c.attr("value");var g=e[h];if(g!==null&&g!==undefined){c.attr("value",g)}else{if(b!=""){c.attr("value",b)}else{c.attr("value","?")}}})})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0!
){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text(k)}else{j=$("<input type='text'></input>").attr({value:k,size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){l.text(o);if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}$(document).ready(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus()});
\ No newline at end of file
+$(document).ready(function(){replace_big_select_inputs()});$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}function make_popupmen!
u(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id")+"-menu'></ul>");$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d)}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function array_length(b){if(b.length){return b.length}var c=0;for(var a in b){c++}return c}function replace_big_select_inputs(){$("select[name=dbkey]").each(function(){var a=$(this);if(a!
.find("option").length<20){return}var b=a.attr("value");var c=$("<inpu
t type='text' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",a.attr("name"));c.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var f=[];var e={};a.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}f.push(h);e[h]=g;e[g]=g;if(g==b){c.attr("value",h)}});if(c.attr("value")==""){c.attr("value","Click to Search or Select")}var d={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};c.autocomplete(f,d);a.replaceWith(c);c.parents("form").submit(function(){var h=c.attr("value");var g=e[h];if(g!==null&&g!==undefined){c.attr("value",g)}else{if(b!=""){c.attr("value",b)}else{c.attr("value","?")}}})})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-activ!
e").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text(k)}else{j=$("<input type='text'></input>").attr({value:k,size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){l.text(o);if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}$(document).ready(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus()});
\ No newline at end of file
1
0
15 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/58ba6fbe22b3
changeset: 3624:58ba6fbe22b3
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Fri Apr 09 11:35:02 2010 -0400
description:
Add additional tests to FASTQ Quality Trimmer tool
diffstat:
test-data/sanger_full_range_empty_reads.fastqsanger | 8 ++++++
tools/fastq/fastq_trimmer_by_quality.py | 11 ++++++--
tools/fastq/fastq_trimmer_by_quality.xml | 26 +++++++++++++++++++++
3 files changed, 42 insertions(+), 3 deletions(-)
diffs (90 lines):
diff -r ac044bb17d24 -r 58ba6fbe22b3 test-data/sanger_full_range_empty_reads.fastqsanger
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/sanger_full_range_empty_reads.fastqsanger Fri Apr 09 11:35:02 2010 -0400
@@ -0,0 +1,8 @@
+@FAKE0001 Original version has PHRED scores from 0 to 93 inclusive (in that order)
+
++
+
+@FAKE0002 Original version has PHRED scores from 93 to 0 inclusive (in that order)
+
++
+
diff -r ac044bb17d24 -r 58ba6fbe22b3 tools/fastq/fastq_trimmer_by_quality.py
--- a/tools/fastq/fastq_trimmer_by_quality.py Fri Apr 09 11:29:26 2010 -0400
+++ b/tools/fastq/fastq_trimmer_by_quality.py Fri Apr 09 11:35:02 2010 -0400
@@ -55,6 +55,12 @@
if len ( args ) != 2:
parser.error( "Need to specify an input file and an output file" )
+ if options.window_size < 1:
+ parser.error( 'You must specify a strictly positive window size' )
+
+ if options.window_step < 1:
+ parser.error( 'You must specify a strictly positive step size' )
+
#determine an exhaustive list of window indexes that can be excluded from aggregation
exclude_window_indexes = []
last_exclude_indexes = []
@@ -76,7 +82,6 @@
out = fastqWriter( open( args[1], 'wb' ), format = options.format )
action = ACTION_METHODS[ options.aggregation_action ]
- window_step = abs( options.window_step )
num_reads = None
num_reads_excluded = 0
@@ -93,7 +98,7 @@
if exclude_and_compare( action, quality_list[ lwindow_position:lwindow_position + options.window_size ], options.score_comparison, options.quality_score, exclude_window_indexes ):
fastq_read = fastq_read.slice( lwindow_position, None )
break
- lwindow_position += window_step
+ lwindow_position += options.window_step
else:
rwindow_position = len( quality_list ) #right position of window
while True:
@@ -105,7 +110,7 @@
if exclude_and_compare( action, quality_list[ lwindow_position:rwindow_position ], options.score_comparison, options.quality_score, exclude_window_indexes ):
fastq_read = fastq_read.slice( None, rwindow_position )
break
- rwindow_position -= window_step
+ rwindow_position -= options.window_step
if options.keep_zero_length or len( fastq_read ):
out.write( fastq_read )
else:
diff -r ac044bb17d24 -r 58ba6fbe22b3 tools/fastq/fastq_trimmer_by_quality.xml
--- a/tools/fastq/fastq_trimmer_by_quality.xml Fri Apr 09 11:29:26 2010 -0400
+++ b/tools/fastq/fastq_trimmer_by_quality.xml Fri Apr 09 11:35:02 2010 -0400
@@ -94,6 +94,32 @@
<param name="quality_score" value="1"/>
<output name="output_file" file="sanger_full_range_original_sanger.fastqsanger" />
</test>
+ <test>
+ <!-- Trim entire sequences; keep empty reads -->
+ <param name="input_file" value="sanger_full_range_original_sanger.fastqsanger" ftype="fastqsanger" />
+ <param name="keep_zero_length" value="true" />
+ <param name="trim_ends" value="53"/>
+ <param name="window_size" value="1"/>
+ <param name="step_size" value="1"/>
+ <param name="exclude_count" value="0"/>
+ <param name="aggregation_action" value="min"/>
+ <param name="score_comparison" value=">="/>
+ <param name="quality_score" value="999"/>
+ <output name="output_file" file="sanger_full_range_empty_reads.fastqsanger" />
+ </test>
+ <test>
+ <!-- Trim entire sequences; discard empty reads -->
+ <param name="input_file" value="sanger_full_range_original_sanger.fastqsanger" ftype="fastqsanger" />
+ <param name="keep_zero_length"/>
+ <param name="trim_ends" value="53"/>
+ <param name="window_size" value="1"/>
+ <param name="step_size" value="1"/>
+ <param name="exclude_count" value="0"/>
+ <param name="aggregation_action" value="min"/>
+ <param name="score_comparison" value=">="/>
+ <param name="quality_score" value="999"/>
+ <output name="output_file" file="empty_file.dat" />
+ </test>
</tests>
<help>
This tool allows you to trim the ends of reads based upon the aggregate value of quality scores found within a sliding window; a sliding window of size 1 is equivalent to 'simple' trimming of the ends.
1
0
15 Apr '10
details: http://www.bx.psu.edu/hg/galaxy/rev/ac044bb17d24
changeset: 3623:ac044bb17d24
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Fri Apr 09 11:29:26 2010 -0400
description:
Fix Test framework's handling of boolean and multiple select checkboxes and radio buttons.
diffstat:
test/base/twilltestcase.py | 22 +++++++---------------
1 files changed, 7 insertions(+), 15 deletions(-)
diffs (55 lines):
diff -r ab319f94495c -r ac044bb17d24 test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Thu Apr 08 16:21:53 2010 -0400
+++ b/test/base/twilltestcase.py Fri Apr 09 11:29:26 2010 -0400
@@ -1000,24 +1000,21 @@
break
# To help with debugging a tool, print out the form controls when the test fails
print "form '%s' contains the following controls ( note the values )" % f.name
- control_names = []
- hidden_control_names = [] # cannot change these, so ignore or many complex page tool tests will fail
+ controls = {}
hc_prefix = '<HiddenControl('
for i, control in enumerate( f.controls ):
print "control %d: %s" % ( i, str( control ) )
- if hc_prefix in str(control):
- hidden_control_names.append(control.name) # cannot do much with these
- else:
+ if not hc_prefix in str( control ):
try:
#check if a repeat element needs to be added
if control.name not in kwd and control.name.endswith( '_add' ):
#control name doesn't exist, could be repeat
repeat_startswith = control.name[0:-4]
- if repeat_startswith and not [ c_name for c_name in control_names if c_name.startswith( repeat_startswith ) ] and [ c_name for c_name in kwd.keys() if c_name.startswith( repeat_startswith ) ]:
+ if repeat_startswith and not [ c_name for c_name in controls.keys() if c_name.startswith( repeat_startswith ) ] and [ c_name for c_name in kwd.keys() if c_name.startswith( repeat_startswith ) ]:
tc.submit( control.name )
return self.submit_form( form_no=form_no, button=button, **kwd )
# Check for refresh_on_change attribute, submit a change if required
- if 'refresh_on_change' in control.attrs.keys():
+ if hasattr( control, 'attrs' ) and 'refresh_on_change' in control.attrs.keys():
changed = False
item_labels = [ item.attrs[ 'label' ] for item in control.get_items() if item.selected ] #For DataToolParameter, control.value is the HDA id, but kwd contains the filename. This loop gets the filename/label for the selected values.
for value in kwd[ control.name ]:
@@ -1040,19 +1037,14 @@
except Exception, e:
log.debug( "In submit_form, continuing, but caught exception: %s" % str( e ) )
continue
- control_names.append( control.name )
+ controls[ control.name ] = control
# No refresh_on_change attribute found in current form, so process as usual
for control_name, control_value in kwd.items():
- if control_name in hidden_control_names:
+ if control_name not in controls:
continue # these cannot be handled safely - cause the test to barf out
if not isinstance( control_value, list ):
control_value = [ control_value ]
- try:
- control = f.find_control( name=control_name )
- except:
- # This assumes we always want the first control of the given name,
- # which may not be ideal...
- control = f.find_control( name=control_name, nr=0 )
+ control = controls[ control_name ]
control.clear()
if control.is_of_kind( "text" ):
tc.fv( f.name, control.name, ",".join( control_value ) )
1
0