hell 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +108 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/bin/hell +12 -0
- data/lib/hell.rb +0 -0
- data/lib/hell/app.rb +128 -0
- data/lib/hell/config.ru +4 -0
- data/lib/hell/hell.rb +0 -0
- data/lib/hell/lib/helpers.rb +119 -0
- data/lib/hell/lib/monkey_patch.rb +79 -0
- data/lib/hell/public/assets/css/bootstrap-responsive.css +1088 -0
- data/lib/hell/public/assets/css/bootstrap-responsive.min.css +9 -0
- data/lib/hell/public/assets/css/bootstrap.css +5893 -0
- data/lib/hell/public/assets/css/bootstrap.min.css +9 -0
- data/lib/hell/public/assets/css/hell.css +158 -0
- data/lib/hell/public/assets/ico/favicon.ico +0 -0
- data/lib/hell/public/assets/ico/favicon.png +0 -0
- data/lib/hell/public/assets/img/glyphicons-halflings-white.png +0 -0
- data/lib/hell/public/assets/img/glyphicons-halflings.png +0 -0
- data/lib/hell/public/assets/js/backbone-localstorage.js +84 -0
- data/lib/hell/public/assets/js/backbone.js +1431 -0
- data/lib/hell/public/assets/js/backbone.min.js +38 -0
- data/lib/hell/public/assets/js/bankersbox.js +768 -0
- data/lib/hell/public/assets/js/bootstrap.growl.js +2 -0
- data/lib/hell/public/assets/js/bootstrap.js +2025 -0
- data/lib/hell/public/assets/js/bootstrap.min.js +6 -0
- data/lib/hell/public/assets/js/hashchange.min.js +9 -0
- data/lib/hell/public/assets/js/hell.js +444 -0
- data/lib/hell/public/assets/js/jquery.min.js +4 -0
- data/lib/hell/public/assets/js/timeago.js +152 -0
- data/lib/hell/public/assets/js/underscore.min.js +1 -0
- data/lib/hell/views/index.erb +146 -0
- data/test/helper.rb +18 -0
- data/test/test_hell.rb +7 -0
- metadata +201 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
// Backbone.js 0.9.2
|
2
|
+
|
3
|
+
// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
4
|
+
// Backbone may be freely distributed under the MIT license.
|
5
|
+
// For all details and documentation:
|
6
|
+
// http://backbonejs.org
|
7
|
+
(function(){var l=this,y=l.Backbone,z=Array.prototype.slice,A=Array.prototype.splice,g;g="undefined"!==typeof exports?exports:l.Backbone={};g.VERSION="0.9.2";var f=l._;!f&&"undefined"!==typeof require&&(f=require("underscore"));var i=l.jQuery||l.Zepto||l.ender;g.setDomLibrary=function(a){i=a};g.noConflict=function(){l.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var p=/\s+/,k=g.Events={on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(p);for(d=this._callbacks||(this._callbacks=
|
8
|
+
{});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,h,g,j,q;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(p):f.keys(e);d=a.shift();)if(h=e[d],delete e[d],h&&(b||c))for(g=h.tail;(h=h.next)!==g;)if(j=h.callback,q=h.context,b&&j!==b||c&&q!==c)this.on(d,j,q);return this}},trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(p);for(g=
|
9
|
+
z.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};k.bind=k.on;k.unbind=k.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,"defaults"))a=f.extend({},c,a);b&&b.collection&&(this.collection=b.collection);this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");this.changed={};this._silent=
|
10
|
+
{};this._pending={};this.set(a,{silent:!0});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,k,{changed:null,_silent:null,_pending:null,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(null==
|
11
|
+
b?"":""+b)},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;d instanceof o&&(d=d.attributes);if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return!1;this.idAttribute in d&&(this.id=d[this.idAttribute]);var b=c.changes={},h=this.attributes,g=this._escapedAttributes,j=this._previousAttributes||{};for(e in d){a=d[e];if(!f.isEqual(h[e],a)||c.unset&&f.has(h,e))delete g[e],(c.silent?this._silent:
|
12
|
+
b)[e]=!0;c.unset?delete h[e]:h[e]=a;!f.isEqual(j[e],a)||f.has(h,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=!0)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=!0;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=!0;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&c(b,d)};
|
13
|
+
a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return!1;e=f.clone(this.attributes)}a=f.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c))return!1;var h=this,i=c.success;c.success=function(a,b,e){b=h.parse(a,e);if(c.wait){delete c.wait;b=f.extend(d||{},b)}if(!h.set(b,c))return false;i?i(h,a):h.trigger("sync",h,a,c)};c.error=g.wrapError(c.error,
|
14
|
+
h,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d(),!1;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=n(this,"urlRoot")||n(this.collection,"url")||t();
|
15
|
+
return this.isNew()?a:a+("/"==a.charAt(a.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){a||(a={});var b=this._changing;this._changing=!0;for(var c in this._silent)this._pending[c]=!0;var d=f.extend({},a.changes,this._silent);this._silent={};for(c in d)this.trigger("change:"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending=
|
16
|
+
{};this.trigger("change",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=!1;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length||
|
17
|
+
!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return!0;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error?b.error(this,c,b):this.trigger("error",this,c,b);return!1}});var r=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);b.comparator&&(this.comparator=b.comparator);
|
18
|
+
this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:!0,parse:b.parse})};f.extend(r.prototype,k,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,i,j={},k={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];c=0;for(d=a.length;c<d;c++){if(!(e=a[c]=this._prepareModel(a[c],b)))throw Error("Can't add an invalid model to a collection");g=e.cid;i=e.id;j[g]||this._byCid[g]||null!=i&&(k[i]||this._byId[i])?
|
19
|
+
l.push(c):j[g]=k[i]=e}for(c=l.length;c--;)a.splice(l[c],1);c=0;for(d=a.length;c<d;c++)(e=a[c]).on("all",this._onModelEvent,this),this._byCid[e.cid]=e,null!=e.id&&(this._byId[e.id]=e);this.length+=d;A.apply(this.models,[null!=b.at?b.at:this.models.length,0].concat(a));this.comparator&&this.sort({silent:!0});if(b.silent)return this;c=0;for(d=this.models.length;c<d;c++)if(j[(e=this.models[c]).cid])b.index=c,e.trigger("add",e,this,b);return this},remove:function(a,b){var c,d,e,g;b||(b={});a=f.isArray(a)?
|
20
|
+
a.slice():[a];c=0;for(d=a.length;c<d;c++)if(g=this.getByCid(a[c])||this.get(a[c]))delete this._byId[g.id],delete this._byCid[g.cid],e=this.indexOf(g),this.models.splice(e,1),this.length--,b.silent||(b.index=e,g.trigger("remove",g,this,b)),this._removeReference(g);return this},push:function(a,b){a=this._prepareModel(a,b);this.add(a,b);return a},pop:function(a){var b=this.at(this.length-1);this.remove(b,a);return b},unshift:function(a,b){a=this._prepareModel(a,b);this.add(a,f.extend({at:0},b));return a},
|
21
|
+
shift:function(a){var b=this.at(0);this.remove(b,a);return b},get:function(a){return null==a?void 0:this._byId[null!=a.id?a.id:a]},getByCid:function(a){return a&&this._byCid[a.cid||a]},at:function(a){return this.models[a]},where:function(a){return f.isEmpty(a)?[]:this.filter(function(b){for(var c in a)if(a[c]!==b.get(c))return!1;return!0})},sort:function(a){a||(a={});if(!this.comparator)throw Error("Cannot sort a set without a comparator");var b=f.bind(this.comparator,this);1==this.comparator.length?
|
22
|
+
this.models=this.sortBy(b):this.models.sort(b);a.silent||this.trigger("reset",this,a);return this},pluck:function(a){return f.map(this.models,function(b){return b.get(a)})},reset:function(a,b){a||(a=[]);b||(b={});for(var c=0,d=this.models.length;c<d;c++)this._removeReference(this.models[c]);this._reset();this.add(a,f.extend({silent:!0},b));b.silent||this.trigger("reset",this,b);return this},fetch:function(a){a=a?f.clone(a):{};void 0===a.parse&&(a.parse=!0);var b=this,c=a.success;a.success=function(d,
|
23
|
+
e,f){b[a.add?"add":"reset"](b.parse(d,f),a);c&&c(b,d)};a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},create:function(a,b){var c=this,b=b?f.clone(b):{},a=this._prepareModel(a,b);if(!a)return!1;b.wait||c.add(a,b);var d=b.success;b.success=function(e,f){b.wait&&c.add(e,b);d?d(e,f):e.trigger("sync",a,f,b)};a.save(null,b);return a},parse:function(a){return a},chain:function(){return f(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId=
|
24
|
+
{};this._byCid={}},_prepareModel:function(a,b){b||(b={});a instanceof o?a.collection||(a.collection=this):(b.collection=this,a=new this.model(a,b),a._validate(a.attributes,b)||(a=!1));return a},_removeReference:function(a){this==a.collection&&delete a.collection;a.off("all",this._onModelEvent,this)},_onModelEvent:function(a,b,c,d){("add"==a||"remove"==a)&&c!=this||("destroy"==a&&this.remove(b,d),b&&a==="change:"+b.idAttribute&&(delete this._byId[b.previous(b.idAttribute)],this._byId[b.id]=b),this.trigger.apply(this,
|
25
|
+
arguments))}});f.each("forEach,each,map,reduce,reduceRight,find,detect,filter,select,reject,every,all,some,any,include,contains,invoke,max,min,sortBy,sortedIndex,toArray,size,first,initial,rest,last,without,indexOf,shuffle,lastIndexOf,isEmpty,groupBy".split(","),function(a){r.prototype[a]=function(){return f[a].apply(f,[this.models].concat(f.toArray(arguments)))}});var u=g.Router=function(a){a||(a={});a.routes&&(this.routes=a.routes);this._bindRoutes();this.initialize.apply(this,arguments)},B=/:\w+/g,
|
26
|
+
C=/\*\w+/g,D=/[-[\]{}()+?.,\\^$|#\s]/g;f.extend(u.prototype,k,{initialize:function(){},route:function(a,b,c){g.history||(g.history=new m);f.isRegExp(a)||(a=this._routeToRegExp(a));c||(c=this[b]);g.history.route(a,f.bind(function(d){d=this._extractParameters(a,d);c&&c.apply(this,d);this.trigger.apply(this,["route:"+b].concat(d));g.history.trigger("route",this,b,d)},this));return this},navigate:function(a,b){g.history.navigate(a,b)},_bindRoutes:function(){if(this.routes){var a=[],b;for(b in this.routes)a.unshift([b,
|
27
|
+
this.routes[b]]);b=0;for(var c=a.length;b<c;b++)this.route(a[b][0],a[b][1],this[a[b][1]])}},_routeToRegExp:function(a){a=a.replace(D,"\\$&").replace(B,"([^/]+)").replace(C,"(.*?)");return RegExp("^"+a+"$")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});var m=g.History=function(){this.handlers=[];f.bindAll(this,"checkUrl")},s=/^[#\/]/,E=/msie [\w.]+/;m.started=!1;f.extend(m.prototype,k,{interval:50,getHash:function(a){return(a=(a?a.location:window.location).href.match(/#(.*)$/))?a[1]:
|
28
|
+
""},getFragment:function(a,b){if(null==a)if(this._hasPushState||b){var a=window.location.pathname,c=window.location.search;c&&(a+=c)}else a=this.getHash();a.indexOf(this.options.root)||(a=a.substr(this.options.root.length));return a.replace(s,"")},start:function(a){if(m.started)throw Error("Backbone.history has already been started");m.started=!0;this.options=f.extend({},{root:"/"},this.options,a);this._wantsHashChange=!1!==this.options.hashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=
|
29
|
+
!(!this.options.pushState||!window.history||!window.history.pushState);var a=this.getFragment(),b=document.documentMode;if(b=E.exec(navigator.userAgent.toLowerCase())&&(!b||7>=b))this.iframe=i('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(a);this._hasPushState?i(window).bind("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!b?i(window).bind("hashchange",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,
|
30
|
+
this.interval));this.fragment=a;a=window.location;b=a.pathname==this.options.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,!0),window.location.replace(this.options.root+"#"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&b&&a.hash&&(this.fragment=this.getHash().replace(s,""),window.history.replaceState({},document.title,a.protocol+"//"+a.host+this.options.root+this.fragment));if(!this.options.silent)return this.loadUrl()},
|
31
|
+
stop:function(){i(window).unbind("popstate",this.checkUrl).unbind("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);m.started=!1},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a==this.fragment&&this.iframe&&(a=this.getFragment(this.getHash(this.iframe)));if(a==this.fragment)return!1;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(a){var b=this.fragment=this.getFragment(a);return f.any(this.handlers,
|
32
|
+
function(a){if(a.route.test(b))return a.callback(b),!0})},navigate:function(a,b){if(!m.started)return!1;if(!b||!0===b)b={trigger:b};var c=(a||"").replace(s,"");this.fragment!=c&&(this._hasPushState?(0!=c.indexOf(this.options.root)&&(c=this.options.root+c),this.fragment=c,window.history[b.replace?"replaceState":"pushState"]({},document.title,c)):this._wantsHashChange?(this.fragment=c,this._updateHash(window.location,c,b.replace),this.iframe&&c!=this.getFragment(this.getHash(this.iframe))&&(b.replace||
|
33
|
+
this.iframe.document.open().close(),this._updateHash(this.iframe.location,c,b.replace))):window.location.assign(this.options.root+a),b.trigger&&this.loadUrl(a))},_updateHash:function(a,b,c){c?a.replace(a.toString().replace(/(javascript:|#).*$/,"")+"#"+b):a.hash=b}});var v=g.View=function(a){this.cid=f.uniqueId("view");this._configure(a||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},F=/^(\S+)\s*(.*)$/,w="model,collection,el,id,attributes,className,tagName".split(",");
|
34
|
+
f.extend(v.prototype,k,{tagName:"div",$:function(a){return this.$el.find(a)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();return this},make:function(a,b,c){a=document.createElement(a);b&&i(a).attr(b);c&&i(a).html(c);return a},setElement:function(a,b){this.$el&&this.undelegateEvents();this.$el=a instanceof i?a:i(a);this.el=this.$el[0];!1!==b&&this.delegateEvents();return this},delegateEvents:function(a){if(a||(a=n(this,"events"))){this.undelegateEvents();
|
35
|
+
for(var b in a){var c=a[b];f.isFunction(c)||(c=this[a[b]]);if(!c)throw Error('Method "'+a[b]+'" does not exist');var d=b.match(F),e=d[1],d=d[2],c=f.bind(c,this),e=e+(".delegateEvents"+this.cid);""===d?this.$el.bind(e,c):this.$el.delegate(d,e,c)}}},undelegateEvents:function(){this.$el.unbind(".delegateEvents"+this.cid)},_configure:function(a){this.options&&(a=f.extend({},this.options,a));for(var b=0,c=w.length;b<c;b++){var d=w[b];a[d]&&(this[d]=a[d])}this.options=a},_ensureElement:function(){if(this.el)this.setElement(this.el,
|
36
|
+
!1);else{var a=n(this,"attributes")||{};this.id&&(a.id=this.id);this.className&&(a["class"]=this.className);this.setElement(this.make(this.tagName,a),!1)}}});o.extend=r.extend=u.extend=v.extend=function(a,b){var c=G(this,a,b);c.extend=this.extend;return c};var H={create:"POST",update:"PUT","delete":"DELETE",read:"GET"};g.sync=function(a,b,c){var d=H[a];c||(c={});var e={type:d,dataType:"json"};c.url||(e.url=n(b,"url")||t());if(!c.data&&b&&("create"==a||"update"==a))e.contentType="application/json",
|
37
|
+
e.data=JSON.stringify(b.toJSON());g.emulateJSON&&(e.contentType="application/x-www-form-urlencoded",e.data=e.data?{model:e.data}:{});if(g.emulateHTTP&&("PUT"===d||"DELETE"===d))g.emulateJSON&&(e.data._method=d),e.type="POST",e.beforeSend=function(a){a.setRequestHeader("X-HTTP-Method-Override",d)};"GET"!==e.type&&!g.emulateJSON&&(e.processData=!1);return i.ajax(f.extend(e,c))};g.wrapError=function(a,b,c){return function(d,e){e=d===b?e:d;a?a(b,e,c):b.trigger("error",b,e,c)}};var x=function(){},G=function(a,
|
38
|
+
b,c){var d;d=b&&b.hasOwnProperty("constructor")?b.constructor:function(){a.apply(this,arguments)};f.extend(d,a);x.prototype=a.prototype;d.prototype=new x;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},n=function(a,b){return!a||!a[b]?null:f.isFunction(a[b])?a[b]():a[b]},t=function(){throw Error('A "url" property or function must be specified');}}).call(this);
|
@@ -0,0 +1,768 @@
|
|
1
|
+
/**
|
2
|
+
* @license MIT License
|
3
|
+
*
|
4
|
+
* Copyright (c) 2012 Twilio Inc.
|
5
|
+
*
|
6
|
+
* Authors: Chad Etzel <chetzel@twilio.com>
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
* a copy of this software and associated documentation files (the
|
10
|
+
* "Software"), to deal in the Software without restriction, including
|
11
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
* the following conditions:
|
15
|
+
*
|
16
|
+
* The above copyright notice and this permission notice shall be
|
17
|
+
* included in all copies or substantial portions of the Software.
|
18
|
+
*
|
19
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
22
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
23
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
24
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
25
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
(function(ctx) {
|
29
|
+
|
30
|
+
if (typeof(window) === 'undefined') {
|
31
|
+
window = {};
|
32
|
+
}
|
33
|
+
|
34
|
+
if (typeof(window.localStorage) === 'undefined' && ctx !== window) {
|
35
|
+
// fake out localStorage functionality, mostly for testing purposes
|
36
|
+
window.localStorage = {};
|
37
|
+
window.localStorage.store = {};
|
38
|
+
window.localStorage.setItem = function(k, v) {
|
39
|
+
window.localStorage.store[k] = v;
|
40
|
+
};
|
41
|
+
window.localStorage.getItem = function(k) {
|
42
|
+
var ret;
|
43
|
+
ret = window.localStorage.store[k];
|
44
|
+
if (ret === undefined) {
|
45
|
+
return null;
|
46
|
+
}
|
47
|
+
return ret;
|
48
|
+
};
|
49
|
+
window.localStorage.removeItem = function(k) {
|
50
|
+
delete window.localStorage.store[k];
|
51
|
+
};
|
52
|
+
window.localStorage.clear = function() {
|
53
|
+
window.localStorage.store = {};
|
54
|
+
};
|
55
|
+
}
|
56
|
+
|
57
|
+
// Array Remove - By John Resig (MIT Licensed)
|
58
|
+
var arr_remove = function(array, from, to) {
|
59
|
+
var rest = array.slice((to || from) + 1 || array.length);
|
60
|
+
array.length = from < 0 ? array.length + from : from;
|
61
|
+
return array.push.apply(array, rest);
|
62
|
+
};
|
63
|
+
|
64
|
+
var BB = function(dbi, opts) {
|
65
|
+
|
66
|
+
if (isNaN(parseInt(dbi, 10))) {
|
67
|
+
throw(new BankersBoxException("db index must be an integer"));
|
68
|
+
}
|
69
|
+
dbi = parseInt(dbi, 10);
|
70
|
+
|
71
|
+
opts = opts || {};
|
72
|
+
|
73
|
+
var self = this;
|
74
|
+
|
75
|
+
var db = dbi;
|
76
|
+
var adapter = opts.adapter;
|
77
|
+
|
78
|
+
if (adapter === undefined) {
|
79
|
+
adapter = new BankersBoxLocalStorageAdapter();
|
80
|
+
} else if (adapter === null) {
|
81
|
+
adapter = new BankersBoxNullAdapter();
|
82
|
+
}
|
83
|
+
|
84
|
+
var prefix = "bb:" + db.toString() + ":";
|
85
|
+
var keyskey = "bb:" + db.toString() + "k:___keys___";
|
86
|
+
var store = {};
|
87
|
+
|
88
|
+
this.toString = function() {
|
89
|
+
return "bb:" + db.toString();
|
90
|
+
};
|
91
|
+
|
92
|
+
if (typeof(JSON) == 'undefined' && !(window.JSON && window.JSON.parse && window.JSON.stringify)) {
|
93
|
+
throw("No JSON support detected. Please include a JSON module with 'parse' and 'stringify' functions.");
|
94
|
+
}
|
95
|
+
|
96
|
+
var exists_raw = function(k) {
|
97
|
+
var ret = store[k] || adapter.getItem(k);
|
98
|
+
return ret ? true : false;
|
99
|
+
};
|
100
|
+
|
101
|
+
var get_raw = function(k, t) {
|
102
|
+
var ret = store[k];
|
103
|
+
if (ret !== undefined) {
|
104
|
+
return ret;
|
105
|
+
}
|
106
|
+
ret = adapter.getItem(k);
|
107
|
+
var obj = ret;
|
108
|
+
try {
|
109
|
+
obj = JSON.parse(ret);
|
110
|
+
} catch (e) {
|
111
|
+
} finally {
|
112
|
+
store[k] = obj;
|
113
|
+
}
|
114
|
+
return obj;
|
115
|
+
};
|
116
|
+
|
117
|
+
var set_raw = function(k, v, t) {
|
118
|
+
store[k] = v;
|
119
|
+
adapter.storeItem(k, JSON.stringify(v));
|
120
|
+
};
|
121
|
+
|
122
|
+
var del_raw = function(k) {
|
123
|
+
delete store[k];
|
124
|
+
adapter.removeItem(k);
|
125
|
+
};
|
126
|
+
|
127
|
+
var get_raw_value = function(k, t) {
|
128
|
+
var val = get_raw(k, t);
|
129
|
+
if (val === null) {
|
130
|
+
return null;
|
131
|
+
}
|
132
|
+
return val.v;
|
133
|
+
};
|
134
|
+
|
135
|
+
var get_raw_meta = function(k, meta, t) {
|
136
|
+
var val = get_raw(k, t);
|
137
|
+
if (val === null) {
|
138
|
+
return null;
|
139
|
+
}
|
140
|
+
return val.m[meta];
|
141
|
+
};
|
142
|
+
|
143
|
+
var set_raw_value = function(k, v, t) {
|
144
|
+
var val = get_raw(k, t);
|
145
|
+
if (val === undefined || val === null) {
|
146
|
+
val = {};
|
147
|
+
val.m = {};
|
148
|
+
}
|
149
|
+
val.v = v;
|
150
|
+
if (t !== undefined) {
|
151
|
+
val.m.t = t;
|
152
|
+
}
|
153
|
+
set_raw(k, val, t);
|
154
|
+
};
|
155
|
+
|
156
|
+
var set_raw_meta = function(k, meta, v) {
|
157
|
+
var val = store[k];
|
158
|
+
if (val === undefined || val === null) {
|
159
|
+
return;
|
160
|
+
}
|
161
|
+
val.m[meta] = v;
|
162
|
+
set_raw(k, val);
|
163
|
+
};
|
164
|
+
|
165
|
+
var exists_bbkey = function(k) {
|
166
|
+
return exists_raw(prefix + k);
|
167
|
+
};
|
168
|
+
|
169
|
+
var set_bbkey = function(k, v, t) {
|
170
|
+
set_raw_value(prefix + k, v, t);
|
171
|
+
if (t !== undefined) {
|
172
|
+
set_bbkeytype(k, t);
|
173
|
+
}
|
174
|
+
keystore[k] = 1;
|
175
|
+
set_raw_value(keyskey, keystore, "set");
|
176
|
+
};
|
177
|
+
|
178
|
+
var get_bbkey = function(k, t) {
|
179
|
+
return get_raw_value(prefix + k, t);
|
180
|
+
};
|
181
|
+
|
182
|
+
var del_bbkey = function(k) {
|
183
|
+
del_raw(prefix + k);
|
184
|
+
delete keystore[k];
|
185
|
+
set_raw_value(keyskey, keystore, "set");
|
186
|
+
};
|
187
|
+
|
188
|
+
var set_bbkeymeta = function(k, meta, v) {
|
189
|
+
set_raw_meta(prefix + k, meta, v);
|
190
|
+
};
|
191
|
+
|
192
|
+
var get_bbkeymeta = function(k, meta) {
|
193
|
+
return get_raw_meta(prefix + k, meta);
|
194
|
+
};
|
195
|
+
|
196
|
+
var set_bbkeytype = function(k, v) {
|
197
|
+
set_bbkeymeta(k, "t", v);
|
198
|
+
};
|
199
|
+
|
200
|
+
var get_bbkeytype = function(k) {
|
201
|
+
return get_bbkeymeta(k, "t");
|
202
|
+
};
|
203
|
+
|
204
|
+
var validate_key = function(k, checktype) {
|
205
|
+
var keytype = self.type(k);
|
206
|
+
var tmap = {};
|
207
|
+
tmap["get"] = "string";
|
208
|
+
tmap["set"] = "string";
|
209
|
+
tmap["strlen"] = "string";
|
210
|
+
tmap["setnx"] = "string";
|
211
|
+
tmap["append"] = "string";
|
212
|
+
tmap["incr"] = "string";
|
213
|
+
tmap["incrby"] = "string";
|
214
|
+
tmap["getset"] = "string";
|
215
|
+
tmap["lpush"] = "list";
|
216
|
+
tmap["lpushx"] = "list";
|
217
|
+
tmap["lpop"] = "list";
|
218
|
+
tmap["rpush"] = "list";
|
219
|
+
tmap["rpushx"] = "list";
|
220
|
+
tmap["rpop"] = "list";
|
221
|
+
tmap["rpoplpush"] = "list";
|
222
|
+
tmap["llen"] = "list";
|
223
|
+
tmap["lindex"] = "list";
|
224
|
+
tmap["lrange"] = "list";
|
225
|
+
tmap["lrem"] = "list";
|
226
|
+
tmap["lset"] = "list";
|
227
|
+
tmap["ltrim"] = "list";
|
228
|
+
tmap["sadd"] = "set";
|
229
|
+
tmap["scard"] = "set";
|
230
|
+
tmap["sismember"] = "set";
|
231
|
+
tmap["smembers"] = "set";
|
232
|
+
tmap["srem"] = "set";
|
233
|
+
tmap["smove"] = "set";
|
234
|
+
tmap["spop"] = "set";
|
235
|
+
tmap["srandmember"] = "set";
|
236
|
+
|
237
|
+
if (tmap[checktype] === undefined) {
|
238
|
+
throw new BankersBoxException("unknown key operation in validate_key");
|
239
|
+
}
|
240
|
+
|
241
|
+
if (keytype === undefined || keytype === null || tmap[checktype] === undefined || tmap[checktype] == keytype) {
|
242
|
+
return true;
|
243
|
+
}
|
244
|
+
throw(new BankersBoxKeyException("invalid operation on key type: " + keytype));
|
245
|
+
};
|
246
|
+
|
247
|
+
/* ---- PRIVILEGED METHODS ---- */
|
248
|
+
|
249
|
+
/* ---- KEY ---- */
|
250
|
+
|
251
|
+
this.del = function(k) {
|
252
|
+
var ret = 0;
|
253
|
+
if (get_bbkey(k)) {
|
254
|
+
ret = 1;
|
255
|
+
}
|
256
|
+
del_bbkey(k);
|
257
|
+
return ret;
|
258
|
+
};
|
259
|
+
|
260
|
+
this.exists = function(k) {
|
261
|
+
return exists_bbkey(k);
|
262
|
+
};
|
263
|
+
|
264
|
+
this.type = function(k) {
|
265
|
+
return get_bbkeytype(k);
|
266
|
+
};
|
267
|
+
|
268
|
+
|
269
|
+
/* ---- STRING ---- */
|
270
|
+
|
271
|
+
this.get = function(k) {
|
272
|
+
validate_key(k, "get");
|
273
|
+
return get_bbkey(k);
|
274
|
+
};
|
275
|
+
|
276
|
+
this.getset = function(k, v) {
|
277
|
+
validate_key(k, "getset");
|
278
|
+
var val = self.get(k);
|
279
|
+
self.set(k, v);
|
280
|
+
return val;
|
281
|
+
};
|
282
|
+
|
283
|
+
this.append = function(k, v) {
|
284
|
+
validate_key(k, "append");
|
285
|
+
var val = self.get(k);
|
286
|
+
if (val !== null) {
|
287
|
+
self.set(k, val + v);
|
288
|
+
return (val + v).length;
|
289
|
+
}
|
290
|
+
self.set(k, v);
|
291
|
+
return v.toString().length;
|
292
|
+
};
|
293
|
+
|
294
|
+
this.decr = function(k) {
|
295
|
+
return self.incrby(k, -1);
|
296
|
+
};
|
297
|
+
|
298
|
+
this.decrby = function(k, i) {
|
299
|
+
return self.incrby(k, 0 - i);
|
300
|
+
};
|
301
|
+
|
302
|
+
this.incr = function(k) {
|
303
|
+
return self.incrby(k, 1);
|
304
|
+
};
|
305
|
+
|
306
|
+
this.incrby = function(k, i) {
|
307
|
+
validate_key(k, "incrby");
|
308
|
+
var val = self.get(k);
|
309
|
+
if (val !== null) {
|
310
|
+
if (isNaN(parseInt(val, 10))) {
|
311
|
+
throw(new BankersBoxKeyException("key is not parsable as an integer"));
|
312
|
+
}
|
313
|
+
self.set(k, val + i);
|
314
|
+
return val + i;
|
315
|
+
}
|
316
|
+
self.set(k, i);
|
317
|
+
return i;
|
318
|
+
};
|
319
|
+
|
320
|
+
this.set = function(k, v) {
|
321
|
+
validate_key(k, "set");
|
322
|
+
set_bbkey(k, v);
|
323
|
+
set_bbkeytype(k, "string");
|
324
|
+
return "OK";
|
325
|
+
};
|
326
|
+
|
327
|
+
this.setnx = function(k, v) {
|
328
|
+
validate_key(k, "setnx");
|
329
|
+
var val = self.get(k);
|
330
|
+
if (val !== null) {
|
331
|
+
return 0;
|
332
|
+
}
|
333
|
+
self.set(k, v);
|
334
|
+
return 1;
|
335
|
+
};
|
336
|
+
|
337
|
+
this.strlen = function(k) {
|
338
|
+
validate_key(k, "strlen");
|
339
|
+
var v = self.get(k);
|
340
|
+
if (v !== null) {
|
341
|
+
return v.toString().length;
|
342
|
+
}
|
343
|
+
return 0;
|
344
|
+
};
|
345
|
+
|
346
|
+
/* ---- LIST ---- */
|
347
|
+
|
348
|
+
this.llen = function(k) {
|
349
|
+
validate_key(k, "llen");
|
350
|
+
var val = get_bbkey(k, "list");
|
351
|
+
if (val === null) {
|
352
|
+
return 0;
|
353
|
+
}
|
354
|
+
return val.length;
|
355
|
+
};
|
356
|
+
|
357
|
+
this.lindex = function(k, i) {
|
358
|
+
validate_key(k, "lindex");
|
359
|
+
var val = get_bbkey(k, "list");
|
360
|
+
if (val !== null) {
|
361
|
+
if (i < 0) {
|
362
|
+
i = val.length + i;
|
363
|
+
}
|
364
|
+
var ret = val[i];
|
365
|
+
if (ret === undefined) {
|
366
|
+
ret = null;
|
367
|
+
}
|
368
|
+
return ret;
|
369
|
+
}
|
370
|
+
return null;
|
371
|
+
};
|
372
|
+
|
373
|
+
this.lpop = function(k) {
|
374
|
+
validate_key(k, "lpop");
|
375
|
+
var val = get_bbkey(k, "list");
|
376
|
+
if (val === null) {
|
377
|
+
return null;
|
378
|
+
}
|
379
|
+
var ret = val.shift();
|
380
|
+
if (val.length === 0) {
|
381
|
+
self.del(k);
|
382
|
+
} else {
|
383
|
+
set_bbkey(k, val, "list");
|
384
|
+
}
|
385
|
+
return ret;
|
386
|
+
};
|
387
|
+
|
388
|
+
this.lpush = function(k, v) {
|
389
|
+
validate_key(k, "lpush");
|
390
|
+
var val = get_bbkey(k, "list");
|
391
|
+
if (val === null) {
|
392
|
+
val = [];
|
393
|
+
}
|
394
|
+
val.unshift(v);
|
395
|
+
set_bbkey(k, val, "list");
|
396
|
+
return val.length;
|
397
|
+
};
|
398
|
+
|
399
|
+
this.lpushx = function(k, v) {
|
400
|
+
validate_key(k, "lpushx");
|
401
|
+
var val = get_bbkey(k, "list");
|
402
|
+
if (val !== null) {
|
403
|
+
return self.lpush(k, v);
|
404
|
+
}
|
405
|
+
return 0;
|
406
|
+
};
|
407
|
+
|
408
|
+
this.lrange = function(k, start, end) {
|
409
|
+
validate_key(k, "lrange");
|
410
|
+
var val = get_bbkey(k, "list");
|
411
|
+
if (val === null) {
|
412
|
+
return [];
|
413
|
+
}
|
414
|
+
if (end === -1) {
|
415
|
+
return val.slice(start);
|
416
|
+
}
|
417
|
+
return val.slice(start, end + 1);
|
418
|
+
};
|
419
|
+
|
420
|
+
this.lrem = function(k, count, v) {
|
421
|
+
validate_key(k, "lrem");
|
422
|
+
var val = get_bbkey(k, "list");
|
423
|
+
if (val === null) {
|
424
|
+
return 0;
|
425
|
+
}
|
426
|
+
var ret = 0;
|
427
|
+
var to_remove = [];
|
428
|
+
for (var i = 0; i < val.length; i++) {
|
429
|
+
if (val[i] == v) {
|
430
|
+
to_remove.push(i);
|
431
|
+
ret++;
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
if (count > 0) {
|
436
|
+
to_remove = to_remove.slice(0, count);
|
437
|
+
} else if (count < 0) {
|
438
|
+
to_remove = to_remove.slice(count);
|
439
|
+
}
|
440
|
+
|
441
|
+
while(to_remove.length) {
|
442
|
+
var el = to_remove.pop();
|
443
|
+
arr_remove(val, el);
|
444
|
+
}
|
445
|
+
|
446
|
+
if (val.length === 0) {
|
447
|
+
self.del(k);
|
448
|
+
} else {
|
449
|
+
set_bbkey(k, val, "list");
|
450
|
+
}
|
451
|
+
if (count === 0) {
|
452
|
+
return ret;
|
453
|
+
} else {
|
454
|
+
return Math.min(ret, Math.abs(count));
|
455
|
+
}
|
456
|
+
};
|
457
|
+
|
458
|
+
this.lset = function(k, i, v) {
|
459
|
+
validate_key(k, "lset");
|
460
|
+
var val = get_bbkey(k, "list");
|
461
|
+
if (val === null) {
|
462
|
+
throw(new BankersBoxKeyException("no such key"));
|
463
|
+
}
|
464
|
+
if (i < 0) {
|
465
|
+
i = val.length + i;
|
466
|
+
}
|
467
|
+
if (i < 0 || i >= val.length) {
|
468
|
+
throw(new BankersBoxException("index out of range"));
|
469
|
+
}
|
470
|
+
val[i] = v;
|
471
|
+
set_bbkey(k, val, "list");
|
472
|
+
return "OK";
|
473
|
+
};
|
474
|
+
|
475
|
+
this.ltrim = function(k, start, end) {
|
476
|
+
validate_key(k, "ltrim");
|
477
|
+
var val = get_bbkey(k, "list");
|
478
|
+
if (val === null) {
|
479
|
+
return "OK";
|
480
|
+
}
|
481
|
+
if (end === -1) {
|
482
|
+
val = val.slice(start);
|
483
|
+
} else {
|
484
|
+
val = val.slice(start, end + 1);
|
485
|
+
}
|
486
|
+
if (val.length === 0) {
|
487
|
+
self.del(k);
|
488
|
+
} else {
|
489
|
+
set_bbkey(k, val, "list");
|
490
|
+
}
|
491
|
+
return "OK";
|
492
|
+
};
|
493
|
+
|
494
|
+
this.rpop = function(k) {
|
495
|
+
validate_key(k, "rpop");
|
496
|
+
var val = get_bbkey(k, "list");
|
497
|
+
if (val === null) {
|
498
|
+
return null;
|
499
|
+
}
|
500
|
+
var ret = val.pop();
|
501
|
+
if (val.length === 0) {
|
502
|
+
self.del(k);
|
503
|
+
} else {
|
504
|
+
set_bbkey(k, val, "list");
|
505
|
+
}
|
506
|
+
return ret;
|
507
|
+
};
|
508
|
+
|
509
|
+
this.rpush = function(k, v) {
|
510
|
+
validate_key(k, "rpush");
|
511
|
+
var val = get_bbkey(k);
|
512
|
+
if (val === null) {
|
513
|
+
val = [];
|
514
|
+
}
|
515
|
+
val.push(v);
|
516
|
+
set_bbkey(k, val, "list");
|
517
|
+
return val.length;
|
518
|
+
};
|
519
|
+
|
520
|
+
this.rpushx = function(k, v) {
|
521
|
+
validate_key(k, "rpushx");
|
522
|
+
var val = get_bbkey(k, "list");
|
523
|
+
if (val !== null) {
|
524
|
+
return self.rpush(k, v);
|
525
|
+
}
|
526
|
+
return 0;
|
527
|
+
};
|
528
|
+
|
529
|
+
this.rpoplpush = function(src, dest) {
|
530
|
+
validate_key(src, "rpoplpush");
|
531
|
+
validate_key(dest, "rpoplpush");
|
532
|
+
|
533
|
+
var srcval = get_bbkey(src, "list");
|
534
|
+
var destval = get_bbkey(dest, "list");
|
535
|
+
|
536
|
+
if (srcval === null) {
|
537
|
+
return null;
|
538
|
+
}
|
539
|
+
|
540
|
+
var val = self.rpop(src);
|
541
|
+
self.lpush(dest, val);
|
542
|
+
return val;
|
543
|
+
};
|
544
|
+
|
545
|
+
|
546
|
+
/* ---- SET ---- */
|
547
|
+
|
548
|
+
this.sadd = function(k, v) {
|
549
|
+
validate_key(k, "sadd");
|
550
|
+
var val = get_bbkey(k, "set");
|
551
|
+
var scard;
|
552
|
+
var ret = 0;
|
553
|
+
if (val === null) {
|
554
|
+
val = {};
|
555
|
+
scard = 0;
|
556
|
+
} else {
|
557
|
+
scard = parseInt(get_bbkeymeta(k, "card"), 10);
|
558
|
+
}
|
559
|
+
if (val[v] !== 1) {
|
560
|
+
ret = 1;
|
561
|
+
scard = scard + 1;
|
562
|
+
}
|
563
|
+
val[v] = 1;
|
564
|
+
set_bbkey(k, val, "set");
|
565
|
+
set_bbkeymeta(k, "card", scard);
|
566
|
+
return ret;
|
567
|
+
};
|
568
|
+
|
569
|
+
this.scard = function(k) {
|
570
|
+
validate_key(k, "scard");
|
571
|
+
if (self.exists(k)) {
|
572
|
+
return parseInt(get_bbkeymeta(k, "card"), 10);
|
573
|
+
}
|
574
|
+
return 0;
|
575
|
+
};
|
576
|
+
|
577
|
+
this.sismember = function(k, v) {
|
578
|
+
validate_key(k, "sismember");
|
579
|
+
var val = get_bbkey(k, "set");
|
580
|
+
if (val === null) {
|
581
|
+
return false;
|
582
|
+
}
|
583
|
+
if (val[v] === 1) {
|
584
|
+
return true;
|
585
|
+
}
|
586
|
+
return false;
|
587
|
+
};
|
588
|
+
|
589
|
+
this.smembers = function(k) {
|
590
|
+
validate_key(k, "smembers");
|
591
|
+
var val = get_bbkey(k, "set");
|
592
|
+
if (val === null) {
|
593
|
+
return [];
|
594
|
+
}
|
595
|
+
var ret = [];
|
596
|
+
for (var v in val) {
|
597
|
+
if (val.hasOwnProperty(v)) {
|
598
|
+
ret.push(v);
|
599
|
+
}
|
600
|
+
}
|
601
|
+
return ret;
|
602
|
+
};
|
603
|
+
|
604
|
+
this.smove = function(src, dest, v) {
|
605
|
+
validate_key(src, "smove");
|
606
|
+
validate_key(dest, "smove");
|
607
|
+
var srcval = get_bbkey(src, "set");
|
608
|
+
if (srcval === null) {
|
609
|
+
return 0;
|
610
|
+
}
|
611
|
+
var ret = self.srem(src, v);
|
612
|
+
if (ret) {
|
613
|
+
self.sadd(dest, v);
|
614
|
+
}
|
615
|
+
return ret;
|
616
|
+
};
|
617
|
+
|
618
|
+
this.spop = function(k) {
|
619
|
+
validate_key(k, "spop");
|
620
|
+
var member = self.srandmember(k);
|
621
|
+
if (member !== null) {
|
622
|
+
self.srem(k, member);
|
623
|
+
}
|
624
|
+
return member;
|
625
|
+
};
|
626
|
+
|
627
|
+
this.srandmember = function(k) {
|
628
|
+
validate_key(k, "srandmember");
|
629
|
+
var val = get_bbkey(k, "set");
|
630
|
+
if (val === null) {
|
631
|
+
return null;
|
632
|
+
}
|
633
|
+
var members = self.smembers(k);
|
634
|
+
var i = Math.floor(Math.random() * members.length);
|
635
|
+
var ret = members[i];
|
636
|
+
return ret;
|
637
|
+
};
|
638
|
+
|
639
|
+
this.srem = function(k, v) {
|
640
|
+
validate_key(k, "srem");
|
641
|
+
var val = get_bbkey(k, "set");
|
642
|
+
if (val === null) {
|
643
|
+
return 0;
|
644
|
+
}
|
645
|
+
var ret = 0;
|
646
|
+
if (val[v] === 1) {
|
647
|
+
ret = 1;
|
648
|
+
delete val[v];
|
649
|
+
var scard = parseInt(get_bbkeymeta(k, "card"), 10) - 1;
|
650
|
+
if (scard === 0) {
|
651
|
+
self.del(k);
|
652
|
+
} else {
|
653
|
+
set_bbkey(k, val, "set");
|
654
|
+
set_bbkeymeta(k, "card", scard);
|
655
|
+
}
|
656
|
+
}
|
657
|
+
return ret;
|
658
|
+
};
|
659
|
+
|
660
|
+
/* ---- SERVER ---- */
|
661
|
+
|
662
|
+
this.keys = function(filter) {
|
663
|
+
// TODO: implement filter.. for now just return *
|
664
|
+
var ret = [];
|
665
|
+
for (var k in keystore) {
|
666
|
+
if (keystore.hasOwnProperty(k)) {
|
667
|
+
ret.push(k);
|
668
|
+
}
|
669
|
+
}
|
670
|
+
return ret;
|
671
|
+
};
|
672
|
+
|
673
|
+
this.flushdb = function() {
|
674
|
+
var keys = self.keys("*");
|
675
|
+
for (var i in keys) {
|
676
|
+
self.del(keys[i]);
|
677
|
+
}
|
678
|
+
del_raw(keyskey);
|
679
|
+
return "OK";
|
680
|
+
};
|
681
|
+
|
682
|
+
this.select = function(i) {
|
683
|
+
if (isNaN(parseInt(i, 10))) {
|
684
|
+
throw(new BankersBoxException("db index must be an integer"));
|
685
|
+
}
|
686
|
+
db = i;
|
687
|
+
prefix = "bb:" + i.toString() + ":";
|
688
|
+
keyskey = "bb:" + i.toString() + "k:___keys___";
|
689
|
+
keystore = get_raw_value(keyskey, "set") || {};
|
690
|
+
};
|
691
|
+
|
692
|
+
var keystore = get_raw_value(keyskey, "set") || {};
|
693
|
+
|
694
|
+
}; /* end constructor */
|
695
|
+
|
696
|
+
|
697
|
+
BB.toString = function() {
|
698
|
+
return "[object BankersBox]";
|
699
|
+
};
|
700
|
+
|
701
|
+
|
702
|
+
var BankersBoxException = function(msg) {
|
703
|
+
this.type = "BankersBoxException";
|
704
|
+
this.toString = function() {
|
705
|
+
return this.type + ": " + msg.toString();
|
706
|
+
};
|
707
|
+
};
|
708
|
+
|
709
|
+
var BankersBoxKeyException = function(msg) {
|
710
|
+
BankersBoxException.call(this, msg);
|
711
|
+
this.type = "BankersBoxKeyException";
|
712
|
+
};
|
713
|
+
|
714
|
+
var BankersBoxLocalStorageAdapter = function() {
|
715
|
+
|
716
|
+
if (typeof(window) === 'undefined' || typeof(window.localStorage) === 'undefined') {
|
717
|
+
throw("window.localStorage is undefined, consider a different storage adapter");
|
718
|
+
}
|
719
|
+
|
720
|
+
this.getItem = function(k) {
|
721
|
+
return window.localStorage.getItem(k);
|
722
|
+
};
|
723
|
+
|
724
|
+
this.storeItem = function(k, v) {
|
725
|
+
try {
|
726
|
+
window.localStorage.setItem(k, v);
|
727
|
+
} catch (e) {
|
728
|
+
if (e == QUOTA_EXCEEDED_ERR) {
|
729
|
+
// TODO: properly handle quota exceeded behavior
|
730
|
+
}
|
731
|
+
throw(e);
|
732
|
+
}
|
733
|
+
};
|
734
|
+
|
735
|
+
this.removeItem = function(k) {
|
736
|
+
window.localStorage.removeItem(k);
|
737
|
+
};
|
738
|
+
|
739
|
+
this.clear = function() {
|
740
|
+
window.localStorage.clear();
|
741
|
+
};
|
742
|
+
};
|
743
|
+
|
744
|
+
var BankersBoxNullAdapter = function() {
|
745
|
+
|
746
|
+
this.getItem = function(k) {
|
747
|
+
};
|
748
|
+
|
749
|
+
this.storeItem = function(k, v) {
|
750
|
+
};
|
751
|
+
|
752
|
+
this.removeItem = function(k) {
|
753
|
+
};
|
754
|
+
|
755
|
+
this.clear = function() {
|
756
|
+
};
|
757
|
+
};
|
758
|
+
|
759
|
+
ctx.BankersBox = BB;
|
760
|
+
ctx.BankersBoxException = BankersBoxException;
|
761
|
+
ctx.BankersBoxKeyException = BankersBoxKeyException;
|
762
|
+
ctx.BankersBoxLocalStorageAdapter = BankersBoxLocalStorageAdapter;
|
763
|
+
ctx.BankersBoxNullAdapter = BankersBoxNullAdapter;
|
764
|
+
if (ctx !== window) {
|
765
|
+
ctx.mock_window = window;
|
766
|
+
}
|
767
|
+
|
768
|
+
})(typeof(module) !== 'undefined' && module && module.exports ? module.exports : window);
|