Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

persisto

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

persisto - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

.github/CONTRIBUTING.md

2

bower.json
{
"name": "persisto",
"description": "Persist Javascript objects to localStorage and remote servers.",
"version": "1.0.0",
"version": "1.1.0",
"main": [

@@ -6,0 +6,0 @@ "dist/persisto.js"

@@ -1,2 +0,9 @@

# 1.0.0-0 / Unreleased
# 1.1.1-0 / Unreleased
*
# 1.1.0 / 2016-08-14
* [CHANGE] rename `.init` option to `.defaults`
* [CHANGE] rename `.debug` option to `.debugLevel`
# 1.0.0 / 2016-08-11
* [ADD] .set() creates intermediate objects if missing

@@ -3,0 +10,0 @@ * [ADD] .writeToForm() and .readFromForm() accept inputs with nested names

/*!
* persisto.js
*
* Persistent, editable objects for Javascript.
* Persistent Javascript objects and web forms using Web Storage.
*

@@ -9,4 +9,4 @@ * Copyright (c) 2016, Martin Wendt (http://wwWendt.de)

*
* @version 1.0.0
* @date 2016-08-11T21:56
* @version 1.1.0
* @date 2016-08-14T10:00
*/

@@ -41,15 +41,21 @@

if ( typeof namespace !== "string" ) { $.error("Missing required argument: namespace"); }
/* jshint ignore:start */ // disable warning 'PersistentObject is not defined'
if ( !(this instanceof PersistentObject) ) { $.error("Must use 'new' keyword"); }
/* jshint ignore:end */
if ( typeof namespace !== "string" ) {
$.error(this + ": Missing required argument: namespace");
}
this.opts = $.extend({
remote: null, // URL for GET/PUT, ajax options, or callback
init: {}, // default value if no data is found in localStorage
defaults: {}, // default value if no data is found in localStorage
commitDelay: 500, // commit changes after 0.5 seconds of inactivity
createParents: true, // set() creates missing intermediate parent objects for children
maxCommitDelay: 3000, // commit changes max. 3 seconds after first change
pushDelay: 5000, // push commits after 5 seconds of inactivity
maxPushDelay: 30000, // push commits max. 30 seconds after first change
debug: 2, // 0:quiet, 1:normal, 2:verbose
createParents: true, // set() creates intermediate parent objects for children
storage: window.localStorage,
// form: {},
// Default debugLevel is set to 1 by `grunt build`:
debugLevel: 1, // 0:quiet, 1:normal, 2:verbose
// Events

@@ -64,8 +70,6 @@ change: $.noop,

}, opts);
this.debugLevel = 1; // Set to 1 by 'grunt build'
this._checkTimer = null;
this.namespace = namespace;
this.storage = this.opts.storage;
this._data = this.opts.init;
this._data = this.opts.defaults;

@@ -98,3 +102,3 @@ this.offline = undefined;

// self._data = JSON.parse(prevValue);
self._data = $.extend({}, self.opts.init, JSON.parse(prevValue));
self._data = $.extend({}, self.opts.defaults, JSON.parse(prevValue));
} else {

@@ -107,4 +111,4 @@ console.warn(self + ": could not init from remote; falling back default.");

this.update();
// We still extend from opts.init, in case some fields where missing
this._data = $.extend({}, this.opts.init, this._data);
// We still extend from opts.defaults, in case some fields where missing
this._data = $.extend({}, this.opts.defaults, this._data);
// this.debug("init from storage", this._data);

@@ -122,3 +126,3 @@ dfd.resolve();

/** @type {string} */
version: "1.0.0", // Set to semver by 'grunt release'
version: "1.1.0", // Set to semver by 'grunt release'

@@ -146,3 +150,3 @@ /* Trigger commit/push according to current settings. */

} else {
this.debug("_invalidate recursive()");
this.debug("_invalidate() recursive");
}

@@ -156,3 +160,3 @@

this.debug("_invalidate: force commit",
this.debug("_invalidate(): force commit",
((now - prevChange) >= this.opts.commitDelay),

@@ -173,3 +177,3 @@ ((now - this.uncommittedSince) >= this.opts.maxCommitDelay));

this.debug("_invalidate: force push", ((now - prevChange) >= this.opts.pushDelay),
this.debug("_invalidate(): force push", ((now - prevChange) >= this.opts.pushDelay),
((now - this.unpushedSince) >= this.opts.maxPushDelay));

@@ -188,3 +192,3 @@ this.push();

// this.debug("Defer update:", nextCheck - now)
this.debug("_invalidate defer (" + hint + ") by " + (nextCheck - now) + "ms" );
this.debug("_invalidate(" + hint + ") defer by " + (nextCheck - now) + "ms" );
this._checkTimer = setTimeout(function() {

@@ -208,9 +212,9 @@ self._checkTimer = null; // no need to call clearTimeout in the handler...

},
/* */
/* Return readable string representation for this instance. */
toString: function() {
return "PersistentObject('" + this.namespace + "')";
},
/* */
/* Log to console if opts.debugLevel >= 2 */
debug: function() {
if ( this.opts.debug >= 1 ) {
if ( this.opts.debugLevel >= 2 ) {
Array.prototype.unshift.call(arguments, this.toString());

@@ -220,2 +224,9 @@ console.log.apply(window.console, arguments);

},
/* Log to console if opts.debugLevel >= 1 */
log: function() {
if ( this.opts.debugLevel >= 1 ) {
Array.prototype.unshift.call(arguments, this.toString());
console.log.apply(window.console, arguments);
}
},
/** Return true if there are uncommited or unpushed modifications. */

@@ -248,6 +259,4 @@ isDirty: function() {

if ( cur === undefined && i < (parts.length - 1) ) {
$.error("The property '" + key +
"' could not be accessed because parent '" +
parts.slice(0, i + 1).join(".") +
"' does not exist");
$.error(this + ": Property '" + key + "' could not be accessed because parent '" +
parts.slice(0, i + 1).join(".") + "' does not exist");
}

@@ -273,9 +282,7 @@ }

if ( this.opts.createParents ) {
this.debug("Creating intermediate parent '" + parts[i] + "'");
cur = parent[parts[i]] = {};
this.debug("Creating intermediate property '" + parts[i] + "'");
} else {
$.error("The property '" + key +
"' could not be set because parent '" +
parts.slice(0, i + 1).join(".") +
"' does not exist");
$.error(this + ": Property '" + key + "' could not be set because parent '" +
parts.slice(0, i + 1).join(".") + "' does not exist");
}

@@ -319,7 +326,7 @@ }

}
if ( this.opts.debug >= 2 && console.time ) { console.time(this + ".update"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.time(this + ".update"); }
var data = this.storage.getItem(this.namespace);
data = JSON.parse(data);
this._update(data);
if ( this.opts.debug >= 2 && console.time ) { console.timeEnd(this + ".update"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.timeEnd(this + ".update"); }
},

@@ -332,3 +339,3 @@ /** Write data to localStorage. */

}
if ( this.opts.debug >= 2 && console.time ) { console.time(this + ".commit"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.time(this + ".commit"); }
// try { data = JSON.stringify(this._data); } catch(e) { }

@@ -341,3 +348,3 @@ data = JSON.stringify(this._data);

// this.lastCommit = _getNow();
if ( this.opts.debug >= 2 && console.time ) { console.timeEnd(this + ".commit"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.timeEnd(this + ".commit"); }
return data;

@@ -352,3 +359,3 @@ },

}
if ( this.opts.debug >= 2 && console.time ) { console.time(this + ".pull"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.time(this + ".pull"); }
this.phase = "pull";

@@ -373,3 +380,3 @@ // return $.get(this.opts.remote, function(objData) {

self.phase = null;
if ( self.opts.debug >= 2 && console.time ) { console.timeEnd(self + ".pull"); }
if ( self.opts.debugLevel >= 2 && console.time ) { console.timeEnd(self + ".pull"); }
});

@@ -385,5 +392,5 @@ },

}
if ( this.opts.debug >= 2 && console.time ) { console.time(self + ".push"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.time(self + ".push"); }
this.phase = "push";
if ( !this.opts.remote ) { $.error(this + ": missing remote option"); }
if ( !this.opts.remote ) { $.error(this + ": Missing remote option"); }
return $.ajax({

@@ -402,3 +409,3 @@ type: "PUT",

self.phase = null;
if ( self.opts.debug >= 2 && console.time ) { console.timeEnd(self + ".push"); }
if ( self.opts.debugLevel >= 2 && console.time ) { console.timeEnd(self + ".push"); }
});

@@ -423,4 +430,4 @@ },

if ( self._data[name] === undefined ) {
self.debug("readFromForm: add field '" + name + "'");
self._data[name] = null;
self.debug("readFromForm: add field '" + name + "'");
}

@@ -427,0 +434,0 @@ });

@@ -1,4 +0,4 @@

/*! Persistent, editable objects for Javascript. - v1.0.0 - 2016-08-11 | https://github.com/mar10/persisto | Copyright (c) 2016 Martin Wendt; Licensed MIT */
/*! Persistent Javascript objects and web forms using Web Storage. - v1.1.0 - 2016-08-14 | https://github.com/mar10/persisto | Copyright (c) 2016 Martin Wendt; Licensed MIT */
!function(a,b,c,d){"use strict";function e(){return(new Date).getTime()}var f=9007199254740991;b.PersistentObject=function(c,f){var g,h=this,i=a.Deferred(),j=e();"string"!=typeof c&&a.error("Missing required argument: namespace"),this.opts=a.extend({remote:null,init:{},commitDelay:500,maxCommitDelay:3e3,pushDelay:5e3,maxPushDelay:3e4,debug:2,createParents:!0,storage:b.localStorage,change:a.noop,commit:a.noop,conflict:a.noop,error:a.noop,pull:a.noop,push:a.noop,update:a.noop},f),this.debugLevel = 1,this._checkTimer=null,this.namespace=c,this.storage=this.opts.storage,this._data=this.opts.init,this.offline=d,this.phase=null,this.uncommittedSince=null,this.unpushedSince=null,this.lastUpdate=0,this.lastPull=0,this.commitCount=0,this.pushCount=0,this.lastModified=j,this.ready=i.promise,g=this.storage?this.storage.getItem(this.namespace):null,this.opts.remote?this.pull().done(function(){h.offline=!1,i.resolve()}).fail(function(){h.offline=!0,null!=g?(console.warn(h+": could not init from remote; falling back to storage."),h._data=a.extend({},h.opts.init,JSON.parse(g))):console.warn(h+": could not init from remote; falling back default."),i.resolve()}):null!=g?(this.update(),this._data=a.extend({},this.opts.init,this._data),i.resolve()):i.resolve()},b.PersistentObject.prototype={version:"1.0.0",_invalidate:function(a,b){var c=this,d=this.lastModified,g=e(),h=0,i=0,j=0;this._checkTimer&&(clearTimeout(this._checkTimer),this._checkTimer=null),b?this.debug("_invalidate recursive()"):(this.lastModified=g,this.uncommittedSince||(this.uncommittedSince=g),this.unpushedSince||(this.unpushedSince=g),this.opts.change(a)),this.storage&&(g-d>=this.opts.commitDelay||g-this.uncommittedSince>=this.opts.maxCommitDelay?(this.debug("_invalidate: force commit",g-d>=this.opts.commitDelay,g-this.uncommittedSince>=this.opts.maxCommitDelay),this.commit()):h=Math.min(g+this.opts.commitDelay+1,this.uncommittedSince+this.opts.maxCommitDelay+1)),this.opts.remote&&(g-d>=this.opts.pushDelay||g-this.unpushedSince>=this.opts.maxPushDelay?(this.debug("_invalidate: force push",g-d>=this.opts.pushDelay,g-this.unpushedSince>=this.opts.maxPushDelay),this.push()):i=Math.min(g+this.opts.pushDelay+1,this.unpushedSince+this.opts.maxPushDelay+1)),(h||i)&&(j=Math.min(h||f,i||f),this.debug("_invalidate defer ("+a+") by "+(j-g)+"ms"),this._checkTimer=setTimeout(function(){c._checkTimer=null,c._invalidate.call(c,null,!0)},j-g))},_update:function(a){this.uncommittedSince&&(console.warn("Updating an uncommitted object."),this.conflict(a,this._data)===!1)||(this._data=a,this.lastUpdate=e())},toString:function(){return"PersistentObject('"+this.namespace+"')"},debug:function(){this.opts.debug>=1&&(Array.prototype.unshift.call(arguments,this.toString()),console.log.apply(b.console,arguments))},isDirty:function(){return!!(this.storage&&this.uncommittedSince||this.opts.remote&&this.unpushedSince)},isReady:function(){return"pending"!==this.ready.state},get:function(b){var c,e=this._data,f=(""+b).replace(/\[(\w+)\]/g,".$1").replace(/^\./,"").split(".");for(c=0;c<f.length;c++)e=e[f[c]],e===d&&c<f.length-1&&a.error("The property '"+b+"' could not be accessed because parent '"+f.slice(0,c+1).join(".")+"' does not exist");return e},_setOrRemove:function(b,c,e){var f,g,h=this._data,i=(""+b).replace(/\[(\w+)\]/g,".$1").replace(/^\./,"").split("."),j=i.pop();for(f=0;f<i.length;f++)g=h,h=g[i[f]],h===d&&(this.opts.createParents?(h=g[i[f]]={},this.debug("Creating intermediate property '"+i[f]+"'")):a.error("The property '"+b+"' could not be set because parent '"+i.slice(0,f+1).join(".")+"' does not exist"));h[j]!==c&&(e===!0?(delete h[j],this._invalidate("remove")):(h[j]=c,this._invalidate("set")))},set:function(a,b){return this._setOrRemove(a,b,!1)},remove:function(a){return this._setOrRemove(a,d,!0)},reset:function(a){this._data=a||{},this._invalidate("reset")},setDirty:function(a){a===!1||this._invalidate("explicit")},update:function(){this.phase&&a.error(this+": Trying to update while '"+this.phase+"' is pending."),this.opts.debug>=2&&console.time&&console.time(this+".update");var b=this.storage.getItem(this.namespace);b=JSON.parse(b),this._update(b),this.opts.debug>=2&&console.time&&console.timeEnd(this+".update")},commit:function(){var b;return this.phase&&a.error(this+": Trying to commit while '"+this.phase+"' is pending."),this.opts.debug>=2&&console.time&&console.time(this+".commit"),b=JSON.stringify(this._data),this.storage.setItem(this.namespace,b),this.uncommittedSince=null,this.commitCount+=1,this.opts.debug>=2&&console.time&&console.timeEnd(this+".commit"),b},pull:function(){var b=this;return this.phase&&a.error(this+": Trying to pull while '"+this.phase+"' is pending."),this.opts.debug>=2&&console.time&&console.time(this+".pull"),this.phase="pull",a.ajax({type:"GET",url:this.opts.remote}).done(function(c){var d=c;a.isArray(c)||a.isPlainObject(c)?d=JSON.stringify(c):c=JSON.parse(c),b.storage.setItem(b.namespace,d),b._update(c),b.lastPull=e()}).fail(function(){b.opts.error(arguments)}).always(function(){b.phase=null,b.opts.debug>=2&&console.time&&console.timeEnd(b+".pull")})},push:function(){var b=this,c=this.commit();return this.phase&&a.error(this+": Trying to push while '"+this.phase+"' is pending."),this.opts.debug>=2&&console.time&&console.time(b+".push"),this.phase="push",this.opts.remote||a.error(this+": missing remote option"),a.ajax({type:"PUT",url:this.opts.remote,data:c}).done(function(){b.unpushedSince=null,b.pushCount+=1}).fail(function(){b.opts.error(arguments)}).always(function(){b.phase=null,b.opts.debug>=2&&console.time&&console.timeEnd(b+".push")})},readFromForm:function(b,c){var e=this,f=a(b),g=a.extend({addNew:!1,coerce:!0,trim:!0},c);g.addNew&&f.find("[name]").each(function(){var b=a(this).attr("name");e._data[b]===d&&(e._data[b]=null,e.debug("readFromForm: add field '"+b+"'"))}),a.each(this._data,function(b,c){var d,h=f.find("[name='"+b+"']"),i=h.attr("type");return h.length?("radio"===i?d=h.filter(":checked").val():"checkbox"===i&&1===h.length?d=!!h.filter(":checked").length:"checkbox"===i&&h.length>1?(d=[],h.filter(":checked").each(function(){d.push(a(this).val())})):(d=h.val(),g.trim&&"string"==typeof d&&(d=a.trim(d))),void e.set(b,d)):void e.debug("readFromForm: field not found: '"+b+"'")})},writeToForm:function(b,c){var d=a(b);a.each(this._data,function(b,c){var e=d.find("[name='"+b+"']"),f=e.attr("type");e.length&&("radio"===f?e.filter("[value='"+c+"']").prop("checked",!0):"checkbox"===f?1===e.length?e.prop("checked",!!c):e.each(function(){a(this).prop("checked",a.isArray(c)?a.inArray(this.value,c)>=0:this.value===c)}):e.is("select")?e.find("option").each(function(){a(this).prop("selected",a.isArray(c)?a.inArray(this.value,c)>=0:this.value===c)}):e.val(c))})}}}(jQuery,window,document);
!function(a,b,c,d){"use strict";function e(){return(new Date).getTime()}var f=9007199254740991;b.PersistentObject=function(c,f){var g,h=this,i=a.Deferred(),j=e();this instanceof PersistentObject||a.error("Must use 'new' keyword"),"string"!=typeof c&&a.error(this+": Missing required argument: namespace"),this.opts=a.extend({remote:null,defaults:{},commitDelay:500,createParents:!0,maxCommitDelay:3e3,pushDelay:5e3,maxPushDelay:3e4,storage:b.localStorage,debugLevel: 1,change:a.noop,commit:a.noop,conflict:a.noop,error:a.noop,pull:a.noop,push:a.noop,update:a.noop},f),this._checkTimer=null,this.namespace=c,this.storage=this.opts.storage,this._data=this.opts.defaults,this.offline=d,this.phase=null,this.uncommittedSince=null,this.unpushedSince=null,this.lastUpdate=0,this.lastPull=0,this.commitCount=0,this.pushCount=0,this.lastModified=j,this.ready=i.promise,g=this.storage?this.storage.getItem(this.namespace):null,this.opts.remote?this.pull().done(function(){h.offline=!1,i.resolve()}).fail(function(){h.offline=!0,null!=g?(console.warn(h+": could not init from remote; falling back to storage."),h._data=a.extend({},h.opts.defaults,JSON.parse(g))):console.warn(h+": could not init from remote; falling back default."),i.resolve()}):null!=g?(this.update(),this._data=a.extend({},this.opts.defaults,this._data),i.resolve()):i.resolve()},b.PersistentObject.prototype={version:"1.1.0",_invalidate:function(a,b){var c=this,d=this.lastModified,g=e(),h=0,i=0,j=0;this._checkTimer&&(clearTimeout(this._checkTimer),this._checkTimer=null),b?this.debug("_invalidate() recursive"):(this.lastModified=g,this.uncommittedSince||(this.uncommittedSince=g),this.unpushedSince||(this.unpushedSince=g),this.opts.change(a)),this.storage&&(g-d>=this.opts.commitDelay||g-this.uncommittedSince>=this.opts.maxCommitDelay?(this.debug("_invalidate(): force commit",g-d>=this.opts.commitDelay,g-this.uncommittedSince>=this.opts.maxCommitDelay),this.commit()):h=Math.min(g+this.opts.commitDelay+1,this.uncommittedSince+this.opts.maxCommitDelay+1)),this.opts.remote&&(g-d>=this.opts.pushDelay||g-this.unpushedSince>=this.opts.maxPushDelay?(this.debug("_invalidate(): force push",g-d>=this.opts.pushDelay,g-this.unpushedSince>=this.opts.maxPushDelay),this.push()):i=Math.min(g+this.opts.pushDelay+1,this.unpushedSince+this.opts.maxPushDelay+1)),(h||i)&&(j=Math.min(h||f,i||f),this.debug("_invalidate("+a+") defer by "+(j-g)+"ms"),this._checkTimer=setTimeout(function(){c._checkTimer=null,c._invalidate.call(c,null,!0)},j-g))},_update:function(a){this.uncommittedSince&&(console.warn("Updating an uncommitted object."),this.conflict(a,this._data)===!1)||(this._data=a,this.lastUpdate=e())},toString:function(){return"PersistentObject('"+this.namespace+"')"},debug:function(){this.opts.debugLevel>=2&&(Array.prototype.unshift.call(arguments,this.toString()),console.log.apply(b.console,arguments))},log:function(){this.opts.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),console.log.apply(b.console,arguments))},isDirty:function(){return!!(this.storage&&this.uncommittedSince||this.opts.remote&&this.unpushedSince)},isReady:function(){return"pending"!==this.ready.state},get:function(b){var c,e=this._data,f=(""+b).replace(/\[(\w+)\]/g,".$1").replace(/^\./,"").split(".");for(c=0;c<f.length;c++)e=e[f[c]],e===d&&c<f.length-1&&a.error(this+": Property '"+b+"' could not be accessed because parent '"+f.slice(0,c+1).join(".")+"' does not exist");return e},_setOrRemove:function(b,c,e){var f,g,h=this._data,i=(""+b).replace(/\[(\w+)\]/g,".$1").replace(/^\./,"").split("."),j=i.pop();for(f=0;f<i.length;f++)g=h,h=g[i[f]],h===d&&(this.opts.createParents?(this.debug("Creating intermediate parent '"+i[f]+"'"),h=g[i[f]]={}):a.error(this+": Property '"+b+"' could not be set because parent '"+i.slice(0,f+1).join(".")+"' does not exist"));h[j]!==c&&(e===!0?(delete h[j],this._invalidate("remove")):(h[j]=c,this._invalidate("set")))},set:function(a,b){return this._setOrRemove(a,b,!1)},remove:function(a){return this._setOrRemove(a,d,!0)},reset:function(a){this._data=a||{},this._invalidate("reset")},setDirty:function(a){a===!1||this._invalidate("explicit")},update:function(){this.phase&&a.error(this+": Trying to update while '"+this.phase+"' is pending."),this.opts.debugLevel>=2&&console.time&&console.time(this+".update");var b=this.storage.getItem(this.namespace);b=JSON.parse(b),this._update(b),this.opts.debugLevel>=2&&console.time&&console.timeEnd(this+".update")},commit:function(){var b;return this.phase&&a.error(this+": Trying to commit while '"+this.phase+"' is pending."),this.opts.debugLevel>=2&&console.time&&console.time(this+".commit"),b=JSON.stringify(this._data),this.storage.setItem(this.namespace,b),this.uncommittedSince=null,this.commitCount+=1,this.opts.debugLevel>=2&&console.time&&console.timeEnd(this+".commit"),b},pull:function(){var b=this;return this.phase&&a.error(this+": Trying to pull while '"+this.phase+"' is pending."),this.opts.debugLevel>=2&&console.time&&console.time(this+".pull"),this.phase="pull",a.ajax({type:"GET",url:this.opts.remote}).done(function(c){var d=c;a.isArray(c)||a.isPlainObject(c)?d=JSON.stringify(c):c=JSON.parse(c),b.storage.setItem(b.namespace,d),b._update(c),b.lastPull=e()}).fail(function(){b.opts.error(arguments)}).always(function(){b.phase=null,b.opts.debugLevel>=2&&console.time&&console.timeEnd(b+".pull")})},push:function(){var b=this,c=this.commit();return this.phase&&a.error(this+": Trying to push while '"+this.phase+"' is pending."),this.opts.debugLevel>=2&&console.time&&console.time(b+".push"),this.phase="push",this.opts.remote||a.error(this+": Missing remote option"),a.ajax({type:"PUT",url:this.opts.remote,data:c}).done(function(){b.unpushedSince=null,b.pushCount+=1}).fail(function(){b.opts.error(arguments)}).always(function(){b.phase=null,b.opts.debugLevel>=2&&console.time&&console.timeEnd(b+".push")})},readFromForm:function(b,c){var e=this,f=a(b),g=a.extend({addNew:!1,coerce:!0,trim:!0},c);g.addNew&&f.find("[name]").each(function(){var b=a(this).attr("name");e._data[b]===d&&(e.debug("readFromForm: add field '"+b+"'"),e._data[b]=null)}),a.each(this._data,function(b,c){var d,h=f.find("[name='"+b+"']"),i=h.attr("type");return h.length?("radio"===i?d=h.filter(":checked").val():"checkbox"===i&&1===h.length?d=!!h.filter(":checked").length:"checkbox"===i&&h.length>1?(d=[],h.filter(":checked").each(function(){d.push(a(this).val())})):(d=h.val(),g.trim&&"string"==typeof d&&(d=a.trim(d))),void e.set(b,d)):void e.debug("readFromForm: field not found: '"+b+"'")})},writeToForm:function(b,c){var d=a(b);a.each(this._data,function(b,c){var e=d.find("[name='"+b+"']"),f=e.attr("type");e.length&&("radio"===f?e.filter("[value='"+c+"']").prop("checked",!0):"checkbox"===f?1===e.length?e.prop("checked",!!c):e.each(function(){a(this).prop("checked",a.isArray(c)?a.inArray(this.value,c)>=0:this.value===c)}):e.is("select")?e.find("option").each(function(){a(this).prop("selected",a.isArray(c)?a.inArray(this.value,c)>=0:this.value===c)}):e.val(c))})}}}(jQuery,window,document);
//# sourceMappingURL=persisto.min.js.map
{
"name": "persisto",
"title": "Persistent, editable objects for Javascript.",
"title": "Persistent Javascript objects and web forms using Web Storage.",
"description": "Persist Javascript objects to localStorage and remote servers.",
"filename": "dist/persisto.min.js",
"main": "dist/persisto.js",
"version": "1.0.0",
"version": "1.1.0",
"homepage": "https://github.com/mar10/persisto",

@@ -9,0 +9,0 @@ "author": {

# persisto [![GitHub version](https://badge.fury.io/gh/mar10%2Fpersisto.svg)](https://github.com/mar10/persisto/releases/latest) [![Build Status](https://travis-ci.org/mar10/persisto.svg?branch=master)](https://travis-ci.org/mar10/persisto)
> Persistent, editable objects for Javascript.
> Persistent Javascript objects and web forms using Web Storage.

@@ -32,5 +32,14 @@ Features

[Download the latest persisto.js](https://github.com/mar10/persisto/releases)
or include directly [from CDN](https://www.jsdelivr.com/projects/persisto):
```html
<script src="//cdn.jsdelivr.net/persisto/1/persisto.min.js"></script>
```
then instantiate a `PersistentObject`:
```js
var store = PersistentObject("mySettings", {
init: {
defaults: {
theme: "default"

@@ -43,3 +52,3 @@ }

present. Otherwise, `store` is initialized to the default values that we
passed with the `.init` option.
passed with the `.defaults` option.

@@ -60,3 +69,8 @@ We can access data using `set`, `get`, `remove`, `reset`:

**More:**
* Try the [online example](http://plnkr.co/edit/qcDmvN?p=preview).
* Run the [unit tests](http://rawgit.com/mar10/persisto/master/test/unit/test-core.html).
## Synchronize Data with HTML Forms

@@ -71,3 +85,3 @@

var settingsStore = PersistentObject("mySettings", {
init: {
defaults: {
nickname: "anonymous",

@@ -82,6 +96,6 @@ theme: "default"

// Allow users to edit and save settings:
$("#settingsForm").submit(function(e){
$("#settingsForm").submit(function(event){
// ... maybe some validations here ...
settingsStore.readFromForm(this);
e.preventDefault();
event.preventDefault();
});

@@ -137,12 +151,28 @@ ```

Arrays are only a special form of plain Javascript objects, so we can store and
access them like this:
access them as top level type like this:
```js
var store = PersistentObject("mySettings", {
init: ["a", "b", "c"]
defaults: ["a", "b", "c"]
});
store.get("[0]"); // 'a'
store.set("[1]", "b2");
```
However if we use child properties, it is even easier:
```js
var store = PersistentObject("mySettings", {
defaults: {
values: ["a", "b", "c"]
}
});
store.get("values")[0]; // 'a'
store.get("values[0]"); // 'a'
S.each(store.get("values"), function(idx, obj) { ... });
store.set("values[1]", "b2");
```
### Performance and Direct Access

@@ -156,3 +186,3 @@

```js
store._data.owner = {name: "joe", age: 42});
store._data.owner = { name: "joe", age: 42 };
store._data.owner.role = "manager";

@@ -167,3 +197,3 @@ delete store._data.owner.age;

By default, changed values will be commited to webStorage after a small delay
(see `.commitDelay` option). This allows to collate sequences of mutliple changes
(see `.commitDelay` option). This allows to collate sequences of multiple changes
into one single write command.

@@ -199,3 +229,3 @@

$.ready,
// PersistentObjects must be pulled
// PersistentObject must be pulled
store.ready

@@ -230,9 +260,9 @@

</dd>
<dt>debug</dt>
<dt>debugLevel</dt>
<dd>
Type: <code>int</code>,
default: <code>2</code><br>
default: <code>1</code><br>
Verbosity level: 0:quiet, 1:normal, 2:verbose.
</dd>
<dt>init</dt>
<dt>defaults</dt>
<dd>

@@ -239,0 +269,0 @@ Type: <code>object</code>,

/*!
* persisto.js
*
* Persistent, editable objects for Javascript.
* Persistent Javascript objects and web forms using Web Storage.
*

@@ -40,15 +40,21 @@ * Copyright (c) 2016, Martin Wendt (http://wwWendt.de)

if ( typeof namespace !== "string" ) { $.error("Missing required argument: namespace"); }
/* jshint ignore:start */ // disable warning 'PersistentObject is not defined'
if ( !(this instanceof PersistentObject) ) { $.error("Must use 'new' keyword"); }
/* jshint ignore:end */
if ( typeof namespace !== "string" ) {
$.error(this + ": Missing required argument: namespace");
}
this.opts = $.extend({
remote: null, // URL for GET/PUT, ajax options, or callback
init: {}, // default value if no data is found in localStorage
defaults: {}, // default value if no data is found in localStorage
commitDelay: 500, // commit changes after 0.5 seconds of inactivity
createParents: true, // set() creates missing intermediate parent objects for children
maxCommitDelay: 3000, // commit changes max. 3 seconds after first change
pushDelay: 5000, // push commits after 5 seconds of inactivity
maxPushDelay: 30000, // push commits max. 30 seconds after first change
debug: 2, // 0:quiet, 1:normal, 2:verbose
createParents: true, // set() creates intermediate parent objects for children
storage: window.localStorage,
// form: {},
// Default debugLevel is set to 1 by `grunt build`:
debugLevel: 2, // 0:quiet, 1:normal, 2:verbose
// Events

@@ -63,8 +69,6 @@ change: $.noop,

}, opts);
this.debugLevel = 2; // Set to 1 by 'grunt build'
this._checkTimer = null;
this.namespace = namespace;
this.storage = this.opts.storage;
this._data = this.opts.init;
this._data = this.opts.defaults;

@@ -97,3 +101,3 @@ this.offline = undefined;

// self._data = JSON.parse(prevValue);
self._data = $.extend({}, self.opts.init, JSON.parse(prevValue));
self._data = $.extend({}, self.opts.defaults, JSON.parse(prevValue));
} else {

@@ -106,4 +110,4 @@ console.warn(self + ": could not init from remote; falling back default.");

this.update();
// We still extend from opts.init, in case some fields where missing
this._data = $.extend({}, this.opts.init, this._data);
// We still extend from opts.defaults, in case some fields where missing
this._data = $.extend({}, this.opts.defaults, this._data);
// this.debug("init from storage", this._data);

@@ -144,3 +148,3 @@ dfd.resolve();

} else {
this.debug("_invalidate recursive()");
this.debug("_invalidate() recursive");
}

@@ -154,3 +158,3 @@

this.debug("_invalidate: force commit",
this.debug("_invalidate(): force commit",
((now - prevChange) >= this.opts.commitDelay),

@@ -171,3 +175,3 @@ ((now - this.uncommittedSince) >= this.opts.maxCommitDelay));

this.debug("_invalidate: force push", ((now - prevChange) >= this.opts.pushDelay),
this.debug("_invalidate(): force push", ((now - prevChange) >= this.opts.pushDelay),
((now - this.unpushedSince) >= this.opts.maxPushDelay));

@@ -186,3 +190,3 @@ this.push();

// this.debug("Defer update:", nextCheck - now)
this.debug("_invalidate defer (" + hint + ") by " + (nextCheck - now) + "ms" );
this.debug("_invalidate(" + hint + ") defer by " + (nextCheck - now) + "ms" );
this._checkTimer = setTimeout(function() {

@@ -206,9 +210,9 @@ self._checkTimer = null; // no need to call clearTimeout in the handler...

},
/* */
/* Return readable string representation for this instance. */
toString: function() {
return "PersistentObject('" + this.namespace + "')";
},
/* */
/* Log to console if opts.debugLevel >= 2 */
debug: function() {
if ( this.opts.debug >= 1 ) {
if ( this.opts.debugLevel >= 2 ) {
Array.prototype.unshift.call(arguments, this.toString());

@@ -218,2 +222,9 @@ console.log.apply(window.console, arguments);

},
/* Log to console if opts.debugLevel >= 1 */
log: function() {
if ( this.opts.debugLevel >= 1 ) {
Array.prototype.unshift.call(arguments, this.toString());
console.log.apply(window.console, arguments);
}
},
/** Return true if there are uncommited or unpushed modifications. */

@@ -246,6 +257,4 @@ isDirty: function() {

if ( cur === undefined && i < (parts.length - 1) ) {
$.error("The property '" + key +
"' could not be accessed because parent '" +
parts.slice(0, i + 1).join(".") +
"' does not exist");
$.error(this + ": Property '" + key + "' could not be accessed because parent '" +
parts.slice(0, i + 1).join(".") + "' does not exist");
}

@@ -271,9 +280,7 @@ }

if ( this.opts.createParents ) {
this.debug("Creating intermediate parent '" + parts[i] + "'");
cur = parent[parts[i]] = {};
this.debug("Creating intermediate property '" + parts[i] + "'");
} else {
$.error("The property '" + key +
"' could not be set because parent '" +
parts.slice(0, i + 1).join(".") +
"' does not exist");
$.error(this + ": Property '" + key + "' could not be set because parent '" +
parts.slice(0, i + 1).join(".") + "' does not exist");
}

@@ -317,7 +324,7 @@ }

}
if ( this.opts.debug >= 2 && console.time ) { console.time(this + ".update"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.time(this + ".update"); }
var data = this.storage.getItem(this.namespace);
data = JSON.parse(data);
this._update(data);
if ( this.opts.debug >= 2 && console.time ) { console.timeEnd(this + ".update"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.timeEnd(this + ".update"); }
},

@@ -330,3 +337,3 @@ /** Write data to localStorage. */

}
if ( this.opts.debug >= 2 && console.time ) { console.time(this + ".commit"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.time(this + ".commit"); }
// try { data = JSON.stringify(this._data); } catch(e) { }

@@ -339,3 +346,3 @@ data = JSON.stringify(this._data);

// this.lastCommit = _getNow();
if ( this.opts.debug >= 2 && console.time ) { console.timeEnd(this + ".commit"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.timeEnd(this + ".commit"); }
return data;

@@ -350,3 +357,3 @@ },

}
if ( this.opts.debug >= 2 && console.time ) { console.time(this + ".pull"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.time(this + ".pull"); }
this.phase = "pull";

@@ -371,3 +378,3 @@ // return $.get(this.opts.remote, function(objData) {

self.phase = null;
if ( self.opts.debug >= 2 && console.time ) { console.timeEnd(self + ".pull"); }
if ( self.opts.debugLevel >= 2 && console.time ) { console.timeEnd(self + ".pull"); }
});

@@ -383,5 +390,5 @@ },

}
if ( this.opts.debug >= 2 && console.time ) { console.time(self + ".push"); }
if ( this.opts.debugLevel >= 2 && console.time ) { console.time(self + ".push"); }
this.phase = "push";
if ( !this.opts.remote ) { $.error(this + ": missing remote option"); }
if ( !this.opts.remote ) { $.error(this + ": Missing remote option"); }
return $.ajax({

@@ -400,3 +407,3 @@ type: "PUT",

self.phase = null;
if ( self.opts.debug >= 2 && console.time ) { console.timeEnd(self + ".push"); }
if ( self.opts.debugLevel >= 2 && console.time ) { console.timeEnd(self + ".push"); }
});

@@ -421,4 +428,4 @@ },

if ( self._data[name] === undefined ) {
self.debug("readFromForm: add field '" + name + "'");
self._data[name] = null;
self.debug("readFromForm: add field '" + name + "'");
}

@@ -425,0 +432,0 @@ });

@@ -22,6 +22,16 @@ ;(function($, window, document, undefined) {

QUnit.test( "Access core data (storage = null)", function( assert ) {
assert.expect(19);
assert.expect(21);
assert.equal( window.localStorage.length, 0, "localStorage is clean" );
assert.throws(function(){
var _dummy = PersistentObject();
}, /Must use 'new' keyword/,
"Fail if 'new' keyword is missing");
assert.throws(function(){
var _dummy = new PersistentObject();
}, /Missing required argument: namespace/,
"Fail if 'namespace' argument is missing");
var store = new PersistentObject("foo", {

@@ -59,3 +69,3 @@ storage: null, // don't commit/update local storage

},
/The property 'bar.qux.undefined.boo' could not be accessed because parent 'bar.qux.undefined' does not exist/,
/PersistentObject\('foo'\): Property 'bar.qux.undefined.boo' could not be accessed because parent 'bar.qux.undefined' does not exist/,
"get() raises error if parent does not exist");

@@ -79,3 +89,3 @@

},
/The property 'bar.undefined2.test' could not be set because parent 'bar.undefined2' does not exist/,
/PersistentObject\('foo'\): Property 'bar.undefined2.test' could not be set because parent 'bar.undefined2' does not exist/,
"set() raises error if createParents is false");

@@ -137,3 +147,3 @@

remote: null, // don't pull/push remote endpoint
init: {
defaults: {
title: "foo",

@@ -182,3 +192,3 @@ details: "bar\nbaz",

store = new PersistentObject("foo", {
init: {
defaults: {
title: "qux",

@@ -230,3 +240,3 @@ details: "qux",

var i, v,
store = new PersistentObject("foo", {storage: null, debug: 0}),
store = new PersistentObject("foo", {storage: null, debugLevel: 0}),
count = 100000;

@@ -290,3 +300,3 @@

var i, v,
store = new PersistentObject("foo", {storage: window.sessionStorage, debug: 0}),
store = new PersistentObject("foo", {storage: window.sessionStorage, debugLevel: 0}),
count = 10000;

@@ -350,3 +360,3 @@

var i, v,
store = new PersistentObject("foo", {storage: window.sessionStorage, commitDelay: 0, debug: 0}),
store = new PersistentObject("foo", {storage: window.sessionStorage, commitDelay: 0, debugLevel: 0}),
count = 1000;

@@ -353,0 +363,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc