[galaxy-dev] [hg] galaxy 3626: - Update jQuery.jStore, JSON2
Greg Von Kuster
greg at bx.psu.edu
Thu Apr 15 20:18:47 EDT 2010
details: http://www.bx.psu.edu/hg/galaxy/rev/5536d57237a3
changeset: 3626:5536d57237a3
user: Kanwei Li <kanwei at gmail.com>
date: Fri Apr 09 18:09:54 2010 -0400
description:
- Update jQuery.jStore, JSON2
- Fix issue with all local prefs being deleted on "collapse all"
- Refactored history display code into galaxy.base
diffstat:
static/jStore.Flash.html | 19 -
static/jStore.swf | 0
static/scripts/class.js | 80 +
static/scripts/galaxy.base.js | 87 +
static/scripts/jquery.jstore-all.js | 748 -----------
static/scripts/jquery.jstore.js | 1810 ++++++++++++++++++++++++++++
static/scripts/json2.js | 26 +-
static/scripts/packed/class.js | 7 +
static/scripts/packed/galaxy.base.js | 2 +-
static/scripts/packed/jquery.jstore-all.js | 1 -
static/scripts/packed/jquery.jstore.js | 17 +
static/scripts/packed/json2.js | 2 +-
templates/display_base.mako | 29 +-
templates/history/display.mako | 264 +---
templates/history/view.mako | 259 +---
templates/page/display.mako | 272 +---
templates/root/history.mako | 222 +--
templates/workflow/editor.mako | 42 +-
18 files changed, 2216 insertions(+), 1671 deletions(-)
diffs (truncated from 4199 to 3000 lines):
diff -r a9402fc7ce1b -r 5536d57237a3 static/jStore.Flash.html
--- a/static/jStore.Flash.html Fri Apr 09 13:02:15 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
- <head>
- <title>Flash External Object</title>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <script type="text/javascript">
- /**
- * This function captures the flash_ready event. We need to relay this
- * back to the parent so it knows flash is ready.
- */
- function flash_ready(){
- parent.flash_ready();
- }
- </script>
- </head>
- <body>
- <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="1" height="1" id="jStoreFlash"><param name="allowScriptAccess" value="always" /><param name="movie" value="jStore.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffcc00" /><embed src="jStore.swf" quality="high" bgcolor="#ffcc00" width="1" height="1" name="jStoreFlash" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /></object>
- </body>
-</html>
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/jStore.swf
Binary file static/jStore.swf has changed
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/class.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/class.js Fri Apr 09 18:09:54 2010 -0400
@@ -0,0 +1,80 @@
+/*!
+ * Class definition
+ *
+ * Copyright (c) 2008 John Resig (http://ejohn.org/blog/simple-javascript-inheritance/)
+ * Inspired by base2 and Prototype
+ */
+
+"use strict";
+
+(function () {
+
+ var initializing = false,
+
+ fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
+
+ // The base Class implementation (does nothing)
+ this.Class = function(){};
+
+ // Create a new Class that inherits from this class
+ Class.extend = function (prop)
+ {
+ var _super = this.prototype;
+
+ // Instantiate a base class (but only create the instance, don't run the init constructor)
+ initializing = true;
+
+ var prototype = new this();
+
+ initializing = false;
+
+ // Copy the properties over onto the new prototype
+ for (var name in prop)
+ {
+
+ // Check if we're overwriting an existing function
+ prototype[name] = (typeof prop[name] === "function" && typeof _super[name] === "function" && fnTest.test(prop[name]) ?
+
+ (function(name, fn)
+ {
+ return function()
+ {
+ var tmp = this._super;
+
+ // Add a new ._super() method that is the same method
+ // but on the super-class
+ this._super = _super[name];
+
+ // The method only need to be bound temporarily, so we
+ // remove it when we're done executing
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+
+ return ret;
+ };
+ }(name, prop[name])) : prop[name]);
+ }
+
+ // The dummy class constructor
+ function Class()
+ {
+ // All construction is actually done in the init method
+ if (!initializing && this.init)
+ {
+ this.init.apply(this, arguments);
+ }
+ }
+
+ // Populate our constructed prototype object
+ Class.prototype = prototype;
+
+ // Enforce the constructor to be what we expect
+ Class.constructor = Class;
+
+ // And make this class extendable
+ Class.extend = arguments.callee;
+
+ return Class;
+ };
+
+}());
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Fri Apr 09 13:02:15 2010 -0400
+++ b/static/scripts/galaxy.base.js Fri Apr 09 18:09:54 2010 -0400
@@ -275,6 +275,93 @@
});
}
+function init_history_items(historywrapper, noinit) {
+
+ var action = function() {
+ // Load saved state and show as necessary
+ try {
+ var stored = $.jStore.store("history_expand_state");
+ if (stored) {
+ for (var id in stored) {
+ $("#" + id + " div.historyItemBody" ).show();
+ }
+ }
+ } catch(err) {
+ // Something was wrong with values in storage, so clear storage
+ $.jStore.remove("history_expand_state");
+ }
+
+ // If Mozilla, hide scrollbars in hidden items since they cause animation bugs
+ if ( $.browser.mozilla ) {
+ $( "div.historyItemBody" ).each( function() {
+ if ( ! $(this).is( ":visible" ) ) $(this).find( "pre.peek" ).css( "overflow", "hidden" );
+ })
+ }
+
+ historywrapper.each( function() {
+ var id = this.id;
+ var body = $(this).children( "div.historyItemBody" );
+ var peek = body.find( "pre.peek" )
+ $(this).children( ".historyItemTitleBar" ).find( ".historyItemTitle" ).wrap( "<a href='#'></a>" ).click( function() {
+ if ( body.is(":visible") ) {
+ // Hiding stuff here
+ if ( $.browser.mozilla ) { peek.css( "overflow", "hidden" ) }
+ body.slideUp( "fast" );
+
+ if (!noinit) { // Ignore embedded item actions
+ // Save setting
+ var prefs = $.jStore.store("history_expand_state");
+ if (prefs) {
+ delete prefs[id];
+ $.jStore.store("history_expand_state", prefs);
+ }
+ }
+ } else {
+ // Showing stuff here
+ body.slideDown( "fast", function() {
+ if ( $.browser.mozilla ) { peek.css( "overflow", "auto" ); }
+ });
+
+ if (!noinit) {
+ // Save setting
+ var prefs = $.jStore.store("history_expand_state");
+ if (prefs === undefined) { prefs = {}; }
+ prefs[id] = true;
+ $.jStore.store("history_expand_state", prefs);
+ }
+ }
+ return false;
+ });
+ });
+
+ // Generate 'collapse all' link
+ $("#top-links > a.toggle").click( function() {
+ var prefs = $.jStore.store("history_expand_state");
+ if (prefs === undefined) { prefs = {}; }
+ $( "div.historyItemBody:visible" ).each( function() {
+ if ( $.browser.mozilla ) {
+ $(this).find( "pre.peek" ).css( "overflow", "hidden" );
+ }
+ $(this).slideUp( "fast" );
+ if (prefs) {
+ delete prefs[$(this).parent().attr("id")];
+ }
+ });
+ $.jStore.store("history_expand_state", prefs);
+ }).show();
+ }
+
+ if (noinit) {
+ action();
+ } else {
+ // Load jStore for local storage
+ $.jStore.init("galaxy"); // Auto-select best storage
+ $.jStore.engineReady(function() {
+ action();
+ });
+ }
+}
+
$(document).ready( function() {
// Links with confirmation
$( "a[confirm]" ).click( function() {
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/jquery.jstore-all.js
--- a/static/scripts/jquery.jstore-all.js Fri Apr 09 13:02:15 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,748 +0,0 @@
-/*
- * jStore - Persistent Client-Side Storage
- *
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- *
- * Dual licensed under:
- * MIT: http://www.opensource.org/licenses/mit-license.php
- * GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
- *//**
- * Javascript Class Framework
- *
- * Copyright (c) 2008 John Resig (http://ejohn.org/blog/simple-javascript-inheritance/)
- * Inspired by base2 and Prototype
- */
-(function(){
- var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
-
- // The base Class implementation (does nothing)
- this.Class = function(){};
-
- // Create a new Class that inherits from this class
- Class.extend = function(prop) {
- var _super = this.prototype;
-
- // Instantiate a base class (but only create the instance,
- // don't run the init constructor)
- initializing = true;
- var prototype = new this();
- initializing = false;
-
- // Copy the properties over onto the new prototype
- for (var name in prop) {
- // Check if we're overwriting an existing function
- prototype[name] = typeof prop[name] == "function" &&
- typeof _super[name] == "function" && fnTest.test(prop[name]) ?
- (function(name, fn){
- return function() {
- var tmp = this._super;
-
- // Add a new ._super() method that is the same method
- // but on the super-class
- this._super = _super[name];
-
- // The method only need to be bound temporarily, so we
- // remove it when we're done executing
- var ret = fn.apply(this, arguments);
- this._super = tmp;
-
- return ret;
- };
- })(name, prop[name]) :
- prop[name];
- }
-
- // The dummy class constructor
- function Class() {
- // All construction is actually done in the init method
- if ( !initializing && this.init )
- this.init.apply(this, arguments);
- }
-
- // Populate our constructed prototype object
- Class.prototype = prototype;
-
- // Enforce the constructor to be what we expect
- Class.constructor = Class;
-
- // And make this class extendable
- Class.extend = arguments.callee;
-
- return Class;
- };
-})();
-/*
- * jStore Delegate Framework
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- this.jStoreDelegate = Class.extend({
- init: function(parent){
- // The Object this delgate operates for
- this.parent = parent;
- // Container for callbacks to dispatch.
- // eventType => [ callback, callback, ... ]
- this.callbacks = {};
- },
- bind: function(event, callback){
- if ( !$.isFunction(callback) ) return this;
- if ( !this.callbacks[ event ] ) this.callbacks[ event ] = [];
-
- this.callbacks[ event ].push(callback);
-
- return this;
- },
- trigger: function(){
- var parent = this.parent,
- args = [].slice.call(arguments),
- event = args.shift(),
- handlers = this.callbacks[ event ];
-
- if ( !handlers ) return false;
-
- $.each(handlers, function(){ this.apply(parent, args) });
- return this;
- }
- });
-
-})(jQuery);/**
- * jStore-jQuery Interface
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Setup the jStore namespace in jQuery for options storage
- $.jStore = {};
-
- // Seed the options in
- $.extend($.jStore, {
- EngineOrder: [],
- // Engines should put their availability tests within jStore.Availability
- Availability: {},
- // Defined engines should enter themselves into the jStore.Engines
- Engines: {},
- // Instanciated engines should exist within jStore.Instances
- Instances: {},
- // The current engine to use for storage
- CurrentEngine: null,
- // Provide global settings for overwriting
- defaults: {
- project: null,
- engine: null,
- autoload: true,
- flash: 'jStore.Flash.html'
- },
- // Boolean for ready state handling
- isReady: false,
- // Boolean for flash ready state handling
- isFlashReady: false,
- // An event delegate
- delegate: new jStoreDelegate($.jStore)
- .bind('jStore-ready', function(engine){
- $.jStore.isReady = true;
- if ($.jStore.defaults.autoload) engine.connect();
- })
- .bind('flash-ready', function(){
- $.jStore.isFlashReady = true;
- })
- });
-
- // Enable ready callback for jStore
- $.jStore.ready = function(callback){
- if ($.jStore.isReady) callback.apply($.jStore, [$.jStore.CurrentEngine]);
- else $.jStore.delegate.bind('jStore-ready', callback);
- }
-
- // Enable failure callback registration for jStore
- $.jStore.fail = function(callback){
- $.jStore.delegate.bind('jStore-failure', callback);
- }
-
- // Enable ready callback for Flash
- $.jStore.flashReady = function(callback){
- if ($.jStore.isFlashReady) callback.apply($.jStore, [$.jStore.CurrentEngine]);
- else $.jStore.delegate.bind('flash-ready', callback);
- }
-
- // Enable and test an engine
- $.jStore.use = function(engine, project, identifier){
- project = project || $.jStore.defaults.project || location.hostname.replace(/\./g, '-') || 'unknown';
-
- var e = $.jStore.Engines[engine.toLowerCase()] || null,
- name = (identifier ? identifier + '.' : '') + project + '.' + engine;
-
- if ( !e ) throw 'JSTORE_ENGINE_UNDEFINED';
-
- // Instanciate the engine
- e = new e(project, name);
-
- // Prevent against naming conflicts
- if ($.jStore.Instances[name]) throw 'JSTORE_JRI_CONFLICT';
-
- // Test the engine
- if (e.isAvailable()){
- $.jStore.Instances[name] = e; // The Easy Way
- if (!$.jStore.CurrentEngine){
- $.jStore.CurrentEngine = e;
- }
- $.jStore.delegate.trigger('jStore-ready', e);
- } else {
- if (!e.autoload) // Not available
- throw 'JSTORE_ENGINE_UNAVILABLE';
- else { // The hard way
- e.included(function(){
- if (this.isAvailable()) { // Worked out
- $.jStore.Instances[name] = this;
- // If there is no current engine, use this one
- if (!$.jStore.CurrentEngine){
- $.jStore.CurrentEngine = this;
- }
- $.jStore.delegate.trigger('jStore-ready', this);
- }
- else $.jStore.delegate.trigger('jStore-failure', this);
- }).include();
- }
- }
- }
-
- // Set the current storage engine
- $.jStore.setCurrentEngine = function(name){
- if (!$.jStore.Instances.length ) // If no instances exist, attempt to load one
- return $.jStore.FindEngine();
-
- if (!name && $.jStore.Instances.length >= 1) { // If no name is specified, use the first engine
- $.jStore.delegate.trigger('jStore-ready', $.jStore.Instances[0]);
- return $.jStore.CurrentEngine = $.jStore.Instances[0];
- }
-
- if (name && $.jStore.Instances[name]) { // If a name is specified and exists, use it
- $.jStore.delegate.trigger('jStore-ready', $.jStore.Instances[name]);
- return $.jStore.CurrentEngine = $.jStore.Instances[name];
- }
-
- throw 'JSTORE_JRI_NO_MATCH';
- }
-
- // Test all possible engines for straightforward useability
- $.jStore.FindEngine = function(){
- $.each($.jStore.EngineOrder, function(k){
- if ($.jStore.Availability[this]()){ // Find the first, easiest option and use it.
- $.jStore.use(this, $.jStore.defaults.project, 'default');
- return false;
- }
- })
- }
-
- // Provide a simple interface for storing/getting values
- $.jStore.store = function(key, value){
- if (!$.jStore.CurrentEngine) return false;
-
- if ( !value ) // Executing a get command
- return $.jStore.CurrentEngine.get(key);
- // Executing a set command
- return $.jStore.CurrentEngine.set(key, value);
- }
- // Provide a simple interface for storing/getting values
- $.jStore.remove = function(key){
- if (!$.jStore.CurrentEngine) return false;
-
- return $.jStore.CurrentEngine.rem(key);
- }
-
- // Provide a chainable interface for storing values/getting a value at the end of a chain
- $.fn.store = function(key, value){
- if (!$.jStore.CurrentEngine) return this;
-
- var result = $.jStore.store(key, value);
-
- return !value ? result : this;
- }
-
- // Provide a chainable interface for removing values
- $.fn.removeStore = function(key){
- $.jStore.remove(key);
-
- return this;
- }
-
- // Provide a way for users to call for auto-loading
- $.jStore.load = function(){
- if ($.jStore.defaults.engine)
- return $.jStore.use($.jStore.defaults.engine, $.jStore.defaults.project, 'default');
-
- // Attempt to find a valid engine, and catch any exceptions if we can't
- try {
- $.jStore.FindEngine();
- } catch (e) {}
- }
-
-})(jQuery);
-/**
- * jStore Engine Core
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- this.StorageEngine = Class.extend({
- init: function(project, name){
- // Configure the project name
- this.project = project;
- // The JRI name given by the manager
- this.jri = name;
- // Cache the data so we can work synchronously
- this.data = {};
- // The maximum limit of the storage engine
- this.limit = -1;
- // Third party script includes
- this.includes = [];
- // Create an event delegate for users to subscribe to event triggers
- this.delegate = new jStoreDelegate(this)
- .bind('engine-ready', function(){
- this.isReady = true;
- })
- .bind('engine-included', function(){
- this.hasIncluded = true;
- });
- // If enabled, the manager will check availability, then run include(), then check again
- this.autoload = false; // This should be changed by the engines, if they have required includes
- // When set, we're ready to transact data
- this.isReady = false;
- // When the includer is finished, it will set this to true
- this.hasIncluded = false;
- },
- // Performs all necessary script includes
- include: function(){
- var self = this,
- total = this.includes.length,
- count = 0;
-
- $.each(this.includes, function(){
- $.ajax({type: 'get', url: this, dataType: 'script', cache: true,
- success: function(){
- count++;
- if (count == total) self.delegate.trigger('engine-included');
- }
- })
- });
- },
- // This should be overloaded with an actual functionality presence check
- isAvailable: function(){
- return false;
- },
- /** Event Subscription Shortcuts **/
- ready: function(callback){
- if (this.isReady) callback.apply(this);
- else this.delegate.bind('engine-ready', callback);
- return this;
- },
- included: function(callback){
- if (this.hasIncluded) callback.apply(this);
- else this.delegate.bind('engine-included', callback);
- return this;
- },
- /** Cache Data Access **/
- get: function(key){
- return this.data[key] || null;
- },
- set: function(key, value){
- this.data[key] = value;
- return value;
- },
- rem: function(key){
- var beforeDelete = this.data[key];
- this.data[key] = null;
- return beforeDelete;
- }
- });
-
-})(jQuery);
-/*
- * jStore DOM Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Set up a static test function for this instance
- var sessionAvailability = $.jStore.Availability.session = function(){
- return !!window.sessionStorage;
- },
- localAvailability = $.jStore.Availability.local = function(){
- return !!(window.localStorage || window.globalStorage);
- };
-
- this.jStoreDom = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'DOM';
-
- // Set the Database limit
- this.limit = 5 * 1024 * 1024;
- },
- connect: function(){
- // Fire our delegate to indicate we're ready for data transactions
- this.delegate.trigger('engine-ready');
- },
- get: function(key){
- var out = this.db.getItem(key);
- // Gecko's getItem returns {value: 'the value'}, WebKit returns 'the value'
- return out && out.value ? out.value : out
- },
- set: function(key, value){
- this.db.setItem(key,value);
- return value;
- },
- rem: function(key){
- var out = this.get(key);
- this.db.removeItem(key);
- return out
- }
- })
-
- this.jStoreLocal = jStoreDom.extend({
- connect: function(){
- // Gecko uses a non-standard globalStorage[ www.example.com ] DOM access object for persistant storage.
- this.db = !window.globalStorage ? window.localStorage : window.globalStorage[location.hostname];
- this._super();
- },
- isAvailable: localAvailability
- })
-
- this.jStoreSession = jStoreDom.extend({
- connect: function(){
- this.db = sessionStorage;
- this._super();
- },
- isAvailable: sessionAvailability
- })
-
- $.jStore.Engines.local = jStoreLocal;
- $.jStore.Engines.session = jStoreSession;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 1 ] = 'local';
-
-})(jQuery);
-/*
- * jStore Flash Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- * jStore.swf Copyright (c) 2008 Daniel Bulli (http://www.nuff-respec.com)
- */
-(function($){
-
- // Set up a static test function for this instance
- var avilability = $.jStore.Availability.flash = function(){
- return !!($.jStore.hasFlash('8.0.0'));
- }
-
- this.jStoreFlash = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'Flash';
-
- // Bind our flashReady function to the jStore Delegate
- var self = this;
- $.jStore.flashReady(function(){ self.flashReady() });
- },
- connect: function(){
- var name = 'jstore-flash-embed-' + this.project;
-
- // To make Flash Storage work on IE, we have to load up an iFrame
- // which contains an HTML page that embeds the object using an
- // object tag wrapping an embed tag. Of course, this is unnecessary for
- // all browsers except for IE, which, to my knowledge, is the only browser
- // in existance where you need to complicate your code to fix bugs. Goddamnit. :(
- $(document.body)
- .append('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" ' +
- 'id="jStoreFlashFrame" src="' +$.jStore.defaults.flash + '"></iframe>');
- },
- flashReady: function(e){
- var iFrame = $('#jStoreFlashFrame')[0];
-
- // IE
- if (iFrame.Document && $.isFunction(iFrame.Document['jStoreFlash'].f_get_cookie)) this.db = iFrame.Document['jStoreFlash'];
- // Safari && Firefox
- else if (iFrame.contentWindow && iFrame.contentWindow.document){
- var doc = iFrame.contentWindow.document;
- // Safari
- if ($.isFunction($('object', $(doc))[0].f_get_cookie)) this.db = $('object', $(doc))[0];
- // Firefox
- else if ($.isFunction($('embed', $(doc))[0].f_get_cookie)) this.db = $('embed', $(doc))[0];
- }
-
- // We're ready to process data
- if (this.db) this.delegate.trigger('engine-ready');
- },
- isAvailable: avilability,
- get: function(key){
- var out = this.db.f_get_cookie(key);
- return out == 'null' ? null : out;
- },
- set: function(key, value){
- this.db.f_set_cookie(key, value);
- return value;
- },
- rem: function(key){
- var beforeDelete = this.get(key);
- this.db.f_delete_cookie(key);
- return beforeDelete;
- }
- })
-
- $.jStore.Engines.flash = jStoreFlash;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 2 ] = 'flash';
-
- /**
- * Flash Detection functions copied from the jQuery Flash Plugin
- * Copyright (c) 2006 Luke Lutman (http://jquery.lukelutman.com/plugins/flash)
- * Dual licensed under the MIT and GPL licenses.
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.opensource.org/licenses/gpl-license.php
- */
- $.jStore.hasFlash = function(version){
- var pv = $.jStore.flashVersion().match(/\d+/g),
- rv = version.match(/\d+/g);
-
- for(var i = 0; i < 3; i++) {
- pv[i] = parseInt(pv[i] || 0);
- rv[i] = parseInt(rv[i] || 0);
- // player is less than required
- if(pv[i] < rv[i]) return false;
- // player is greater than required
- if(pv[i] > rv[i]) return true;
- }
- // major version, minor version and revision match exactly
- return true;
- }
-
- $.jStore.flashVersion = function(){
- // ie
- try {
- try {
- // avoid fp6 minor version lookup issues
- // see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
- var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
- try { axo.AllowScriptAccess = 'always'; }
- catch(e) { return '6,0,0'; }
- } catch(e) {}
- return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
- // other browsers
- } catch(e) {
- try {
- if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
- return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
- }
- } catch(e) {}
- }
- return '0,0,0';
- }
-
-})(jQuery);
-
-// Callback fired when ExternalInterface is established
-function flash_ready(){
- $.jStore.delegate.trigger('flash-ready');
-}
-/*
- * jStore Google Gears Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Set up a static test function for this instance
- var avilability = $.jStore.Availability.gears = function(){
- return !!(window.google && window.google.gears)
- }
-
- this.jStoreGears = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'Google Gears';
-
- // Add required third-party scripts
- this.includes.push('http://code.google.com/apis/gears/gears_init.js');
-
- // Allow Autoloading on fail
- this.autoload = true;
- },
- connect: function(){
- // Create our database connection
- var db = this.db = google.gears.factory.create('beta.database');
- db.open( 'jstore-' + this.project );
- db.execute( 'CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)' );
-
- // Cache the data from the table
- this.updateCache();
- },
- updateCache: function(){
- // Read the database into our cache object
- var result = this.db.execute( 'SELECT k,v FROM jstore' );
- while (result.isValidRow()){
- this.data[result.field(0)] = result.field(1);
- result.next();
- } result.close();
-
- // Fire our delegate to indicate we're ready for data transactions
- this.delegate.trigger('engine-ready');
- },
- isAvailable: avilability,
- set: function(key, value){
- // Update the database
- var db = this.db;
- db.execute( 'BEGIN' );
- db.execute( 'INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key,value] );
- db.execute( 'COMMIT' );
- return this._super(key, value);
- },
- rem: function(key){
- // Update the database
- var db = this.db;
- db.execute( 'BEGIN' );
- db.execute( 'DELETE FROM jstore WHERE k = ?', [key] );
- db.execute( 'COMMIT' );
- return this._super(key);
- }
- })
-
- $.jStore.Engines.gears = jStoreGears;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 3 ] = 'gears';
-
-})(jQuery);
-/*
- * jStore HTML5 Specification Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Set up a static test function for this instance
- var avilability = $.jStore.Availability.html5 = function(){
- return !!window.openDatabase
- }
-
- this.jStoreHtml5 = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'HTML5';
-
- // Set the Database limit
- this.limit = 1024 * 200;
- },
- connect: function(){
- // Create our database connection
- var db = this.db = openDatabase('jstore-' + this.project, '1.0', this.project, this.limit);
- if (!db) throw 'JSTORE_ENGINE_HTML5_NODB';
- db.transaction(function(db){
- db.executeSql( 'CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)' );
- });
-
- // Cache the data from the table
- this.updateCache();
- },
- updateCache: function(){
- var self = this;
- // Read the database into our cache object
- this.db.transaction(function(db){
- db.executeSql( 'SELECT k,v FROM jstore', [], function(db, result){
- var rows = result.rows, i = 0, row;
- for (; i < rows.length; ++i){
- row = rows.item(i);
- self.data[row.k] = row.v;
- }
-
- // Fire our delegate to indicate we're ready for data transactions
- self.delegate.trigger('engine-ready');
- });
- });
- },
- isAvailable: avilability,
- set: function(key, value){
- // Update the database
- this.db.transaction(function(db){
- db.executeSql( 'INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key,value]);
- });
- return this._super(key, value);
- },
- rem: function(key){
- // Update the database
- this.db.transaction(function(db){
- db.executeSql( 'DELETE FROM jstore WHERE k = ?', [key] )
- })
- return this._super(key);
- }
- })
-
- $.jStore.Engines.html5 = jStoreHtml5;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 0 ] = 'html5';
-
-})(jQuery);
-/*
- * jStore IE Storage Engine
- * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
- */
-(function($){
-
- // Set up a static test function for this instance
- var avilability = $.jStore.Availability.ie = function(){
- return !!window.ActiveXObject;
- }
-
- this.jStoreIE = StorageEngine.extend({
- init: function(project, name){
- // Call the parental init object
- this._super(project, name);
-
- // The type of storage engine
- this.type = 'IE';
-
- // Allow Autoloading on fail
- this.limit = 64 * 1024;
- },
- connect: function(){
- // Create a hidden div to store attributes in
- this.db = $('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-' + this.project + '"></div>')
- .appendTo(document.body).get(0);
- // Fire our delegate to indicate we're ready for data transactions
- this.delegate.trigger('engine-ready');
- },
- isAvailable: avilability,
- get: function(key){
- this.db.load(this.project);
- return this.db.getAttribute(key);
- },
- set: function(key, value){
- this.db.setAttribute(key, value);
- this.db.save(this.project);
- return value;
- },
- rem: function(key){
- var beforeDelete = this.get(key);
- this.db.removeAttribute(key);
- this.db.save(this.project);
- return beforeDelete;
- }
- })
-
- $.jStore.Engines.ie = jStoreIE;
-
- // Store the ordering preference
- $.jStore.EngineOrder[ 4 ] = 'ie';
-
-})(jQuery);
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/jquery.jstore.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/jquery.jstore.js Fri Apr 09 18:09:54 2010 -0400
@@ -0,0 +1,1810 @@
+/*!
+ * jStore 2.0 - Persistent Client Side Storage
+ *
+ * Copyright (c) 2010 Eric Garside (http://eric.garside.name/)
+ * Dual licensed under:
+ * MIT: http://www.opensource.org/licenses/mit-license.php
+ * GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
+ *
+ * ---------------------------
+ *
+ * jStore Flash Storage Component
+ *
+ * Copyright (c) 2006 Jeff Lerman (jeff at blip.tv)
+ * Licensed under the Creative Commons Attribution 3.0 United States License:
+ * http://creativecommons.org/licenses/by/3.0/us
+ */
+
+"use strict";
+
+/*global Class, window, jQuery, ActiveXObject, google */
+
+/*jslint white: true, browser: true, onevar: true, undef: true, eqeqeq: true, bitwise: true, regexp: false, strict: true, newcap: true, immed: true, maxerr: 50, indent: 4 */
+
+(function ($, window) {
+
+ //------------------------------
+ //
+ // Constants
+ //
+ //------------------------------
+
+ //------------------------------
+ // Exceptions
+ //------------------------------
+
+ /**
+ * An exception thrown by the StorageEngine class whenever its data accessor methods
+ * are called before the engine is ready to transact data.
+ */
+ var EX_UNSTABLE = 'JSTORE_ENGINE_UNSTABLE',
+
+ /**
+ * An exception thrown by jStore whenever an undefined storage engine is referenced for
+ * some task by an invalid JRI (jStore Resource Identifier).
+ */
+ EX_UNKNOWN = 'JSTORE_UNKNOWN_ENGINE_REQUESTED',
+
+ /**
+ * An exception thrown by jStore whenever a given flavor of storage is double defined.
+ */
+ EX_COLLISION = 'JSTORE_ENGINE_NAMESPACE_COLLISION',
+
+ /**
+ * An exception thrown by jStore whenever a jri is double applied to a resource.
+ */
+ EX_DUPLICATE = 'JSTORE_RESOURCE_NAMESPACE_COLLISION',
+
+ /**
+ * An exception thrown by jStore whenever a given flavor of storage has no defined engine.
+ */
+ EX_UNAVAILABLE = 'JSTORE_ENGINE_UNAVAILABLE',
+
+ /**
+ * An exception thrown by jStore whenever an invalid flavor type is used.
+ */
+ EX_INVALID = 'JSTORE_INVALID_FLAVOR',
+
+ //------------------------------
+ // Regular Expressions
+ //------------------------------
+
+ /**
+ * Regular expression to test property values for being JSON.
+ */
+ RX_JSON = (function ()
+ {
+ try
+ {
+ return new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$');
+ }
+ catch (e)
+ {
+ return (/^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/);
+ }
+ }()),
+
+ //------------------------------
+ // Storage Flavors
+ //------------------------------
+
+ /**
+ * The storage flavor identifier for HTML5 local storage.
+ */
+ FLAVOR_LOCAL = 'jstore-html5-local',
+
+ /**
+ * The storage flavor identifier for HTML5 database storage.
+ */
+ FLAVOR_SQL = 'jstore-html5-sql',
+
+ /**
+ * The storage flavor identifier for Adobe Flash SharedObject storage.
+ */
+ FLAVOR_FLASH = 'jstore-flash',
+
+ /**
+ * The storage flavor identifier for Google Gears storage.
+ */
+ FLAVOR_GEARS = 'jstore-google-gears',
+
+ /**
+ * The storage flavor identifier for Internet Explorer storage, available to IE7 and IE6.
+ */
+ FLAVOR_MSIE = 'jstore-msie',
+
+ //------------------------------
+ //
+ // Property Declaration
+ //
+ //------------------------------
+
+ /**
+ * The base StorageEngine class which each "storage flavor" will extend to meet the
+ * requirements for its specific implementation.
+ */
+ StorageEngine,
+
+ /**
+ * The jStore object. Internal to this closure, jStore is referenced by "_". It is
+ * exposed to jQuery below, and made publicly accessible through jQuery.jStore
+ */
+ _ = {},
+
+ /**
+ * The engines available to jStore for use. These are the class definitions for flavored
+ * storage engines.
+ *
+ * Signature:
+ * {
+ * <storageFlavor>: <flavoredStorageEngineDefinition>,
+ *
+ * ...
+ * }
+ */
+ definitions = {},
+
+ /**
+ * Active engines instantiated by jStore, indexed by their JRI.
+ *
+ * Signature:
+ * {
+ * <engineJRI>: <engineInstance>,
+ *
+ * ...
+ * }
+ */
+ engines = {},
+
+ /**
+ * If we are going to be using the flash storage engine, we want to postpone the jStore ready event until the jStore
+ * isFlashReady flag is also true. This property is set whenever flash is determined to be the storage engine.
+ */
+ waitForFlash = false,
+
+ /**
+ * Storage for listeners, indexed by content and event type.
+ *
+ * Signature:
+ * {
+ * <context>:
+ * {
+ * <eventType>: [<listener>, ...],
+ *
+ * ...
+ * },
+ *
+ * ...
+ * }
+ */
+ events = {},
+
+ /**
+ * The configuration for this implementation.
+ *
+ * Signature:
+ * {
+ * project: <defaultProjectName>,
+ *
+ * flash: <pathToFlashBootloader>,
+ *
+ * json: <pathToJSONFile>,
+ *
+ * errorCallback: <listenerToNotifyOnError>
+ * }
+ */
+ configurations =
+ {
+ project: undefined,
+
+ flash: 'jStore.Flash.html',
+
+ json: 'browser.json.js'
+ },
+
+ /**
+ * The active storage engine, being used to satisfy the get/set/remove functions on the jStore and jQuery
+ * objects.
+ */
+ active;
+
+ //------------------------------
+ //
+ // Internal Methods
+ //
+ //------------------------------
+
+ /**
+ * Determine if the given flavor is valid.
+ *
+ * @param flavor The flavor to test.
+ *
+ * @return True if the flavor is valid, false otherwise.
+ */
+ function validFlavor(flavor)
+ {
+ switch (flavor)
+ {
+
+ case FLAVOR_LOCAL:
+ case FLAVOR_SQL:
+ case FLAVOR_FLASH:
+ case FLAVOR_GEARS:
+ case FLAVOR_MSIE:
+ return true;
+
+ default:
+ return false;
+
+ }
+ }
+
+ /**
+ * Performs enhanced type comparison on an object. This is more reliable method
+ * of type checking a variable than a simple typeof comparison. The reason is that,
+ * typeof will reduce to the lowest common type.
+ *
+ * "typeof []" returns Object, and not Array.
+ * "typeof {}" returns Object as well.
+ *
+ * typecheck( [], 'Array' ) : returns true;
+ * typecheck( [], 'Object' ) : returns false;
+ *
+ * @param type The variable type to check.
+ *
+ * @param compare A string representing the literal type to check.
+ *
+ * @return True if the variable "type" matches the compare literal.
+ */
+ function typecheck(type, compare)
+ {
+ return !type ? false : type.constructor.toString().match(new RegExp(compare + '\\(\\)', 'i')) !== null;
+ }
+
+ /**
+ * If the provided listener is a valid function, it will be triggered with the provided context
+ * and parameters.
+ *
+ * @param listener The listener being triggered.
+ *
+ * @param context The context to provide to the listener.
+ *
+ * @param parameters The parameters to pass to the listener as arguments.
+ *
+ * @return The response of the notified listener.
+ */
+ function notify(listener, context, parameters)
+ {
+ if (typecheck(listener, 'Function'))
+ {
+ return listener.apply(context || _, typecheck(parameters, 'Array') ? parameters : [parameters]);
+ }
+ }
+
+ /**
+ * Load the given script.
+ *
+ * @param path The path to the file to include.
+ *
+ * @param listener The listener to notify when the file finishes loading.
+ */
+ function loadScript(path, listener)
+ {
+ $.ajax(
+ {
+ url: path,
+ complete: listener || $.noop(),
+ type: 'GET',
+ dataType: 'script',
+ cache: false
+ });
+ }
+
+ /**
+ * Checks the type of the value, and returns a value safe to persist in any client-side mechanism.
+ *
+ * @param value The value which should be prepared for storage.
+ *
+ * @return A value safe for storage.
+ */
+ function prepareForStorage(value)
+ {
+ if (value === undefined)
+ {
+ return '';
+ }
+
+ if (typecheck(value, 'Object') ||
+ typecheck(value, 'Array') ||
+ typecheck(value, 'Function'))
+ {
+ return JSON.stringify(value);
+ }
+
+ return value;
+ }
+
+ /**
+ * Checks the type of the value, and returns a value safe for access in any client-side mechanism.
+ *
+ * @param value The value which should be prepared for use.
+ *
+ * @return A value safe for use.
+ */
+ function prepareForRevival(value)
+ {
+ return RX_JSON.test(value) ? JSON.parse(value) : value;
+ }
+
+ /**
+ * Normalize a key before using it, to ensure it's valid.
+ *
+ * @param key The key to normalize.
+ *
+ * @return A normalized key, safe for storage.
+ */
+ function normalizeKey(key)
+ {
+ return key.replace(/^\s+|\s+$/g, "");
+ }
+
+ /**
+ * Define a flavored storage engine.
+ *
+ * @throws EX_COLLISION, EX_INVALID
+ *
+ * @param flavor The flavor of engine being defined.
+ *
+ * @param definition An object containing the new properties and methods for the engine extension.
+ *
+ * @param availability A function to invoke which must return a boolean value indicating the
+ * availability of the storage flavor on this browser.
+ */
+ function define(flavor, definition, availability)
+ {
+ if (!validFlavor(flavor))
+ {
+ throw EX_INVALID;
+ }
+
+ if (availability[flavor] !== undefined)
+ {
+ throw EX_COLLISION;
+ }
+
+ /**
+ * The logic here has been reworked so unavailable flavors are discarded, so we don't needlessly
+ * bloat the runtime size of jStore.
+ */
+ if (notify(availability) === true)
+ {
+ _.available[flavor] = true;
+
+ definition.flavor = flavor;
+
+ definitions[flavor] = StorageEngine.extend(definition);
+ }
+ else
+ {
+ _.available[flavor] = false;
+
+ // Filter the invalid flavor out of the priority list.
+ _.enginePriority = $.map(_.enginePriority, function (engine)
+ {
+ if (engine === flavor)
+ {
+ return null;
+ }
+ else
+ {
+ return engine;
+ }
+ });
+ }
+ }
+
+ /**
+ * Make the jStore library ready.
+ */
+ function makeReady()
+ {
+ if (_.isReady)
+ {
+ return;
+ }
+
+ if ((waitForFlash && _.isFlashReady) || !waitForFlash)
+ {
+ _.isReady = true;
+ _.trigger('jstore-ready', [engines[active]]);
+ }
+ }
+
+ /**
+ * Create a best-fit engine.
+ */
+ function createBestFitEngine()
+ {
+ _.create(_.enginePriority[0], undefined, 'best-fit');
+ }
+
+ /**
+ * Get the flash version currently supported in this browser.
+ *
+ * @return The flash version.
+ */
+ function flashVersion()
+ {
+ // MSIE
+ try
+ {
+ // avoid fp6 minor version lookup issues
+ // see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
+
+ try
+ {
+ axo.AllowScriptAccess = 'always';
+ }
+ catch (axo_e)
+ {
+ return '6,0,0';
+ }
+
+ return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
+ }
+
+ // Real browsers
+ catch (e)
+ {
+ try
+ {
+ if (navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin)
+ {
+ return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
+ }
+ }
+ catch (flash_e)
+ {}
+ }
+
+ return '0,0,0';
+ }
+
+ /**
+ * Flash Detection functions copied from the jQuery Flash Plugin
+ *
+ * Copyright (c) 2006 Luke Lutman (http://jquery.lukelutman.com/plugins/flash)
+ *
+ * Dual licensed under the MIT and GPL licenses.
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/gpl-license.php
+ *
+ * @param version The version to compare to.
+ *
+ * @return True if the version is greater than or equal to the required version, false otherwise.
+ */
+ function hasFlashVersion(version)
+ {
+ var playerVersion = flashVersion().match(/\d+/g),
+ requiredVersion = version.match(/\d+/g),
+ index = 0,
+ player,
+ required;
+
+ for (; index < 3; index++)
+ {
+ player = parseInt(playerVersion[index], 10);
+ required = parseInt(requiredVersion[index], 10);
+
+ // Player version is less than what is required.
+ if (player < required)
+ {
+ return false;
+ }
+
+ // Player version is greater than what is required.
+ else if (player > required)
+ {
+ return true;
+ }
+ }
+
+ // Player and required version match exactly.
+ return true;
+ }
+
+ //------------------------------
+ //
+ // Plugin Definition
+ //
+ //------------------------------
+
+ //------------------------------
+ // Error Declaration
+ //------------------------------
+
+ //------------------------------
+ // Plugin Creation
+ //------------------------------
+
+ /**
+ * The jStore object. Manages a collection of StorageEngines for particular "storage flavors", or the types
+ * of storage solutions available to each browser.
+ *
+ * 2.0 Version Notes:
+ *
+ * - The user is now responsible for third-party script includes, with the exception of flash.
+ *
+ * - jStore has been given sole responsibility for testing engine availability.
+ *
+ * - For the sake of naming conventions, all property names now start with a lowercase, and are camel-cased.
+ *
+ * The following properties have been changed since the 1.2.x release:
+ *
+ * - EngineOrder: For the sake of naming conventions, renamed to enginePriority.
+ *
+ * The following properties and methods have been removed since the 1.2.x release:
+ *
+ * - Availability: jStore's engines would add their availability tests to this object, so jStore could test
+ * them. With the changes to how availability testing works, this property has been removed.
+ * A new property, "available" on jStore contains a set of available engines.
+ *
+ * - Engines: Formerly contained the definitions of storage engines. This property has been removed, and
+ * storage of these definitions has been moved internal to the closure.
+ *
+ * - Instances: Formerly contained instantiated storage engines. This property has been removed, and storage
+ * of instantiated engines has been moved internal to the closure.
+ *
+ * - CurrentEngine: Formerly contained the active storage engine being used for transacting data through the jStore
+ * and/or jQuery objects. This property has been removed, and storage of the current engine has
+ * been moved internal to the closure. A new method, "activeEngine" has been added to jQuery to
+ * get and set the active engine to use.
+ *
+ * - defaults: Formerly used to set the implementation options for jStore. This property has been removed and
+ * replaced with a new configuration metho on the jStore object.
+ *
+ * - delegate: The delegate class has been removed in favor of a much simpler bind/trigger accessor system, which
+ * is accessible contextually through storage engines, or generically through jStore.
+ *
+ * + fail: This registration class bound events on the delegate for jstore-fail events. Instead, use:
+ * jStore.bind('jstore-failure', listener);
+ *
+ * + flashReady: This registration class bound events on the delegate for flash-ready events. The jstore-ready method
+ * now accounts for waiting for flash readyness, if and only if the flash engine is being used. Simply
+ * call to jStore.ready().
+ *
+ * + load: Replaced with the init() method, which performs the same basic functions as the old load() method. Also,
+ * the init function is now domready safe, meaning it wraps itself in a domready listener, so the end user
+ * doesn't have to.
+ *
+ * + FindEngine: Removed entirely. The functionality provided by this method now implicitly occurs with the new define()
+ * system implemented for engine flavors.
+ *
+ * + setCurrentEngine: Replaced by activeEngine(). Set the current active engine by passing in the JRI.
+ *
+ * + safeStore: Replaced by a method internal to this closure, "prepareForStorage".
+ *
+ * + safeResurrect: Replaced by a method internal to this closure, "prepareForRevival".
+ *
+ * + use: Replaced by "create".
+ */
+ $.extend(_, {
+
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ /**
+ * The priority order in which engines should be tested for use. The lower their index in the array, the higher
+ * their priority for use.
+ *
+ * Be weary when reconfiguring the priority order of engines! jStore will use the first available engine it finds
+ * based on its priority when autoloading.
+ *
+ * This array is filtered out as engines are defined, with invalid engines being removed.
+ *
+ * Signature:
+ * [FLAVOR_<storageFlavor>, ...]
+ */
+ enginePriority: [FLAVOR_LOCAL, FLAVOR_SQL, FLAVOR_FLASH, FLAVOR_MSIE],
+
+ /**
+ * A collection of the availability states of engines, indexed by their flavor.
+ *
+ * Signature:
+ * {
+ * <storageFlavor>: true|false,
+ *
+ * ...
+ * }
+ */
+ available: {},
+
+ /**
+ * Flag to determine if the jStore library is ready. jStore becomes ready once the dom is ready and all necessary
+ * startup procedures required by jStore to function properly are completed.
+ */
+ isReady: false,
+
+ /**
+ * With the flash storage engine, we have to jump through a couple of hoops before the flash engine is ready to work.
+ * This flag tracks whether or not the flash storage is available.
+ */
+ isFlashReady: false,
+
+ /**
+ * The available engine flavors.
+ */
+ flavors:
+ {
+ local: FLAVOR_LOCAL,
+
+ sql: FLAVOR_SQL,
+
+ flash: FLAVOR_FLASH,
+
+ gears: FLAVOR_GEARS,
+
+ msie: FLAVOR_MSIE
+ },
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @throws EX_INVALID
+ *
+ * @param project The name of the jStore project. Used to generate a JRI for the engine we create.
+ *
+ * @param configuration Optionally, an object containing configuration options for this implementation.
+ *
+ * @param flavor Optionally, the flavor of storage to use. If not provided, jStore will pick the
+ * best flavor, based on the current browser.
+ *
+ * @return jStore
+ */
+ init: function (project, configuration, flavor)
+ {
+ // Extend our plugin configurations
+ $.extend(configurations, {project: project}, configuration);
+
+ $(function ()
+ {
+ // If JSON parsing isn't defined in this browser, include it.
+ if (window.JSON === undefined)
+ {
+ loadScript(configurations.json);
+ }
+
+ // If we have an explicit flavor to use, use it.
+ if (flavor !== undefined)
+ {
+ _.create(flavor, project, 'default');
+ }
+
+ // Otherwise, attempt to create a best-fit engine.
+ else
+ {
+ createBestFitEngine();
+ }
+ });
+
+ return _;
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ /**
+ * Create an instance of a flavored engine.
+ *
+ * @throws EX_INVALID, EX_UNAVAILABLE, EX_DUPLICATE
+ *
+ * @param flavor The flavor to create the engine with.
+ *
+ * @param project The project identifier for this instance.
+ *
+ * @param identifier Some arbitrary identifier for this project instance of the engine.
+ *
+ * @return The created instance.
+ */
+ create: function (flavor, project, identifier)
+ {
+ project = project || configurations.project || location.hostname.replace(/\./g, '-') || 'unknown';
+
+ if (!validFlavor(flavor))
+ {
+ throw EX_INVALID;
+ }
+
+ if (definitions[flavor] === undefined)
+ {
+ throw EX_UNAVAILABLE;
+ }
+
+ var jri = (identifier !== undefined ? identifier + '.' : '') + project + '.' + flavor,
+ engine;
+
+ if (engines[jri] !== undefined)
+ {
+ throw EX_DUPLICATE;
+ }
+
+ // Create our engine instance.
+ engine = engines[jri] = new definitions[flavor](project, jri);
+
+ // Set up a listener for our jstore-engine-ready event.
+ engine.ready(function ()
+ {
+ _.trigger('jstore-engine-ready', [engine]);
+ });
+
+ if (flavor === FLAVOR_FLASH && !_.isFlashReady)
+ {
+ if (active === undefined)
+ {
+ waitForFlash = true;
+ }
+
+ // Define a window-accessible function for flash to call via ExternalInterface
+ window.jstore_ready = function ()
+ {
+ _.isFlashReady = true;
+ _.trigger('flash-ready');
+
+ if (active === undefined)
+ {
+ makeReady();
+ }
+
+ // Remove the callback from the window scope, as it is no longer necessary
+ window.flash_ready = undefined;
+ };
+
+ window.jstore_error = function (message)
+ {
+ _.trigger('jstore-error', ['JSTORE_FLASH_EXCEPTION', null, message]);
+ };
+
+ $('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="' +
+ configurations.flash + '"></iframe>').appendTo('body');
+ }
+ else if (active === undefined)
+ {
+ active = jri;
+ makeReady();
+ }
+
+ return engine;
+ },
+
+ /**
+ * Fetch an engine by it's JRI.
+ *
+ * @param jri The JRI of the engine to retrieve.
+ *
+ * @return The requested engine.
+ */
+ engine: function (jri)
+ {
+ return engines[jri];
+ },
+
+ /**
+ * Returns the active storage engine being used. If a value is passed, sets that engine as the active engine.
+ *
+ * @throws EX_UNKNOWN
+ *
+ * @param jri Optionally, the JRI of the engine to make active, if it should be changed.
+ *
+ * @return The active storage engine.
+ */
+ activeEngine: function (jri)
+ {
+ if (jri !== undefined)
+ {
+ if (engines[jri] === undefined)
+ {
+ throw EX_UNKNOWN;
+ }
+ else
+ {
+ active = jri;
+ }
+ }
+
+ return engines[active];
+ },
+
+ /**
+ * Bind an event listener.
+ *
+ * @param event The event to bind a listener on.
+ *
+ * @param listener The listener to notify when the event occurs.
+ *
+ * @param context The context of the binding. A string representing the engine flavor
+ * binding the event, or undefined to indicate it's a jStore event.
+ *
+ * @return jStore
+ */
+ bind: function (event, listener, context)
+ {
+ context = context || 'jstore';
+
+ if (events[context] === undefined)
+ {
+ events[context] = {};
+ }
+
+ if (events[context][event] === undefined)
+ {
+ events[context][event] = [listener];
+ }
+ else
+ {
+ events[context][event].push(listener);
+ }
+
+ return _;
+ },
+
+ /**
+ * Trigger an event, notifying any bound listeners.
+ *
+ * @param event The event to trigger.
+ *
+ * @param parameters Any additional parameters to pass to the listeners being notified.
+ *
+ * @param context The context of the binding. A string representing the engine flavor
+ * binding the event, or undefined to indicate it's a jStore event.
+ *
+ * @return jStore
+ */
+ trigger: function (event, parameters, context)
+ {
+ context = context || 'jstore';
+
+ if (events[context] !== undefined)
+ {
+ if (events[context][event] !== undefined)
+ {
+ $.each(events[context][event], function ()
+ {
+ notify(this, _, parameters);
+ });
+ }
+ }
+
+ return _;
+ },
+
+ /**
+ * Bind a listener to be notified when jStore causes a non-fatal exception.
+ *
+ * @param listener The listener to notify when a failure occurs.
+ */
+ error: function (listener)
+ {
+ _.bind('jstore-error', listener);
+ },
+
+ /**
+ * Bind a listener to be notified when jStore is ready.
+ *
+ * @param listener The listener to notify when jStore is ready.
+ *
+ * @return jStore
+ */
+ ready: function (listener)
+ {
+ if (_.isReady)
+ {
+ notify(listener);
+ }
+ else
+ {
+ _.bind('jstore-ready', listener);
+ }
+
+ return _;
+ },
+
+ /**
+ * Bind a listener to be notified when jStore and the default engine are ready.
+ *
+ * @param listener The listener to notify when jStore and it's default engine are ready.
+ *
+ * @return jStore
+ */
+ engineReady: function (listener)
+ {
+ if (_.isReady)
+ {
+ notify(listener);
+ }
+ else
+ {
+ _.bind('jstore-engine-ready', listener);
+ }
+
+ return _;
+ },
+
+ /**
+ * A combined getter/setter for the active engine.
+ *
+ * @param key The key of the property to get, or set.
+ *
+ * @param value If a valid value is provided, sets the engine.
+ *
+ * @return The requested property value.
+ */
+ store: function (key, value)
+ {
+ return value === undefined ? _.get(key) : _.set(key, value);
+ },
+
+ /**
+ * Remove a property from the active engine.
+ *
+ * @param key The key of the property to remove.
+ *
+ * @return The value of the property before removal.
+ */
+ remove: function (key)
+ {
+ return _.activeEngine().remove(key);
+ },
+
+ /**
+ * Get a property from the active engine.
+ *
+ * @param key The key of the property to get.
+ *
+ * @return The value of the property.
+ */
+ get: function (key)
+ {
+ return _.activeEngine().get(key);
+ },
+
+ /**
+ * Set a property on the active engine.
+ *
+ * @param key The key of the property to set.
+ *
+ * @param value The value to set the property to.
+ *
+ * @return The new value of the property.
+ */
+ set: function (key, value)
+ {
+ return _.activeEngine().set(key, value);
+ }
+
+ });
+
+ //------------------------------
+ // Core Extension
+ //------------------------------
+
+ //------------------------------
+ //
+ // Class Definition
+ //
+ //------------------------------
+
+ /**
+ * The StorageEngine class is the unified API through which jStore accesses and manipulates
+ * the various storage flavors available.
+ *
+ * 2.0 Version Notes:
+ *
+ * - All third-party loading is now the responsibility of the developer.
+ *
+ * - The delegate class has been removed entirely. Engines have been given "bind" and "trigger" methods
+ * to interact directly with the delegate like-replacement that has been added to jStore.
+ *
+ * - Engine availability has been moved out of the engines themselves, and elevated to a jStore
+ * responsibility.
+ *
+ * The following methods have changed since the 1.2.x release:
+ *
+ * - get: When "get"ting a non-stored property, the get function will now return "undefined"
+ * instead of "null". "null" can now be used as a valid property value.
+ *
+ * - rem: Renamed to "remove". I always felt dirty about "rem" being vaguely explicit.
+ *
+ * The following properties have been removed since the 1.2.x release:
+ *
+ * - autoload: Part of the third-party loading logic.
+ *
+ * - hasIncluded: Part of the third-party loading logic.
+ *
+ * - includes: Part of the third-party loading logic.
+ *
+ * - isAvailable: Part of the availability logic elevated to jStore.
+ *
+ * @throws EX_UNSTABLE
+ */
+ StorageEngine = Class.extend({
+
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ /**
+ * The project which owns this storage engine.
+ */
+ project: undefined,
+
+ /**
+ * The JRI (jStore Resource Identifier) acts as a uuid for this specific instance
+ * of the storage engine.
+ */
+ jri: undefined,
+
+ /**
+ * The flavor of this engine.
+ */
+ flavor: undefined,
+
+ /**
+ * The actual database object which data is transacted through.
+ */
+ database: undefined,
+
+ /**
+ * A StorageEngine should always respond to fetch requests synchronously. However, some
+ * of the storage flavors require callback-based asynchronous access. To get around this,
+ * we simlpy require all engines to function off a primary data cache, to allow for
+ * synchronous access across all implementations.
+ *
+ * Signature:
+ * {
+ * <propertyKey>: <propertyValue>,
+ *
+ * ...
+ * }
+ */
+ data: undefined,
+
+ /**
+ * A number of storage engines enforce a size limit as to what they will persist for a given site.
+ * This limit is not monitored or computed by jStore currently, and this property will merely give
+ * a static indication of the total size alloted to the engine, as defined by the storage flavor.
+ */
+ limit: undefined,
+
+ /**
+ * Each storage flavor has a different process to go through before it's "ready" to transact data. This
+ * property stores the state of the engine's readyness, and uses it to notify listeners whenever jStore
+ * is ready to function.
+ */
+ isReady: undefined,
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param project The project which instantiated this engine.
+ *
+ * @param jri The uuid assigned to this instance by jStore.
+ */
+ init: function (project, jri)
+ {
+ this.project = project;
+ this.jri = jri;
+ this.data = {};
+ this.isReady = false;
+ this.updateCache();
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ /**
+ * Update the cache.
+ */
+ updateCache: function ()
+ {
+ this.isReady = true;
+ this.trigger('engine-ready', [this]);
+ },
+
+ /**
+ * Bind a listener to an event dispatched by this engine.
+ *
+ * @param event The event to bind on.
+ *
+ * @param listener The listener to notify when the event occurs.
+ */
+ bind: function (event, listener)
+ {
+ _.bind(event, listener, this.jri);
+ },
+
+ /**
+ * Trigger an event, notifying all bound listeners.
+ *
+ * @param event The event to trigger.
+ *
+ * @param parameters An optional Array of parameters to pass to the listeners.
+ */
+ trigger: function (event, parameters)
+ {
+ _.trigger(event, parameters, this.jri);
+ },
+
+ /**
+ * Bind a listener to the StorageEngine's ready event.
+ *
+ * @param listener The listener to notify whenever this engine is ready to transact data.
+ */
+ ready: function (listener)
+ {
+ if (this.isReady)
+ {
+ notify(listener, this);
+ }
+ else
+ {
+ this.bind('engine-ready', listener);
+ }
+ },
+
+ /**
+ * Get a property from the StorageEngine.
+ *
+ * @param key The property key of the data to retrieve.
+ *
+ * @return The property value, or "undefined" if the property isn't stored.
+ */
+ get: function (key)
+ {
+ this.__interruptAccess();
+
+ return this.data[key];
+ },
+
+ /**
+ * Sets a property in the StorageEngine.
+ *
+ * @param key The key of the property.
+ *
+ * @param value The value of the property.
+ *
+ * @return The new value of the property.
+ */
+ set: function (key, value)
+ {
+ this.__interruptAccess();
+
+ key = normalizeKey(key);
+
+ try
+ {
+ this.__set(key, value);
+ }
+ catch (e)
+ {
+ _.trigger('jstore-error', ['JSTORE_STORAGE_FAILURE', this.jri, e]);
+ }
+
+ this.data[key] = value;
+
+ return value;
+ },
+
+ /**
+ * Removes a property from the StorageEngine.
+ *
+ * @param key The property key of the data to remove.
+ *
+ * @return The value of the property, before it was removed.
+ */
+ remove: function (key)
+ {
+ this.__interruptAccess();
+
+ key = normalizeKey(key);
+
+ try
+ {
+ this.__remove(key);
+ }
+ catch (e)
+ {
+ _.trigger('jstore-error', ['JSTORE_REMOVE_FAILURE', this.jri, e]);
+ }
+
+ var buffer = this.data[key];
+
+ this.data[key] = undefined;
+
+ return buffer;
+ },
+
+ //------------------------------
+ // Internal Methods
+ //------------------------------
+
+ /**
+ * Ensures the engine is in a stable state for transacting data.
+ *
+ * @throws EX_UNSTABLE
+ */
+ __interruptAccess: function ()
+ {
+ if (!this.isReady)
+ {
+ throw EX_UNSTABLE;
+ }
+ },
+
+ /**
+ * Sets a property in the StorageEngine. This method should be overloaded to provide actual
+ * storage flavor integration.
+ *
+ * @param key The key of the property.
+ *
+ * @param value The value of the property.
+ *
+ * @return The new value of the property.
+ */
+ __set: function (key, value)
+ {
+ return;
+ },
+
+ /**
+ * Removes a property from the StorageEngine. This method should be overloaded to provide actual
+ * storage flavor integration.
+ *
+ * @param key The property key of the data to remove.
+ *
+ * @return The value of the property, before it was removed.
+ */
+ __remove: function (key)
+ {
+ return;
+ }
+
+ });
+
+ //------------------------------
+ //
+ // jQuery Hooks
+ //
+ //------------------------------
+
+ $.extend($.fn, {
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ /**
+ * A combined getter/setter for the active engine.
+ *
+ * @param key The key of the property to get, or set.
+ *
+ * @param value If a valid value is provided, sets the engine.
+ *
+ * @return jQuery
+ */
+ store: function (key, value)
+ {
+ if (value === undefined)
+ {
+ _.get(key);
+ }
+ else
+ {
+ _.set(key, value);
+ }
+
+ return this;
+ },
+
+ /**
+ * Remove a property from the active engine.
+ *
+ * @param key The key of the property to remove.
+ *
+ * @return jQuery
+ */
+ removeStore: function (key)
+ {
+ _.activeEngine().remove(key);
+
+ return this;
+ },
+
+ /**
+ * Get a property from the active engine.
+ *
+ * @param key The key of the property to get.
+ *
+ * @return The value of the property.
+ */
+ getStore: function (key)
+ {
+ return _.activeEngine().get(key);
+ },
+
+ /**
+ * Set a property on the active engine.
+ *
+ * @param key The key of the property to set.
+ *
+ * @param value The value to set the property to.
+ *
+ * @return jQuery
+ */
+ setStore: function (key, value)
+ {
+ _.activeEngine().set(key, value);
+
+ return this;
+ }
+
+ });
+
+ //------------------------------
+ //
+ // Event Bindings
+ //
+ //------------------------------
+
+ //------------------------------
+ //
+ // Startup Code
+ //
+ //------------------------------
+
+ //------------------------------
+ // Expose jStore through jQuery
+ //------------------------------
+
+ window.jStore = $.jStore = _;
+
+ //------------------------------
+ //
+ // Engine Definitions
+ //
+ //------------------------------
+
+ //------------------------------
+ // Local
+ //------------------------------
+
+ define(FLAVOR_LOCAL,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: parseInt(5e5, 16),
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ this.database = window.globalStorage === undefined ? window.localStorage : window.globalStorage[location.hostname];
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function ()
+ {
+ var key, value;
+
+ for (key in this.database)
+ {
+ var has_key = false;
+ if (this.database.hasOwnProperty) {
+ if (this.database.hasOwnProperty(key)) {
+ has_key = true;
+ }
+ } else { // IE 8
+ if (this.database.getItem(key) !== null) {
+ has_key = true;
+ }
+ }
+
+ if (has_key) {
+ value = this.database.getItem(key);
+
+ // Gecko's getItem returns {value: 'the value'}, WebKit returns 'the value'
+ this.data[key] = prepareForRevival(value && value.value ? value.value : value);
+ }
+ }
+
+ this._super();
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ this.database.setItem(key, prepareForStorage(value));
+ },
+
+ __remove: function (key)
+ {
+ this.database.removeItem(key);
+ }
+ },
+
+ function ()
+ {
+ return window.localStorage !== undefined || window.globalStorage !== undefined;
+ });
+
+ //------------------------------
+ // SQL
+ //------------------------------
+
+ define(FLAVOR_SQL,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: parseInt(32e3, 16),
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ this.database = window.openDatabase('jstore-' + project, '1.0', project, this.limit);
+
+ if (!this.database)
+ {
+ throw 'JSTORE_SQL_NO_DB';
+ }
+
+ this.database.transaction(function (database)
+ {
+ database.executeSql('CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)');
+ });
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function ()
+ {
+ var self = this,
+ _super = this._super;
+
+ this.database.transaction(function (database)
+ {
+ database.executeSql('SELECT k,v FROM jstore', [], function (database, result)
+ {
+ var rows = result.rows,
+ index = 0,
+ row;
+
+ for (; index < rows.length; ++index)
+ {
+ row = rows.item(index);
+ self.data[row.k] = prepareForRevival(row.v);
+ }
+
+ _super.apply(self);
+ });
+ });
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ this.database.transaction(function (database)
+ {
+ database.executeSql('INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key, prepareForStorage(value)]);
+ });
+ },
+
+ __remove: function (key)
+ {
+ this.database.transaction(function (database)
+ {
+ database.executeSql('DELETE FROM jstore WHERE k = ?', [key]);
+ });
+ }
+ },
+
+ function ()
+ {
+ return window.openDatabase !== undefined;
+ });
+
+ //------------------------------
+ // Flash
+ //------------------------------
+
+ define(FLAVOR_FLASH,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: -1,
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ var self = this;
+
+ _.bind('flash-ready', function ()
+ {
+ self.__flashReadyListener();
+ });
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function (enable)
+ {
+ /**
+ * The default call to updateCache passes no variable, so we can short circuit the
+ * ready state until we explictly call this after flash ready.
+ */
+ if (enable === true)
+ {
+ var key,
+ dataset = this.database.jstore_get_all();
+
+ for (key in dataset)
+ {
+ if (dataset.hasOwnProperty(key))
+ {
+ this.data[key] = prepareForRevival(this.database.jstore_get(key));
+ }
+ }
+
+ this._super();
+ }
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ if (!this.database.jstore_set(key, prepareForStorage(value)))
+ {
+ _.trigger('jstore-error', ['JSTORE_STORAGE_FAILURE', this.jri, 'Flash Exception']);
+ }
+ },
+
+ __remove: function (key)
+ {
+ this.database.jstore_remove(key);
+ },
+
+ /**
+ * Triggered whenever flash is ready.
+ */
+ __flashReadyListener: function ()
+ {
+ var iFrame = $('#jStoreFlashFrame')[0],
+ frameDocument;
+
+ // MSIE
+ if (iFrame.Document !== undefined && typecheck(iFrame.Document.jStoreFlash.jstore_get, 'Function'))
+ {
+ this.database = iFrame.Document.jStoreFlash;
+ }
+
+ // Real Browsers
+ else if (iFrame.contentWindow && iFrame.contentWindow.document)
+ {
+ frameDocument = $(iFrame.contentWindow.document);
+
+ // Webkit
+ if (typecheck($('object', frameDocument)[0].jstore_get, 'Function'))
+ {
+ this.database = $('object', frameDocument)[0];
+ }
+
+ // Gecko
+ else if (typecheck($('embed', frameDocument)[0].jstore_get, 'Function'))
+ {
+ this.database = $('embed', frameDocument)[0];
+ }
+ }
+
+ if (this.database === undefined)
+ {
+ throw 'JSTORE_FLASH_REFERENCE_ISSUE';
+ }
+ else
+ {
+ this.updateCache(true);
+ }
+ }
+ },
+
+ function ()
+ {
+ return hasFlashVersion('9.0.0');
+ });
+
+ //------------------------------
+ // Gears
+ //------------------------------
+
+ define(FLAVOR_GEARS,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: -1,
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ this.database = google.gears.factory.create('beta.database');
+ this.database.open('jstore-' + project);
+ this.database.execute('CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)');
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function ()
+ {
+ var result = this.database.execute('SELECT k,v FROM jstore');
+
+ while (result.isValidRow())
+ {
+ this.data[result.field(0)] = prepareForRevival(result.field(1));
+ result.next();
+ }
+
+ result.close();
+
+ this._super();
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ this.database.execute('BEGIN');
+ this.database.execute('INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key, prepareForStorage(value)]);
+ this.database.execute('COMMIT');
+ },
+
+ __remove: function (key)
+ {
+ this.database.execute('BEGIN');
+ this.database.execute('DELETE FROM jstore WHERE k = ?', [key]);
+ this.database.execute('COMMIT');
+ }
+ },
+
+ function ()
+ {
+ return window.google !== undefined && window.google.gears !== undefined;
+ });
+
+ //------------------------------
+ // MSIE
+ //------------------------------
+
+ define(FLAVOR_MSIE,
+ {
+ //------------------------------
+ // Properties
+ //------------------------------
+
+ limit: parseInt(1e4, 16),
+
+ //------------------------------
+ // Constructor
+ //------------------------------
+
+ init: function (project, name)
+ {
+ this.database = $('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-' + project + '"></div>')
+ .appendTo(document.body).get(0);
+
+ this._super(project, name);
+ },
+
+ //------------------------------
+ // Methods
+ //------------------------------
+
+ updateCache: function ()
+ {
+ this.database.load(this.project);
+
+ var node = document.getElementById('jstore-' + this.project),
+ xmlDoc = node.XMLDocument,
+ root,
+ index = 0;
+
+ if (xmlDoc && xmlDoc.documentElement && xmlDoc.documentElement.attributes)
+ {
+ root = xmlDoc.documentElement;
+
+ for (; index < root.attributes.length; ++index)
+ {
+ this.data[root.attributes.item(index).nodeName] = prepareForRevival(root.attributes.item(index).nodeValue);
+ }
+ }
+
+ this._super();
+ },
+
+ //------------------------------
+ // Internal methods
+ //------------------------------
+
+ __set: function (key, value)
+ {
+ this.database.setAttribute(key, prepareForStorage(value));
+ this.database.save(this.project);
+ },
+
+ __remove: function (key)
+ {
+ this.database.removeAttribute(key);
+ this.database.save(this.project);
+ }
+ },
+
+ function ()
+ {
+ return window.ActiveXObject !== undefined;
+ });
+
+}(jQuery, window));
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/json2.js
--- a/static/scripts/json2.js Fri Apr 09 13:02:15 2010 -0400
+++ b/static/scripts/json2.js Fri Apr 09 18:09:54 2010 -0400
@@ -1,6 +1,6 @@
/*
http://www.JSON.org/json2.js
- 2009-06-29
+ 2010-03-20
Public Domain.
@@ -8,6 +8,14 @@
See http://www.JSON.org/js.html
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+
+
This file creates a global JSON object containing two methods: stringify
and parse.
@@ -33,7 +41,7 @@
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
- bound to the object holding the key.
+ bound to the value
For example, this would serialize Dates as ISO strings.
@@ -136,15 +144,9 @@
This is a reference implementation. You are free to copy, modify, or
redistribute.
-
- This code should be minified before deployment.
- See http://javascript.crockford.com/jsmin.html
-
- USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
- NOT CONTROL.
*/
-/*jslint evil: true */
+/*jslint evil: true, strict: false */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
@@ -153,10 +155,13 @@
test, toJSON, toString, valueOf
*/
+
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
-var JSON = JSON || {};
+if (!this.JSON) {
+ this.JSON = {};
+}
(function () {
@@ -428,6 +433,7 @@
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
+ text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/class.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/packed/class.js Fri Apr 09 18:09:54 2010 -0400
@@ -0,0 +1,7 @@
+/*
+ * Class definition
+ *
+ * Copyright (c) 2008 John Resig (http://ejohn.org/blog/simple-javascript-inheritance/)
+ * Inspired by base2 and Prototype
+ */
+"use strict";(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(g){var f=this.prototype;a=true;var e=new this();a=false;for(var d in g){e[d]=(typeof g[d]==="function"&&typeof f[d]==="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super;this._super=f[h];var j=i.apply(this,arguments);this._super=k;return j}}(d,g[d])):g[d])}function c(){if(!a&&this.init){this.init.apply(this,arguments)}}c.prototype=e;c.constructor=c;c.extend=arguments.callee;return c}}());
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/galaxy.base.js
--- a/static/scripts/packed/galaxy.base.js Fri Apr 09 13:02:15 2010 -0400
+++ b/static/scripts/packed/galaxy.base.js Fri Apr 09 18:09:54 2010 -0400
@@ -1,1 +1,1 @@
-$(document).ready(function(){replace_big_select_inputs()});$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}function make_popupmen!
u(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id")+"-menu'></ul>");$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d)}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function array_length(b){if(b.length){return b.length}var c=0;for(var a in b){c++}return c}function replace_big_select_inputs(){$("select[name=dbkey]").each(function(){var a=$(this);if(a!
.find("option").length<20){return}var b=a.attr("value");var c=$("<inpu
t type='text' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",a.attr("name"));c.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var f=[];var e={};a.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}f.push(h);e[h]=g;e[g]=g;if(g==b){c.attr("value",h)}});if(c.attr("value")==""){c.attr("value","Click to Search or Select")}var d={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};c.autocomplete(f,d);a.replaceWith(c);c.parents("form").submit(function(){var h=c.attr("value");var g=e[h];if(g!==null&&g!==undefined){c.attr("value",g)}else{if(b!=""){c.attr("value",b)}else{c.attr("value","?")}}})})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-activ!
e").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text(k)}else{j=$("<input type='text'></input>").attr({value:k,size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){l.text(o);if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}$(document).ready(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus()});
\ No newline at end of file
+$(document).ready(function(){replace_big_select_inputs()});$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}function make_popupmen!
u(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id")+"-menu'></ul>");$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d)}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function array_length(b){if(b.length){return b.length}var c=0;for(var a in b){c++}return c}function replace_big_select_inputs(){$("select[name=dbkey]").each(function(){var a=$(this);if(a!
.find("option").length<20){return}var b=a.attr("value");var c=$("<inpu
t type='text' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",a.attr("name"));c.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var f=[];var e={};a.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}f.push(h);e[h]=g;e[g]=g;if(g==b){c.attr("value",h)}});if(c.attr("value")==""){c.attr("value","Click to Search or Select")}var d={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};c.autocomplete(f,d);a.replaceWith(c);c.parents("form").submit(function(){var h=c.attr("value");var g=e[h];if(g!==null&&g!==undefined){c.attr("value",g)}else{if(b!=""){c.attr("value",b)}else{c.attr("value","?")}}})})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-activ!
e").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text(k)}else{j=$("<input type='text'></input>").attr({value:k,size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){l.text(o);if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(c,a){var b=function(){try{var d=$.jStore.store("history_expand_state");if(d){for(var f in d){$("#"+f+" div.historyItemBody").show()}}}catch(e){$.jStore.remove("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}c.each(function(){var i=this.i!
d;var g=$(this).children("div.historyItemBody");var h=g.find("pre.peek
");$(this).children(".historyItemTitleBar").find(".historyItemTitle").wrap("<a href='#'></a>").click(function(){if(g.is(":visible")){if($.browser.mozilla){h.css("overflow","hidden")}g.slideUp("fast");if(!a){var j=$.jStore.store("history_expand_state");if(j){delete j[i];$.jStore.store("history_expand_state",j)}}}else{g.slideDown("fast",function(){if($.browser.mozilla){h.css("overflow","auto")}});if(!a){var j=$.jStore.store("history_expand_state");if(j===undefined){j={}}j[i]=true;$.jStore.store("history_expand_state",j)}}return false})});$("#top-links > a.toggle").click(function(){var g=$.jStore.store("history_expand_state");if(g===undefined){g={}}$("div.historyItemBody:visible").each(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(g){delete g[$(this).parent().attr("id")]}});$.jStore.store("history_expand_state",g)}).show()};if(a){b()}else{$.jStore.init("galaxy");$.jStore.engineReady(function(){b()})}}$(document).re!
ady(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus()});
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/jquery.jstore-all.js
--- a/static/scripts/packed/jquery.jstore-all.js Fri Apr 09 13:02:15 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(g){var f=this.prototype;a=true;var e=new this();a=false;for(var d in g){e[d]=typeof g[d]=="function"&&typeof f[d]=="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super;this._super=f[h];var j=i.apply(this,arguments);this._super=k;return j}})(d,g[d]):g[d]}function c(){if(!a&&this.init){this.init.apply(this,arguments)}}c.prototype=e;c.constructor=c;c.extend=arguments.callee;return c}})();(function(a){this.jStoreDelegate=Class.extend({init:function(b){this.parent=b;this.callbacks={}},bind:function(b,c){if(!a.isFunction(c)){return this}if(!this.callbacks[b]){this.callbacks[b]=[]}this.callbacks[b].push(c);return this},trigger:function(){var d=this.parent,c=[].slice.call(arguments),e=c.shift(),b=this.callbacks[e];if(!b){return false}a.each(b,function(){this.apply(d,c)});return this}})})(jQuery);(function(a){a.jStore={};a.extend(a.jStore,{Engi!
neOrder:[],Availability:{},Engines:{},Instances:{},CurrentEngine:null,defaults:{project:null,engine:null,autoload:true,flash:"jStore.Flash.html"},isReady:false,isFlashReady:false,delegate:new jStoreDelegate(a.jStore).bind("jStore-ready",function(b){a.jStore.isReady=true;if(a.jStore.defaults.autoload){b.connect()}}).bind("flash-ready",function(){a.jStore.isFlashReady=true})});a.jStore.ready=function(b){if(a.jStore.isReady){b.apply(a.jStore,[a.jStore.CurrentEngine])}else{a.jStore.delegate.bind("jStore-ready",b)}};a.jStore.fail=function(b){a.jStore.delegate.bind("jStore-failure",b)};a.jStore.flashReady=function(b){if(a.jStore.isFlashReady){b.apply(a.jStore,[a.jStore.CurrentEngine])}else{a.jStore.delegate.bind("flash-ready",b)}};a.jStore.use=function(d,g,c){g=g||a.jStore.defaults.project||location.hostname.replace(/\./g,"-")||"unknown";var f=a.jStore.Engines[d.toLowerCase()]||null,b=(c?c+".":"")+g+"."+d;if(!f){throw"JSTORE_ENGINE_UNDEFINED"}f=new f(g,b);if(a.jStore.Instances[b]!
){throw"JSTORE_JRI_CONFLICT"}if(f.isAvailable()){a.jStore.Instances[b]
=f;if(!a.jStore.CurrentEngine){a.jStore.CurrentEngine=f}a.jStore.delegate.trigger("jStore-ready",f)}else{if(!f.autoload){throw"JSTORE_ENGINE_UNAVILABLE"}else{f.included(function(){if(this.isAvailable()){a.jStore.Instances[b]=this;if(!a.jStore.CurrentEngine){a.jStore.CurrentEngine=this}a.jStore.delegate.trigger("jStore-ready",this)}else{a.jStore.delegate.trigger("jStore-failure",this)}}).include()}}};a.jStore.setCurrentEngine=function(b){if(!a.jStore.Instances.length){return a.jStore.FindEngine()}if(!b&&a.jStore.Instances.length>=1){a.jStore.delegate.trigger("jStore-ready",a.jStore.Instances[0]);return a.jStore.CurrentEngine=a.jStore.Instances[0]}if(b&&a.jStore.Instances[b]){a.jStore.delegate.trigger("jStore-ready",a.jStore.Instances[b]);return a.jStore.CurrentEngine=a.jStore.Instances[b]}throw"JSTORE_JRI_NO_MATCH"};a.jStore.FindEngine=function(){a.each(a.jStore.EngineOrder,function(b){if(a.jStore.Availability[this]()){a.jStore.use(this,a.jStore.defaults.project,"default");re!
turn false}})};a.jStore.store=function(b,c){if(!a.jStore.CurrentEngine){return false}if(!c){return a.jStore.CurrentEngine.get(b)}return a.jStore.CurrentEngine.set(b,c)};a.jStore.remove=function(b){if(!a.jStore.CurrentEngine){return false}return a.jStore.CurrentEngine.rem(b)};a.fn.store=function(c,d){if(!a.jStore.CurrentEngine){return this}var b=a.jStore.store(c,d);return !d?b:this};a.fn.removeStore=function(b){a.jStore.remove(b);return this};a.jStore.load=function(){if(a.jStore.defaults.engine){return a.jStore.use(a.jStore.defaults.engine,a.jStore.defaults.project,"default")}try{a.jStore.FindEngine()}catch(b){}}})(jQuery);(function(a){this.StorageEngine=Class.extend({init:function(c,b){this.project=c;this.jri=b;this.data={};this.limit=-1;this.includes=[];this.delegate=new jStoreDelegate(this).bind("engine-ready",function(){this.isReady=true}).bind("engine-included",function(){this.hasIncluded=true});this.autoload=false;this.isReady=false;this.hasIncluded=false},include:func!
tion(){var b=this,d=this.includes.length,c=0;a.each(this.includes,func
tion(){a.ajax({type:"get",url:this,dataType:"script",cache:true,success:function(){c++;if(c==d){b.delegate.trigger("engine-included")}}})})},isAvailable:function(){return false},ready:function(b){if(this.isReady){b.apply(this)}else{this.delegate.bind("engine-ready",b)}return this},included:function(b){if(this.hasIncluded){b.apply(this)}else{this.delegate.bind("engine-included",b)}return this},get:function(b){return this.data[b]||null},set:function(b,c){this.data[b]=c;return c},rem:function(b){var c=this.data[b];this.data[b]=null;return c}})})(jQuery);(function(c){var b=c.jStore.Availability.session=function(){return !!window.sessionStorage},a=c.jStore.Availability.local=function(){return !!(window.localStorage||window.globalStorage)};this.jStoreDom=StorageEngine.extend({init:function(e,d){this._super(e,d);this.type="DOM";this.limit=5*1024*1024},connect:function(){this.delegate.trigger("engine-ready")},get:function(e){var d=this.db.getItem(e);return d&&d.value?d.value:d},set:!
function(d,e){this.db.setItem(d,e);return e},rem:function(e){var d=this.get(e);this.db.removeItem(e);return d}});this.jStoreLocal=jStoreDom.extend({connect:function(){this.db=!window.globalStorage?window.localStorage:window.globalStorage[location.hostname];this._super()},isAvailable:a});this.jStoreSession=jStoreDom.extend({connect:function(){this.db=sessionStorage;this._super()},isAvailable:b});c.jStore.Engines.local=jStoreLocal;c.jStore.Engines.session=jStoreSession;c.jStore.EngineOrder[1]="local"})(jQuery);(function(b){var a=b.jStore.Availability.flash=function(){return !!(b.jStore.hasFlash("8.0.0"))};this.jStoreFlash=StorageEngine.extend({init:function(e,d){this._super(e,d);this.type="Flash";var c=this;b.jStore.flashReady(function(){c.flashReady()})},connect:function(){var c="jstore-flash-embed-"+this.project;b(document.body).append('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="'+b.jStore.defaults.flas!
h+'"></iframe>')},flashReady:function(f){var c=b("#jStoreFlashFrame")[
0];if(c.Document&&b.isFunction(c.Document.jStoreFlash.f_get_cookie)){this.db=c.Document.jStoreFlash}else{if(c.contentWindow&&c.contentWindow.document){var d=c.contentWindow.document;if(b.isFunction(b("object",b(d))[0].f_get_cookie)){this.db=b("object",b(d))[0]}else{if(b.isFunction(b("embed",b(d))[0].f_get_cookie)){this.db=b("embed",b(d))[0]}}}}if(this.db){this.delegate.trigger("engine-ready")}},isAvailable:a,get:function(d){var c=this.db.f_get_cookie(d);return c=="null"?null:c},set:function(c,d){this.db.f_set_cookie(c,d);return d},rem:function(c){var d=this.get(c);this.db.f_delete_cookie(c);return d}});b.jStore.Engines.flash=jStoreFlash;b.jStore.EngineOrder[2]="flash";b.jStore.hasFlash=function(c){var e=b.jStore.flashVersion().match(/\d+/g),f=c.match(/\d+/g);for(var d=0;d<3;d++){e[d]=parseInt(e[d]||0);f[d]=parseInt(f[d]||0);if(e[d]<f[d]){return false}if(e[d]>f[d]){return true}}return true};b.jStore.flashVersion=function(){try{try{var c=new ActiveXObject("ShockwaveFlash.Shock!
waveFlash.6");try{c.AllowScriptAccess="always"}catch(d){return"6,0,0"}}catch(d){}return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(d){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){return(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(d){}}return"0,0,0"}})(jQuery);function flash_ready(){$.jStore.delegate.trigger("flash-ready")}(function(b){var a=b.jStore.Availability.gears=function(){return !!(window.google&&window.google.gears)};this.jStoreGears=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="Google Gears";this.includes.push("http://code.google.com/apis/gears/gears_init.js");this.autoload=true},connect:function(){var c=this.db=google.gears.factory.create("beta.database");c.open("jstore-"+this.project);c.execute("CREATE TABLE IF NOT EXISTS jstore (k TEX!
T UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)");this.updateCache()},
updateCache:function(){var c=this.db.execute("SELECT k,v FROM jstore");while(c.isValidRow()){this.data[c.field(0)]=c.field(1);c.next()}c.close();this.delegate.trigger("engine-ready")},isAvailable:a,set:function(d,e){var c=this.db;c.execute("BEGIN");c.execute("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[d,e]);c.execute("COMMIT");return this._super(d,e)},rem:function(d){var c=this.db;c.execute("BEGIN");c.execute("DELETE FROM jstore WHERE k = ?",[d]);c.execute("COMMIT");return this._super(d)}});b.jStore.Engines.gears=jStoreGears;b.jStore.EngineOrder[3]="gears"})(jQuery);(function(b){var a=b.jStore.Availability.html5=function(){return !!window.openDatabase};this.jStoreHtml5=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="HTML5";this.limit=1024*200},connect:function(){var c=this.db=openDatabase("jstore-"+this.project,"1.0",this.project,this.limit);if(!c){throw"JSTORE_ENGINE_HTML5_NODB"}c.transaction(function(d){d.executeSql("CREATE TABLE IF NOT EXISTS!
jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)")});this.updateCache()},updateCache:function(){var c=this;this.db.transaction(function(d){d.executeSql("SELECT k,v FROM jstore",[],function(f,e){var h=e.rows,g=0,j;for(;g<h.length;++g){j=h.item(g);c.data[j.k]=j.v}c.delegate.trigger("engine-ready")})})},isAvailable:a,set:function(c,d){this.db.transaction(function(e){e.executeSql("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[c,d])});return this._super(c,d)},rem:function(c){this.db.transaction(function(d){d.executeSql("DELETE FROM jstore WHERE k = ?",[c])});return this._super(c)}});b.jStore.Engines.html5=jStoreHtml5;b.jStore.EngineOrder[0]="html5"})(jQuery);(function(b){var a=b.jStore.Availability.ie=function(){return !!window.ActiveXObject};this.jStoreIE=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="IE";this.limit=64*1024},connect:function(){this.db=b('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-'+this.proj!
ect+'"></div>').appendTo(document.body).get(0);this.delegate.trigger("
engine-ready")},isAvailable:a,get:function(c){this.db.load(this.project);return this.db.getAttribute(c)},set:function(c,d){this.db.setAttribute(c,d);this.db.save(this.project);return d},rem:function(c){var d=this.get(c);this.db.removeAttribute(c);this.db.save(this.project);return d}});b.jStore.Engines.ie=jStoreIE;b.jStore.EngineOrder[4]="ie"})(jQuery);
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/jquery.jstore.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/packed/jquery.jstore.js Fri Apr 09 18:09:54 2010 -0400
@@ -0,0 +1,17 @@
+/*
+ * jStore 2.0 - Persistent Client Side Storage
+ *
+ * Copyright (c) 2010 Eric Garside (http://eric.garside.name/)
+ * Dual licensed under:
+ * MIT: http://www.opensource.org/licenses/mit-license.php
+ * GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
+ *
+ * ---------------------------
+ *
+ * jStore Flash Storage Component
+ *
+ * Copyright (c) 2006 Jeff Lerman (jeff at blip.tv)
+ * Licensed under the Creative Commons Attribution 3.0 United States License:
+ * http://creativecommons.org/licenses/by/3.0/us
+ */
+"use strict";(function(i,n){var h="JSTORE_ENGINE_UNSTABLE",t="JSTORE_UNKNOWN_ENGINE_REQUESTED",r="JSTORE_ENGINE_NAMESPACE_COLLISION",j="JSTORE_RESOURCE_NAMESPACE_COLLISION",m="JSTORE_ENGINE_UNAVAILABLE",o="JSTORE_INVALID_FLAVOR",f=(function(){try{return new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$')}catch(I){return(/^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/)}}()),b="jstore-html5-local",y="jstore-html5-sql",F="jstore-flash",G="jstore-google-gears",A="jstore-msie",u,E={},D={},C={},c=false,d={},q={project:undefined,flash:"jStore.Flash.html",json:"browser.json.js"},l;function z(I){switch(I){case b:case y:case F:case G:case A:return true;default:return false}}function g(I,J){return !I?false:I.constructor.toString().match(new RegExp(J+"\\(\\)","i"))!==null}function s(K,I,J){if(g(K,"Function")){return K.apply(I||E,g(J,"Array")?J:[J])}}function p(J,I){i.ajax({url:J,complete:I||i.noop(),type:"GET",dataType:"script",cache:false})}fun!
ction x(I){if(I===undefined){return""}if(g(I,"Object")||g(I,"Array")||g(I,"Function")){return JSON.stringify(I)}return I}function k(I){return f.test(I)?JSON.parse(I):I}function w(I){return I.replace(/^\s+|\s+$/g,"")}function e(I,J,K){if(!z(I)){throw o}if(K[I]!==undefined){throw r}if(s(K)===true){E.available[I]=true;J.flavor=I;D[I]=u.extend(J)}else{E.available[I]=false;E.enginePriority=i.map(E.enginePriority,function(L){if(L===I){return null}else{return L}})}}function v(){if(E.isReady){return}if((c&&E.isFlashReady)||!c){E.isReady=true;E.trigger("jstore-ready",[C[l]])}}function a(){E.create(E.enginePriority[0],undefined,"best-fit")}function H(){try{var J=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");try{J.AllowScriptAccess="always"}catch(L){return"6,0,0"}return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(K){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){return(na!
vigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave F
lash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(I){}}return"0,0,0"}function B(I){var N=H().match(/\d+/g),L=I.match(/\d+/g),J=0,K,M;for(;J<3;J++){K=parseInt(N[J],10);M=parseInt(L[J],10);if(K<M){return false}else{if(K>M){return true}}}return true}i.extend(E,{enginePriority:[b,y,F,A],available:{},isReady:false,isFlashReady:false,flavors:{local:b,sql:y,flash:F,gears:G,msie:A},init:function(J,K,I){i.extend(q,{project:J},K);i(function(){if(n.JSON===undefined){p(q.json)}if(I!==undefined){E.create(I,J,"default")}else{a()}});return E},create:function(I,M,J){M=M||q.project||location.hostname.replace(/\./g,"-")||"unknown";if(!z(I)){throw o}if(D[I]===undefined){throw m}var L=(J!==undefined?J+".":"")+M+"."+I,K;if(C[L]!==undefined){throw j}K=C[L]=new D[I](M,L);K.ready(function(){E.trigger("jstore-engine-ready",[K])});if(I===F&&!E.isFlashReady){if(l===undefined){c=true}n.jstore_ready=function(){E.isFlashReady=true;E.trigger("flash-ready");if(l===undefined){v()}n.flash!
_ready=undefined};n.jstore_error=function(N){E.trigger("jstore-error",["JSTORE_FLASH_EXCEPTION",null,N])};i('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="'+q.flash+'"></iframe>').appendTo("body")}else{if(l===undefined){l=L;v()}}return K},engine:function(I){return C[I]},activeEngine:function(I){if(I!==undefined){if(C[I]===undefined){throw t}else{l=I}}return C[l]},bind:function(J,K,I){I=I||"jstore";if(d[I]===undefined){d[I]={}}if(d[I][J]===undefined){d[I][J]=[K]}else{d[I][J].push(K)}return E},trigger:function(K,J,I){I=I||"jstore";if(d[I]!==undefined){if(d[I][K]!==undefined){i.each(d[I][K],function(){s(this,E,J)})}}return E},error:function(I){E.bind("jstore-error",I)},ready:function(I){if(E.isReady){s(I)}else{E.bind("jstore-ready",I)}return E},engineReady:function(I){if(E.isReady){s(I)}else{E.bind("jstore-engine-ready",I)}return E},store:function(I,J){return J===undefined?E.get(I):E.set(I,J)},remove:function!
(I){return E.activeEngine().remove(I)},get:function(I){return E.active
Engine().get(I)},set:function(I,J){return E.activeEngine().set(I,J)}});u=Class.extend({project:undefined,jri:undefined,flavor:undefined,database:undefined,data:undefined,limit:undefined,isReady:undefined,init:function(J,I){this.project=J;this.jri=I;this.data={};this.isReady=false;this.updateCache()},updateCache:function(){this.isReady=true;this.trigger("engine-ready",[this])},bind:function(I,J){E.bind(I,J,this.jri)},trigger:function(J,I){E.trigger(J,I,this.jri)},ready:function(I){if(this.isReady){s(I,this)}else{this.bind("engine-ready",I)}},get:function(I){this.__interruptAccess();return this.data[I]},set:function(I,J){this.__interruptAccess();I=w(I);try{this.__set(I,J)}catch(K){E.trigger("jstore-error",["JSTORE_STORAGE_FAILURE",this.jri,K])}this.data[I]=J;return J},remove:function(J){this.__interruptAccess();J=w(J);try{this.__remove(J)}catch(K){E.trigger("jstore-error",["JSTORE_REMOVE_FAILURE",this.jri,K])}var I=this.data[J];this.data[J]=undefined;return I},__interruptAcces!
s:function(){if(!this.isReady){throw h}},__set:function(I,J){return},__remove:function(I){return}});i.extend(i.fn,{store:function(I,J){if(J===undefined){E.get(I)}else{E.set(I,J)}return this},removeStore:function(I){E.activeEngine().remove(I);return this},getStore:function(I){return E.activeEngine().get(I)},setStore:function(I,J){E.activeEngine().set(I,J);return this}});n.jStore=i.jStore=E;e(b,{limit:parseInt(500000,16),init:function(J,I){this.database=n.globalStorage===undefined?n.localStorage:n.globalStorage[location.hostname];this._super(J,I)},updateCache:function(){var J,K;for(J in this.database){var I=false;if(this.database.hasOwnProperty){if(this.database.hasOwnProperty(J)){I=true}}else{if(this.database.getItem(J)!==null){I=true}}if(I){K=this.database.getItem(J);this.data[J]=k(K&&K.value?K.value:K)}}this._super()},__set:function(I,J){this.database.setItem(I,x(J))},__remove:function(I){this.database.removeItem(I)}},function(){return n.localStorage!==undefined||n.globalS!
torage!==undefined});e(y,{limit:parseInt(32000,16),init:function(J,I){
this.database=n.openDatabase("jstore-"+J,"1.0",J,this.limit);if(!this.database){throw"JSTORE_SQL_NO_DB"}this.database.transaction(function(K){K.executeSql("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)")});this._super(J,I)},updateCache:function(){var I=this,J=this._super;this.database.transaction(function(K){K.executeSql("SELECT k,v FROM jstore",[],function(O,L){var N=L.rows,M=0,P;for(;M<N.length;++M){P=N.item(M);I.data[P.k]=k(P.v)}J.apply(I)})})},__set:function(I,J){this.database.transaction(function(K){K.executeSql("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[I,x(J)])})},__remove:function(I){this.database.transaction(function(J){J.executeSql("DELETE FROM jstore WHERE k = ?",[I])})}},function(){return n.openDatabase!==undefined});e(F,{limit:-1,init:function(K,J){var I=this;E.bind("flash-ready",function(){I.__flashReadyListener()});this._super(K,J)},updateCache:function(I){if(I===true){var J,K=this.database.jstore_get_all();f!
or(J in K){if(K.hasOwnProperty(J)){this.data[J]=k(this.database.jstore_get(J))}}this._super()}},__set:function(I,J){if(!this.database.jstore_set(I,x(J))){E.trigger("jstore-error",["JSTORE_STORAGE_FAILURE",this.jri,"Flash Exception"])}},__remove:function(I){this.database.jstore_remove(I)},__flashReadyListener:function(){var I=i("#jStoreFlashFrame")[0],J;if(I.Document!==undefined&&g(I.Document.jStoreFlash.jstore_get,"Function")){this.database=I.Document.jStoreFlash}else{if(I.contentWindow&&I.contentWindow.document){J=i(I.contentWindow.document);if(g(i("object",J)[0].jstore_get,"Function")){this.database=i("object",J)[0]}else{if(g(i("embed",J)[0].jstore_get,"Function")){this.database=i("embed",J)[0]}}}}if(this.database===undefined){throw"JSTORE_FLASH_REFERENCE_ISSUE"}else{this.updateCache(true)}}},function(){return B("9.0.0")});e(G,{limit:-1,init:function(J,I){this.database=google.gears.factory.create("beta.database");this.database.open("jstore-"+J);this.database.execute("CREA!
TE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v T
EXT NOT NULL)");this._super(J,I)},updateCache:function(){var I=this.database.execute("SELECT k,v FROM jstore");while(I.isValidRow()){this.data[I.field(0)]=k(I.field(1));I.next()}I.close();this._super()},__set:function(I,J){this.database.execute("BEGIN");this.database.execute("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[I,x(J)]);this.database.execute("COMMIT")},__remove:function(I){this.database.execute("BEGIN");this.database.execute("DELETE FROM jstore WHERE k = ?",[I]);this.database.execute("COMMIT")}},function(){return n.google!==undefined&&n.google.gears!==undefined});e(A,{limit:parseInt(10000,16),init:function(J,I){this.database=i('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-'+J+'"></div>').appendTo(document.body).get(0);this._super(J,I)},updateCache:function(){this.database.load(this.project);var K=document.getElementById("jstore-"+this.project),L=K.XMLDocument,I,J=0;if(L&&L.documentElement&&L.documentElement.attributes){I=L.document!
Element;for(;J<I.attributes.length;++J){this.data[I.attributes.item(J).nodeName]=k(I.attributes.item(J).nodeValue)}}this._super()},__set:function(I,J){this.database.setAttribute(I,x(J));this.database.save(this.project)},__remove:function(I){this.database.removeAttribute(I);this.database.save(this.project)}},function(){return n.ActiveXObject!==undefined})}(jQuery,window));
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 static/scripts/packed/json2.js
--- a/static/scripts/packed/json2.js Fri Apr 09 13:02:15 2010 -0400
+++ b/static/scripts/packed/json2.js Fri Apr 09 18:09:54 2010 -0400
@@ -1,1 +1,1 @@
-var JSON=JSON||{};(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0!
).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=st!
r(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.
length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test!
(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());
\ No newline at end of file
+if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.ch!
arCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(valu!
e,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}
v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-!
4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());
\ No newline at end of file
diff -r a9402fc7ce1b -r 5536d57237a3 templates/display_base.mako
--- a/templates/display_base.mako Fri Apr 09 13:02:15 2010 -0400
+++ b/templates/display_base.mako Fri Apr 09 18:09:54 2010 -0400
@@ -32,29 +32,25 @@
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "jquery", "jquery.tipsy", "galaxy.base", "json2", "jquery.autocomplete", "jquery.jstore-all", "autocomplete_tagging" )}
+ ${h.js( "jquery", "jquery.tipsy", "galaxy.base", "json2", "class", "jquery.jstore", "jquery.autocomplete", "autocomplete_tagging" )}
<script type="text/javascript">
- //
+
// Handle click on community tag.
- //
- function community_tag_click(tag_name, tag_value)
- {
+ function community_tag_click(tag_name, tag_value) {
<% controller_name = get_controller_name( item ) %>
var href = '${h.url_for ( controller='/' + controller_name , action='list_published')}';
href = href + "?f-tags=" + tag_name;
- if (tag_value != undefined && tag_value != "")
+ if (tag_value != undefined && tag_value != "") {
href = href + ":" + tag_value;
+ }
self.location = href;
}
- $(document).ready( function()
- {
+ $(function() {
// Set links to Galaxy screencasts to open in overlay.
- $(this).find("a[href^='http://screencast.g2.bx.psu.edu/']").each( function()
- {
- $(this).click( function()
- {
+ $(this).find("a[href^='http://screencast.g2.bx.psu.edu/']").each( function() {
+ $(this).click( function() {
var href = $(this).attr('href');
show_in_overlay(
{
@@ -67,7 +63,8 @@
return false;
});
});
-
+ // Init history boxes
+ init_history_items( $("div.historyItemWrapper") );
});
</script>
</%def>
@@ -76,14 +73,12 @@
${parent.stylesheets()}
${h.css( "autocomplete_tagging", "embed_item" )}
<style type="text/css">
- .page-body
- {
+ .page-body {
padding: 10px;
## float: left;
## width: 65%;
}
- .page-meta
- {
+ .page-meta {
float: right;
width: 27%;
padding: 0.5em;
diff -r a9402fc7ce1b -r 5536d57237a3 templates/history/display.mako
--- a/templates/history/display.mako Fri Apr 09 13:02:15 2010 -0400
+++ b/templates/history/display.mako Fri Apr 09 18:09:54 2010 -0400
@@ -1,207 +1,14 @@
<%inherit file="/display_base.mako"/>
<%namespace file="/root/history_common.mako" import="render_dataset" />
+## Set vars so that there's no need to change the code below.
+<%
+ history = published_item
+ datasets = published_item_data
+%>
+
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "jquery.jstore-all" )}
-
- ## Set vars so that there's no need to change the code below.
- <%
- history = published_item
- datasets = published_item_data
- %>
-
- <script type="text/javascript">
- $(function() {
- // Load jStore for local storage
- $.extend(jQuery.jStore.defaults, { project: 'galaxy', flash: '/static/jStore.Flash.html' })
- $.jStore.load(); // Auto-select best storage
More information about the galaxy-dev
mailing list