galaxy-dev
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- 10007 discussions
25 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/d0fb5c640d43
changeset: 2621:d0fb5c640d43
user: Nate Coraor <nate(a)bx.psu.edu>
date: Tue Aug 25 11:53:42 2009 -0400
description:
set job state to new in upload tool action so that track_jobs_in_database works
2 file(s) affected in this change:
lib/galaxy/tools/actions/upload.py
tools/data_source/upload.py
diffs (23 lines):
diff -r 899a830754a3 -r d0fb5c640d43 lib/galaxy/tools/actions/upload.py
--- a/lib/galaxy/tools/actions/upload.py Mon Aug 24 16:38:24 2009 -0400
+++ b/lib/galaxy/tools/actions/upload.py Tue Aug 25 11:53:42 2009 -0400
@@ -144,6 +144,7 @@
job.add_parameter( 'paramfile', to_json_string( json_file_path ) )
for i, dataset in enumerate( data_list ):
job.add_output_dataset( i, dataset )
+ job.state = trans.app.model.Job.states.NEW
trans.app.model.flush()
# Queue the job for execution
diff -r 899a830754a3 -r d0fb5c640d43 tools/data_source/upload.py
--- a/tools/data_source/upload.py Mon Aug 24 16:38:24 2009 -0400
+++ b/tools/data_source/upload.py Tue Aug 25 11:53:42 2009 -0400
@@ -206,6 +206,8 @@
elif ext == 'scf' and dataset.file_type != 'scf':
file_err( "You must manually set the 'File Format' to 'Scf' when uploading scf files.", dataset, json_file )
return
+ else:
+ ext = 'binary'
data_type = 'binary'
if not data_type:
# We must have a text file
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/3ca815c4be07
changeset: 2619:3ca815c4be07
user: James Taylor <james(a)jamestaylor.org>
date: Mon Aug 24 15:55:39 2009 -0400
description:
Merge
1 file(s) affected in this change:
static/scripts/json_cookie.js
diffs (66 lines):
diff -r 9c325f3656b5 -r 3ca815c4be07 static/scripts/json_cookie.js
--- a/static/scripts/json_cookie.js Mon Aug 24 15:53:17 2009 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- JSONCookie: Uses JSON to allow the settings of multiple preferences in one cookie.
- Kanwei Li, 2009
-
- cookie = new JSONCookie("cookie_name"); // Pass in the name of the cookie
-
- // Gets the value of a preference, returns optional second argument if pref not found
- cookie.get("pref", "val_if_not_found");
-
- cookie.set("pref", "val"); // Sets a value for the preference and saves cookie
- cookie.unset("pref"); // Unsets the preference and saves cookie
- cookie.clear() // Deletes the cookie
-
-*/
-
-function JSONCookie(name) {
- this.cookie_name = name;
-
-}
-
-JSONCookie.prototype = {
- json_data : function() {
- cookie = $.cookie(this.cookie_name);
- return cookie ? JSON.parse(cookie) : null;
- },
-
- save : function(data) {
- $.cookie(this.cookie_name, JSON.stringify(data));
- },
-
- get : function(attr, else_val) {
- data = this.json_data();
- if (data && data[attr]) { return data[attr];
- } else if (else_val) { return else_val;
- } else { return null;
- }
- },
-
- set : function(attr, val) {
- data = this.json_data();
- if (data) {
- data[attr] = val;
- } else {
- data = { attr : val }
- }
- this.save(data);
- },
-
- unset : function(attr) {
- data = this.json_data();
- if (data) {
- delete data[attr];
- }
- this.save(data);
- },
-
- clear : function() {
- this.save(null);
- }
-
-};
\ No newline at end of file
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/899a830754a3
changeset: 2620:899a830754a3
user: James Taylor <james(a)jamestaylor.org>
date: Mon Aug 24 16:38:24 2009 -0400
description:
Message for page change script
1 file(s) affected in this change:
lib/galaxy/model/migrate/versions/0014_pages.py
diffs (21 lines):
diff -r 3ca815c4be07 -r 899a830754a3 lib/galaxy/model/migrate/versions/0014_pages.py
--- a/lib/galaxy/model/migrate/versions/0014_pages.py Mon Aug 24 15:55:39 2009 -0400
+++ b/lib/galaxy/model/migrate/versions/0014_pages.py Mon Aug 24 16:38:24 2009 -0400
@@ -1,3 +1,9 @@
+"""
+Migration script to add support for "Pages".
+ 1) Creates Page and PageRevision tables
+ 2) Adds username column to User table
+"""
+
from sqlalchemy import *
from migrate import *
from migrate.changeset import *
@@ -31,6 +37,7 @@
)
def upgrade():
+ print __doc__
metadata.reflect()
try:
Page_table.create()
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/07a02ebbdf1a
changeset: 2618:07a02ebbdf1a
user: Kanwei Li <kanwei(a)gmail.com>
date: Mon Aug 24 15:46:03 2009 -0400
description:
Remove unused js
1 file(s) affected in this change:
static/scripts/json_cookie.js
diffs (66 lines):
diff -r 168a6ef6a99a -r 07a02ebbdf1a static/scripts/json_cookie.js
--- a/static/scripts/json_cookie.js Sun Aug 23 17:13:04 2009 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- JSONCookie: Uses JSON to allow the settings of multiple preferences in one cookie.
- Kanwei Li, 2009
-
- cookie = new JSONCookie("cookie_name"); // Pass in the name of the cookie
-
- // Gets the value of a preference, returns optional second argument if pref not found
- cookie.get("pref", "val_if_not_found");
-
- cookie.set("pref", "val"); // Sets a value for the preference and saves cookie
- cookie.unset("pref"); // Unsets the preference and saves cookie
- cookie.clear() // Deletes the cookie
-
-*/
-
-function JSONCookie(name) {
- this.cookie_name = name;
-
-}
-
-JSONCookie.prototype = {
- json_data : function() {
- cookie = $.cookie(this.cookie_name);
- return cookie ? JSON.parse(cookie) : null;
- },
-
- save : function(data) {
- $.cookie(this.cookie_name, JSON.stringify(data));
- },
-
- get : function(attr, else_val) {
- data = this.json_data();
- if (data && data[attr]) { return data[attr];
- } else if (else_val) { return else_val;
- } else { return null;
- }
- },
-
- set : function(attr, val) {
- data = this.json_data();
- if (data) {
- data[attr] = val;
- } else {
- data = { attr : val }
- }
- this.save(data);
- },
-
- unset : function(attr) {
- data = this.json_data();
- if (data) {
- delete data[attr];
- }
- this.save(data);
- },
-
- clear : function() {
- this.save(null);
- }
-
-};
\ No newline at end of file
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/4ff4be2f436f
changeset: 2616:4ff4be2f436f
user: James Taylor <james(a)jamestaylor.org>
date: Mon Aug 24 15:27:27 2009 -0400
description:
Cache defeat for css/js
3 file(s) affected in this change:
lib/galaxy/web/framework/helpers/__init__.py
templates/base.mako
templates/workflow/editor.mako
diffs (70 lines):
diff -r 168a6ef6a99a -r 4ff4be2f436f lib/galaxy/web/framework/helpers/__init__.py
--- a/lib/galaxy/web/framework/helpers/__init__.py Sun Aug 23 17:13:04 2009 -0400
+++ b/lib/galaxy/web/framework/helpers/__init__.py Mon Aug 24 15:27:27 2009 -0400
@@ -27,14 +27,17 @@
Take a list of stylesheet names (no extension) and return appropriate string
of link tags.
- TODO: This has a hardcoded "?v=1" to defeat caching. This should be done
+ TODO: This has a hardcoded "?v=2" to defeat caching. This should be done
in a better way.
"""
- return "\n".join( [ stylesheet_link_tag( "/static/style/" + name + ".css?v=1" ) for name in args ] )
+ return "\n".join( [ stylesheet_link_tag( "/static/style/" + name + ".css?v=2" ) for name in args ] )
def js( *args ):
"""
Take a list of javascript names (no extension) and return appropriate
string of script tags.
+
+ TODO: This has a hardcoded "?v=2" to defeat caching. This should be done
+ in a better way.
"""
- return "\n".join( [ javascript_include_tag( "/static/scripts/" + name + ".js" ) for name in args ] )
\ No newline at end of file
+ return "\n".join( [ javascript_include_tag( "/static/scripts/" + name + ".js?v=2" ) for name in args ] )
diff -r 168a6ef6a99a -r 4ff4be2f436f templates/base.mako
--- a/templates/base.mako Sun Aug 23 17:13:04 2009 -0400
+++ b/templates/base.mako Mon Aug 24 15:27:27 2009 -0400
@@ -27,9 +27,6 @@
## <!--[if lt IE 7]>
## <script type='text/javascript' src="/static/scripts/IE7.js"> </script>
## <![endif]-->
- <script type="text/javascript" src="${h.url_for('/static/scripts/jquery.js')}"></script>
- <script type="text/javascript" src="${h.url_for('/static/scripts/galaxy.base.js')}"></script>
-
-
+ ${h.js( "jquery", "galaxy.base" )}
</%def>
diff -r 168a6ef6a99a -r 4ff4be2f436f templates/workflow/editor.mako
--- a/templates/workflow/editor.mako Sun Aug 23 17:13:04 2009 -0400
+++ b/templates/workflow/editor.mako Mon Aug 24 15:27:27 2009 -0400
@@ -25,17 +25,17 @@
<!--[if IE]>
<script type='text/javascript' src="${h.url_for('/static/scripts/excanvas.js')}"> </script>
<![endif]-->
- <script type='text/javascript' src="${h.url_for('/static/scripts/jquery.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/jquery.event.drag.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/jquery.event.drop.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/jquery.event.hover.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/jquery.form.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/jquery.jstore-all.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/json2.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.base.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.workflow_editor.canvas.js')}"> </script>
-
+ ${h.js( "jquery",
+ "jquery.event.drag",
+ "jquery.event.drop",
+ "jquery.event.hover",
+ "jquery.form",
+ "jquery.jstore-all",
+ "json2",
+ "galaxy.base",
+ "galaxy.workflow_editor.canvas" )}
+
<!--[if lt IE 7]>
<script type='text/javascript'>
window.lt_ie_7 = true;
1
0
25 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/9c325f3656b5
changeset: 2617:9c325f3656b5
user: James Taylor <james(a)jamestaylor.org>
date: Mon Aug 24 15:53:17 2009 -0400
description:
Support for user defined pages. Page content is stripped down XHTML. Pages can be edited using a WYM editor, and have stable public urls. This is VERY PRELIMINARY, but functional
67 file(s) affected in this change:
lib/galaxy/model/__init__.py
lib/galaxy/model/mapping.py
lib/galaxy/model/migrate/versions/0014_pages.py
lib/galaxy/util/sanitize_html.py
lib/galaxy/web/__init__.py
lib/galaxy/web/buildapp.py
lib/galaxy/web/controllers/page.py
lib/galaxy/web/controllers/user.py
lib/galaxy/web/framework/helpers/grids.py
static/scripts/jquery.wymeditor.js
static/wymeditor/iframe/default/lbl-blockquote.png
static/wymeditor/iframe/default/lbl-h1.png
static/wymeditor/iframe/default/lbl-h2.png
static/wymeditor/iframe/default/lbl-h3.png
static/wymeditor/iframe/default/lbl-h4.png
static/wymeditor/iframe/default/lbl-h5.png
static/wymeditor/iframe/default/lbl-h6.png
static/wymeditor/iframe/default/lbl-p.png
static/wymeditor/iframe/default/lbl-pre.png
static/wymeditor/iframe/default/wymiframe.css
static/wymeditor/iframe/default/wymiframe.html
static/wymeditor/iframe/galaxy/lbl-blockquote.png
static/wymeditor/iframe/galaxy/lbl-h1.png
static/wymeditor/iframe/galaxy/lbl-h2.png
static/wymeditor/iframe/galaxy/lbl-h3.png
static/wymeditor/iframe/galaxy/lbl-h4.png
static/wymeditor/iframe/galaxy/lbl-h5.png
static/wymeditor/iframe/galaxy/lbl-h6.png
static/wymeditor/iframe/galaxy/lbl-p.png
static/wymeditor/iframe/galaxy/lbl-pre.png
static/wymeditor/iframe/galaxy/wymiframe.css
static/wymeditor/iframe/galaxy/wymiframe.html
static/wymeditor/lang/bg.js
static/wymeditor/lang/ca.js
static/wymeditor/lang/cs.js
static/wymeditor/lang/de.js
static/wymeditor/lang/en.js
static/wymeditor/lang/es.js
static/wymeditor/lang/fa.js
static/wymeditor/lang/fi.js
static/wymeditor/lang/fr.js
static/wymeditor/lang/he.js
static/wymeditor/lang/hr.js
static/wymeditor/lang/hu.js
static/wymeditor/lang/it.js
static/wymeditor/lang/nb.js
static/wymeditor/lang/nl.js
static/wymeditor/lang/nn.js
static/wymeditor/lang/pl.js
static/wymeditor/lang/pt-br.js
static/wymeditor/lang/pt.js
static/wymeditor/lang/ru.js
static/wymeditor/lang/sv.js
static/wymeditor/lang/tr.js
static/wymeditor/lang/zh_cn.js
static/wymeditor/skins/default/icons.png
static/wymeditor/skins/default/skin.css
static/wymeditor/skins/default/skin.js
static/wymeditor/skins/galaxy/icons.png
static/wymeditor/skins/galaxy/skin.css
static/wymeditor/skins/galaxy/skin.js
templates/grid.mako
templates/page/create.mako
templates/page/display.mako
templates/page/editor.mako
templates/page/index.mako
templates/user/index.mako
diffs (truncated from 7896 to 3000 lines):
diff -r 4ff4be2f436f -r 9c325f3656b5 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Mon Aug 24 15:27:27 2009 -0400
+++ b/lib/galaxy/model/__init__.py Mon Aug 24 15:53:17 2009 -0400
@@ -33,6 +33,7 @@
self.external = False
self.deleted = False
self.purged = False
+ self.username = None
# Relationships
self.histories = []
@@ -1118,7 +1119,20 @@
self.country+'<br/>'+ \
'Phone: '+self.phone
+class Page( object ):
+ def __init__( self ):
+ self.id = None
+ self.user = None
+ self.title = None
+ self.slug = None
+ self.latest_revision_id = None
+ self.revisions = []
+class PageRevision( object ):
+ def __init__( self ):
+ self.user = None
+ self.title = None
+ self.content = None
diff -r 4ff4be2f436f -r 9c325f3656b5 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Mon Aug 24 15:27:27 2009 -0400
+++ b/lib/galaxy/model/mapping.py Mon Aug 24 15:53:17 2009 -0400
@@ -42,6 +42,7 @@
Column( "create_time", DateTime, default=now ),
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "email", TrimmedString( 255 ), nullable=False ),
+ Column( "username", TrimmedString( 255 ), index=True, unique=True ),
Column( "password", TrimmedString( 40 ), nullable=False ),
Column( "external", Boolean, default=False ),
Column( "deleted", Boolean, index=True, default=False ),
@@ -523,6 +524,26 @@
Column( "sample_state_id", Integer, ForeignKey( "sample_state.id" ), index=True ),
Column( "comment", TEXT ) )
+Page.table = Table( "page", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
+ Column( "latest_revision_id", Integer,
+ ForeignKey( "page_revision.id", use_alter=True, name='page_latest_revision_id_fk' ), index=True ),
+ Column( "title", TEXT ),
+ Column( "slug", TEXT, unique=True, index=True ),
+ )
+
+PageRevision.table = Table( "page_revision", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "page_id", Integer, ForeignKey( "page.id" ), index=True, nullable=False ),
+ Column( "title", TEXT ),
+ Column( "content", TEXT )
+ )
+
# With the tables defined we can define the mappers and setup the
# relationships between the model objects.
@@ -905,6 +926,18 @@
assign_mapper( context, MetadataFile, MetadataFile.table,
properties=dict( history_dataset=relation( HistoryDatasetAssociation ), library_dataset=relation( LibraryDatasetDatasetAssociation ) ) )
+assign_mapper( context, PageRevision, PageRevision.table )
+
+assign_mapper( context, Page, Page.table,
+ properties=dict( user=relation( User ),
+ revisions=relation( PageRevision, backref='page',
+ cascade="all, delete-orphan",
+ primaryjoin=( Page.table.c.id == PageRevision.table.c.page_id ) ),
+ latest_revision=relation( PageRevision, post_update=True,
+ primaryjoin=( Page.table.c.latest_revision_id == PageRevision.table.c.id ),
+ lazy=False )
+ ) )
+
def db_next_hid( self ):
"""
Override __next_hid to generate from the database in a concurrency
diff -r 4ff4be2f436f -r 9c325f3656b5 lib/galaxy/model/migrate/versions/0014_pages.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/model/migrate/versions/0014_pages.py Mon Aug 24 15:53:17 2009 -0400
@@ -0,0 +1,55 @@
+from sqlalchemy import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+
+Page_table = Table( "page", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
+ Column( "latest_revision_id", Integer,
+ ForeignKey( "page_revision.id", use_alter=True, name='page_latest_revision_id_fk' ), index=True ),
+ Column( "title", TEXT ),
+ Column( "slug", TEXT, unique=True, index=True ),
+ )
+
+PageRevision_table = Table( "page_revision", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "page_id", Integer, ForeignKey( "page.id" ), index=True, nullable=False ),
+ Column( "title", TEXT ),
+ Column( "content", TEXT )
+ )
+
+def upgrade():
+ metadata.reflect()
+ try:
+ Page_table.create()
+ except:
+ log.debug( "Could not create page table" )
+ try:
+ PageRevision_table.create()
+ except:
+ log.debug( "Could not create page_revision table" )
+
+ # Add 1 column to the user table
+ User_table = Table( "galaxy_user", metadata, autoload=True )
+ col = Column( 'username', String(255), index=True, unique=True, default=False )
+ col.create( User_table )
+ assert col is User_table.c.username
+
+def downgrade():
+ metadata.reflect()
+ Page_table.drop()
+ PageRevision_table.drop()
+ User_table = Table( "galaxy_user", metadata, autoload=True )
+ User_table.c.username.drop()
diff -r 4ff4be2f436f -r 9c325f3656b5 lib/galaxy/util/sanitize_html.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/util/sanitize_html.py Mon Aug 24 15:53:17 2009 -0400
@@ -0,0 +1,439 @@
+"""
+HTML Sanitizer (ripped from feedparser)
+"""
+
+import re, sgmllib
+
+# reversable htmlentitydefs mappings for Python 2.2
+try:
+ from htmlentitydefs import name2codepoint, codepoint2name
+except:
+ import htmlentitydefs
+ name2codepoint={}
+ codepoint2name={}
+ for (name,codepoint) in htmlentitydefs.entitydefs.iteritems():
+ if codepoint.startswith('&#'): codepoint=unichr(int(codepoint[2:-1]))
+ name2codepoint[name]=ord(codepoint)
+ codepoint2name[ord(codepoint)]=name
+
+_cp1252 = {
+ unichr(128): unichr(8364), # euro sign
+ unichr(130): unichr(8218), # single low-9 quotation mark
+ unichr(131): unichr( 402), # latin small letter f with hook
+ unichr(132): unichr(8222), # double low-9 quotation mark
+ unichr(133): unichr(8230), # horizontal ellipsis
+ unichr(134): unichr(8224), # dagger
+ unichr(135): unichr(8225), # double dagger
+ unichr(136): unichr( 710), # modifier letter circumflex accent
+ unichr(137): unichr(8240), # per mille sign
+ unichr(138): unichr( 352), # latin capital letter s with caron
+ unichr(139): unichr(8249), # single left-pointing angle quotation mark
+ unichr(140): unichr( 338), # latin capital ligature oe
+ unichr(142): unichr( 381), # latin capital letter z with caron
+ unichr(145): unichr(8216), # left single quotation mark
+ unichr(146): unichr(8217), # right single quotation mark
+ unichr(147): unichr(8220), # left double quotation mark
+ unichr(148): unichr(8221), # right double quotation mark
+ unichr(149): unichr(8226), # bullet
+ unichr(150): unichr(8211), # en dash
+ unichr(151): unichr(8212), # em dash
+ unichr(152): unichr( 732), # small tilde
+ unichr(153): unichr(8482), # trade mark sign
+ unichr(154): unichr( 353), # latin small letter s with caron
+ unichr(155): unichr(8250), # single right-pointing angle quotation mark
+ unichr(156): unichr( 339), # latin small ligature oe
+ unichr(158): unichr( 382), # latin small letter z with caron
+ unichr(159): unichr( 376)} # latin capital letter y with diaeresis
+
+class _BaseHTMLProcessor(sgmllib.SGMLParser):
+ special = re.compile('''[<>'"]''')
+ bare_ampersand = re.compile("&(?!#\d+;|#x[0-9a-fA-F]+;|\w+;)")
+ elements_no_end_tag = ['area', 'base', 'basefont', 'br', 'col', 'frame', 'hr',
+ 'img', 'input', 'isindex', 'link', 'meta', 'param']
+
+ def __init__(self, encoding, type):
+ self.encoding = encoding
+ self.type = type
+ ## if _debug: sys.stderr.write('entering BaseHTMLProcessor, encoding=%s\n' % self.encoding)
+ sgmllib.SGMLParser.__init__(self)
+
+ def reset(self):
+ self.pieces = []
+ sgmllib.SGMLParser.reset(self)
+
+ def _shorttag_replace(self, match):
+ tag = match.group(1)
+ if tag in self.elements_no_end_tag:
+ return '<' + tag + ' />'
+ else:
+ return '<' + tag + '></' + tag + '>'
+
+ def parse_starttag(self,i):
+ j=sgmllib.SGMLParser.parse_starttag(self, i)
+ if self.type == 'application/xhtml+xml':
+ if j>2 and self.rawdata[j-2:j]=='/>':
+ self.unknown_endtag(self.lasttag)
+ return j
+
+ def feed(self, data):
+ data = re.compile(r'<!((?!DOCTYPE|--|\[))', re.IGNORECASE).sub(r'<!\1', data)
+ #data = re.sub(r'<(\S+?)\s*?/>', self._shorttag_replace, data) # bug [ 1399464 ] Bad regexp for _shorttag_replace
+ data = re.sub(r'<([^<>\s]+?)\s*/>', self._shorttag_replace, data)
+ data = data.replace(''', "'")
+ data = data.replace('"', '"')
+ if self.encoding and type(data) == type(u''):
+ data = data.encode(self.encoding)
+ sgmllib.SGMLParser.feed(self, data)
+ sgmllib.SGMLParser.close(self)
+
+ def normalize_attrs(self, attrs):
+ if not attrs: return attrs
+ # utility method to be called by descendants
+ attrs = dict([(k.lower(), v) for k, v in attrs]).items()
+ attrs = [(k, k in ('rel', 'type') and v.lower() or v) for k, v in attrs]
+ attrs.sort()
+ return attrs
+
+ def unknown_starttag(self, tag, attrs):
+ # called for each start tag
+ # attrs is a list of (attr, value) tuples
+ # e.g. for <pre class='screen'>, tag='pre', attrs=[('class', 'screen')]
+ ## if _debug: sys.stderr.write('_BaseHTMLProcessor, unknown_starttag, tag=%s\n' % tag)
+ uattrs = []
+ strattrs=''
+ if attrs:
+ for key, value in attrs:
+ value=value.replace('>','>').replace('<','<').replace('"','"')
+ value = self.bare_ampersand.sub("&", value)
+ # thanks to Kevin Marks for this breathtaking hack to deal with (valid) high-bit attribute values in UTF-8 feeds
+ if type(value) != type(u''):
+ try:
+ value = unicode(value, self.encoding)
+ except:
+ value = unicode(value, 'iso-8859-1')
+ uattrs.append((unicode(key, self.encoding), value))
+ strattrs = u''.join([u' %s="%s"' % (key, value) for key, value in uattrs])
+ if self.encoding:
+ try:
+ strattrs=strattrs.encode(self.encoding)
+ except:
+ pass
+ if tag in self.elements_no_end_tag:
+ self.pieces.append('<%(tag)s%(strattrs)s />' % locals())
+ else:
+ self.pieces.append('<%(tag)s%(strattrs)s>' % locals())
+
+ def unknown_endtag(self, tag):
+ # called for each end tag, e.g. for </pre>, tag will be 'pre'
+ # Reconstruct the original end tag.
+ if tag not in self.elements_no_end_tag:
+ self.pieces.append("</%(tag)s>" % locals())
+
+ def handle_charref(self, ref):
+ # called for each character reference, e.g. for ' ', ref will be '160'
+ # Reconstruct the original character reference.
+ if ref.startswith('x'):
+ value = unichr(int(ref[1:],16))
+ else:
+ value = unichr(int(ref))
+
+ if value in _cp1252.keys():
+ self.pieces.append('&#%s;' % hex(ord(_cp1252[value]))[1:])
+ else:
+ self.pieces.append('&#%(ref)s;' % locals())
+
+ def handle_entityref(self, ref):
+ # called for each entity reference, e.g. for '©', ref will be 'copy'
+ # Reconstruct the original entity reference.
+ if name2codepoint.has_key(ref):
+ self.pieces.append('&%(ref)s;' % locals())
+ else:
+ self.pieces.append('&%(ref)s' % locals())
+
+ def handle_data(self, text):
+ # called for each block of plain text, i.e. outside of any tag and
+ # not containing any character or entity references
+ # Store the original text verbatim.
+ ## if _debug: sys.stderr.write('_BaseHTMLProcessor, handle_text, text=%s\n' % text)
+ self.pieces.append(text)
+
+ def handle_comment(self, text):
+ # called for each HTML comment, e.g. <!-- insert Javascript code here -->
+ # Reconstruct the original comment.
+ self.pieces.append('<!--%(text)s-->' % locals())
+
+ def handle_pi(self, text):
+ # called for each processing instruction, e.g. <?instruction>
+ # Reconstruct original processing instruction.
+ self.pieces.append('<?%(text)s>' % locals())
+
+ def handle_decl(self, text):
+ # called for the DOCTYPE, if present, e.g.
+ # <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ # "http://www.w3.org/TR/html4/loose.dtd">
+ # Reconstruct original DOCTYPE
+ self.pieces.append('<!%(text)s>' % locals())
+
+ _new_declname_match = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9:]*\s*').match
+ def _scan_name(self, i, declstartpos):
+ rawdata = self.rawdata
+ n = len(rawdata)
+ if i == n:
+ return None, -1
+ m = self._new_declname_match(rawdata, i)
+ if m:
+ s = m.group()
+ name = s.strip()
+ if (i + len(s)) == n:
+ return None, -1 # end of buffer
+ return name.lower(), m.end()
+ else:
+ self.handle_data(rawdata)
+# self.updatepos(declstartpos, i)
+ return None, -1
+
+ def convert_charref(self, name):
+ return '&#%s;' % name
+
+ def convert_entityref(self, name):
+ return '&%s;' % name
+
+ def output(self):
+ '''Return processed HTML as a single string'''
+ return ''.join([str(p) for p in self.pieces])
+
+class _HTMLSanitizer(_BaseHTMLProcessor):
+ acceptable_elements = ['a', 'abbr', 'acronym', 'address', 'area', 'article',
+ 'aside', 'audio', 'b', 'big', 'blockquote', 'br', 'button', 'canvas',
+ 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'command',
+ 'datagrid', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'dir',
+ 'div', 'dl', 'dt', 'em', 'event-source', 'fieldset', 'figure', 'footer',
+ 'font', 'form', 'header', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i',
+ 'img', 'input', 'ins', 'keygen', 'kbd', 'label', 'legend', 'li', 'm', 'map',
+ 'menu', 'meter', 'multicol', 'nav', 'nextid', 'ol', 'output', 'optgroup',
+ 'option', 'p', 'pre', 'progress', 'q', 's', 'samp', 'section', 'select',
+ 'small', 'sound', 'source', 'spacer', 'span', 'strike', 'strong', 'sub',
+ 'sup', 'table', 'tbody', 'td', 'textarea', 'time', 'tfoot', 'th', 'thead',
+ 'tr', 'tt', 'u', 'ul', 'var', 'video', 'noscript']
+
+ acceptable_attributes = ['abbr', 'accept', 'accept-charset', 'accesskey',
+ 'action', 'align', 'alt', 'autocomplete', 'autofocus', 'axis',
+ 'background', 'balance', 'bgcolor', 'bgproperties', 'border',
+ 'bordercolor', 'bordercolordark', 'bordercolorlight', 'bottompadding',
+ 'cellpadding', 'cellspacing', 'ch', 'challenge', 'char', 'charoff',
+ 'choff', 'charset', 'checked', 'cite', 'class', 'clear', 'color', 'cols',
+ 'colspan', 'compact', 'contenteditable', 'controls', 'coords', 'data',
+ 'datafld', 'datapagesize', 'datasrc', 'datetime', 'default', 'delay',
+ 'dir', 'disabled', 'draggable', 'dynsrc', 'enctype', 'end', 'face', 'for',
+ 'form', 'frame', 'galleryimg', 'gutter', 'headers', 'height', 'hidefocus',
+ 'hidden', 'high', 'href', 'hreflang', 'hspace', 'icon', 'id', 'inputmode',
+ 'ismap', 'keytype', 'label', 'leftspacing', 'lang', 'list', 'longdesc',
+ 'loop', 'loopcount', 'loopend', 'loopstart', 'low', 'lowsrc', 'max',
+ 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'nohref',
+ 'noshade', 'nowrap', 'open', 'optimum', 'pattern', 'ping', 'point-size',
+ 'prompt', 'pqg', 'radiogroup', 'readonly', 'rel', 'repeat-max',
+ 'repeat-min', 'replace', 'required', 'rev', 'rightspacing', 'rows',
+ 'rowspan', 'rules', 'scope', 'selected', 'shape', 'size', 'span', 'src',
+ 'start', 'step', 'summary', 'suppress', 'tabindex', 'target', 'template',
+ 'title', 'toppadding', 'type', 'unselectable', 'usemap', 'urn', 'valign',
+ 'value', 'variable', 'volume', 'vspace', 'vrml', 'width', 'wrap',
+ 'xml:lang']
+
+ unacceptable_elements_with_end_tag = ['script', 'applet', 'style']
+
+ acceptable_css_properties = ['azimuth', 'background-color',
+ 'border-bottom-color', 'border-collapse', 'border-color',
+ 'border-left-color', 'border-right-color', 'border-top-color', 'clear',
+ 'color', 'cursor', 'direction', 'display', 'elevation', 'float', 'font',
+ 'font-family', 'font-size', 'font-style', 'font-variant', 'font-weight',
+ 'height', 'letter-spacing', 'line-height', 'overflow', 'pause',
+ 'pause-after', 'pause-before', 'pitch', 'pitch-range', 'richness',
+ 'speak', 'speak-header', 'speak-numeral', 'speak-punctuation',
+ 'speech-rate', 'stress', 'text-align', 'text-decoration', 'text-indent',
+ 'unicode-bidi', 'vertical-align', 'voice-family', 'volume',
+ 'white-space', 'width']
+
+ # survey of common keywords found in feeds
+ acceptable_css_keywords = ['auto', 'aqua', 'black', 'block', 'blue',
+ 'bold', 'both', 'bottom', 'brown', 'center', 'collapse', 'dashed',
+ 'dotted', 'fuchsia', 'gray', 'green', '!important', 'italic', 'left',
+ 'lime', 'maroon', 'medium', 'none', 'navy', 'normal', 'nowrap', 'olive',
+ 'pointer', 'purple', 'red', 'right', 'solid', 'silver', 'teal', 'top',
+ 'transparent', 'underline', 'white', 'yellow']
+
+ valid_css_values = re.compile('^(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|' +
+ '\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$')
+
+ mathml_elements = ['annotation', 'annotation-xml', 'maction', 'math',
+ 'merror', 'mfenced', 'mfrac', 'mi', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded',
+ 'mphantom', 'mprescripts', 'mroot', 'mrow', 'mspace', 'msqrt', 'mstyle',
+ 'msub', 'msubsup', 'msup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder',
+ 'munderover', 'none', 'semantics']
+
+ mathml_attributes = ['actiontype', 'align', 'columnalign', 'columnalign',
+ 'columnalign', 'close', 'columnlines', 'columnspacing', 'columnspan', 'depth',
+ 'display', 'displaystyle', 'encoding', 'equalcolumns', 'equalrows',
+ 'fence', 'fontstyle', 'fontweight', 'frame', 'height', 'linethickness',
+ 'lspace', 'mathbackground', 'mathcolor', 'mathvariant', 'mathvariant',
+ 'maxsize', 'minsize', 'open', 'other', 'rowalign', 'rowalign', 'rowalign',
+ 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'scriptlevel', 'selection',
+ 'separator', 'separators', 'stretchy', 'width', 'width', 'xlink:href',
+ 'xlink:show', 'xlink:type', 'xmlns', 'xmlns:xlink']
+
+ # svgtiny - foreignObject + linearGradient + radialGradient + stop
+ svg_elements = ['a', 'animate', 'animateColor', 'animateMotion',
+ 'animateTransform', 'circle', 'defs', 'desc', 'ellipse', 'foreignObject',
+ 'font-face', 'font-face-name', 'font-face-src', 'g', 'glyph', 'hkern',
+ 'linearGradient', 'line', 'marker', 'metadata', 'missing-glyph', 'mpath',
+ 'path', 'polygon', 'polyline', 'radialGradient', 'rect', 'set', 'stop',
+ 'svg', 'switch', 'text', 'title', 'tspan', 'use']
+
+ # svgtiny + class + opacity + offset + xmlns + xmlns:xlink
+ svg_attributes = ['accent-height', 'accumulate', 'additive', 'alphabetic',
+ 'arabic-form', 'ascent', 'attributeName', 'attributeType',
+ 'baseProfile', 'bbox', 'begin', 'by', 'calcMode', 'cap-height',
+ 'class', 'color', 'color-rendering', 'content', 'cx', 'cy', 'd', 'dx',
+ 'dy', 'descent', 'display', 'dur', 'end', 'fill', 'fill-opacity',
+ 'fill-rule', 'font-family', 'font-size', 'font-stretch', 'font-style',
+ 'font-variant', 'font-weight', 'from', 'fx', 'fy', 'g1', 'g2',
+ 'glyph-name', 'gradientUnits', 'hanging', 'height', 'horiz-adv-x',
+ 'horiz-origin-x', 'id', 'ideographic', 'k', 'keyPoints', 'keySplines',
+ 'keyTimes', 'lang', 'mathematical', 'marker-end', 'marker-mid',
+ 'marker-start', 'markerHeight', 'markerUnits', 'markerWidth', 'max',
+ 'min', 'name', 'offset', 'opacity', 'orient', 'origin',
+ 'overline-position', 'overline-thickness', 'panose-1', 'path',
+ 'pathLength', 'points', 'preserveAspectRatio', 'r', 'refX', 'refY',
+ 'repeatCount', 'repeatDur', 'requiredExtensions', 'requiredFeatures',
+ 'restart', 'rotate', 'rx', 'ry', 'slope', 'stemh', 'stemv',
+ 'stop-color', 'stop-opacity', 'strikethrough-position',
+ 'strikethrough-thickness', 'stroke', 'stroke-dasharray',
+ 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin',
+ 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'systemLanguage',
+ 'target', 'text-anchor', 'to', 'transform', 'type', 'u1', 'u2',
+ 'underline-position', 'underline-thickness', 'unicode', 'unicode-range',
+ 'units-per-em', 'values', 'version', 'viewBox', 'visibility', 'width',
+ 'widths', 'x', 'x-height', 'x1', 'x2', 'xlink:actuate', 'xlink:arcrole',
+ 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type',
+ 'xml:base', 'xml:lang', 'xml:space', 'xmlns', 'xmlns:xlink', 'y', 'y1',
+ 'y2', 'zoomAndPan']
+
+ svg_attr_map = None
+ svg_elem_map = None
+
+ acceptable_svg_properties = [ 'fill', 'fill-opacity', 'fill-rule',
+ 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin',
+ 'stroke-opacity']
+
+ def reset(self):
+ _BaseHTMLProcessor.reset(self)
+ self.unacceptablestack = 0
+ self.mathmlOK = 0
+ self.svgOK = 0
+
+ def unknown_starttag(self, tag, attrs):
+ acceptable_attributes = self.acceptable_attributes
+ keymap = {}
+ if not tag in self.acceptable_elements or self.svgOK:
+ if tag in self.unacceptable_elements_with_end_tag:
+ self.unacceptablestack += 1
+
+ # not otherwise acceptable, perhaps it is MathML or SVG?
+ if tag=='math' and ('xmlns','http://www.w3.org/1998/Math/MathML') in attrs:
+ self.mathmlOK += 1
+ if tag=='svg' and ('xmlns','http://www.w3.org/2000/svg') in attrs:
+ self.svgOK += 1
+
+ # chose acceptable attributes based on tag class, else bail
+ if self.mathmlOK and tag in self.mathml_elements:
+ acceptable_attributes = self.mathml_attributes
+ elif self.svgOK and tag in self.svg_elements:
+ # for most vocabularies, lowercasing is a good idea. Many
+ # svg elements, however, are camel case
+ if not self.svg_attr_map:
+ lower=[attr.lower() for attr in self.svg_attributes]
+ mix=[a for a in self.svg_attributes if a not in lower]
+ self.svg_attributes = lower
+ self.svg_attr_map = dict([(a.lower(),a) for a in mix])
+
+ lower=[attr.lower() for attr in self.svg_elements]
+ mix=[a for a in self.svg_elements if a not in lower]
+ self.svg_elements = lower
+ self.svg_elem_map = dict([(a.lower(),a) for a in mix])
+ acceptable_attributes = self.svg_attributes
+ tag = self.svg_elem_map.get(tag,tag)
+ keymap = self.svg_attr_map
+ elif not tag in self.acceptable_elements:
+ return
+
+ # declare xlink namespace, if needed
+ if self.mathmlOK or self.svgOK:
+ if filter(lambda (n,v): n.startswith('xlink:'),attrs):
+ if not ('xmlns:xlink','http://www.w3.org/1999/xlink') in attrs:
+ attrs.append(('xmlns:xlink','http://www.w3.org/1999/xlink'))
+
+ clean_attrs = []
+ for key, value in self.normalize_attrs(attrs):
+ if key in acceptable_attributes:
+ key=keymap.get(key,key)
+ clean_attrs.append((key,value))
+ elif key=='style':
+ pass
+ ## clean_value = self.sanitize_style(value)
+ ## if clean_value: clean_attrs.append((key,clean_value))
+ _BaseHTMLProcessor.unknown_starttag(self, tag, clean_attrs)
+
+ def unknown_endtag(self, tag):
+ if not tag in self.acceptable_elements:
+ if tag in self.unacceptable_elements_with_end_tag:
+ self.unacceptablestack -= 1
+ if self.mathmlOK and tag in self.mathml_elements:
+ if tag == 'math' and self.mathmlOK: self.mathmlOK -= 1
+ elif self.svgOK and tag in self.svg_elements:
+ tag = self.svg_elem_map.get(tag,tag)
+ if tag == 'svg' and self.svgOK: self.svgOK -= 1
+ else:
+ return
+ _BaseHTMLProcessor.unknown_endtag(self, tag)
+
+ def handle_pi(self, text):
+ pass
+
+ def handle_decl(self, text):
+ pass
+
+ def handle_data(self, text):
+ if not self.unacceptablestack:
+ _BaseHTMLProcessor.handle_data(self, text)
+
+ def sanitize_style(self, style):
+ # disallow urls
+ style=re.compile('url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ',style)
+
+ # gauntlet
+ if not re.match("""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): return ''
+ if not re.match("^(\s*[-\w]+\s*:\s*[^:;]*(;|$))*$", style): return ''
+
+ clean = []
+ for prop,value in re.findall("([-\w]+)\s*:\s*([^:;]*)",style):
+ if not value: continue
+ if prop.lower() in self.acceptable_css_properties:
+ clean.append(prop + ': ' + value + ';')
+ elif prop.split('-')[0].lower() in ['background','border','margin','padding']:
+ for keyword in value.split():
+ if not keyword in self.acceptable_css_keywords and \
+ not self.valid_css_values.match(keyword):
+ break
+ else:
+ clean.append(prop + ': ' + value + ';')
+ elif self.svgOK and prop.lower() in self.acceptable_svg_properties:
+ clean.append(prop + ': ' + value + ';')
+
+ return ' '.join(clean)
+
+
+def sanitize_html(htmlSource, encoding, type):
+ p = _HTMLSanitizer(encoding, type)
+ p.feed(htmlSource)
+ data = p.output()
+ data = data.strip().replace('\r\n', '\n')
+ return data
\ No newline at end of file
diff -r 4ff4be2f436f -r 9c325f3656b5 lib/galaxy/web/__init__.py
--- a/lib/galaxy/web/__init__.py Mon Aug 24 15:27:27 2009 -0400
+++ b/lib/galaxy/web/__init__.py Mon Aug 24 15:53:17 2009 -0400
@@ -3,4 +3,5 @@
"""
from framework import expose, json, require_login, require_admin, url_for, error, form, FormBuilder
+from framework.base import httpexceptions
diff -r 4ff4be2f436f -r 9c325f3656b5 lib/galaxy/web/buildapp.py
--- a/lib/galaxy/web/buildapp.py Mon Aug 24 15:27:27 2009 -0400
+++ b/lib/galaxy/web/buildapp.py Mon Aug 24 15:53:17 2009 -0400
@@ -74,6 +74,7 @@
webapp.add_route( '/:controller/:action', action='index' )
webapp.add_route( '/:action', controller='root', action='index' )
webapp.add_route( '/datasets/:dataset_id/:action/:filename', controller='dataset', action='index', dataset_id=None, filename=None)
+ webapp.add_route( '/u/:username/p/:slug', controller='page', action='display_by_username_and_slug' )
webapp.finalize_config()
# Wrap the webapp in some useful middleware
if kwargs.get( 'middleware', True ):
diff -r 4ff4be2f436f -r 9c325f3656b5 lib/galaxy/web/controllers/page.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/web/controllers/page.py Mon Aug 24 15:53:17 2009 -0400
@@ -0,0 +1,142 @@
+from galaxy.web.base.controller import *
+from galaxy.web.framework.helpers import *
+from galaxy.util.sanitize_html import sanitize_html
+
+import re
+
+VALID_SLUG_RE = re.compile( "^[a-z0-9\-]+$" )
+
+class PageListGrid( grids.Grid ):
+ class URLColumn( grids.GridColumn ):
+ def get_value( self, trans, grid, item ):
+ username = trans.user.username or "???"
+ return username + "/" + item.slug
+ def get_link( self, trans, grid, item ):
+ if trans.user.username:
+ return dict( action='display_by_username_and_slug', username=trans.user.username, slug=item.slug )
+ else:
+ return None
+ # Grid definition
+ use_panels = True
+ title = "Your pages"
+ model_class = model.Page
+ default_sort_key = "-create_time"
+ columns = [
+ grids.GridColumn( "Title", key="title", attach_popup=True ),
+ URLColumn( "Public URL" ),
+ grids.GridColumn( "Created", key="create_time", format=time_ago ),
+ grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
+ ]
+ global_actions = [
+ grids.GridAction( "Add new page", dict( action='create' ) )
+ ]
+ operations = [
+ grids.GridOperation( "View", allow_multiple=False, url_args=dict( action='display') ),
+ grids.GridOperation( "Edit", allow_multiple=False, url_args=dict( action='edit') )
+ ]
+
+class PageController( BaseController ):
+
+ list = PageListGrid()
+
+ @web.expose
+ @web.require_admin
+ def index( self, trans, *args, **kwargs ):
+ grid = self.list( trans, *args, **kwargs )
+ return trans.fill_template( "page/index.mako", grid=grid )
+
+ @web.expose
+ @web.require_admin
+ @web.require_login( "create pages" )
+ def create( self, trans, page_title="", page_slug="" ):
+ """
+ Create a new page
+ """
+ user = trans.get_user()
+ page_title_err = page_slug_err = ""
+ if trans.request.method == "POST":
+ if not page_title:
+ page_title_err = "Page name is required"
+ elif not page_slug:
+ page_slug_err = "Page id is required"
+ elif not VALID_SLUG_RE.match( page_slug ):
+ page_slug_err = "Page identifier must consist of only lowercase letters, numbers, and the '-' character"
+ elif model.Page.filter_by( user=user, slug=page_slug ).first():
+ page_slug_err = "Page id must be unique"
+ else:
+ # Create the new stored workflow
+ page = model.Page()
+ page.title = page_title
+ page.slug = page_slug
+ page.user = user
+ # And the first (empty) workflow revision
+ page_revision = model.PageRevision()
+ page_revision.title = page_title
+ page_revision.page = page
+ page.latest_revision = page_revision
+ page_revision.content = ""
+ # Persist
+ session = trans.sa_session
+ session.save_or_update( page )
+ session.flush()
+ # Display the management page
+ trans.set_message( "Page '%s' created" % page.title )
+ return self.list( trans )
+ return trans.show_form(
+ web.FormBuilder( web.url_for(), "Create new page", submit_text="Submit" )
+ .add_text( "page_title", "Page title", value=page_title, error=page_title_err )
+ .add_text( "page_slug", "Page identifier", value=page_slug, error=page_slug_err,
+ help="""A unique identifier that will be used for
+ public links to this page. A default is generated
+ from the page title, but can be edited. This field
+ must contain only lowercase letters, numbers, and
+ the '-' character.""" ),
+ template="page/create.mako" )
+
+ @web.expose
+ @web.require_admin
+ @web.require_login( "edit pages" )
+ def edit( self, trans, id ):
+ """
+ Render the main page editor interface.
+ """
+ id = trans.security.decode_id( id )
+ page = trans.sa_session.query( model.Page ).get( id )
+ assert page.user == trans.user
+ return trans.fill_template( "page/editor.mako", page=page )
+
+ @web.expose
+ @web.require_admin
+ def save( self, trans, id, content ):
+ id = trans.security.decode_id( id )
+ page = trans.sa_session.query( model.Page ).get( id )
+ assert page.user == trans.user
+ # Sanitize content
+ content = sanitize_html( content, 'utf-8', 'text/html' )
+ # Add a new revision to the page with the provided content
+ page_revision = model.PageRevision()
+ page_revision.title = page.title
+ page_revision.page = page
+ page.latest_revision = page_revision
+ page_revision.content = content
+ trans.sa_session.flush()
+
+ @web.expose
+ @web.require_admin
+ def display( self, trans, id ):
+ id = trans.security.decode_id( id )
+ page = trans.sa_session.query( model.Page ).get( id )
+ return trans.fill_template( "page/display.mako", page=page )
+
+ @web.expose
+ def display_by_username_and_slug( self, trans, username, slug ):
+ session = trans.sa_session
+ user = session.query( model.User ).filter_by( username=username ).first()
+ if user is None:
+ raise web.httpexceptions.HTTPNotFound()
+ page = trans.sa_session.query( model.Page ).filter_by( user=user, slug=slug ).first()
+ if page is None:
+ raise web.httpexceptions.HTTPNotFound()
+ return trans.fill_template( "page/display.mako", page=page )
+
+
\ No newline at end of file
diff -r 4ff4be2f436f -r 9c325f3656b5 lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py Mon Aug 24 15:27:27 2009 -0400
+++ b/lib/galaxy/web/controllers/user.py Mon Aug 24 15:53:17 2009 -0400
@@ -4,7 +4,7 @@
from galaxy.web.base.controller import *
from galaxy.model.orm import *
from galaxy import util
-import logging, os, string
+import logging, os, string, re
from random import choice
log = logging.getLogger( __name__ )
@@ -19,6 +19,8 @@
"""
require_login_nocreation_template = require_login_template % ""
require_login_creation_template = require_login_template % " If you don't already have an account, <a href='%s'>you may create one</a>."
+
+VALID_USERNAME_RE = re.compile( "^[a-z0-9\-]+$" )
class User( BaseController ):
edit_address_id = None
@@ -78,6 +80,37 @@
.add_text( "email", "Email", value=email, error=email_err )
.add_text( "conf_email", "Confirm Email", value='', error=conf_email_err )
.add_password( "password", "Password", value='', error=pass_err ) )
+
+ @web.expose
+ def change_username(self, trans, username='', **kwd):
+ username_err = ''
+ user = trans.get_user()
+ if not user:
+ trans.response.send_redirect( web.url_for( action='login' ) )
+ if trans.request.method == "POST":
+ if len( username ) < 4:
+ username_err = "Username must be at least 4 characters in length"
+ elif len( username ) > 255:
+ username_err = "USername must be at most 255 characters in length"
+ elif not( VALID_USERNAME_RE.match( username ) ):
+ username_err = "Username must contain only letters, numbers, '-', and '_'"
+ elif trans.app.model.User.filter_by( username=username ).first():
+ username_err = "This username is not available"
+ else:
+ user.username = username
+ user.flush()
+ trans.log_event( "User change username" )
+ return trans.show_ok_message( "Username been set to: " + user.username )
+ else:
+ username = user.username or ''
+ return trans.show_form(
+ web.FormBuilder( web.url_for(), "Change username", submit_text="Submit" )
+ .add_text( "username", "Username", value=username, error=username_err,
+ help="""Your username is an optional identifier that
+ will be used to generate adresses for information
+ you share publicly. Usernames must be at least
+ four characters in length and contain only lowercase
+ letters, numbers, and the '-' character.""" ) )
@web.expose
def login( self, trans, email='', password='' ):
diff -r 4ff4be2f436f -r 9c325f3656b5 lib/galaxy/web/framework/helpers/grids.py
--- a/lib/galaxy/web/framework/helpers/grids.py Mon Aug 24 15:27:27 2009 -0400
+++ b/lib/galaxy/web/framework/helpers/grids.py Mon Aug 24 15:53:17 2009 -0400
@@ -15,6 +15,7 @@
exposed = True
model_class = None
template = "grid.mako"
+ global_actions = []
columns = []
operations = []
standard_filters = []
@@ -22,7 +23,12 @@
default_sort_key = None
pass_through_operations = {}
def __init__( self ):
- pass
+ # Determine if any multiple row operations are defined
+ self.has_multiple_item_operations = False
+ for operation in self.operations:
+ if operation.allow_multiple:
+ self.has_multiple_item_operations = True
+ break
def __call__( self, trans, **kwargs ):
status = kwargs.get( 'status', None )
message = kwargs.get( 'message', None )
@@ -65,7 +71,13 @@
current_item = self.get_current_item( trans )
# Render
def url( *args, **kwargs ):
- new_kwargs = dict( extra_url_args )
+ # Only include sort/filter arguments if not linking to another
+ # page. This is a bit of a hack.
+ if 'action' in kwargs:
+ new_kwargs = dict()
+ else:
+ new_kwargs = dict( extra_url_args )
+ # Extend new_kwargs with first argument if found
if len(args) > 0:
new_kwargs.update( args[0] )
new_kwargs.update( kwargs )
@@ -158,16 +170,31 @@
return query
class GridOperation( object ):
- def __init__( self, label, key=None, condition=None, allow_multiple=True ):
+ def __init__( self, label, key=None, condition=None, allow_multiple=True, target=None, url_args=None ):
self.label = label
self.key = key
self.allow_multiple = allow_multiple
self.condition = condition
+ self.target = target
+ self.url_args = url_args
+ def get_url_args( self, item ):
+ if self.url_args:
+ temp = dict( self.url_args )
+ temp['id'] = item.id
+ return temp
+ else:
+ return dict( operation=operation.label, id=item.id )
+
def allowed( self, item ):
if self.condition:
return self.condition( item )
else:
return True
+
+class GridAction( object ):
+ def __init__( self, label=None, url_args=None ):
+ self.label = label
+ self.url_args = url_args
class GridColumnFilter( object ):
def __init__( self, label, args=None ):
diff -r 4ff4be2f436f -r 9c325f3656b5 static/scripts/jquery.wymeditor.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/jquery.wymeditor.js Mon Aug 24 15:53:17 2009 -0400
@@ -0,0 +1,4707 @@
+/**
+ * @version 0.5-rc1
+ *
+ * WYMeditor : what you see is What You Mean web-based editor
+ * Copyright (c) 2005 - 2009 Jean-Francois Hovinne, http://www.wymeditor.org/
+ * Dual licensed under the MIT (MIT-license.txt)
+ * and GPL (GPL-license.txt) licenses.
+ *
+ * For further information visit:
+ * http://www.wymeditor.org/
+ *
+ * File: jquery.wymeditor.js
+ *
+ * Main JS file with core classes and functions.
+ * See the documentation for more info.
+ *
+ * About: authors
+ *
+ * Jean-Francois Hovinne (jf.hovinne a-t wymeditor dotorg)
+ * Volker Mische (vmx a-t gmx dotde)
+ * Scott Lewis (lewiscot a-t gmail dotcom)
+ * Bermi Ferrer (wymeditor a-t bermi dotorg)
+ * Daniel Reszka (d.reszka a-t wymeditor dotorg)
+ * Jonatan Lundin (jonatan.lundin _at_ gmail.com)
+ */
+
+/*
+ Namespace: WYMeditor
+ Global WYMeditor namespace.
+*/
+if(!WYMeditor) var WYMeditor = {};
+
+//Wrap the Firebug console in WYMeditor.console
+(function() {
+ if ( !window.console || !console.firebug ) {
+ var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
+ "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
+
+ WYMeditor.console = {};
+ for (var i = 0; i < names.length; ++i)
+ WYMeditor.console[names[i]] = function() {}
+
+ } else WYMeditor.console = window.console;
+})();
+
+jQuery.extend(WYMeditor, {
+
+/*
+ Constants: Global WYMeditor constants.
+
+ VERSION - Defines WYMeditor version.
+ INSTANCES - An array of loaded WYMeditor.editor instances.
+ STRINGS - An array of loaded WYMeditor language pairs/values.
+ SKINS - An array of loaded WYMeditor skins.
+ NAME - The "name" attribute.
+ INDEX - A string replaced by the instance index.
+ WYM_INDEX - A string used to get/set the instance index.
+ BASE_PATH - A string replaced by WYMeditor's base path.
+ SKIN_PATH - A string replaced by WYMeditor's skin path.
+ WYM_PATH - A string replaced by WYMeditor's main JS file path.
+ SKINS_DEFAULT_PATH - The skins default base path.
+ SKINS_DEFAULT_CSS - The skins default CSS file.
+ LANG_DEFAULT_PATH - The language files default path.
+ IFRAME_BASE_PATH - A string replaced by the designmode iframe's base path.
+ IFRAME_DEFAULT - The iframe's default base path.
+ JQUERY_PATH - A string replaced by the computed jQuery path.
+ DIRECTION - A string replaced by the text direction (rtl or ltr).
+ LOGO - A string replaced by WYMeditor logo.
+ TOOLS - A string replaced by the toolbar's HTML.
+ TOOLS_ITEMS - A string replaced by the toolbar items.
+ TOOL_NAME - A string replaced by a toolbar item's name.
+ TOOL_TITLE - A string replaced by a toolbar item's title.
+ TOOL_CLASS - A string replaced by a toolbar item's class.
+ CLASSES - A string replaced by the classes panel's HTML.
+ CLASSES_ITEMS - A string replaced by the classes items.
+ CLASS_NAME - A string replaced by a class item's name.
+ CLASS_TITLE - A string replaced by a class item's title.
+ CONTAINERS - A string replaced by the containers panel's HTML.
+ CONTAINERS_ITEMS - A string replaced by the containers items.
+ CONTAINER_NAME - A string replaced by a container item's name.
+ CONTAINER_TITLE - A string replaced by a container item's title.
+ CONTAINER_CLASS - A string replaced by a container item's class.
+ HTML - A string replaced by the HTML view panel's HTML.
+ IFRAME - A string replaced by the designmode iframe.
+ STATUS - A string replaced by the status panel's HTML.
+ DIALOG_TITLE - A string replaced by a dialog's title.
+ DIALOG_BODY - A string replaced by a dialog's HTML body.
+ BODY - The BODY element.
+ STRING - The "string" type.
+ BODY,DIV,P,
+ H1,H2,H3,H4,H5,H6,
+ PRE,BLOCKQUOTE,
+ A,BR,IMG,
+ TABLE,TD,TH,
+ UL,OL,LI - HTML elements string representation.
+ CLASS,HREF,SRC,
+ TITLE,ALT - HTML attributes string representation.
+ DIALOG_LINK - A link dialog type.
+ DIALOG_IMAGE - An image dialog type.
+ DIALOG_TABLE - A table dialog type.
+ DIALOG_PASTE - A 'Paste from Word' dialog type.
+ BOLD - Command: (un)set selection to <strong>.
+ ITALIC - Command: (un)set selection to <em>.
+ CREATE_LINK - Command: open the link dialog or (un)set link.
+ INSERT_IMAGE - Command: open the image dialog or insert an image.
+ INSERT_TABLE - Command: open the table dialog.
+ PASTE - Command: open the paste dialog.
+ INDENT - Command: nest a list item.
+ OUTDENT - Command: unnest a list item.
+ TOGGLE_HTML - Command: display/hide the HTML view.
+ FORMAT_BLOCK - Command: set a block element to another type.
+ PREVIEW - Command: open the preview dialog.
+ UNLINK - Command: unset a link.
+ INSERT_UNORDEREDLIST- Command: insert an unordered list.
+ INSERT_ORDEREDLIST - Command: insert an ordered list.
+ MAIN_CONTAINERS - An array of the main HTML containers used in WYMeditor.
+ BLOCKS - An array of the HTML block elements.
+ KEY - Standard key codes.
+ NODE - Node types.
+
+*/
+
+ VERSION : "0.5-rc1",
+ INSTANCES : [],
+ STRINGS : [],
+ SKINS : [],
+ NAME : "name",
+ INDEX : "{Wym_Index}",
+ WYM_INDEX : "wym_index",
+ BASE_PATH : "{Wym_Base_Path}",
+ CSS_PATH : "{Wym_Css_Path}",
+ WYM_PATH : "{Wym_Wym_Path}",
+ SKINS_DEFAULT_PATH : "skins/",
+ SKINS_DEFAULT_CSS : "skin.css",
+ SKINS_DEFAULT_JS : "skin.js",
+ LANG_DEFAULT_PATH : "lang/",
+ IFRAME_BASE_PATH : "{Wym_Iframe_Base_Path}",
+ IFRAME_DEFAULT : "iframe/default/",
+ JQUERY_PATH : "{Wym_Jquery_Path}",
+ DIRECTION : "{Wym_Direction}",
+ LOGO : "{Wym_Logo}",
+ TOOLS : "{Wym_Tools}",
+ TOOLS_ITEMS : "{Wym_Tools_Items}",
+ TOOL_NAME : "{Wym_Tool_Name}",
+ TOOL_TITLE : "{Wym_Tool_Title}",
+ TOOL_CLASS : "{Wym_Tool_Class}",
+ CLASSES : "{Wym_Classes}",
+ CLASSES_ITEMS : "{Wym_Classes_Items}",
+ CLASS_NAME : "{Wym_Class_Name}",
+ CLASS_TITLE : "{Wym_Class_Title}",
+ CONTAINERS : "{Wym_Containers}",
+ CONTAINERS_ITEMS : "{Wym_Containers_Items}",
+ CONTAINER_NAME : "{Wym_Container_Name}",
+ CONTAINER_TITLE : "{Wym_Containers_Title}",
+ CONTAINER_CLASS : "{Wym_Container_Class}",
+ HTML : "{Wym_Html}",
+ IFRAME : "{Wym_Iframe}",
+ STATUS : "{Wym_Status}",
+ DIALOG_TITLE : "{Wym_Dialog_Title}",
+ DIALOG_BODY : "{Wym_Dialog_Body}",
+ STRING : "string",
+ BODY : "body",
+ DIV : "div",
+ P : "p",
+ H1 : "h1",
+ H2 : "h2",
+ H3 : "h3",
+ H4 : "h4",
+ H5 : "h5",
+ H6 : "h6",
+ PRE : "pre",
+ BLOCKQUOTE : "blockquote",
+ A : "a",
+ BR : "br",
+ IMG : "img",
+ TABLE : "table",
+ TD : "td",
+ TH : "th",
+ UL : "ul",
+ OL : "ol",
+ LI : "li",
+ CLASS : "class",
+ HREF : "href",
+ SRC : "src",
+ TITLE : "title",
+ ALT : "alt",
+ DIALOG_LINK : "Link",
+ DIALOG_IMAGE : "Image",
+ DIALOG_TABLE : "Table",
+ DIALOG_PASTE : "Paste_From_Word",
+ BOLD : "Bold",
+ ITALIC : "Italic",
+ CREATE_LINK : "CreateLink",
+ INSERT_IMAGE : "InsertImage",
+ INSERT_TABLE : "InsertTable",
+ INSERT_HTML : "InsertHTML",
+ PASTE : "Paste",
+ INDENT : "Indent",
+ OUTDENT : "Outdent",
+ TOGGLE_HTML : "ToggleHtml",
+ FORMAT_BLOCK : "FormatBlock",
+ PREVIEW : "Preview",
+ UNLINK : "Unlink",
+ INSERT_UNORDEREDLIST: "InsertUnorderedList",
+ INSERT_ORDEREDLIST : "InsertOrderedList",
+
+ MAIN_CONTAINERS : new Array("p","h1","h2","h3","h4","h5","h6","pre","blockquote"),
+
+ BLOCKS : new Array("address", "blockquote", "div", "dl",
+ "fieldset", "form", "h1", "h2", "h3", "h4", "h5", "h6", "hr",
+ "noscript", "ol", "p", "pre", "table", "ul", "dd", "dt",
+ "li", "tbody", "td", "tfoot", "th", "thead", "tr"),
+
+ KEY : {
+ BACKSPACE: 8,
+ ENTER: 13,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ CURSOR: new Array(37, 38, 39, 40),
+ DELETE: 46
+ },
+
+ NODE : {
+ ELEMENT: 1,
+ ATTRIBUTE: 2,
+ TEXT: 3
+ },
+
+ /*
+ Class: WYMeditor.editor
+ WYMeditor editor main class, instanciated for each editor occurrence.
+ */
+
+ editor : function(elem, options) {
+
+ /*
+ Constructor: WYMeditor.editor
+
+ Initializes main values (index, elements, paths, ...)
+ and call WYMeditor.editor.init which initializes the editor.
+
+ Parameters:
+
+ elem - The HTML element to be replaced by the editor.
+ options - The hash of options.
+
+ Returns:
+
+ Nothing.
+
+ See Also:
+
+ <WYMeditor.editor.init>
+ */
+
+ //store the instance in the INSTANCES array and store the index
+ this._index = WYMeditor.INSTANCES.push(this) - 1;
+ //store the element replaced by the editor
+ this._element = elem;
+ //store the options
+ this._options = options;
+ //store the element's inner value
+ this._html = jQuery(elem).val();
+
+ //store the HTML option, if any
+ if(this._options.html) this._html = this._options.html;
+ //get or compute the base path (where the main JS file is located)
+ this._options.basePath = this._options.basePath
+ || this.computeBasePath();
+ //get or set the skin path (where the skin files are located)
+ this._options.skinPath = this._options.skinPath
+ || this._options.basePath + WYMeditor.SKINS_DEFAULT_PATH
+ + this._options.skin + '/';
+ //get or compute the main JS file location
+ this._options.wymPath = this._options.wymPath
+ || this.computeWymPath();
+ //get or set the language files path
+ this._options.langPath = this._options.langPath
+ || this._options.basePath + WYMeditor.LANG_DEFAULT_PATH;
+ //get or set the designmode iframe's base path
+ this._options.iframeBasePath = this._options.iframeBasePath
+ || this._options.basePath + WYMeditor.IFRAME_DEFAULT;
+ //get or compute the jQuery JS file location
+ this._options.jQueryPath = this._options.jQueryPath
+ || this.computeJqueryPath();
+
+ //initialize the editor instance
+ this.init();
+
+ }
+
+});
+
+
+/********** JQUERY **********/
+
+/**
+ * Replace an HTML element by WYMeditor
+ *
+ * @example jQuery(".wymeditor").wymeditor(
+ * {
+ *
+ * }
+ * );
+ * @desc Example description here
+ *
+ * @name WYMeditor
+ * @description WYMeditor is a web-based WYSIWYM XHTML editor
+ * @param Hash hash A hash of parameters
+ * @option Integer iExample Description here
+ * @option String sExample Description here
+ *
+ * @type jQuery
+ * @cat Plugins/WYMeditor
+ * @author Jean-Francois Hovinne
+ */
+jQuery.fn.wymeditor = function(options) {
+
+ options = jQuery.extend({
+
+ html: "",
+
+ basePath: false,
+
+ skinPath: false,
+
+ wymPath: false,
+
+ iframeBasePath: false,
+
+ jQueryPath: false,
+
+ styles: false,
+
+ stylesheet: false,
+
+ skin: "default",
+ initSkin: true,
+ loadSkin: true,
+
+ lang: "en",
+
+ direction: "ltr",
+
+ boxHtml: "<div class='wym_box'>"
+ + "<div class='wym_area_top'>"
+ + WYMeditor.TOOLS
+ + "</div>"
+ + "<div class='wym_area_left'></div>"
+ + "<div class='wym_area_right'>"
+ + WYMeditor.CONTAINERS
+ + WYMeditor.CLASSES
+ + "</div>"
+ + "<div class='wym_area_main'>"
+ + WYMeditor.HTML
+ + WYMeditor.IFRAME
+ + WYMeditor.STATUS
+ + "</div>"
+ + "<div class='wym_area_bottom'>"
+ + WYMeditor.LOGO
+ + "</div>"
+ + "</div>",
+
+ logoHtml: "<a class='wym_wymeditor_link' "
+ + "href='http://www.wymeditor.org/'>WYMeditor</a>",
+
+ iframeHtml:"<div class='wym_iframe wym_section'>"
+ + "<iframe "
+ + "src='"
+ + WYMeditor.IFRAME_BASE_PATH
+ + "wymiframe.html' "
+ + "onload='this.contentWindow.parent.WYMeditor.INSTANCES["
+ + WYMeditor.INDEX + "].initIframe(this)'"
+ + "></iframe>"
+ + "</div>",
+
+ editorStyles: [],
+
+ toolsHtml: "<div class='wym_tools wym_section'>"
+ + "<h2>{Tools}</h2>"
+ + "<ul>"
+ + WYMeditor.TOOLS_ITEMS
+ + "</ul>"
+ + "</div>",
+
+ toolsItemHtml: "<li class='"
+ + WYMeditor.TOOL_CLASS
+ + "'><a href='#' name='"
+ + WYMeditor.TOOL_NAME
+ + "' title='"
+ + WYMeditor.TOOL_TITLE
+ + "'>"
+ + WYMeditor.TOOL_TITLE
+ + "</a></li>",
+
+ toolsItems: [
+ {'name': 'Bold', 'title': 'Strong', 'css': 'wym_tools_strong'},
+ {'name': 'Italic', 'title': 'Emphasis', 'css': 'wym_tools_emphasis'},
+ {'name': 'Superscript', 'title': 'Superscript',
+ 'css': 'wym_tools_superscript'},
+ {'name': 'Subscript', 'title': 'Subscript',
+ 'css': 'wym_tools_subscript'},
+ {'name': 'InsertOrderedList', 'title': 'Ordered_List',
+ 'css': 'wym_tools_ordered_list'},
+ {'name': 'InsertUnorderedList', 'title': 'Unordered_List',
+ 'css': 'wym_tools_unordered_list'},
+ {'name': 'Indent', 'title': 'Indent', 'css': 'wym_tools_indent'},
+ {'name': 'Outdent', 'title': 'Outdent', 'css': 'wym_tools_outdent'},
+ {'name': 'Undo', 'title': 'Undo', 'css': 'wym_tools_undo'},
+ {'name': 'Redo', 'title': 'Redo', 'css': 'wym_tools_redo'},
+ {'name': 'CreateLink', 'title': 'Link', 'css': 'wym_tools_link'},
+ {'name': 'Unlink', 'title': 'Unlink', 'css': 'wym_tools_unlink'},
+ {'name': 'InsertImage', 'title': 'Image', 'css': 'wym_tools_image'},
+ {'name': 'InsertTable', 'title': 'Table', 'css': 'wym_tools_table'},
+ {'name': 'Paste', 'title': 'Paste_From_Word',
+ 'css': 'wym_tools_paste'},
+ {'name': 'ToggleHtml', 'title': 'HTML', 'css': 'wym_tools_html'},
+ {'name': 'Preview', 'title': 'Preview', 'css': 'wym_tools_preview'}
+ ],
+
+ containersHtml: "<div class='wym_containers wym_section'>"
+ + "<h2>{Containers}</h2>"
+ + "<ul>"
+ + WYMeditor.CONTAINERS_ITEMS
+ + "</ul>"
+ + "</div>",
+
+ containersItemHtml:"<li class='"
+ + WYMeditor.CONTAINER_CLASS
+ + "'>"
+ + "<a href='#' name='"
+ + WYMeditor.CONTAINER_NAME
+ + "'>"
+ + WYMeditor.CONTAINER_TITLE
+ + "</a></li>",
+
+ containersItems: [
+ {'name': 'P', 'title': 'Paragraph', 'css': 'wym_containers_p'},
+ {'name': 'H1', 'title': 'Heading_1', 'css': 'wym_containers_h1'},
+ {'name': 'H2', 'title': 'Heading_2', 'css': 'wym_containers_h2'},
+ {'name': 'H3', 'title': 'Heading_3', 'css': 'wym_containers_h3'},
+ {'name': 'H4', 'title': 'Heading_4', 'css': 'wym_containers_h4'},
+ {'name': 'H5', 'title': 'Heading_5', 'css': 'wym_containers_h5'},
+ {'name': 'H6', 'title': 'Heading_6', 'css': 'wym_containers_h6'},
+ {'name': 'PRE', 'title': 'Preformatted', 'css': 'wym_containers_pre'},
+ {'name': 'BLOCKQUOTE', 'title': 'Blockquote',
+ 'css': 'wym_containers_blockquote'},
+ {'name': 'TH', 'title': 'Table_Header', 'css': 'wym_containers_th'}
+ ],
+
+ classesHtml: "<div class='wym_classes wym_section'>"
+ + "<h2>{Classes}</h2><ul>"
+ + WYMeditor.CLASSES_ITEMS
+ + "</ul></div>",
+
+ classesItemHtml: "<li><a href='#' name='"
+ + WYMeditor.CLASS_NAME
+ + "'>"
+ + WYMeditor.CLASS_TITLE
+ + "</a></li>",
+
+ classesItems: [],
+
+ statusHtml: "<div class='wym_status wym_section'>"
+ + "<h2>{Status}</h2>"
+ + "</div>",
+
+ htmlHtml: "<div class='wym_html wym_section'>"
+ + "<h2>{Source_Code}</h2>"
+ + "<textarea class='wym_html_val'></textarea>"
+ + "</div>",
+
+ boxSelector: ".wym_box",
+ toolsSelector: ".wym_tools",
+ toolsListSelector: " ul",
+ containersSelector:".wym_containers",
+ classesSelector: ".wym_classes",
+ htmlSelector: ".wym_html",
+ iframeSelector: ".wym_iframe iframe",
+ iframeBodySelector:".wym_iframe",
+ statusSelector: ".wym_status",
+ toolSelector: ".wym_tools a",
+ containerSelector: ".wym_containers a",
+ classSelector: ".wym_classes a",
+ htmlValSelector: ".wym_html_val",
+
+ hrefSelector: ".wym_href",
+ srcSelector: ".wym_src",
+ titleSelector: ".wym_title",
+ altSelector: ".wym_alt",
+ textSelector: ".wym_text",
+
+ rowsSelector: ".wym_rows",
+ colsSelector: ".wym_cols",
+ captionSelector: ".wym_caption",
+ summarySelector: ".wym_summary",
+
+ submitSelector: ".wym_submit",
+ cancelSelector: ".wym_cancel",
+ previewSelector: "",
+
+ dialogTypeSelector: ".wym_dialog_type",
+ dialogLinkSelector: ".wym_dialog_link",
+ dialogImageSelector: ".wym_dialog_image",
+ dialogTableSelector: ".wym_dialog_table",
+ dialogPasteSelector: ".wym_dialog_paste",
+ dialogPreviewSelector: ".wym_dialog_preview",
+
+ updateSelector: ".wymupdate",
+ updateEvent: "click",
+
+ dialogFeatures: "menubar=no,titlebar=no,toolbar=no,resizable=no"
+ + ",width=560,height=300,top=0,left=0",
+ dialogFeaturesPreview: "menubar=no,titlebar=no,toolbar=no,resizable=no"
+ + ",scrollbars=yes,width=560,height=300,top=0,left=0",
+
+ dialogHtml: "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'"
+ + " 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>"
+ + "<html dir='"
+ + WYMeditor.DIRECTION
+ + "'><head>"
+ + "<link rel='stylesheet' type='text/css' media='screen'"
+ + " href='"
+ + WYMeditor.CSS_PATH
+ + "' />"
+ + "<title>"
+ + WYMeditor.DIALOG_TITLE
+ + "</title>"
+ + "<script type='text/javascript'"
+ + " src='"
+ + WYMeditor.JQUERY_PATH
+ + "'></script>"
+ + "<script type='text/javascript'"
+ + " src='"
+ + WYMeditor.WYM_PATH
+ + "'></script>"
+ + "</head>"
+ + WYMeditor.DIALOG_BODY
+ + "</html>",
+
+ dialogLinkHtml: "<body class='wym_dialog wym_dialog_link'"
+ + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
+ + ">"
+ + "<form>"
+ + "<fieldset>"
+ + "<input type='hidden' class='wym_dialog_type' value='"
+ + WYMeditor.DIALOG_LINK
+ + "' />"
+ + "<legend>{Link}</legend>"
+ + "<div class='row'>"
+ + "<label>{URL}</label>"
+ + "<input type='text' class='wym_href' value='' size='40' />"
+ + "</div>"
+ + "<div class='row'>"
+ + "<label>{Title}</label>"
+ + "<input type='text' class='wym_title' value='' size='40' />"
+ + "</div>"
+ + "<div class='row row-indent'>"
+ + "<input class='wym_submit' type='button'"
+ + " value='{Submit}' />"
+ + "<input class='wym_cancel' type='button'"
+ + "value='{Cancel}' />"
+ + "</div>"
+ + "</fieldset>"
+ + "</form>"
+ + "</body>",
+
+ dialogImageHtml: "<body class='wym_dialog wym_dialog_image'"
+ + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
+ + ">"
+ + "<form>"
+ + "<fieldset>"
+ + "<input type='hidden' class='wym_dialog_type' value='"
+ + WYMeditor.DIALOG_IMAGE
+ + "' />"
+ + "<legend>{Image}</legend>"
+ + "<div class='row'>"
+ + "<label>{URL}</label>"
+ + "<input type='text' class='wym_src' value='' size='40' />"
+ + "</div>"
+ + "<div class='row'>"
+ + "<label>{Alternative_Text}</label>"
+ + "<input type='text' class='wym_alt' value='' size='40' />"
+ + "</div>"
+ + "<div class='row'>"
+ + "<label>{Title}</label>"
+ + "<input type='text' class='wym_title' value='' size='40' />"
+ + "</div>"
+ + "<div class='row row-indent'>"
+ + "<input class='wym_submit' type='button'"
+ + " value='{Submit}' />"
+ + "<input class='wym_cancel' type='button'"
+ + "value='{Cancel}' />"
+ + "</div>"
+ + "</fieldset>"
+ + "</form>"
+ + "</body>",
+
+ dialogTableHtml: "<body class='wym_dialog wym_dialog_table'"
+ + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
+ + ">"
+ + "<form>"
+ + "<fieldset>"
+ + "<input type='hidden' class='wym_dialog_type' value='"
+ + WYMeditor.DIALOG_TABLE
+ + "' />"
+ + "<legend>{Table}</legend>"
+ + "<div class='row'>"
+ + "<label>{Caption}</label>"
+ + "<input type='text' class='wym_caption' value='' size='40' />"
+ + "</div>"
+ + "<div class='row'>"
+ + "<label>{Summary}</label>"
+ + "<input type='text' class='wym_summary' value='' size='40' />"
+ + "</div>"
+ + "<div class='row'>"
+ + "<label>{Number_Of_Rows}</label>"
+ + "<input type='text' class='wym_rows' value='3' size='3' />"
+ + "</div>"
+ + "<div class='row'>"
+ + "<label>{Number_Of_Cols}</label>"
+ + "<input type='text' class='wym_cols' value='2' size='3' />"
+ + "</div>"
+ + "<div class='row row-indent'>"
+ + "<input class='wym_submit' type='button'"
+ + " value='{Submit}' />"
+ + "<input class='wym_cancel' type='button'"
+ + "value='{Cancel}' />"
+ + "</div>"
+ + "</fieldset>"
+ + "</form>"
+ + "</body>",
+
+ dialogPasteHtml: "<body class='wym_dialog wym_dialog_paste'"
+ + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
+ + ">"
+ + "<form>"
+ + "<input type='hidden' class='wym_dialog_type' value='"
+ + WYMeditor.DIALOG_PASTE
+ + "' />"
+ + "<fieldset>"
+ + "<legend>{Paste_From_Word}</legend>"
+ + "<div class='row'>"
+ + "<textarea class='wym_text' rows='10' cols='50'></textarea>"
+ + "</div>"
+ + "<div class='row'>"
+ + "<input class='wym_submit' type='button'"
+ + " value='{Submit}' />"
+ + "<input class='wym_cancel' type='button'"
+ + "value='{Cancel}' />"
+ + "</div>"
+ + "</fieldset>"
+ + "</form>"
+ + "</body>",
+
+ dialogPreviewHtml: "<body class='wym_dialog wym_dialog_preview'"
+ + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
+ + "></body>",
+
+ dialogStyles: [],
+
+ stringDelimiterLeft: "{",
+ stringDelimiterRight:"}",
+
+ preInit: null,
+ preBind: null,
+ postInit: null,
+
+ preInitDialog: null,
+ postInitDialog: null
+
+ }, options);
+
+ return this.each(function() {
+
+ new WYMeditor.editor(jQuery(this),options);
+ });
+};
+
+/* @name extend
+ * @description Returns the WYMeditor instance based on its index
+ */
+jQuery.extend({
+ wymeditors: function(i) {
+ return (WYMeditor.INSTANCES[i]);
+ }
+});
+
+
+/********** WYMeditor **********/
+
+/* @name Wymeditor
+ * @description WYMeditor class
+ */
+
+/* @name init
+ * @description Initializes a WYMeditor instance
+ */
+WYMeditor.editor.prototype.init = function() {
+
+ //load subclass - browser specific
+ //unsupported browsers: do nothing
+ if (jQuery.browser.msie) {
+ var WymClass = new WYMeditor.WymClassExplorer(this);
+ }
+ else if (jQuery.browser.mozilla) {
+ var WymClass = new WYMeditor.WymClassMozilla(this);
+ }
+ else if (jQuery.browser.opera) {
+ var WymClass = new WYMeditor.WymClassOpera(this);
+ }
+ else if (jQuery.browser.safari) {
+ var WymClass = new WYMeditor.WymClassSafari(this);
+ }
+
+ if(WymClass) {
+
+ if(jQuery.isFunction(this._options.preInit)) this._options.preInit(this);
+
+ var SaxListener = new WYMeditor.XhtmlSaxListener();
+ jQuery.extend(SaxListener, WymClass);
+ this.parser = new WYMeditor.XhtmlParser(SaxListener);
+
+ if(this._options.styles || this._options.stylesheet){
+ this.configureEditorUsingRawCss();
+ }
+
+ this.helper = new WYMeditor.XmlHelper();
+
+ //extend the Wymeditor object
+ //don't use jQuery.extend since 1.1.4
+ //jQuery.extend(this, WymClass);
+ for (var prop in WymClass) { this[prop] = WymClass[prop]; }
+
+ //load wymbox
+ this._box = jQuery(this._element).hide().after(this._options.boxHtml).next().addClass('wym_box_' + this._index);
+
+ //store the instance index in wymbox and element replaced by editor instance
+ //but keep it compatible with jQuery < 1.2.3, see #122
+ if( jQuery.isFunction( jQuery.fn.data ) ) {
+ jQuery.data(this._box.get(0), WYMeditor.WYM_INDEX, this._index);
+ jQuery.data(this._element.get(0), WYMeditor.WYM_INDEX, this._index);
+ }
+
+ var h = WYMeditor.Helper;
+
+ //construct the iframe
+ var iframeHtml = this._options.iframeHtml;
+ iframeHtml = h.replaceAll(iframeHtml, WYMeditor.INDEX, this._index);
+ iframeHtml = h.replaceAll(iframeHtml, WYMeditor.IFRAME_BASE_PATH, this._options.iframeBasePath);
+
+ //construct wymbox
+ var boxHtml = jQuery(this._box).html();
+
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.LOGO, this._options.logoHtml);
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.TOOLS, this._options.toolsHtml);
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.CONTAINERS,this._options.containersHtml);
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.CLASSES, this._options.classesHtml);
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.HTML, this._options.htmlHtml);
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.IFRAME, iframeHtml);
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.STATUS, this._options.statusHtml);
+
+ //construct tools list
+ var aTools = eval(this._options.toolsItems);
+ var sTools = "";
+
+ for(var i = 0; i < aTools.length; i++) {
+ var oTool = aTools[i];
+ if(oTool.name && oTool.title)
+ var sTool = this._options.toolsItemHtml;
+ var sTool = h.replaceAll(sTool, WYMeditor.TOOL_NAME, oTool.name);
+ sTool = h.replaceAll(sTool, WYMeditor.TOOL_TITLE, this._options.stringDelimiterLeft
+ + oTool.title
+ + this._options.stringDelimiterRight);
+ sTool = h.replaceAll(sTool, WYMeditor.TOOL_CLASS, oTool.css);
+ sTools += sTool;
+ }
+
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.TOOLS_ITEMS, sTools);
+
+ //construct classes list
+ var aClasses = eval(this._options.classesItems);
+ var sClasses = "";
+
+ for(var i = 0; i < aClasses.length; i++) {
+ var oClass = aClasses[i];
+ if(oClass.name && oClass.title)
+ var sClass = this._options.classesItemHtml;
+ sClass = h.replaceAll(sClass, WYMeditor.CLASS_NAME, oClass.name);
+ sClass = h.replaceAll(sClass, WYMeditor.CLASS_TITLE, oClass.title);
+ sClasses += sClass;
+ }
+
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.CLASSES_ITEMS, sClasses);
+
+ //construct containers list
+ var aContainers = eval(this._options.containersItems);
+ var sContainers = "";
+
+ for(var i = 0; i < aContainers.length; i++) {
+ var oContainer = aContainers[i];
+ if(oContainer.name && oContainer.title)
+ var sContainer = this._options.containersItemHtml;
+ sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_NAME, oContainer.name);
+ sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_TITLE,
+ this._options.stringDelimiterLeft
+ + oContainer.title
+ + this._options.stringDelimiterRight);
+ sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_CLASS, oContainer.css);
+ sContainers += sContainer;
+ }
+
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.CONTAINERS_ITEMS, sContainers);
+
+ //l10n
+ boxHtml = this.replaceStrings(boxHtml);
+
+ //load html in wymbox
+ jQuery(this._box).html(boxHtml);
+
+ //hide the html value
+ jQuery(this._box).find(this._options.htmlSelector).hide();
+
+ //enable the skin
+ this.loadSkin();
+
+ }
+};
+
+WYMeditor.editor.prototype.bindEvents = function() {
+
+ //copy the instance
+ var wym = this;
+
+ //handle click event on tools buttons
+ jQuery(this._box).find(this._options.toolSelector).click(function() {
+ wym._iframe.contentWindow.focus(); //See #154
+ wym.exec(jQuery(this).attr(WYMeditor.NAME));
+ return(false);
+ });
+
+ //handle click event on containers buttons
+ jQuery(this._box).find(this._options.containerSelector).click(function() {
+ wym.container(jQuery(this).attr(WYMeditor.NAME));
+ return(false);
+ });
+
+ //handle keyup event on html value: set the editor value
+ //handle focus/blur events to check if the element has focus, see #147
+ jQuery(this._box).find(this._options.htmlValSelector)
+ .keyup(function() { jQuery(wym._doc.body).html(jQuery(this).val());})
+ .focus(function() { jQuery(this).toggleClass('hasfocus'); })
+ .blur(function() { jQuery(this).toggleClass('hasfocus'); });
+
+ //handle click event on classes buttons
+ jQuery(this._box).find(this._options.classSelector).click(function() {
+
+ var aClasses = eval(wym._options.classesItems);
+ var sName = jQuery(this).attr(WYMeditor.NAME);
+
+ var oClass = WYMeditor.Helper.findByName(aClasses, sName);
+
+ if(oClass) {
+ var jqexpr = oClass.expr;
+ wym.toggleClass(sName, jqexpr);
+ }
+ wym._iframe.contentWindow.focus(); //See #154
+ return(false);
+ });
+
+ //handle event on update element
+ jQuery(this._options.updateSelector)
+ .bind(this._options.updateEvent, function() {
+ wym.update();
+ });
+};
+
+WYMeditor.editor.prototype.ready = function() {
+ return(this._doc != null);
+};
+
+
+/********** METHODS **********/
+
+/* @name box
+ * @description Returns the WYMeditor container
+ */
+WYMeditor.editor.prototype.box = function() {
+ return(this._box);
+};
+
+/* @name html
+ * @description Get/Set the html value
+ */
+WYMeditor.editor.prototype.html = function(html) {
+
+ if(typeof html === 'string') jQuery(this._doc.body).html(html);
+ else return(jQuery(this._doc.body).html());
+};
+
+/* @name xhtml
+ * @description Cleans up the HTML
+ */
+WYMeditor.editor.prototype.xhtml = function() {
+ return this.parser.parse(this.html());
+};
+
+/* @name exec
+ * @description Executes a button command
+ */
+WYMeditor.editor.prototype.exec = function(cmd) {
+
+ //base function for execCommand
+ //open a dialog or exec
+ switch(cmd) {
+ case WYMeditor.CREATE_LINK:
+ var container = this.container();
+ if(container || this._selected_image) this.dialog(WYMeditor.DIALOG_LINK);
+ break;
+
+ case WYMeditor.INSERT_IMAGE:
+ this.dialog(WYMeditor.DIALOG_IMAGE);
+ break;
+
+ case WYMeditor.INSERT_TABLE:
+ this.dialog(WYMeditor.DIALOG_TABLE);
+ break;
+
+ case WYMeditor.PASTE:
+ this.dialog(WYMeditor.DIALOG_PASTE);
+ break;
+
+ case WYMeditor.TOGGLE_HTML:
+ this.update();
+ this.toggleHtml();
+
+ //partially fixes #121 when the user manually inserts an image
+ if(!jQuery(this._box).find(this._options.htmlSelector).is(':visible'))
+ this.listen();
+ break;
+
+ case WYMeditor.PREVIEW:
+ this.dialog(WYMeditor.PREVIEW, this._options.dialogFeaturesPreview);
+ break;
+
+ default:
+ this._exec(cmd);
+ break;
+ }
+};
+
+/* @name container
+ * @description Get/Set the selected container
+ */
+WYMeditor.editor.prototype.container = function(sType) {
+
+ if(sType) {
+
+ var container = null;
+
+ if(sType.toLowerCase() == WYMeditor.TH) {
+
+ container = this.container();
+
+ //find the TD or TH container
+ switch(container.tagName.toLowerCase()) {
+
+ case WYMeditor.TD: case WYMeditor.TH:
+ break;
+ default:
+ var aTypes = new Array(WYMeditor.TD,WYMeditor.TH);
+ container = this.findUp(this.container(), aTypes);
+ break;
+ }
+
+ //if it exists, switch
+ if(container!=null) {
+
+ sType = (container.tagName.toLowerCase() == WYMeditor.TD)? WYMeditor.TH: WYMeditor.TD;
+ this.switchTo(container,sType);
+ this.update();
+ }
+ } else {
+
+ //set the container type
+ var aTypes=new Array(WYMeditor.P,WYMeditor.H1,WYMeditor.H2,WYMeditor.H3,WYMeditor.H4,WYMeditor.H5,
+ WYMeditor.H6,WYMeditor.PRE,WYMeditor.BLOCKQUOTE);
+ container = this.findUp(this.container(), aTypes);
+
+ if(container) {
+
+ var newNode = null;
+
+ //blockquotes must contain a block level element
+ if(sType.toLowerCase() == WYMeditor.BLOCKQUOTE) {
+
+ var blockquote = this.findUp(this.container(), WYMeditor.BLOCKQUOTE);
+
+ if(blockquote == null) {
+
+ newNode = this._doc.createElement(sType);
+ container.parentNode.insertBefore(newNode,container);
+ newNode.appendChild(container);
+ this.setFocusToNode(newNode.firstChild);
+
+ } else {
+
+ var nodes = blockquote.childNodes;
+ var lgt = nodes.length;
+ var firstNode = null;
+
+ if(lgt > 0) firstNode = nodes.item(0);
+ for(var x=0; x<lgt; x++) {
+ blockquote.parentNode.insertBefore(nodes.item(0),blockquote);
+ }
+ blockquote.parentNode.removeChild(blockquote);
+ if(firstNode) this.setFocusToNode(firstNode);
+ }
+ }
+
+ else this.switchTo(container,sType);
+
+ this.update();
+ }
+ }
+ }
+ else return(this.selected());
+};
+
+/* @name toggleClass
+ * @description Toggles class on selected element, or one of its parents
+ */
+WYMeditor.editor.prototype.toggleClass = function(sClass, jqexpr) {
+
+ var container = (this._selected_image
+ ? this._selected_image
+ : jQuery(this.selected()));
+ container = jQuery(container).parentsOrSelf(jqexpr);
+ jQuery(container).toggleClass(sClass);
+
+ if(!jQuery(container).attr(WYMeditor.CLASS)) jQuery(container).removeAttr(this._class);
+
+};
+
+/* @name findUp
+ * @description Returns the first parent or self container, based on its type
+ */
+WYMeditor.editor.prototype.findUp = function(node, filter) {
+
+ //filter is a string or an array of strings
+
+ if(node) {
+
+ var tagname = node.tagName.toLowerCase();
+
+ if(typeof(filter) == WYMeditor.STRING) {
+
+ while(tagname != filter && tagname != WYMeditor.BODY) {
+
+ node = node.parentNode;
+ tagname = node.tagName.toLowerCase();
+ }
+
+ } else {
+
+ var bFound = false;
+
+ while(!bFound && tagname != WYMeditor.BODY) {
+ for(var i = 0; i < filter.length; i++) {
+ if(tagname == filter[i]) {
+ bFound = true;
+ break;
+ }
+ }
+ if(!bFound) {
+ node = node.parentNode;
+ tagname = node.tagName.toLowerCase();
+ }
+ }
+ }
+
+ if(tagname != WYMeditor.BODY) return(node);
+ else return(null);
+
+ } else return(null);
+};
+
+/* @name switchTo
+ * @description Switch the node's type
+ */
+WYMeditor.editor.prototype.switchTo = function(node,sType) {
+
+ var newNode = this._doc.createElement(sType);
+ var html = jQuery(node).html();
+ node.parentNode.replaceChild(newNode,node);
+ jQuery(newNode).html(html);
+ this.setFocusToNode(newNode);
+};
+
+WYMeditor.editor.prototype.replaceStrings = function(sVal) {
+ //check if the language file has already been loaded
+ //if not, get it via a synchronous ajax call
+ if(!WYMeditor.STRINGS[this._options.lang]) {
+ try {
+ eval(jQuery.ajax({url:this._options.langPath
+ + this._options.lang + '.js', async:false}).responseText);
+ } catch(e) {
+ WYMeditor.console.error("WYMeditor: error while parsing language file.");
+ return sVal;
+ }
+ }
+
+ //replace all the strings in sVal and return it
+ for (var key in WYMeditor.STRINGS[this._options.lang]) {
+ sVal = WYMeditor.Helper.replaceAll(sVal, this._options.stringDelimiterLeft + key
+ + this._options.stringDelimiterRight,
+ WYMeditor.STRINGS[this._options.lang][key]);
+ };
+ return(sVal);
+};
+
+WYMeditor.editor.prototype.encloseString = function(sVal) {
+
+ return(this._options.stringDelimiterLeft
+ + sVal
+ + this._options.stringDelimiterRight);
+};
+
+/* @name status
+ * @description Prints a status message
+ */
+WYMeditor.editor.prototype.status = function(sMessage) {
+
+ //print status message
+ jQuery(this._box).find(this._options.statusSelector).html(sMessage);
+};
+
+/* @name update
+ * @description Updates the element and textarea values
+ */
+WYMeditor.editor.prototype.update = function() {
+
+ var html = this.xhtml();
+ jQuery(this._element).val(html);
+ jQuery(this._box).find(this._options.htmlValSelector).not('.hasfocus').val(html); //#147
+};
+
+/* @name dialog
+ * @description Opens a dialog box
+ */
+WYMeditor.editor.prototype.dialog = function( dialogType, dialogFeatures, bodyHtml ) {
+
+ var features = dialogFeatures || this._wym._options.dialogFeatures;
+ var wDialog = window.open('', 'dialog', features);
+
+ if(wDialog) {
+
+ var sBodyHtml = "";
+
+ switch( dialogType ) {
+
+ case(WYMeditor.DIALOG_LINK):
+ sBodyHtml = this._options.dialogLinkHtml;
+ break;
+ case(WYMeditor.DIALOG_IMAGE):
+ sBodyHtml = this._options.dialogImageHtml;
+ break;
+ case(WYMeditor.DIALOG_TABLE):
+ sBodyHtml = this._options.dialogTableHtml;
+ break;
+ case(WYMeditor.DIALOG_PASTE):
+ sBodyHtml = this._options.dialogPasteHtml;
+ break;
+ case(WYMeditor.PREVIEW):
+ sBodyHtml = this._options.dialogPreviewHtml;
+ break;
+
+ default:
+ sBodyHtml = bodyHtml;
+ }
+
+ var h = WYMeditor.Helper;
+
+ //construct the dialog
+ var dialogHtml = this._options.dialogHtml;
+ dialogHtml = h.replaceAll(dialogHtml, WYMeditor.BASE_PATH, this._options.basePath);
+ dialogHtml = h.replaceAll(dialogHtml, WYMeditor.DIRECTION, this._options.direction);
+ dialogHtml = h.replaceAll(dialogHtml, WYMeditor.CSS_PATH, this._options.skinPath + WYMeditor.SKINS_DEFAULT_CSS);
+ dialogHtml = h.replaceAll(dialogHtml, WYMeditor.WYM_PATH, this._options.wymPath);
+ dialogHtml = h.replaceAll(dialogHtml, WYMeditor.JQUERY_PATH, this._options.jQueryPath);
+ dialogHtml = h.replaceAll(dialogHtml, WYMeditor.DIALOG_TITLE, this.encloseString( dialogType ));
+ dialogHtml = h.replaceAll(dialogHtml, WYMeditor.DIALOG_BODY, sBodyHtml);
+ dialogHtml = h.replaceAll(dialogHtml, WYMeditor.INDEX, this._index);
+
+ dialogHtml = this.replaceStrings(dialogHtml);
+
+ var doc = wDialog.document;
+ doc.write(dialogHtml);
+ doc.close();
+ }
+};
+
+/* @name toggleHtml
+ * @description Shows/Hides the HTML
+ */
+WYMeditor.editor.prototype.toggleHtml = function() {
+ jQuery(this._box).find(this._options.htmlSelector).toggle();
+};
+
+WYMeditor.editor.prototype.uniqueStamp = function() {
+ var now = new Date();
+ return("wym-" + now.getTime());
+};
+
+WYMeditor.editor.prototype.paste = function(sData) {
+
+ var sTmp;
+ var container = this.selected();
+
+ //split the data, using double newlines as the separator
+ var aP = sData.split(this._newLine + this._newLine);
+ var rExp = new RegExp(this._newLine, "g");
+
+ //add a P for each item
+ if(container && container.tagName.toLowerCase() != WYMeditor.BODY) {
+ for(x = aP.length - 1; x >= 0; x--) {
+ sTmp = aP[x];
+ //simple newlines are replaced by a break
+ sTmp = sTmp.replace(rExp, "<br />");
+ jQuery(container).after("<p>" + sTmp + "</p>");
+ }
+ } else {
+ for(x = 0; x < aP.length; x++) {
+ sTmp = aP[x];
+ //simple newlines are replaced by a break
+ sTmp = sTmp.replace(rExp, "<br />");
+ jQuery(this._doc.body).append("<p>" + sTmp + "</p>");
+ }
+
+ }
+};
+
+WYMeditor.editor.prototype.insert = function(html) {
+ // Do we have a selection?
+ if (this._iframe.contentWindow.getSelection().focusNode != null) {
+ // Overwrite selection with provided html
+ this._exec( WYMeditor.INSERT_HTML, html);
+ } else {
+ // Fall back to the internal paste function if there's no selection
+ this.paste(html)
+ }
+};
+
+WYMeditor.editor.prototype.wrap = function(left, right) {
+ // Do we have a selection?
+ if (this._iframe.contentWindow.getSelection().focusNode != null) {
+ // Wrap selection with provided html
+ this._exec( WYMeditor.INSERT_HTML, left + this._iframe.contentWindow.getSelection().toString() + right);
+ }
+};
+
+WYMeditor.editor.prototype.unwrap = function() {
+ // Do we have a selection?
+ if (this._iframe.contentWindow.getSelection().focusNode != null) {
+ // Unwrap selection
+ this._exec( WYMeditor.INSERT_HTML, this._iframe.contentWindow.getSelection().toString() );
+ }
+};
+
+WYMeditor.editor.prototype.addCssRules = function(doc, aCss) {
+ var styles = doc.styleSheets[0];
+ if(styles) {
+ for(var i = 0; i < aCss.length; i++) {
+ var oCss = aCss[i];
+ if(oCss.name && oCss.css) this.addCssRule(styles, oCss);
+ }
+ }
+};
+
+/********** CONFIGURATION **********/
+
+WYMeditor.editor.prototype.computeBasePath = function() {
+ return jQuery(jQuery.grep(jQuery('script'), function(s){
+ return (s.src && s.src.match(/jquery\.wymeditor(\.pack|\.min|\.packed)?\.js(\?.*)?$/ ))
+ })).attr('src').replace(/jquery\.wymeditor(\.pack|\.min|\.packed)?\.js(\?.*)?$/, '');
+};
+
+WYMeditor.editor.prototype.computeWymPath = function() {
+ return jQuery(jQuery.grep(jQuery('script'), function(s){
+ return (s.src && s.src.match(/jquery\.wymeditor(\.pack|\.min|\.packed)?\.js(\?.*)?$/ ))
+ })).attr('src');
+};
+
+WYMeditor.editor.prototype.computeJqueryPath = function() {
+ return jQuery(jQuery.grep(jQuery('script'), function(s){
+ return (s.src && s.src.match(/jquery(-(.*)){0,1}(\.pack|\.min|\.packed)?\.js(\?.*)?$/ ))
+ })).attr('src');
+};
+
+WYMeditor.editor.prototype.computeCssPath = function() {
+ return jQuery(jQuery.grep(jQuery('link'), function(s){
+ return (s.href && s.href.match(/wymeditor\/skins\/(.*)screen\.css(\?.*)?$/ ))
+ })).attr('href');
+};
+
+WYMeditor.editor.prototype.configureEditorUsingRawCss = function() {
+
+ var CssParser = new WYMeditor.WymCssParser();
+ if(this._options.stylesheet){
+ CssParser.parse(jQuery.ajax({url: this._options.stylesheet,async:false}).responseText);
+ }else{
+ CssParser.parse(this._options.styles, false);
+ }
+
+ if(this._options.classesItems.length == 0) {
+ this._options.classesItems = CssParser.css_settings.classesItems;
+ }
+ if(this._options.editorStyles.length == 0) {
+ this._options.editorStyles = CssParser.css_settings.editorStyles;
+ }
+ if(this._options.dialogStyles.length == 0) {
+ this._options.dialogStyles = CssParser.css_settings.dialogStyles;
+ }
+};
+
+/********** EVENTS **********/
+
+WYMeditor.editor.prototype.listen = function() {
+
+ //don't use jQuery.find() on the iframe body
+ //because of MSIE + jQuery + expando issue (#JQ1143)
+ //jQuery(this._doc.body).find("*").bind("mouseup", this.mouseup);
+
+ jQuery(this._doc.body).bind("mousedown", this.mousedown);
+ var images = this._doc.body.getElementsByTagName("img");
+ for(var i=0; i < images.length; i++) {
+ jQuery(images[i]).bind("mousedown", this.mousedown);
+ }
+};
+
+WYMeditor.editor.prototype.mousedown = function(evt) {
+
+ var wym = WYMeditor.INSTANCES[this.ownerDocument.title];
+ wym._selected_image = (this.tagName.toLowerCase() == WYMeditor.IMG) ? this : null;
+ evt.stopPropagation();
+};
+
+/********** SKINS **********/
+
+/*
+ * Function: WYMeditor.loadCss
+ * Loads a stylesheet in the document.
+ *
+ * Parameters:
+ * href - The CSS path.
+ */
+WYMeditor.loadCss = function(href) {
+
+ var link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.href = href;
+
+ var head = jQuery('head').get(0);
+ head.appendChild(link);
+};
+
+/*
+ * Function: WYMeditor.editor.loadSkin
+ * Loads the skin CSS and initialization script (if needed).
+ */
+WYMeditor.editor.prototype.loadSkin = function() {
+
+ //does the user want to automatically load the CSS (default: yes)?
+ //we also test if it hasn't been already loaded by another instance
+ //see below for a better (second) test
+ if(this._options.loadSkin && !WYMeditor.SKINS[this._options.skin]) {
+
+ //check if it hasn't been already loaded
+ //so we don't load it more than once
+ //(we check the existing <link> elements)
+
+ var found = false;
+ var rExp = new RegExp(this._options.skin
+ + '\/' + WYMeditor.SKINS_DEFAULT_CSS + '$');
+
+ jQuery('link').each( function() {
+ if(this.href.match(rExp)) found = true;
+ });
+
+ //load it, using the skin path
+ if(!found) WYMeditor.loadCss( this._options.skinPath
+ + WYMeditor.SKINS_DEFAULT_CSS );
+ }
+
+ //put the classname (ex. wym_skin_default) on wym_box
+ jQuery(this._box).addClass( "wym_skin_" + this._options.skin );
+
+ //does the user want to use some JS to initialize the skin (default: yes)?
+ //also check if it hasn't already been loaded by another instance
+ if(this._options.initSkin && !WYMeditor.SKINS[this._options.skin]) {
+
+ eval(jQuery.ajax({url:this._options.skinPath
+ + WYMeditor.SKINS_DEFAULT_JS, async:false}).responseText);
+ }
+
+ //init the skin, if needed
+ if(WYMeditor.SKINS[this._options.skin]
+ && WYMeditor.SKINS[this._options.skin].init)
+ WYMeditor.SKINS[this._options.skin].init(this);
+
+};
+
+
+/********** DIALOGS **********/
+
+WYMeditor.INIT_DIALOG = function(index) {
+
+ var wym = window.opener.WYMeditor.INSTANCES[index];
+ var doc = window.document;
+ var selected = wym.selected();
+ var dialogType = jQuery(wym._options.dialogTypeSelector).val();
+ var sStamp = wym.uniqueStamp();
+
+ switch(dialogType) {
+
+ case WYMeditor.DIALOG_LINK:
+ //ensure that we select the link to populate the fields
+ if(selected && selected.tagName && selected.tagName.toLowerCase != WYMeditor.A)
+ selected = jQuery(selected).parentsOrSelf(WYMeditor.A);
+
+ //fix MSIE selection if link image has been clicked
+ if(!selected && wym._selected_image)
+ selected = jQuery(wym._selected_image).parentsOrSelf(WYMeditor.A);
+ break;
+
+ }
+
+ //pre-init functions
+ if(jQuery.isFunction(wym._options.preInitDialog))
+ wym._options.preInitDialog(wym,window);
+
+ //add css rules from options
+ var styles = doc.styleSheets[0];
+ var aCss = eval(wym._options.dialogStyles);
+
+ wym.addCssRules(doc, aCss);
+
+ //auto populate fields if selected container (e.g. A)
+ if(selected) {
+ jQuery(wym._options.hrefSelector).val(jQuery(selected).attr(WYMeditor.HREF));
+ jQuery(wym._options.srcSelector).val(jQuery(selected).attr(WYMeditor.SRC));
+ jQuery(wym._options.titleSelector).val(jQuery(selected).attr(WYMeditor.TITLE));
+ jQuery(wym._options.altSelector).val(jQuery(selected).attr(WYMeditor.ALT));
+ }
+
+ //auto populate image fields if selected image
+ if(wym._selected_image) {
+ jQuery(wym._options.dialogImageSelector + " " + wym._options.srcSelector)
+ .val(jQuery(wym._selected_image).attr(WYMeditor.SRC));
+ jQuery(wym._options.dialogImageSelector + " " + wym._options.titleSelector)
+ .val(jQuery(wym._selected_image).attr(WYMeditor.TITLE));
+ jQuery(wym._options.dialogImageSelector + " " + wym._options.altSelector)
+ .val(jQuery(wym._selected_image).attr(WYMeditor.ALT));
+ }
+
+ jQuery(wym._options.dialogLinkSelector + " "
+ + wym._options.submitSelector).click(function() {
+
+ var sUrl = jQuery(wym._options.hrefSelector).val();
+ if(sUrl.length > 0) {
+
+ wym._exec(WYMeditor.CREATE_LINK, sStamp);
+
+ jQuery("a[href=" + sStamp + "]", wym._doc.body)
+ .attr(WYMeditor.HREF, sUrl)
+ .attr(WYMeditor.TITLE, jQuery(wym._options.titleSelector).val());
+
+ }
+ window.close();
+ });
+
+ jQuery(wym._options.dialogImageSelector + " "
+ + wym._options.submitSelector).click(function() {
+
+ var sUrl = jQuery(wym._options.srcSelector).val();
+ if(sUrl.length > 0) {
+
+ wym._exec(WYMeditor.INSERT_IMAGE, sStamp);
+
+ jQuery("img[src$=" + sStamp + "]", wym._doc.body)
+ .attr(WYMeditor.SRC, sUrl)
+ .attr(WYMeditor.TITLE, jQuery(wym._options.titleSelector).val())
+ .attr(WYMeditor.ALT, jQuery(wym._options.altSelector).val());
+ }
+ window.close();
+ });
+
+ jQuery(wym._options.dialogTableSelector + " "
+ + wym._options.submitSelector).click(function() {
+
+ var iRows = jQuery(wym._options.rowsSelector).val();
+ var iCols = jQuery(wym._options.colsSelector).val();
+
+ if(iRows > 0 && iCols > 0) {
+
+ var table = wym._doc.createElement(WYMeditor.TABLE);
+ var newRow = null;
+ var newCol = null;
+
+ var sCaption = jQuery(wym._options.captionSelector).val();
+
+ //we create the caption
+ var newCaption = table.createCaption();
+ newCaption.innerHTML = sCaption;
+
+ //we create the rows and cells
+ for(x=0; x<iRows; x++) {
+ newRow = table.insertRow(x);
+ for(y=0; y<iCols; y++) {newRow.insertCell(y);}
+ }
+
+ //set the summary attr
+ jQuery(table).attr('summary',
+ jQuery(wym._options.summarySelector).val());
+
+ //append the table after the selected container
+ var node = jQuery(wym.findUp(wym.container(),
+ WYMeditor.MAIN_CONTAINERS)).get(0);
+ if(!node || !node.parentNode) jQuery(wym._doc.body).append(table);
+ else jQuery(node).after(table);
+ }
+ window.close();
+ });
+
+ jQuery(wym._options.dialogPasteSelector + " "
+ + wym._options.submitSelector).click(function() {
+
+ var sText = jQuery(wym._options.textSelector).val();
+ wym.paste(sText);
+ window.close();
+ });
+
+ jQuery(wym._options.dialogPreviewSelector + " "
+ + wym._options.previewSelector)
+ .html(wym.xhtml());
+
+ //cancel button
+ jQuery(wym._options.cancelSelector).mousedown(function() {
+ window.close();
+ });
+
+ //pre-init functions
+ if(jQuery.isFunction(wym._options.postInitDialog))
+ wym._options.postInitDialog(wym,window);
+
+};
+
+/********** XHTML LEXER/PARSER **********/
+
+/*
+* @name xml
+* @description Use these methods to generate XML and XHTML compliant tags and
+* escape tag attributes correctly
+* @author Bermi Ferrer - http://bermi.org
+* @author David Heinemeier Hansson http://loudthinking.com
+*/
+WYMeditor.XmlHelper = function()
+{
+ this._entitiesDiv = document.createElement('div');
+ return this;
+};
+
+
+/*
+* @name tag
+* @description
+* Returns an empty HTML tag of type *name* which by default is XHTML
+* compliant. Setting *open* to true will create an open tag compatible
+* with HTML 4.0 and below. Add HTML attributes by passing an attributes
+* array to *options*. For attributes with no value like (disabled and
+* readonly), give it a value of true in the *options* array.
+*
+* Examples:
+*
+* this.tag('br')
+* # => <br />
+* this.tag ('br', false, true)
+* # => <br>
+* this.tag ('input', jQuery({type:'text',disabled:true }) )
+* # => <input type="text" disabled="disabled" />
+*/
+WYMeditor.XmlHelper.prototype.tag = function(name, options, open)
+{
+ options = options || false;
+ open = open || false;
+ return '<'+name+(options ? this.tagOptions(options) : '')+(open ? '>' : ' />');
+};
+
+/*
+* @name contentTag
+* @description
+* Returns a XML block tag of type *name* surrounding the *content*. Add
+* XML attributes by passing an attributes array to *options*. For attributes
+* with no value like (disabled and readonly), give it a value of true in
+* the *options* array. You can use symbols or strings for the attribute names.
+*
+* this.contentTag ('p', 'Hello world!' )
+* # => <p>Hello world!</p>
+* this.contentTag('div', this.contentTag('p', "Hello world!"), jQuery({class : "strong"}))
+* # => <div class="strong"><p>Hello world!</p></div>
+* this.contentTag("select", options, jQuery({multiple : true}))
+* # => <select multiple="multiple">...options...</select>
+*/
+WYMeditor.XmlHelper.prototype.contentTag = function(name, content, options)
+{
+ options = options || false;
+ return '<'+name+(options ? this.tagOptions(options) : '')+'>'+content+'</'+name+'>';
+};
+
+/*
+* @name cdataSection
+* @description
+* Returns a CDATA section for the given +content+. CDATA sections
+* are used to escape blocks of text containing characters which would
+* otherwise be recognized as markup. CDATA sections begin with the string
+* <tt><![CDATA[</tt> and } with (and may not contain) the string
+* <tt>]]></tt>.
+*/
+WYMeditor.XmlHelper.prototype.cdataSection = function(content)
+{
+ return '<![CDATA['+content+']]>';
+};
+
+
+/*
+* @name escapeOnce
+* @description
+* Returns the escaped +xml+ without affecting existing escaped entities.
+*
+* this.escapeOnce( "1 > 2 & 3")
+* # => "1 > 2 & 3"
+*/
+WYMeditor.XmlHelper.prototype.escapeOnce = function(xml)
+{
+ return this._fixDoubleEscape(this.escapeEntities(xml));
+};
+
+/*
+* @name _fixDoubleEscape
+* @description
+* Fix double-escaped entities, such as &amp;, &#123;, etc.
+*/
+WYMeditor.XmlHelper.prototype._fixDoubleEscape = function(escaped)
+{
+ return escaped.replace(/&([a-z]+|(#\d+));/ig, "&$1;");
+};
+
+/*
+* @name tagOptions
+* @description
+* Takes an array like the one generated by Tag.parseAttributes
+* [["src", "http://www.editam.com/?a=b&c=d&f=g"], ["title", "Editam, <Simplified> CMS"]]
+* or an object like {src:"http://www.editam.com/?a=b&c=d&f=g", title:"Editam, <Simplified> CMS"}
+* and returns a string properly escaped like
+* ' src = "http://www.editam.com/?a=b&c=d&f=g" title = "Editam, <Simplified> CMS"'
+* which is valid for strict XHTML
+*/
+WYMeditor.XmlHelper.prototype.tagOptions = function(options)
+{
+ var xml = this;
+ xml._formated_options = '';
+
+ for (var key in options) {
+ var formated_options = '';
+ var value = options[key];
+ if(typeof value != 'function' && value.length > 0) {
+
+ if(parseInt(key) == key && typeof value == 'object'){
+ key = value.shift();
+ value = value.pop();
+ }
+ if(key != '' && value != ''){
+ xml._formated_options += ' '+key+'="'+xml.escapeOnce(value)+'"';
+ }
+ }
+ }
+ return xml._formated_options;
+};
+
+/*
+* @name escapeEntities
+* @description
+* Escapes XML/HTML entities <, >, & and ". If seccond parameter is set to false it
+* will not escape ". If set to true it will also escape '
+*/
+WYMeditor.XmlHelper.prototype.escapeEntities = function(string, escape_quotes)
+{
+ this._entitiesDiv.innerHTML = string;
+ this._entitiesDiv.textContent = string;
+ var result = this._entitiesDiv.innerHTML;
+ if(typeof escape_quotes == 'undefined'){
+ if(escape_quotes != false) result = result.replace('"', '"');
+ if(escape_quotes == true) result = result.replace('"', ''');
+ }
+ return result;
+};
+
+/*
+* Parses a string conatining tag attributes and values an returns an array formated like
+* [["src", "http://www.editam.com"], ["title", "Editam, Simplified CMS"]]
+*/
+WYMeditor.XmlHelper.prototype.parseAttributes = function(tag_attributes)
+{
+ // Use a compounded regex to match single quoted, double quoted and unquoted attribute pairs
+ var result = [];
+ var matches = tag_attributes.split(/((=\s*")(")("))|((=\s*\')(\')(\'))|((=\s*[^>\s]*))/g);
+ if(matches.toString() != tag_attributes){
+ for (var k in matches) {
+ var v = matches[k];
+ if(typeof v != 'function' && v.length != 0){
+ var re = new RegExp('(\\w+)\\s*'+v);
+ if(match = tag_attributes.match(re) ){
+ var value = v.replace(/^[\s=]+/, "");
+ var delimiter = value.charAt(0);
+ delimiter = delimiter == '"' ? '"' : (delimiter=="'"?"'":'');
+ if(delimiter != ''){
+ value = delimiter == '"' ? value.replace(/^"|"+$/g, '') : value.replace(/^'|'+$/g, '');
+ }
+ tag_attributes = tag_attributes.replace(match[0],'');
+ result.push([match[1] , value]);
+ }
+ }
+ }
+ }
+ return result;
+};
+
+/**
+* XhtmlValidator for validating tag attributes
+*
+* @author Bermi Ferrer - http://bermi.org
+*/
+WYMeditor.XhtmlValidator = {
+ "_attributes":
+ {
+ "core":
+ {
+ "except":[
+ "base",
+ "head",
+ "html",
+ "meta",
+ "param",
+ "script",
+ "style",
+ "title"
+ ],
+ "attributes":[
+ "class",
+ "id",
+ "style",
+ "title",
+ "accesskey",
+ "tabindex"
+ ]
+ },
+ "language":
+ {
+ "except":[
+ "base",
+ "br",
+ "hr",
+ "iframe",
+ "param",
+ "script"
+ ],
+ "attributes":
+ {
+ "dir":[
+ "ltr",
+ "rtl"
+ ],
+ "0":"lang",
+ "1":"xml:lang"
+ }
+ },
+ "keyboard":
+ {
+ "attributes":
+ {
+ "accesskey":/^(\w){1}$/,
+ "tabindex":/^(\d)+$/
+ }
+ }
+ },
+ "_events":
+ {
+ "window":
+ {
+ "only":[
+ "body"
+ ],
+ "attributes":[
+ "onload",
+ "onunload"
+ ]
+ },
+ "form":
+ {
+ "only":[
+ "form",
+ "input",
+ "textarea",
+ "select",
+ "a",
+ "label",
+ "button"
+ ],
+ "attributes":[
+ "onchange",
+ "onsubmit",
+ "onreset",
+ "onselect",
+ "onblur",
+ "onfocus"
+ ]
+ },
+ "keyboard":
+ {
+ "except":[
+ "base",
+ "bdo",
+ "br",
+ "frame",
+ "frameset",
+ "head",
+ "html",
+ "iframe",
+ "meta",
+ "param",
+ "script",
+ "style",
+ "title"
+ ],
+ "attributes":[
+ "onkeydown",
+ "onkeypress",
+ "onkeyup"
+ ]
+ },
+ "mouse":
+ {
+ "except":[
+ "base",
+ "bdo",
+ "br",
+ "head",
+ "html",
+ "meta",
+ "param",
+ "script",
+ "style",
+ "title"
+ ],
+ "attributes":[
+ "onclick",
+ "ondblclick",
+ "onmousedown",
+ "onmousemove",
+ "onmouseover",
+ "onmouseout",
+ "onmouseup"
+ ]
+ }
+ },
+ "_tags":
+ {
+ "a":
+ {
+ "attributes":
+ {
+ "0":"charset",
+ "1":"coords",
+ "2":"href",
+ "3":"hreflang",
+ "4":"name",
+ "rel":/^(alternate|designates|stylesheet|start|next|prev|contents|index|glossary|copyright|chapter|section|subsection|appendix|help|bookmark| |shortcut|icon)+$/,
+ "rev":/^(alternate|designates|stylesheet|start|next|prev|contents|index|glossary|copyright|chapter|section|subsection|appendix|help|bookmark| |shortcut|icon)+$/,
+ "shape":/^(rect|rectangle|circ|circle|poly|polygon)$/,
+ "5":"type"
+ }
+ },
+ "0":"abbr",
+ "1":"acronym",
+ "2":"address",
+ "area":
+ {
+ "attributes":
+ {
+ "0":"alt",
+ "1":"coords",
+ "2":"href",
+ "nohref":/^(true|false)$/,
+ "shape":/^(rect|rectangle|circ|circle|poly|polygon)$/
+ },
+ "required":[
+ "alt"
+ ]
+ },
+ "3":"b",
+ "base":
+ {
+ "attributes":[
+ "href"
+ ],
+ "required":[
+ "href"
+ ]
+ },
+ "bdo":
+ {
+ "attributes":
+ {
+ "dir":/^(ltr|rtl)$/
+ },
+ "required":[
+ "dir"
+ ]
+ },
+ "4":"big",
+ "blockquote":
+ {
+ "attributes":[
+ "cite"
+ ]
+ },
+ "5":"body",
+ "6":"br",
+ "button":
+ {
+ "attributes":
+ {
+ "disabled":/^(disabled)$/,
+ "type":/^(button|reset|submit)$/,
+ "0":"value"
+ },
+ "inside":"form"
+ },
+ "7":"caption",
+ "8":"cite",
+ "9":"code",
+ "col":
+ {
+ "attributes":
+ {
+ "align":/^(right|left|center|justify)$/,
+ "0":"char",
+ "1":"charoff",
+ "span":/^(\d)+$/,
+ "valign":/^(top|middle|bottom|baseline)$/,
+ "2":"width"
+ },
+ "inside":"colgroup"
+ },
+ "colgroup":
+ {
+ "attributes":
+ {
+ "align":/^(right|left|center|justify)$/,
+ "0":"char",
+ "1":"charoff",
+ "span":/^(\d)+$/,
+ "valign":/^(top|middle|bottom|baseline)$/,
+ "2":"width"
+ }
+ },
+ "10":"dd",
+ "del":
+ {
+ "attributes":
+ {
+ "0":"cite",
+ "datetime":/^([0-9]){8}/
+ }
+ },
+ "11":"div",
+ "12":"dfn",
+ "13":"dl",
+ "14":"dt",
+ "15":"em",
+ "fieldset":
+ {
+ "inside":"form"
+ },
+ "form":
+ {
+ "attributes":
+ {
+ "0":"action",
+ "1":"accept",
+ "2":"accept-charset",
+ "3":"enctype",
+ "method":/^(get|post)$/
+ },
+ "required":[
+ "action"
+ ]
+ },
+ "head":
+ {
+ "attributes":[
+ "profile"
+ ]
+ },
+ "16":"h1",
+ "17":"h2",
+ "18":"h3",
+ "19":"h4",
+ "20":"h5",
+ "21":"h6",
+ "22":"hr",
+ "html":
+ {
+ "attributes":[
+ "xmlns"
+ ]
+ },
+ "23":"i",
+ "img":
+ {
+ "attributes":[
+ "alt",
+ "src",
+ "height",
+ "ismap",
+ "longdesc",
+ "usemap",
+ "width"
+ ],
+ "required":[
+ "alt",
+ "src"
+ ]
+ },
+ "input":
+ {
+ "attributes":
+ {
+ "0":"accept",
+ "1":"alt",
+ "checked":/^(checked)$/,
+ "disabled":/^(disabled)$/,
+ "maxlength":/^(\d)+$/,
+ "2":"name",
+ "readonly":/^(readonly)$/,
+ "size":/^(\d)+$/,
+ "3":"src",
+ "type":/^(button|checkbox|file|hidden|image|password|radio|reset|submit|text)$/,
+ "4":"value"
+ },
+ "inside":"form"
+ },
+ "ins":
+ {
+ "attributes":
+ {
+ "0":"cite",
+ "datetime":/^([0-9]){8}/
+ }
+ },
+ "24":"kbd",
+ "label":
+ {
+ "attributes":[
+ "for"
+ ],
+ "inside":"form"
+ },
+ "25":"legend",
+ "26":"li",
+ "link":
+ {
+ "attributes":
+ {
+ "0":"charset",
+ "1":"href",
+ "2":"hreflang",
+ "media":/^(all|braille|print|projection|screen|speech|,|;| )+$/i,
+ //next comment line required by Opera!
+ /*"rel":/^(alternate|appendix|bookmark|chapter|contents|copyright|glossary|help|home|index|next|prev|section|start|stylesheet|subsection| |shortcut|icon)+$/i,*/
+ "rel":/^(alternate|appendix|bookmark|chapter|contents|copyright|glossary|help|home|index|next|prev|section|start|stylesheet|subsection| |shortcut|icon)+$/i,
+ "rev":/^(alternate|appendix|bookmark|chapter|contents|copyright|glossary|help|home|index|next|prev|section|start|stylesheet|subsection| |shortcut|icon)+$/i,
+ "3":"type"
+ },
+ "inside":"head"
+ },
+ "map":
+ {
+ "attributes":[
+ "id",
+ "name"
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/b8205e8e077f
changeset: 2614:b8205e8e077f
user: James Taylor <james(a)jamestaylor.org>
date: Sun Aug 23 15:16:43 2009 -0400
description:
Use small messages by default
5 file(s) affected in this change:
static/june_2007_style/base.css.tmpl
static/june_2007_style/blue/base.css
static/welcome.html
templates/message.mako
templates/tool_executed.mako
diffs (406 lines):
diff -r 5f60d79f483f -r b8205e8e077f static/june_2007_style/base.css.tmpl
--- a/static/june_2007_style/base.css.tmpl Sun Aug 23 14:01:08 2009 -0400
+++ b/static/june_2007_style/base.css.tmpl Sun Aug 23 15:16:43 2009 -0400
@@ -187,8 +187,7 @@
## Messages
-.errormessage, .warningmessage, .donemessage, .infomessage, .welcomeBlue, .welcomeRed , .screencastBox, .yellowbox, .redbox, .bluebox, .greenbox
-{
+.errormessagelarge, .warningmessagelarge, .donemessagelarge, .infomessagelarge {
padding: 10px;
padding-left: 52px;
min-height: 32px;
@@ -199,127 +198,35 @@
background-position: 10px 10px;
}
-.warningmessage
-{
+.warningmessagelarge {
background-image: url(warn_message_icon.png);
border-color: $warn_message_border;
background-color: $warn_message_bg;
}
-.donemessage
-{
+.donemessagelarge {
background-image: url(done_message_icon.png);
border-color: $done_message_border;
background-color: $done_message_bg;
}
-.infomessage
-{
+.infomessagelarge {
background-image: url(info_message_icon.png);
border-color: $info_message_border;
background-color: $info_message_bg;
}
-.welcomeBlue
-{
- padding-left: 10px;
- border-color: $info_message_border;
- background-color: $info_message_bg;
- background-image: none;
-}
-
-.welcomeRed
-{
- padding-left: 10px;
- border-color: $error_message_border;
- background-color: $error_message_bg;
- background-image: none;
-}
-
-.screencastBox
-{
+.screencastBox {
padding-left: 10px;
border-color: #AAAA66;
background-color: #FFFFCC;
background-image: none;
}
-.redbox
-{
- border: none;
- padding: 10px;
- border-color: #000000;
- background-color: #FF6666;
- background-image: none;
- border-right-width: 1px;
- border-right-style: dotted;
- border-bottom-width: 1px;
- border-bottom-style: dotted;
- margin-top: 5px;
- min-height: 32px;
-
-}
-
-.yellowbox
-{
- border: none;
- padding: 10px;
- border-color: #000000;
- background-color: #FFCC00;
- background-image: none;
- border-right-width: 1px;
- border-right-style: dotted;
- border-bottom-width: 1px;
- border-bottom-style: dotted;
- margin-top: 5px;
- min-height: 32px;
-}
-
-.bluebox
-{
- border: none;
- padding: 10px;
- border-color: #000000;
- background-color: #6666FF;
- background-image: none;
- border-right-width: 1px;
- border-right-style: dotted;
- border-bottom-width: 1px;
- border-bottom-style: dotted;
- margin-top: 5px;
- color: #FFFFFF;
- min-height: 32px;
-}
-
-.greenbox
-{
- border: none;
- padding: 10px;
- border-color: #000000;
- background-color: #00CC00;
- background-image: none;
- border-right-width: 1px;
- border-right-style: dotted;
- border-bottom-width: 1px;
- border-bottom-style: dotted;
- margin-top: 5px;
- min-height: 32px;
-}
-
-.redbox li, .yellowbox li, .bluebox li, .greenbox li {
- list-style: disc;
- text-transform: none;
- list-style-position: inside;
- list-style-image: none;
- margin: 3px;
-}
-
-
-.errormessagesmall, .warningmessagesmall, .donemessagesmall, .infomessagesmall
-{
+.errormessage, .warningmessage, .donemessage, .infomessage, .errormessagesmall, .warningmessagesmall, .donemessagesmall, .infomessagesmall {
padding: 5px;
padding-left: 25px;
- min-height: 25px;
+ min-height: 15px;
border: 1px solid $error_message_border;
background-color: $error_message_bg;
background-image: url(error_small.png);
@@ -327,83 +234,70 @@
background-position: 5px 5px;
}
-.warningmessagesmall
-{
+.warningmessage, .warningmessagesmall {
background-image: url(warn_small.png);
border-color: $warn_message_border;
background-color: $warn_message_bg;
}
-.donemessagesmall
-{
+.donemessage, .donemessagesmall {
background-image: url(ok_small.png);
border-color: $done_message_border;
background-color: $done_message_bg;
}
-.infomessagesmall
-{
+.infomessage, .infomessagesmall {
background-image: url(info_small.png);
border-color: $info_message_border;
background-color: $info_message_bg;
}
-.errormark, .warningmark, .donemark, .infomark, .ok_bgr, .err_bgr
-{
+.errormark, .warningmark, .donemark, .infomark, .ok_bgr, .err_bgr {
padding-left: 20px;
min-height: 15px;
background: url(error_small.png) no-repeat;
}
-.warningmark
-{
+.warningmark {
background-image: url(warn_small.png);
}
-.donemark
-{
+.donemark {
background-image: url(ok_small.png);
}
-.infomark, .ok_bgr
-{
+.infomark, .ok_bgr {
background-image: url(info_small.png);
}
-table.colored
-{
- border-top: solid $table_border 1px;
- border-bottom: solid $table_border 1px;
+table.colored {
+ border-top: solid $table_border 1px;
+ border-bottom: solid $table_border 1px;
}
-table.colored td, table.colored th
-{
+table.colored td, table.colored th {
text-align: left;
padding: 5px;
}
-table.colored tr.header
-{
- background: $table_header_bg;
- background-image: url(form_title_bg.png);
- background-repeat: repeat-x;
- background-position: top;
- border-bottom: solid $table_border 1px;
- font-weight: bold;
+table.colored tr.header {
+ background: $table_header_bg;
+ background-image: url(form_title_bg.png);
+ background-repeat: repeat-x;
+ background-position: top;
+ border-bottom: solid $table_border 1px;
+ font-weight: bold;
}
-table.colored tr
-{
- background: $table_row_bg;
+table.colored tr {
+ background: $table_row_bg;
}
-table.colored tr.odd_row
-{
- background: $odd_row_bg;
+table.colored tr.odd_row {
+ background: $odd_row_bg;
}
-div.debug
-{
+div.debug {
margin: 10px;
padding: 5px;
background: #FFFF99;
@@ -411,8 +305,7 @@
color: black;
}
-div.odd_row
-{
+div.odd_row {
background: $odd_row_bg;
}
@@ -422,51 +315,44 @@
## Tool panel stuff
-td.panel-body
-{
+td.panel-body {
background: white;
color: $base_text;
background: $menu_bg_over url(menu_bg.png) top repeat-x;
}
-div.toolSectionPad
-{
+div.toolSectionPad {
margin: 0;
padding: 0;
height: 5px;
font-size: 0px;
}
-div.toolSectionDetailsInner
-{
- margin-left: 5px;
- margin-right: 5px;
+div.toolSectionDetailsInner {
+ margin-left: 5px;
+ margin-right: 5px;
}
-div.toolSectionTitle
-{
- padding-bottom: 0px;
- font-weight: bold;
+div.toolSectionTitle {
+ padding-bottom: 0px;
+ font-weight: bold;
}
-div.toolTitle
-{
- padding-top: 5px;
- padding-bottom: 5px;
- margin-left: 16px;
- margin-right: 10px;
- display: list-item;
- list-style: square outside;
+div.toolTitle {
+ padding-top: 5px;
+ padding-bottom: 5px;
+ margin-left: 16px;
+ margin-right: 10px;
+ display: list-item;
+ list-style: square outside;
}
-span.toolParameterExpandableCollapsable
-{
- font-weight: bold;
- cursor: pointer;
+span.toolParameterExpandableCollapsable {
+ font-weight: bold;
+ cursor: pointer;
}
-ul.toolParameterExpandableCollapsable
-{
- list-style: none;
+ul.toolParameterExpandableCollapsable {
+ list-style: none;
}
ul.manage-table-actions {
diff -r 5f60d79f483f -r b8205e8e077f static/june_2007_style/blue/base.css
--- a/static/june_2007_style/blue/base.css Sun Aug 23 14:01:08 2009 -0400
+++ b/static/june_2007_style/blue/base.css Sun Aug 23 15:16:43 2009 -0400
@@ -35,22 +35,15 @@
div.form-row-error-message{width:300px;float:left;color:red;font-weight:bold;padding:3px 0 0 1em;}
select,input,textarea{font:inherit;font-size:115%;}
select,textarea,input[type="text"],input[type="file"],input[type="password"]{-webkit-box-sizing:border-box;max-width:300px;}
-.errormessage,.warningmessage,.donemessage,.infomessage,.welcomeBlue,.welcomeRed,.screencastBox,.yellowbox,.redbox,.bluebox,.greenbox{padding:10px;padding-left:52px;min-height:32px;border:1px solid #AA6666;background-color:#FFCCCC;background-image:url(error_message_icon.png);background-repeat:no-repeat;background-position:10px 10px;}
-.warningmessage{background-image:url(warn_message_icon.png);border-color:#AAAA66;background-color:#FFFFCC;}
-.donemessage{background-image:url(done_message_icon.png);border-color:#66AA66;background-color:#CCFFCC;}
-.infomessage{background-image:url(info_message_icon.png);border-color:#6666AA;background-color:#CCCCFF;}
-.welcomeBlue{padding-left:10px;border-color:#6666AA;background-color:#CCCCFF;background-image:none;}
-.welcomeRed{padding-left:10px;border-color:#AA6666;background-color:#FFCCCC;background-image:none;}
+.errormessagelarge,.warningmessagelarge,.donemessagelarge,.infomessagelarge{padding:10px;padding-left:52px;min-height:32px;border:1px solid #AA6666;background-color:#FFCCCC;background-image:url(error_message_icon.png);background-repeat:no-repeat;background-position:10px 10px;}
+.warningmessagelarge{background-image:url(warn_message_icon.png);border-color:#AAAA66;background-color:#FFFFCC;}
+.donemessagelarge{background-image:url(done_message_icon.png);border-color:#66AA66;background-color:#CCFFCC;}
+.infomessagelarge{background-image:url(info_message_icon.png);border-color:#6666AA;background-color:#CCCCFF;}
.screencastBox{padding-left:10px;border-color:#AAAA66;background-color:#FFFFCC;background-image:none;}
-.redbox{border:none;padding:10px;border-color:#000000;background-color:#FF6666;background-image:none;border-right-width:1px;border-right-style:dotted;border-bottom-width:1px;border-bottom-style:dotted;margin-top:5px;min-height:32px;}
-.yellowbox{border:none;padding:10px;border-color:#000000;background-color:#FFCC00;background-image:none;border-right-width:1px;border-right-style:dotted;border-bottom-width:1px;border-bottom-style:dotted;margin-top:5px;min-height:32px;}
-.bluebox{border:none;padding:10px;border-color:#000000;background-color:#6666FF;background-image:none;border-right-width:1px;border-right-style:dotted;border-bottom-width:1px;border-bottom-style:dotted;margin-top:5px;color:#FFFFFF;min-height:32px;}
-.greenbox{border:none;padding:10px;border-color:#000000;background-color:#00CC00;background-image:none;border-right-width:1px;border-right-style:dotted;border-bottom-width:1px;border-bottom-style:dotted;margin-top:5px;min-height:32px;}
-.redbox li,.yellowbox li,.bluebox li,.greenbox li{list-style:disc;text-transform:none;list-style-position:inside;list-style-image:none;margin:3px;}
-.errormessagesmall,.warningmessagesmall,.donemessagesmall,.infomessagesmall{padding:5px;padding-left:25px;min-height:25px;border:1px solid #AA6666;background-color:#FFCCCC;background-image:url(error_small.png);background-repeat:no-repeat;background-position:5px 5px;}
-.warningmessagesmall{background-image:url(warn_small.png);border-color:#AAAA66;background-color:#FFFFCC;}
-.donemessagesmall{background-image:url(ok_small.png);border-color:#66AA66;background-color:#CCFFCC;}
-.infomessagesmall{background-image:url(info_small.png);border-color:#6666AA;background-color:#CCCCFF;}
+.errormessage,.warningmessage,.donemessage,.infomessage,.errormessagesmall,.warningmessagesmall,.donemessagesmall,.infomessagesmall{padding:5px;padding-left:25px;min-height:15px;border:1px solid #AA6666;background-color:#FFCCCC;background-image:url(error_small.png);background-repeat:no-repeat;background-position:5px 5px;}
+.warningmessage,.warningmessagesmall{background-image:url(warn_small.png);border-color:#AAAA66;background-color:#FFFFCC;}
+.donemessage,.donemessagesmall{background-image:url(ok_small.png);border-color:#66AA66;background-color:#CCFFCC;}
+.infomessage,.infomessagesmall{background-image:url(info_small.png);border-color:#6666AA;background-color:#CCCCFF;}
.errormark,.warningmark,.donemark,.infomark,.ok_bgr,.err_bgr{padding-left:20px;min-height:15px;background:url(error_small.png) no-repeat;}
.warningmark{background-image:url(warn_small.png);}
.donemark{background-image:url(ok_small.png);}
diff -r 5f60d79f483f -r b8205e8e077f static/welcome.html
--- a/static/welcome.html Sun Aug 23 14:01:08 2009 -0400
+++ b/static/welcome.html Sun Aug 23 15:16:43 2009 -0400
@@ -37,7 +37,7 @@
<body>
<div class="document">
-<div class="infomessage">
+<div class="infomessagelarge">
<strong>We are hiring!</strong>
<hr>
Thanks to your support and an unprecedented level of usage, we are looking for an experienced software developer to join our team. For more information about this position, please, click <a target="_blank" href="https://www.bx.psu.edu/cgi-bin/trac.cgi/galaxy/wiki/PythonDeveloper">here</a>.
diff -r 5f60d79f483f -r b8205e8e077f templates/message.mako
--- a/templates/message.mako Sun Aug 23 14:01:08 2009 -0400
+++ b/templates/message.mako Sun Aug 23 15:16:43 2009 -0400
@@ -45,7 +45,7 @@
</script>
</%def>
-<div class="${message_type}message">${_(message)}</div>
+<div class="${message_type}messagelarge">${_(message)}</div>
## Render a message
<%def name="render_msg( msg, messagetype='done' )">
diff -r 5f60d79f483f -r b8205e8e077f templates/tool_executed.mako
--- a/templates/tool_executed.mako Sun Aug 23 14:01:08 2009 -0400
+++ b/templates/tool_executed.mako Sun Aug 23 15:16:43 2009 -0400
@@ -37,7 +37,7 @@
<body onLoad="main()">
-<div class="donemessage">
+<div class="donemessagelarge">
<p>The following job has been succesfully added to the queue:</p>
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/278df6aa7139
changeset: 2612:278df6aa7139
user: James Taylor <james(a)jamestaylor.org>
date: Fri Aug 21 14:28:46 2009 -0400
description:
Repack jstore without comments
2 file(s) affected in this change:
static/scripts/jquery.jstore-all.js
static/scripts/packed/jquery.jstore-all.js
diffs (118 lines):
diff -r 52a145b22b69 -r 278df6aa7139 static/scripts/jquery.jstore-all.js
--- a/static/scripts/jquery.jstore-all.js Sun Aug 23 12:31:20 2009 -0400
+++ b/static/scripts/jquery.jstore-all.js Fri Aug 21 14:28:46 2009 -0400
@@ -1,4 +1,4 @@
-/*!
+/*
* jStore - Persistent Client-Side Storage
*
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
@@ -71,7 +71,7 @@
return Class;
};
})();
-/*!
+/*
* jStore Delegate Framework
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
@@ -357,7 +357,7 @@
});
})(jQuery);
-/*!
+/*
* jStore DOM Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
@@ -426,7 +426,7 @@
$.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)
@@ -551,7 +551,7 @@
function flash_ready(){
$.jStore.delegate.trigger('flash-ready');
}
-/*!
+/*
* jStore Google Gears Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
@@ -621,7 +621,7 @@
$.jStore.EngineOrder[ 3 ] = 'gears';
})(jQuery);
-/*!
+/*
* jStore HTML5 Specification Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
@@ -693,7 +693,7 @@
$.jStore.EngineOrder[ 0 ] = 'html5';
})(jQuery);
-/*!*
+/*
* jStore IE Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
@@ -745,4 +745,4 @@
// Store the ordering preference
$.jStore.EngineOrder[ 4 ] = 'ie';
-})(jQuery);
\ No newline at end of file
+})(jQuery);
diff -r 52a145b22b69 -r 278df6aa7139 static/scripts/packed/jquery.jstore-all.js
--- a/static/scripts/packed/jquery.jstore-all.js Sun Aug 23 12:31:20 2009 -0400
+++ b/static/scripts/packed/jquery.jstore-all.js Fri Aug 21 14:28:46 2009 -0400
@@ -1,41 +1,1 @@
-/*
- * 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
- */
-(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}})();
-/*
- * jStore Delegate Framework
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(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,{EngineOrder:[],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.Instanc
es.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");return 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=f
unction(){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:function(){var b=this,d=this.includes.length,c=0;a.each(this.includes,function(){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 th
is},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);
-/*
- * jStore DOM Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(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);
-/*
- * 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(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.flash+'"></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_g
et_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.ShockwaveFlash.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){}}r
eturn"0,0,0"}})(jQuery);function flash_ready(){$.jStore.delegate.trigger("flash-ready")}
-/*
- * jStore Google Gears Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(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 TEXT 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.ex
ecute("COMMIT");return this._super(d)}});b.jStore.Engines.gears=jStoreGears;b.jStore.EngineOrder[3]="gears"})(jQuery);
-/*
- * jStore HTML5 Specification Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(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])});ret
urn this._super(c)}});b.jStore.Engines.html5=jStoreHtml5;b.jStore.EngineOrder[0]="html5"})(jQuery);
-/**
- * jStore IE Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(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.project+'"></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
+(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,{Engin
eOrder:[],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.Availabilit
y[this]()){a.jStore.use(this,a.jStore.defaults.project,"default");return 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.aut
oload=false;this.isReady=false;this.hasIncluded=false},include:function(){var b=this,d=this.includes.length,c=0;a.each(this.includes,function(){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*1
024},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('<if
rame style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="'+b.jStore.defaults.flash+'"></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.ShockwaveFlash.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/ap
is/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 TEXT 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.Avail
ability.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.project+'"></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
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/168a6ef6a99a
changeset: 2615:168a6ef6a99a
user: James Taylor <james(a)jamestaylor.org>
date: Sun Aug 23 17:13:04 2009 -0400
description:
IE fixes for menu buttons
3 file(s) affected in this change:
static/scripts/galaxy.base.js
templates/history/grid.mako
templates/workflow/list.mako
diffs (36 lines):
diff -r b8205e8e077f -r 168a6ef6a99a static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Sun Aug 23 15:16:43 2009 -0400
+++ b/static/scripts/galaxy.base.js Sun Aug 23 17:13:04 2009 -0400
@@ -59,7 +59,7 @@
// container_element = container_element.parent();
// }
// ontainer_element).css( "position", "relative" );
- var menu_element = $( "<ul id='" + button_element.attr('id') + "-menu'></div>" );
+ var menu_element = $( "<ul id='" + button_element.attr('id') + "-menu'></ul>" );
$.each( options, function( k, v ) {
if ( v ) {
$( "<li/>" ).html( k ).click( v ).appendTo( menu_element );
diff -r b8205e8e077f -r 168a6ef6a99a templates/history/grid.mako
--- a/templates/history/grid.mako Sun Aug 23 15:16:43 2009 -0400
+++ b/templates/history/grid.mako Sun Aug 23 17:13:04 2009 -0400
@@ -158,7 +158,7 @@
extra = ""
%>
%if href:
- <td><div class="menubutton split"><a class="label" href="${href}">${v}${extra}</a></td>
+ <td><div class="menubutton split" style="float: left;"><a class="label" href="${href}">${v}${extra}</a> </td>
%else:
<td >${v}${extra}</td>
%endif
diff -r b8205e8e077f -r 168a6ef6a99a templates/workflow/list.mako
--- a/templates/workflow/list.mako Sun Aug 23 15:16:43 2009 -0400
+++ b/templates/workflow/list.mako Sun Aug 23 17:13:04 2009 -0400
@@ -37,7 +37,7 @@
%for i, workflow in enumerate( workflows ):
<tr>
<td>
- <div class="menubutton">
+ <div class="menubutton" style="float: left;">
<a id="wf-${i}-popup" class="arrow" style="display: none;"><span>▼</span></a>
${workflow.name}
</div>
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/5f60d79f483f
changeset: 2613:5f60d79f483f
user: James Taylor <james(a)jamestaylor.org>
date: Sun Aug 23 14:01:08 2009 -0400
description:
Remove logging from galaxy.base
2 file(s) affected in this change:
static/scripts/galaxy.base.js
static/scripts/packed/galaxy.base.js
diffs (26 lines):
diff -r 278df6aa7139 -r 5f60d79f483f static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Fri Aug 21 14:28:46 2009 -0400
+++ b/static/scripts/galaxy.base.js Sun Aug 23 14:01:08 2009 -0400
@@ -77,14 +77,12 @@
};
function attach_popupmenu( button_element, wrapper ) {
- console.log( button_element, wrapper );
var clean = function() {
wrapper.unbind().hide();
$("#popup-helper").unbind( "click.popupmenu" ).hide();
// $(document).unbind( "click.popupmenu" );
};
var click = function( e ) {
- console.log( e );
var o = $(button_element).offset();
$("#popup-helper").bind( "click.popupmenu", clean ).show();
// $(document).bind( "click.popupmenu", clean );
diff -r 278df6aa7139 -r 5f60d79f483f static/scripts/packed/galaxy.base.js
--- a/static/scripts/packed/galaxy.base.js Fri Aug 21 14:28:46 2009 -0400
+++ b/static/scripts/packed/galaxy.base.js Sun Aug 23 14:01:08 2009 -0400
@@ -1,1 +1,1 @@
-$.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")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});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}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.show()})});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 make_popupmenu(d,c){ens
ure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></div>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){console.log(b,d);var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){console.log(g);var h=$(b).offset();$("#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)};
\ No newline at end of file
+$.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")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});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}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.show()})});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 make_popupmenu(d,c){ens
ure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></div>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){var h=$(b).offset();$("#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)};
\ No newline at end of file
1
0