diff --git a/dist/bellhop.js b/dist/bellhop.js index 168ca9c..f152e7f 100644 --- a/dist/bellhop.js +++ b/dist/bellhop.js @@ -148,7 +148,7 @@ try { - data = JSON.parse(data); + data = JSON.parse(data, Bellhop.reviver); } catch(err) { @@ -446,6 +446,39 @@ this._sendLater = null; }; + /** + * When restoring from JSON via `JSON.parse`, we may pass a reviver function. + * In our case, this will check if the object has a specially-named property (`__classname`). + * If it does, we will attempt to construct a new instance of that class, rather than using a + * plain old Object. Note that this recurses through the object. + * See JSON.parse() + * @method reviver + * @static + * @param {String} key each key name + * @param {Object} value Object that we wish to restore + * @return {Object} The object that was parsed - either cast to a class, or not + */ + Bellhop.reviver = function(key, value) + { + if(value && typeof value.__classname == "string") + { + var _class = include(value.__classname, false); + if(_class) + { + var rtn = new _class(); + //if we may call fromJSON, do so + if(rtn.fromJSON) + { + rtn.fromJSON(value); + //return the cast Object + return rtn; + } + } + } + //return the object we were passed in + return value; + }; + // Assign to the global namespace window.Bellhop = Bellhop; diff --git a/dist/bellhop.min.js b/dist/bellhop.min.js index 70aeb8d..82b108d 100644 --- a/dist/bellhop.min.js +++ b/dist/bellhop.min.js @@ -1,2 +1,2 @@ /*! Bellhop 1.1.0 */ -!function(){"use strict";!function(a,b){var c=function(){this.onReceive=this.receive.bind(this),this.target=null,this.connected=!1,this.name="",this.isChild=!0,this.connecting=!1,this.origin="*",this._listeners={},this._sendLater=[],this.supported=null},d=c.prototype={};d.receive=function(a){if(a.source===this.target){var b=a.data;if("connected"===b){this.connecting=!1,this.connected=!0,this.trigger("connected"),this.isChild||this.target.postMessage(b,this.origin);var c,d=this._sendLater.length;if(d>0){for(c=0;d>c;c++){var e=this._sendLater[c];this.send(e.type,e.data)}this._sendLater.length=0}}else{if(!this.connected)return;try{b=JSON.parse(b)}catch(f){return}"object"==typeof b&&b.type&&this.trigger(b)}}},d.trigger=function(a){"string"==typeof a&&(a={type:a});var c=this._listeners[a.type];if(c!==b)for(var d=0,e=c.length;e>d;d++)c[d](a)},d.toString=function(){return"[Bellhop '"+this.name+"']"},d.connect=function(c,d){if(this.connecting)return this;this.disconnect(),this.connecting=!0;var e=this.isChild=c===b,f=this.target=e?a.top:c.contentWindow||c;return this.supported=e?!!f&&a!=f:!!f,this.origin=d===b?"*":d,a.attachEvent?a.attachEvent("onmessage",this.onReceive):a.addEventListener("message",this.onReceive),e&&(a===f?this.trigger("failed"):a.onload=function(){f.postMessage("connected",this.origin)}.bind(this)),this},d.disconnect=function(){return this.connected=!1,this.connecting=!1,this.origin=null,this.target=null,this._listeners={},this._sendLater.length=0,this.isChild=!0,a.detachEvent?a.detachEvent("onmessage",this.onReceive):a.removeEventListener("message",this.onReceive),this},d.on=function(a,c){if("string"!=typeof a)for(var d in a)this.on(d,a[d]);else for(var e=a.split(" "),f=0,g=e.length;g>f;f++)a=e[f],this._listeners[a]===b&&(this._listeners[a]=[]),this._listeners[a].push(c);return this},d.off=function(a,c){if(this._listeners[a]===b)return this;if(c===b)delete this._listeners[a];else for(var d=this._listeners[a],e=0,f=d.length;f>e;e++)if(d[e]===c){d.splice(e,1);break}return this},d.send=function(a,c){if("string"!=typeof a)throw"The event type must be a string";if(a={type:a},c!==b&&(a.data=c),this.connecting)this._sendLater.push(a);else{if(!this.connected)return this;this.target.postMessage(JSON.stringify(a),this.origin)}return this},d.fetch=function(a,c,d,e){var f=this;if(!this.connecting&&!this.connected)throw"No connection, please call connect() first";e=e===b?!1:e;var g=function(a){e&&f.off(a.type,g),c(a)};return this.on(a,g),this.send(a,d),this},d.respond=function(a,c,d){d=d===b?!1:d;var e=this,f=function(b){d&&e.off(b.type,f),e.send(a,c)};return this.on(a,f),this},d.destroy=function(){this.disconnect(),this._listeners=null,this._sendLater=null},a.Bellhop=c}(window);}(); \ No newline at end of file +!function(){"use strict";!function(a,b){var c=function(){this.onReceive=this.receive.bind(this),this.target=null,this.connected=!1,this.name="",this.isChild=!0,this.connecting=!1,this.origin="*",this._listeners={},this._sendLater=[],this.supported=null},d=c.prototype={};d.receive=function(a){if(a.source===this.target){var b=a.data;if("connected"===b){this.connecting=!1,this.connected=!0,this.trigger("connected"),this.isChild||this.target.postMessage(b,this.origin);var d,e=this._sendLater.length;if(e>0){for(d=0;e>d;d++){var f=this._sendLater[d];this.send(f.type,f.data)}this._sendLater.length=0}}else{if(!this.connected)return;try{b=JSON.parse(b,c.reviver)}catch(g){return}"object"==typeof b&&b.type&&this.trigger(b)}}},d.trigger=function(a){"string"==typeof a&&(a={type:a});var c=this._listeners[a.type];if(c!==b)for(var d=0,e=c.length;e>d;d++)c[d](a)},d.toString=function(){return"[Bellhop '"+this.name+"']"},d.connect=function(c,d){if(this.connecting)return this;this.disconnect(),this.connecting=!0;var e=this.isChild=c===b,f=this.target=e?a.top:c.contentWindow||c;return this.supported=e?!!f&&a!=f:!!f,this.origin=d===b?"*":d,a.attachEvent?a.attachEvent("onmessage",this.onReceive):a.addEventListener("message",this.onReceive),e&&(a===f?this.trigger("failed"):a.onload=function(){f.postMessage("connected",this.origin)}.bind(this)),this},d.disconnect=function(){return this.connected=!1,this.connecting=!1,this.origin=null,this.target=null,this._listeners={},this._sendLater.length=0,this.isChild=!0,a.detachEvent?a.detachEvent("onmessage",this.onReceive):a.removeEventListener("message",this.onReceive),this},d.on=function(a,c){if("string"!=typeof a)for(var d in a)this.on(d,a[d]);else for(var e=a.split(" "),f=0,g=e.length;g>f;f++)a=e[f],this._listeners[a]===b&&(this._listeners[a]=[]),this._listeners[a].push(c);return this},d.off=function(a,c){if(this._listeners[a]===b)return this;if(c===b)delete this._listeners[a];else for(var d=this._listeners[a],e=0,f=d.length;f>e;e++)if(d[e]===c){d.splice(e,1);break}return this},d.send=function(a,c){if("string"!=typeof a)throw"The event type must be a string";if(a={type:a},c!==b&&(a.data=c),this.connecting)this._sendLater.push(a);else{if(!this.connected)return this;this.target.postMessage(JSON.stringify(a),this.origin)}return this},d.fetch=function(a,c,d,e){var f=this;if(!this.connecting&&!this.connected)throw"No connection, please call connect() first";e=e===b?!1:e;var g=function(a){e&&f.off(a.type,g),c(a)};return this.on(a,g),this.send(a,d),this},d.respond=function(a,c,d){d=d===b?!1:d;var e=this,f=function(b){d&&e.off(b.type,f),e.send(a,c)};return this.on(a,f),this},d.destroy=function(){this.disconnect(),this._listeners=null,this._sendLater=null},c.reviver=function(a,b){if(b&&"string"==typeof b.__classname){var c=include(b.__classname,!1);if(c){var d=new c;if(d.fromJSON)return d.fromJSON(b),d}}return b},a.Bellhop=c}(window);}(); \ No newline at end of file diff --git a/src/Bellhop.js b/src/Bellhop.js index 2c30e24..6c0c3d2 100644 --- a/src/Bellhop.js +++ b/src/Bellhop.js @@ -147,7 +147,7 @@ try { - data = JSON.parse(data); + data = JSON.parse(data, Bellhop.reviver); } catch(err) { @@ -445,6 +445,39 @@ this._sendLater = null; }; + /** + * When restoring from JSON via `JSON.parse`, we may pass a reviver function. + * In our case, this will check if the object has a specially-named property (`__classname`). + * If it does, we will attempt to construct a new instance of that class, rather than using a + * plain old Object. Note that this recurses through the object. + * See JSON.parse() + * @method reviver + * @static + * @param {String} key each key name + * @param {Object} value Object that we wish to restore + * @return {Object} The object that was parsed - either cast to a class, or not + */ + Bellhop.reviver = function(key, value) + { + if(value && typeof value.__classname == "string") + { + var _class = include(value.__classname, false); + if(_class) + { + var rtn = new _class(); + //if we may call fromJSON, do so + if(rtn.fromJSON) + { + rtn.fromJSON(value); + //return the cast Object + return rtn; + } + } + } + //return the object we were passed in + return value; + }; + // Assign to the global namespace window.Bellhop = Bellhop;