mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Replaced jStorage with store
This commit is contained in:
@@ -29,6 +29,7 @@ export { create_chart, create_histogram } from "reports/run_stats";
|
||||
export { default as ToolshedGroups } from "toolshed/toolshed.groups";
|
||||
|
||||
export { chart, chartUtilities } from "./chart";
|
||||
export { default as store } from "store";
|
||||
|
||||
// TODO: update this when galaxy singleton code is merged
|
||||
if (window.Galaxy && window.Galaxy.debug === undefined) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import _l from "utils/localization";
|
||||
import "libs/jquery/jquery.form";
|
||||
import "libs/jquery/jstorage";
|
||||
import "libs/jquery/jquery.wymeditor";
|
||||
import "libs/jquery/jquery.autocomplete";
|
||||
import GridView from "mvc/grid/grid-view";
|
||||
|
||||
@@ -14,7 +14,6 @@ require("imports-loader?jQuery=jqueryVendor!libs/jquery/jquery.form");
|
||||
require("imports-loader?jQuery=jqueryVendor!libs/jquery/jquery.rating");
|
||||
require("imports-loader?jQuery=jqueryVendor!libs/jquery/select2");
|
||||
require("imports-loader?jQuery=jqueryVendor!libs/jquery/jquery-ui");
|
||||
require("imports-loader?jQuery=jqueryVendor!libs/jquery/jstorage");
|
||||
require("imports-loader?jQuery=jqueryVendor!libs/farbtastic");
|
||||
require("imports-loader?jQuery=jqueryVendor,$=jqueryVendor,define=>false!jquery.cookie");
|
||||
require("imports-loader?jQuery=jqueryVendor!libs/jquery/jquery.dynatree");
|
||||
|
||||
-933
@@ -1,933 +0,0 @@
|
||||
/*
|
||||
* ----------------------------- JSTORAGE -------------------------------------
|
||||
* Simple local storage wrapper to save data on the browser side, supporting
|
||||
* all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+
|
||||
*
|
||||
* Copyright (c) 2010 - 2012 Andris Reinman, andris.reinman@gmail.com
|
||||
* Project homepage: www.jstorage.info
|
||||
*
|
||||
* Licensed under MIT-style license:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
(function(){
|
||||
var
|
||||
/* jStorage version */
|
||||
JSTORAGE_VERSION = "0.4.4",
|
||||
|
||||
/* detect a dollar object or create one if not found */
|
||||
$ = window.jQuery || window.$ || (window.$ = {}),
|
||||
|
||||
/* check for a JSON handling support */
|
||||
JSON = {
|
||||
parse:
|
||||
window.JSON && (window.JSON.parse || window.JSON.decode) ||
|
||||
String.prototype.evalJSON && function(str){return String(str).evalJSON();} ||
|
||||
$.parseJSON ||
|
||||
$.evalJSON,
|
||||
stringify:
|
||||
Object.toJSON ||
|
||||
window.JSON && (window.JSON.stringify || window.JSON.encode) ||
|
||||
$.toJSON
|
||||
};
|
||||
|
||||
// Break if no JSON support was found
|
||||
if(!('parse' in JSON) || !('stringify' in JSON)){
|
||||
throw new Error("No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page");
|
||||
}
|
||||
|
||||
var
|
||||
/* This is the object, that holds the cached values */
|
||||
_storage = {__jstorage_meta:{CRC32:{}}},
|
||||
|
||||
/* Actual browser storage (localStorage or globalStorage['domain']) */
|
||||
_storage_service = {jStorage:"{}"},
|
||||
|
||||
/* DOM element for older IE versions, holds userData behavior */
|
||||
_storage_elm = null,
|
||||
|
||||
/* How much space does the storage take */
|
||||
_storage_size = 0,
|
||||
|
||||
/* which backend is currently used */
|
||||
_backend = false,
|
||||
|
||||
/* onchange observers */
|
||||
_observers = {},
|
||||
|
||||
/* timeout to wait after onchange event */
|
||||
_observer_timeout = false,
|
||||
|
||||
/* last update time */
|
||||
_observer_update = 0,
|
||||
|
||||
/* pubsub observers */
|
||||
_pubsub_observers = {},
|
||||
|
||||
/* skip published items older than current timestamp */
|
||||
_pubsub_last = +new Date(),
|
||||
|
||||
/* Next check for TTL */
|
||||
_ttl_timeout,
|
||||
|
||||
/**
|
||||
* XML encoding and decoding as XML nodes can't be JSON'ized
|
||||
* XML nodes are encoded and decoded if the node is the value to be saved
|
||||
* but not if it's as a property of another object
|
||||
* Eg. -
|
||||
* $.jStorage.set("key", xmlNode); // IS OK
|
||||
* $.jStorage.set("key", {xml: xmlNode}); // NOT OK
|
||||
*/
|
||||
_XMLService = {
|
||||
|
||||
/**
|
||||
* Validates a XML node to be XML
|
||||
* based on jQuery.isXML function
|
||||
*/
|
||||
isXML: function(elm){
|
||||
var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement;
|
||||
return documentElement ? documentElement.nodeName !== "HTML" : false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Encodes a XML node to string
|
||||
* based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/
|
||||
*/
|
||||
encode: function(xmlNode) {
|
||||
if(!this.isXML(xmlNode)){
|
||||
return false;
|
||||
}
|
||||
try{ // Mozilla, Webkit, Opera
|
||||
return new XMLSerializer().serializeToString(xmlNode);
|
||||
}catch(E1) {
|
||||
try { // IE
|
||||
return xmlNode.xml;
|
||||
}catch(E2){}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Decodes a XML node from string
|
||||
* loosely based on http://outwestmedia.com/jquery-plugins/xmldom/
|
||||
*/
|
||||
decode: function(xmlString){
|
||||
var dom_parser = ("DOMParser" in window && (new DOMParser()).parseFromString) ||
|
||||
(window.ActiveXObject && function(_xmlString) {
|
||||
var xml_doc = new ActiveXObject('Microsoft.XMLDOM');
|
||||
xml_doc.async = 'false';
|
||||
xml_doc.loadXML(_xmlString);
|
||||
return xml_doc;
|
||||
}),
|
||||
resultXML;
|
||||
if(!dom_parser){
|
||||
return false;
|
||||
}
|
||||
resultXML = dom_parser.call("DOMParser" in window && (new DOMParser()) || window, xmlString, 'text/xml');
|
||||
return this.isXML(resultXML)?resultXML:false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
////////////////////////// PRIVATE METHODS ////////////////////////
|
||||
|
||||
/**
|
||||
* Initialization function. Detects if the browser supports DOM Storage
|
||||
* or userData behavior and behaves accordingly.
|
||||
*/
|
||||
function _init(){
|
||||
/* Check if browser supports localStorage */
|
||||
var localStorageReallyWorks = false;
|
||||
if("localStorage" in window){
|
||||
try {
|
||||
window.localStorage.setItem('_tmptest', 'tmpval');
|
||||
localStorageReallyWorks = true;
|
||||
window.localStorage.removeItem('_tmptest');
|
||||
} catch(BogusQuotaExceededErrorOnIos5) {
|
||||
// Thanks be to iOS5 Private Browsing mode which throws
|
||||
// QUOTA_EXCEEDED_ERRROR DOM Exception 22.
|
||||
}
|
||||
}
|
||||
|
||||
if(localStorageReallyWorks){
|
||||
try {
|
||||
if(window.localStorage) {
|
||||
_storage_service = window.localStorage;
|
||||
_backend = "localStorage";
|
||||
_observer_update = _storage_service.jStorage_update;
|
||||
}
|
||||
} catch(E3) {/* Firefox fails when touching localStorage and cookies are disabled */}
|
||||
}
|
||||
/* Check if browser supports globalStorage */
|
||||
else if("globalStorage" in window){
|
||||
try {
|
||||
if(window.globalStorage) {
|
||||
if(window.location.hostname == 'localhost'){
|
||||
_storage_service = window.globalStorage['localhost.localdomain'];
|
||||
}
|
||||
else{
|
||||
_storage_service = window.globalStorage[window.location.hostname];
|
||||
}
|
||||
_backend = "globalStorage";
|
||||
_observer_update = _storage_service.jStorage_update;
|
||||
}
|
||||
} catch(E4) {/* Firefox fails when touching localStorage and cookies are disabled */}
|
||||
}
|
||||
/* Check if browser supports userData behavior */
|
||||
else {
|
||||
_storage_elm = document.createElement('link');
|
||||
if(_storage_elm.addBehavior){
|
||||
|
||||
/* Use a DOM element to act as userData storage */
|
||||
_storage_elm.style.behavior = 'url(#default#userData)';
|
||||
|
||||
/* userData element needs to be inserted into the DOM! */
|
||||
document.getElementsByTagName('head')[0].appendChild(_storage_elm);
|
||||
|
||||
try{
|
||||
_storage_elm.load("jStorage");
|
||||
}catch(E){
|
||||
// try to reset cache
|
||||
_storage_elm.setAttribute("jStorage", "{}");
|
||||
_storage_elm.save("jStorage");
|
||||
_storage_elm.load("jStorage");
|
||||
}
|
||||
|
||||
var data = "{}";
|
||||
try{
|
||||
data = _storage_elm.getAttribute("jStorage");
|
||||
}catch(E5){}
|
||||
|
||||
try{
|
||||
_observer_update = _storage_elm.getAttribute("jStorage_update");
|
||||
}catch(E6){}
|
||||
|
||||
_storage_service.jStorage = data;
|
||||
_backend = "userDataBehavior";
|
||||
}else{
|
||||
_storage_elm = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Load data from storage
|
||||
_load_storage();
|
||||
|
||||
// remove dead keys
|
||||
_handleTTL();
|
||||
|
||||
// start listening for changes
|
||||
_setupObserver();
|
||||
|
||||
// initialize publish-subscribe service
|
||||
_handlePubSub();
|
||||
|
||||
// handle cached navigation
|
||||
if("addEventListener" in window){
|
||||
window.addEventListener("pageshow", function(event){
|
||||
if(event.persisted){
|
||||
_storageObserver();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload data from storage when needed
|
||||
*/
|
||||
function _reloadData(){
|
||||
var data = "{}";
|
||||
|
||||
if(_backend == "userDataBehavior"){
|
||||
_storage_elm.load("jStorage");
|
||||
|
||||
try{
|
||||
data = _storage_elm.getAttribute("jStorage");
|
||||
}catch(E5){}
|
||||
|
||||
try{
|
||||
_observer_update = _storage_elm.getAttribute("jStorage_update");
|
||||
}catch(E6){}
|
||||
|
||||
_storage_service.jStorage = data;
|
||||
}
|
||||
|
||||
_load_storage();
|
||||
|
||||
// remove dead keys
|
||||
_handleTTL();
|
||||
|
||||
_handlePubSub();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a storage change observer
|
||||
*/
|
||||
function _setupObserver(){
|
||||
if(_backend == "localStorage" || _backend == "globalStorage"){
|
||||
if("addEventListener" in window){
|
||||
window.addEventListener("storage", _storageObserver, false);
|
||||
}else{
|
||||
document.attachEvent("onstorage", _storageObserver);
|
||||
}
|
||||
}else if(_backend == "userDataBehavior"){
|
||||
setInterval(_storageObserver, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired on any kind of data change, needs to check if anything has
|
||||
* really been changed
|
||||
*/
|
||||
function _storageObserver(){
|
||||
var updateTime;
|
||||
// cumulate change notifications with timeout
|
||||
clearTimeout(_observer_timeout);
|
||||
_observer_timeout = setTimeout(function(){
|
||||
|
||||
if(_backend == "localStorage" || _backend == "globalStorage"){
|
||||
updateTime = _storage_service.jStorage_update;
|
||||
}else if(_backend == "userDataBehavior"){
|
||||
_storage_elm.load("jStorage");
|
||||
try{
|
||||
updateTime = _storage_elm.getAttribute("jStorage_update");
|
||||
}catch(E5){}
|
||||
}
|
||||
|
||||
if(updateTime && updateTime != _observer_update){
|
||||
_observer_update = updateTime;
|
||||
_checkUpdatedKeys();
|
||||
}
|
||||
|
||||
}, 25);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the data and checks if any keys are changed
|
||||
*/
|
||||
function _checkUpdatedKeys(){
|
||||
var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)),
|
||||
newCrc32List;
|
||||
|
||||
_reloadData();
|
||||
newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32));
|
||||
|
||||
var key,
|
||||
updated = [],
|
||||
removed = [];
|
||||
|
||||
for(key in oldCrc32List){
|
||||
if(oldCrc32List.hasOwnProperty(key)){
|
||||
if(!newCrc32List[key]){
|
||||
removed.push(key);
|
||||
continue;
|
||||
}
|
||||
if(oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0,2) == "2."){
|
||||
updated.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(key in newCrc32List){
|
||||
if(newCrc32List.hasOwnProperty(key)){
|
||||
if(!oldCrc32List[key]){
|
||||
updated.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_fireObservers(updated, "updated");
|
||||
_fireObservers(removed, "deleted");
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires observers for updated keys
|
||||
*
|
||||
* @param {Array|String} keys Array of key names or a key
|
||||
* @param {String} action What happened with the value (updated, deleted, flushed)
|
||||
*/
|
||||
function _fireObservers(keys, action){
|
||||
keys = [].concat(keys || []);
|
||||
if(action == "flushed"){
|
||||
keys = [];
|
||||
for(var key in _observers){
|
||||
if(_observers.hasOwnProperty(key)){
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
action = "deleted";
|
||||
}
|
||||
for(var i=0, len = keys.length; i<len; i++){
|
||||
if(_observers[keys[i]]){
|
||||
for(var j=0, jlen = _observers[keys[i]].length; j<jlen; j++){
|
||||
_observers[keys[i]][j](keys[i], action);
|
||||
}
|
||||
}
|
||||
if(_observers["*"]){
|
||||
for(var j=0, jlen = _observers["*"].length; j<jlen; j++){
|
||||
_observers["*"][j](keys[i], action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes key change to listeners
|
||||
*/
|
||||
function _publishChange(){
|
||||
var updateTime = (+new Date()).toString();
|
||||
|
||||
if(_backend == "localStorage" || _backend == "globalStorage"){
|
||||
try {
|
||||
_storage_service.jStorage_update = updateTime;
|
||||
} catch (E8) {
|
||||
// safari private mode has been enabled after the jStorage initialization
|
||||
_backend = false;
|
||||
}
|
||||
}else if(_backend == "userDataBehavior"){
|
||||
_storage_elm.setAttribute("jStorage_update", updateTime);
|
||||
_storage_elm.save("jStorage");
|
||||
}
|
||||
|
||||
_storageObserver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the data from the storage based on the supported mechanism
|
||||
*/
|
||||
function _load_storage(){
|
||||
/* if jStorage string is retrieved, then decode it */
|
||||
if(_storage_service.jStorage){
|
||||
try{
|
||||
_storage = JSON.parse(String(_storage_service.jStorage));
|
||||
}catch(E6){_storage_service.jStorage = "{}";}
|
||||
}else{
|
||||
_storage_service.jStorage = "{}";
|
||||
}
|
||||
_storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
|
||||
|
||||
if(!_storage.__jstorage_meta){
|
||||
_storage.__jstorage_meta = {};
|
||||
}
|
||||
if(!_storage.__jstorage_meta.CRC32){
|
||||
_storage.__jstorage_meta.CRC32 = {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This functions provides the "save" mechanism to store the jStorage object
|
||||
*/
|
||||
function _save(){
|
||||
_dropOldEvents(); // remove expired events
|
||||
try{
|
||||
_storage_service.jStorage = JSON.stringify(_storage);
|
||||
// If userData is used as the storage engine, additional
|
||||
if(_storage_elm) {
|
||||
_storage_elm.setAttribute("jStorage",_storage_service.jStorage);
|
||||
_storage_elm.save("jStorage");
|
||||
}
|
||||
_storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
|
||||
}catch(E7){/* probably cache is full, nothing is saved this way*/}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function checks if a key is set and is string or numberic
|
||||
*
|
||||
* @param {String} key Key name
|
||||
*/
|
||||
function _checkKey(key){
|
||||
if(!key || (typeof key != "string" && typeof key != "number")){
|
||||
throw new TypeError('Key name must be string or numeric');
|
||||
}
|
||||
if(key == "__jstorage_meta"){
|
||||
throw new TypeError('Reserved key name');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes expired keys
|
||||
*/
|
||||
function _handleTTL(){
|
||||
var curtime, i, TTL, CRC32, nextExpire = Infinity, changed = false, deleted = [];
|
||||
|
||||
clearTimeout(_ttl_timeout);
|
||||
|
||||
if(!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != "object"){
|
||||
// nothing to do here
|
||||
return;
|
||||
}
|
||||
|
||||
curtime = +new Date();
|
||||
TTL = _storage.__jstorage_meta.TTL;
|
||||
|
||||
CRC32 = _storage.__jstorage_meta.CRC32;
|
||||
for(i in TTL){
|
||||
if(TTL.hasOwnProperty(i)){
|
||||
if(TTL[i] <= curtime){
|
||||
delete TTL[i];
|
||||
delete CRC32[i];
|
||||
delete _storage[i];
|
||||
changed = true;
|
||||
deleted.push(i);
|
||||
}else if(TTL[i] < nextExpire){
|
||||
nextExpire = TTL[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set next check
|
||||
if(nextExpire != Infinity){
|
||||
_ttl_timeout = setTimeout(_handleTTL, nextExpire - curtime);
|
||||
}
|
||||
|
||||
// save changes
|
||||
if(changed){
|
||||
_save();
|
||||
_publishChange();
|
||||
_fireObservers(deleted, "deleted");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there's any events on hold to be fired to listeners
|
||||
*/
|
||||
function _handlePubSub(){
|
||||
var i, len;
|
||||
if(!_storage.__jstorage_meta.PubSub){
|
||||
return;
|
||||
}
|
||||
var pubelm,
|
||||
_pubsubCurrent = _pubsub_last;
|
||||
|
||||
for(i=len=_storage.__jstorage_meta.PubSub.length-1; i>=0; i--){
|
||||
pubelm = _storage.__jstorage_meta.PubSub[i];
|
||||
if(pubelm[0] > _pubsub_last){
|
||||
_pubsubCurrent = pubelm[0];
|
||||
_fireSubscribers(pubelm[1], pubelm[2]);
|
||||
}
|
||||
}
|
||||
|
||||
_pubsub_last = _pubsubCurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires all subscriber listeners for a pubsub channel
|
||||
*
|
||||
* @param {String} channel Channel name
|
||||
* @param {Mixed} payload Payload data to deliver
|
||||
*/
|
||||
function _fireSubscribers(channel, payload){
|
||||
if(_pubsub_observers[channel]){
|
||||
for(var i=0, len = _pubsub_observers[channel].length; i<len; i++){
|
||||
// send immutable data that can't be modified by listeners
|
||||
_pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove old events from the publish stream (at least 2sec old)
|
||||
*/
|
||||
function _dropOldEvents(){
|
||||
if(!_storage.__jstorage_meta.PubSub){
|
||||
return;
|
||||
}
|
||||
|
||||
var retire = +new Date() - 2000;
|
||||
|
||||
for(var i=0, len = _storage.__jstorage_meta.PubSub.length; i<len; i++){
|
||||
if(_storage.__jstorage_meta.PubSub[i][0] <= retire){
|
||||
// deleteCount is needed for IE6
|
||||
_storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!_storage.__jstorage_meta.PubSub.length){
|
||||
delete _storage.__jstorage_meta.PubSub;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish payload to a channel
|
||||
*
|
||||
* @param {String} channel Channel name
|
||||
* @param {Mixed} payload Payload to send to the subscribers
|
||||
*/
|
||||
function _publish(channel, payload){
|
||||
if(!_storage.__jstorage_meta){
|
||||
_storage.__jstorage_meta = {};
|
||||
}
|
||||
if(!_storage.__jstorage_meta.PubSub){
|
||||
_storage.__jstorage_meta.PubSub = [];
|
||||
}
|
||||
|
||||
_storage.__jstorage_meta.PubSub.unshift([+new Date, channel, payload]);
|
||||
|
||||
_save();
|
||||
_publishChange();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* JS Implementation of MurmurHash2
|
||||
*
|
||||
* SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed)
|
||||
*
|
||||
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
|
||||
* @see http://github.com/garycourt/murmurhash-js
|
||||
* @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
|
||||
* @see http://sites.google.com/site/murmurhash/
|
||||
*
|
||||
* @param {string} str ASCII only
|
||||
* @param {number} seed Positive integer only
|
||||
* @return {number} 32-bit positive integer hash
|
||||
*/
|
||||
|
||||
function murmurhash2_32_gc(str, seed) {
|
||||
var
|
||||
l = str.length,
|
||||
h = seed ^ l,
|
||||
i = 0,
|
||||
k;
|
||||
|
||||
while (l >= 4) {
|
||||
k =
|
||||
((str.charCodeAt(i) & 0xff)) |
|
||||
((str.charCodeAt(++i) & 0xff) << 8) |
|
||||
((str.charCodeAt(++i) & 0xff) << 16) |
|
||||
((str.charCodeAt(++i) & 0xff) << 24);
|
||||
|
||||
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
|
||||
k ^= k >>> 24;
|
||||
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
|
||||
|
||||
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
|
||||
|
||||
l -= 4;
|
||||
++i;
|
||||
}
|
||||
|
||||
switch (l) {
|
||||
case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
|
||||
case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
|
||||
case 1: h ^= (str.charCodeAt(i) & 0xff);
|
||||
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
|
||||
}
|
||||
|
||||
h ^= h >>> 13;
|
||||
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
|
||||
h ^= h >>> 15;
|
||||
|
||||
return h >>> 0;
|
||||
}
|
||||
|
||||
////////////////////////// PUBLIC INTERFACE /////////////////////////
|
||||
|
||||
$.jStorage = {
|
||||
/* Version number */
|
||||
version: JSTORAGE_VERSION,
|
||||
|
||||
/**
|
||||
* Sets a key's value.
|
||||
*
|
||||
* @param {String} key Key to set. If this value is not set or not
|
||||
* a string an exception is raised.
|
||||
* @param {Mixed} value Value to set. This can be any value that is JSON
|
||||
* compatible (Numbers, Strings, Objects etc.).
|
||||
* @param {Object} [options] - possible options to use
|
||||
* @param {Number} [options.TTL] - optional TTL value
|
||||
* @return {Mixed} the used value
|
||||
*/
|
||||
set: function(key, value, options){
|
||||
_checkKey(key);
|
||||
|
||||
options = options || {};
|
||||
|
||||
// undefined values are deleted automatically
|
||||
if(typeof value == "undefined"){
|
||||
this.deleteKey(key);
|
||||
return value;
|
||||
}
|
||||
|
||||
if(_XMLService.isXML(value)){
|
||||
value = {_is_xml:true,xml:_XMLService.encode(value)};
|
||||
}else if(typeof value == "function"){
|
||||
return undefined; // functions can't be saved!
|
||||
}else if(value && typeof value == "object"){
|
||||
// clone the object before saving to _storage tree
|
||||
value = JSON.parse(JSON.stringify(value));
|
||||
}
|
||||
|
||||
_storage[key] = value;
|
||||
|
||||
_storage.__jstorage_meta.CRC32[key] = "2." + murmurhash2_32_gc(JSON.stringify(value), 0x9747b28c);
|
||||
|
||||
this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange
|
||||
|
||||
_fireObservers(key, "updated");
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Looks up a key in cache
|
||||
*
|
||||
* @param {String} key - Key to look up.
|
||||
* @param {mixed} def - Default value to return, if key didn't exist.
|
||||
* @return {Mixed} the key value, default value or null
|
||||
*/
|
||||
get: function(key, def){
|
||||
_checkKey(key);
|
||||
if(key in _storage){
|
||||
if(_storage[key] && typeof _storage[key] == "object" && _storage[key]._is_xml) {
|
||||
return _XMLService.decode(_storage[key].xml);
|
||||
}else{
|
||||
return _storage[key];
|
||||
}
|
||||
}
|
||||
return typeof(def) == 'undefined' ? null : def;
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes a key from cache.
|
||||
*
|
||||
* @param {String} key - Key to delete.
|
||||
* @return {Boolean} true if key existed or false if it didn't
|
||||
*/
|
||||
deleteKey: function(key){
|
||||
_checkKey(key);
|
||||
if(key in _storage){
|
||||
delete _storage[key];
|
||||
// remove from TTL list
|
||||
if(typeof _storage.__jstorage_meta.TTL == "object" &&
|
||||
key in _storage.__jstorage_meta.TTL){
|
||||
delete _storage.__jstorage_meta.TTL[key];
|
||||
}
|
||||
|
||||
delete _storage.__jstorage_meta.CRC32[key];
|
||||
|
||||
_save();
|
||||
_publishChange();
|
||||
_fireObservers(key, "deleted");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a TTL for a key, or remove it if ttl value is 0 or below
|
||||
*
|
||||
* @param {String} key - key to set the TTL for
|
||||
* @param {Number} ttl - TTL timeout in milliseconds
|
||||
* @return {Boolean} true if key existed or false if it didn't
|
||||
*/
|
||||
setTTL: function(key, ttl){
|
||||
var curtime = +new Date();
|
||||
_checkKey(key);
|
||||
ttl = Number(ttl) || 0;
|
||||
if(key in _storage){
|
||||
|
||||
if(!_storage.__jstorage_meta.TTL){
|
||||
_storage.__jstorage_meta.TTL = {};
|
||||
}
|
||||
|
||||
// Set TTL value for the key
|
||||
if(ttl>0){
|
||||
_storage.__jstorage_meta.TTL[key] = curtime + ttl;
|
||||
}else{
|
||||
delete _storage.__jstorage_meta.TTL[key];
|
||||
}
|
||||
|
||||
_save();
|
||||
|
||||
_handleTTL();
|
||||
|
||||
_publishChange();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set
|
||||
*
|
||||
* @param {String} key Key to check
|
||||
* @return {Number} Remaining TTL in milliseconds
|
||||
*/
|
||||
getTTL: function(key){
|
||||
var curtime = +new Date(), ttl;
|
||||
_checkKey(key);
|
||||
if(key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]){
|
||||
ttl = _storage.__jstorage_meta.TTL[key] - curtime;
|
||||
return ttl || 0;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes everything in cache.
|
||||
*
|
||||
* @return {Boolean} Always true
|
||||
*/
|
||||
flush: function(){
|
||||
_storage = {__jstorage_meta:{CRC32:{}}};
|
||||
_save();
|
||||
_publishChange();
|
||||
_fireObservers(null, "flushed");
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a read-only copy of _storage
|
||||
*
|
||||
* @return {Object} Read-only copy of _storage
|
||||
*/
|
||||
storageObj: function(){
|
||||
function F() {}
|
||||
F.prototype = _storage;
|
||||
return new F();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an index of all used keys as an array
|
||||
* ['key1', 'key2',..'keyN']
|
||||
*
|
||||
* @return {Array} Used keys
|
||||
*/
|
||||
index: function(){
|
||||
var index = [], i;
|
||||
for(i in _storage){
|
||||
if(_storage.hasOwnProperty(i) && i != "__jstorage_meta"){
|
||||
index.push(i);
|
||||
}
|
||||
}
|
||||
return index;
|
||||
},
|
||||
|
||||
/**
|
||||
* How much space in bytes does the storage take?
|
||||
*
|
||||
* @return {Number} Storage size in chars (not the same as in bytes,
|
||||
* since some chars may take several bytes)
|
||||
*/
|
||||
storageSize: function(){
|
||||
return _storage_size;
|
||||
},
|
||||
|
||||
/**
|
||||
* Which backend is currently in use?
|
||||
*
|
||||
* @return {String} Backend name
|
||||
*/
|
||||
currentBackend: function(){
|
||||
return _backend;
|
||||
},
|
||||
|
||||
/**
|
||||
* Test if storage is available
|
||||
*
|
||||
* @return {Boolean} True if storage can be used
|
||||
*/
|
||||
storageAvailable: function(){
|
||||
return !!_backend;
|
||||
},
|
||||
|
||||
/**
|
||||
* Register change listeners
|
||||
*
|
||||
* @param {String} key Key name
|
||||
* @param {Function} callback Function to run when the key changes
|
||||
*/
|
||||
listenKeyChange: function(key, callback){
|
||||
_checkKey(key);
|
||||
if(!_observers[key]){
|
||||
_observers[key] = [];
|
||||
}
|
||||
_observers[key].push(callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove change listeners
|
||||
*
|
||||
* @param {String} key Key name to unregister listeners against
|
||||
* @param {Function} [callback] If set, unregister the callback, if not - unregister all
|
||||
*/
|
||||
stopListening: function(key, callback){
|
||||
_checkKey(key);
|
||||
|
||||
if(!_observers[key]){
|
||||
return;
|
||||
}
|
||||
|
||||
if(!callback){
|
||||
delete _observers[key];
|
||||
return;
|
||||
}
|
||||
|
||||
for(var i = _observers[key].length - 1; i>=0; i--){
|
||||
if(_observers[key][i] == callback){
|
||||
_observers[key].splice(i,1);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Subscribe to a Publish/Subscribe event stream
|
||||
*
|
||||
* @param {String} channel Channel name
|
||||
* @param {Function} callback Function to run when the something is published to the channel
|
||||
*/
|
||||
subscribe: function(channel, callback){
|
||||
channel = (channel || "").toString();
|
||||
if(!channel){
|
||||
throw new TypeError('Channel not defined');
|
||||
}
|
||||
if(!_pubsub_observers[channel]){
|
||||
_pubsub_observers[channel] = [];
|
||||
}
|
||||
_pubsub_observers[channel].push(callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Publish data to an event stream
|
||||
*
|
||||
* @param {String} channel Channel name
|
||||
* @param {Mixed} payload Payload to deliver
|
||||
*/
|
||||
publish: function(channel, payload){
|
||||
channel = (channel || "").toString();
|
||||
if(!channel){
|
||||
throw new TypeError('Channel not defined');
|
||||
}
|
||||
|
||||
_publish(channel, payload);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reloads the data from browser storage
|
||||
*/
|
||||
reInit: function(){
|
||||
_reloadData();
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize jStorage
|
||||
_init();
|
||||
|
||||
})();
|
||||
@@ -10,6 +10,7 @@ import FormWrappers from "mvc/workflow/workflow-forms";
|
||||
import Ui from "mvc/ui/ui-misc";
|
||||
import async_save_text from "utils/async-save-text";
|
||||
import "ui/editable-text";
|
||||
import store from "store";
|
||||
|
||||
/* global $ */
|
||||
/* global Galaxy */
|
||||
@@ -445,7 +446,7 @@ export default Backbone.View.extend({
|
||||
}
|
||||
|
||||
// On load, set the size to the pref stored in local storage if it exists
|
||||
var overview_size = $.jStorage.get("overview-size");
|
||||
var overview_size = store.get("overview-size");
|
||||
if (overview_size !== undefined) {
|
||||
$("#overview-border").css({
|
||||
width: overview_size,
|
||||
@@ -454,7 +455,7 @@ export default Backbone.View.extend({
|
||||
}
|
||||
|
||||
// Show viewport on load unless pref says it's off
|
||||
if ($.jStorage.get("overview-off")) {
|
||||
if (store.get("overview-off")) {
|
||||
hide_overview();
|
||||
} else {
|
||||
show_overview();
|
||||
@@ -465,17 +466,17 @@ export default Backbone.View.extend({
|
||||
var op = $(this).offsetParent();
|
||||
var opo = op.offset();
|
||||
var new_size = Math.max(op.width() - (d.offsetX - opo.left), op.height() - (d.offsetY - opo.top));
|
||||
$.jStorage.set("overview-size", `${new_size}px`);
|
||||
store.set("overview-size", `${new_size}px`);
|
||||
});
|
||||
|
||||
function show_overview() {
|
||||
$.jStorage.set("overview-off", false);
|
||||
store.remove("overview-off");
|
||||
$("#overview-border").css("right", "0px");
|
||||
$("#close-viewport").css("background-position", "0px 0px");
|
||||
}
|
||||
|
||||
function hide_overview() {
|
||||
$.jStorage.set("overview-off", true);
|
||||
store.set("overview-off", 1);
|
||||
$("#overview-border").css("right", "20000px");
|
||||
$("#close-viewport").css("background-position", "12px 0px");
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ define([
|
||||
"qunit/test-data/fakeserver",
|
||||
"galaxy",
|
||||
"libs/jquery/select2",
|
||||
"libs/jquery/jstorage",
|
||||
"libs/jquery/jquery-ui"
|
||||
], function($, sinon, bootstrap, Backbone, bootstrapped, serverdata, appBase) {
|
||||
var Galaxy = {
|
||||
|
||||
@@ -388,7 +388,7 @@ LoggingCache.defaultOptions = {
|
||||
/** initialize with options */
|
||||
LoggingCache.prototype._init = function _init(options) {
|
||||
if (!this._hasStorage()) {
|
||||
//TODO: fall back to jstorage
|
||||
//TODO: fall back to local storage
|
||||
throw new Error("LoggingCache needs localStorage");
|
||||
}
|
||||
if (!options.key) {
|
||||
|
||||
+2
-1
@@ -106,6 +106,7 @@
|
||||
"qunitjs": "^2.4.1",
|
||||
"sass-loader": "^7.1.0",
|
||||
"sinon": "^4.1.2",
|
||||
"store": "^2.0.12",
|
||||
"style-loader": "^0.23.1",
|
||||
"vue-loader": "^15.4.2",
|
||||
"vue-style-loader": "^4.1.2",
|
||||
@@ -116,4 +117,4 @@
|
||||
"webpack-merge": "^4.1.4",
|
||||
"yaml-loader": "^0.5.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ let buildconfig = {
|
||||
modules: [scriptsBase, "node_modules", styleBase, imageBase],
|
||||
alias: {
|
||||
jquery$: `${libsBase}/jquery.custom.js`,
|
||||
jqueryVendor$: `${libsBase}/jquery/jquery.js`
|
||||
jqueryVendor$: `${libsBase}/jquery/jquery.js`,
|
||||
store$: "store/dist/store.modern.js"
|
||||
}
|
||||
},
|
||||
optimization: {
|
||||
|
||||
@@ -11727,6 +11727,11 @@ stdout-stream@^1.4.0:
|
||||
dependencies:
|
||||
readable-stream "^2.0.1"
|
||||
|
||||
store@^2.0.12:
|
||||
version "2.0.12"
|
||||
resolved "https://registry.yarnpkg.com/store/-/store-2.0.12.tgz#8c534e2a0b831f72b75fc5f1119857c44ef5d593"
|
||||
integrity sha1-jFNOKguDH3K3X8XxEZhXxE711ZM=
|
||||
|
||||
stream-browserify@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
## ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )}
|
||||
${container_javascripts()}
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
## ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )}
|
||||
${container_javascripts()}
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
## ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )}
|
||||
${container_javascripts()}
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -73,10 +73,12 @@
|
||||
|
||||
<%def name="container_javascripts()">
|
||||
<script type="text/javascript">
|
||||
debugger;
|
||||
var store = window.bundleEntries.store;
|
||||
var init_dependencies = function() {
|
||||
var storage_id = "library-expand-state-${trans.security.encode_id(10000)}";
|
||||
var restore_folder_state = function() {
|
||||
var state = $.jStorage.get(storage_id);
|
||||
var state = store.get(storage_id);
|
||||
if (state) {
|
||||
for (var id in state) {
|
||||
if (state[id] === true) {
|
||||
@@ -94,7 +96,7 @@
|
||||
var folder = $(this);
|
||||
state[folder.attr("id")] = folder.hasClass("expanded");
|
||||
});
|
||||
$.jStorage.set(storage_id, state);
|
||||
store.set(storage_id, state);
|
||||
};
|
||||
$(".container-table").each(function() {
|
||||
//var container_id = this.id.split( "-" )[0];
|
||||
|
||||
@@ -104,7 +104,6 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
## ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )}
|
||||
${container_javascripts()}
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
## ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )}
|
||||
${container_javascripts()}
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
## ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )}
|
||||
${container_javascripts()}
|
||||
</%def>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user