New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

tabex

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tabex - npm Package Compare versions

Comparing version

to
1.0.1

support/demo_template/index.jade

7

CHANGELOG.md

@@ -0,1 +1,8 @@

1.0.1 / 2015-06-08
------------------
- Multiple IE fixes.
- Code polish, more tests.
1.0.0 / 2015-06-04

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

142

dist/tabex.js

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

/*! tabex 1.0.0 https://github.com//nodeca/tabex @license MIT */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.tabex = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/*! tabex 1.0.1 https://github.com//nodeca/tabex @license MIT */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.tabex = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';

@@ -227,2 +227,3 @@

router: routerInstances[namespace],
namespace: namespace,
origin: options.origin

@@ -243,3 +244,3 @@ });

/* global window */
/* global document, window */
var localStorage = window.localStorage;

@@ -253,2 +254,5 @@

var LS_OK = (function () {
// IE 8 does not send `key` and `newValue` in event
if (document.documentMode && document.documentMode < 9) { return false; }
if (!localStorage) { return false; }

@@ -314,2 +318,3 @@

var LocalStorage = require('./local_storage');
var $$ = require('./utils');

@@ -340,2 +345,9 @@

// IE broadcasts storage events also to the same window, we should filter that messages
this.__storage_events_filter__ = [];
for (var i = 0; i < 100; i++) {
this.__storage_events_filter__.push('');
}
this.__ls__ = new LocalStorage();

@@ -347,3 +359,3 @@

// Handle `localStorage` update
window.addEventListener('storage', function (e) {
$$.addEvent(window, 'storage', function (e) {
// In IE 9 without delay `e.newValue` will be broken

@@ -360,8 +372,14 @@ // http://stackoverflow.com/questions/9292576/localstorage-getitem-returns-old-data-in-ie-9

this.__destroyed__ = false;
window.addEventListener('beforeunload', this.__destroy__.bind(this));
window.addEventListener('unload', this.__destroy__.bind(this));
$$.addEvent(window, 'beforeunload', function () {
self.__destroy__();
});
$$.addEvent(window, 'unload', function () {
self.__destroy__();
});
// Update current tab info and check master alive
this.__check_master__();
setInterval(this.__check_master__.bind(this), UPDATE_INTERVAL);
setInterval(function () {
self.__check_master__();
}, UPDATE_INTERVAL);
}

@@ -394,4 +412,3 @@

// Add message to `localStorage` to distribute over Router instances
this.__ls__.setItem(this.__namespace__ + 'broadcast', JSON.stringify({
var serializedMessage = JSON.stringify({
channel: channel,

@@ -402,4 +419,9 @@ message: message,

random: Math.floor(Math.random() * 1e10)
}));
});
// Add message to `localStorage` to distribute over Router instances
this.__storage_events_filter__.shift();
this.__storage_events_filter__.push(this.__namespace__ + 'broadcast' + '_' + serializedMessage);
this.__ls__.setItem(this.__namespace__ + 'broadcast', serializedMessage);
// Emit message for all clients and proxies registered on this router

@@ -446,2 +468,4 @@ this.__handlers__.forEach(function (handler) {

if (this.__get_alive_router_ids__().sort()[0] === this.__node_id__) {
this.__storage_events_filter__.pop();
this.__storage_events_filter__.push(this.__namespace__ + 'master' + '_' + this.__node_id__);
this.__ls__.setItem(this.__namespace__ + 'master', this.__node_id__);

@@ -468,14 +492,11 @@ this.__on_master_changed__(this.__node_id__);

// Receive resended message from master and send it to tab subscribers
// localStorage change handler. Updates master ID, receive subscribe requests
//
Router.prototype.__on_data_changed__ = function (serializedData) {
var data = JSON.parse(serializedData);
Router.prototype.__on_changed__ = function (e) {
this.__receive_message__(data.channel, data.message);
};
// IE broadcasts storage events also to the same window, we should filter that messages
if (this.__storage_events_filter__.indexOf(e.key + '_' + e.newValue) !== -1) {
return;
}
// localStorage change handler. Updates master ID, receive subscribe requests
//
Router.prototype.__on_changed__ = function (e) {
// Master changed

@@ -486,7 +507,2 @@ if (e.key === this.__namespace__ + 'master') {

// Receive message from master
if (e.key === this.__namespace__ + 'message') {
this.__on_data_changed__(e.newValue);
}
// Channels list changed

@@ -573,2 +589,4 @@ if (e.key.indexOf(this.__router_channels_prefix__) === 0) {

if (this.__ls__.getItem(this.__router_channels_prefix__ + this.__node_id__) !== serializedChannels) {
this.__storage_events_filter__.pop();
this.__storage_events_filter__.push(this.__router_channels_prefix__ + this.__node_id__ + '_' + serializedChannels);
this.__ls__.setItem(this.__router_channels_prefix__ + this.__node_id__, serializedChannels);

@@ -628,2 +646,4 @@ this.__on_channels_list_changed__();

if (this.__get_alive_router_ids__().indexOf(this.__master_id__) === -1) {
this.__storage_events_filter__.pop();
this.__storage_events_filter__.push(this.__namespace__ + 'master' + '_' + this.__node_id__);
this.__ls__.setItem(this.__namespace__ + 'master', this.__node_id__);

@@ -637,3 +657,3 @@ this.__on_master_changed__(this.__node_id__);

},{"./local_storage":4}],6:[function(require,module,exports){
},{"./local_storage":4,"./utils":7}],6:[function(require,module,exports){
// Tunnel to communicate between client in root window and router in iframe

@@ -645,2 +665,3 @@ //

/* global document, window */
var $$ = require('./utils');

@@ -677,6 +698,7 @@

// Setup target for messages from iframe (we should not use `*` for security reasons)
self.__iframe__.contentWindow.postMessage({
origin: window.location.origin,
self.__iframe__.contentWindow.postMessage(JSON.stringify({
// `window.location.origin` available from IE 11
origin: window.location.origin || window.location.protocol + '//' + window.location.host,
namespace: self.__namespace__
}, self.__iframe_url__);
}), self.__iframe_url__);

@@ -687,3 +709,3 @@ self.__iframe_done__ = true;

self.__pending__.forEach(function (data) {
self.__iframe__.contentWindow.postMessage(data, self.__iframe_url__);
self.__iframe__.contentWindow.postMessage(JSON.stringify(data), self.__iframe_url__);
});

@@ -695,3 +717,3 @@

// Listen messages from iframe
window.addEventListener('message', function (event) {
$$.addEvent(window, 'message', function (event) {
// Check sender origin

@@ -702,4 +724,12 @@ if (self.__iframe_url__.indexOf(event.origin) !== 0) {

var data;
try {
data = JSON.parse(event.data);
} catch (__) {
return;
}
// Ignore messages from another namespace (and messages from other possible senders)
if (event.data.namespace !== self.__namespace__) {
if (data.namespace !== self.__namespace__) {
return;

@@ -709,3 +739,3 @@ }

self.__handlers__.forEach(function (handler) {
handler(event.data.channel, event.data.message);
handler(data.channel, data.message);
});

@@ -716,3 +746,3 @@ });

document.addEventListener('DOMContentLoaded', function () {
$$.addEvent(document, 'DOMContentLoaded', function () {
document.querySelector('body').appendChild(self.__iframe__);

@@ -735,7 +765,7 @@ });

} else {
this.__iframe__.contentWindow.postMessage({
this.__iframe__.contentWindow.postMessage(JSON.stringify({
channel: channel,
message: message,
namespace: this.__namespace__
}, this.__iframe_url__);
}), this.__iframe_url__);
}

@@ -767,4 +797,7 @@ };

this.__namespace__ = options.namespace || 'tabex_default_';
this.__origin_first_check__ = options.origin || window.location.origin;
// `window.location.origin` available from IE 11
this.__origin_first_check__ = options.origin ||
(window.location.origin || window.location.protocol + '//' + window.location.host);
// Always convert origin list to array

@@ -789,3 +822,3 @@ if (!Array.isArray(this.__origin_first_check__)) {

// Handle messages from parent window
window.addEventListener('message', function (event) {
$$.addEvent(window, 'message', function (event) {
var isOriginValid = false;

@@ -809,4 +842,12 @@

var data;
try {
data = JSON.parse(event.data);
} catch (__) {
return;
}
// Ignore messages from another namespace (and messages from other possible senders)
if (event.data.namespace !== self.__namespace__) {
if (data.namespace !== self.__namespace__) {
return;

@@ -816,11 +857,11 @@ }

// Save real origin from parent window and start routing
if (!self.__origin__ && event.data.origin) {
self.__origin__ = event.data.origin;
if (!self.__origin__ && data.origin) {
self.__origin__ = data.origin;
self.__router__.onmessage(function (channel, message) {
window.parent.postMessage({
window.parent.postMessage(JSON.stringify({
channel: channel,
message: message,
namespace: self.__namespace__
}, self.__origin__);
}), self.__origin__);
});

@@ -831,3 +872,3 @@

self.__router__.broadcast(event.data.channel, event.data.message);
self.__router__.broadcast(data.channel, data.message);
});

@@ -840,6 +881,9 @@ }

},{}],7:[function(require,module,exports){
},{"./utils":7}],7:[function(require,module,exports){
'use strict';
/* global document */
// Run each function with params and callback after all

@@ -874,3 +918,15 @@ //

// `addEventListener` not supported in IE <= 8, fallback to `attachEvent`
//
exports.addEvent = function (target, type, listener) {
if (document.addEventListener) {
target.addEventListener(type, listener);
return;
}
target.attachEvent('on' + type, listener);
};
},{}]},{},[1])(1)
});

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

/*! tabex 1.0.0 https://github.com//nodeca/tabex @license MIT */
!function(_){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=_();else if("function"==typeof define&&define.amd)define([],_);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.tabex=_()}}(function(){return function _(e,t,n){function i(r,a){if(!t[r]){if(!e[r]){var o="function"==typeof require&&require;if(!a&&o)return o(r,!0);if(s)return s(r,!0);var h=new Error("Cannot find module '"+r+"'");throw h.code="MODULE_NOT_FOUND",h}var c=t[r]={exports:{}};e[r][0].call(c.exports,function(_){var t=e[r][1][_];return i(t?t:_)},c,c.exports,_,e,t,n)}return t[r].exports}for(var s="function"==typeof require&&require,r=0;r<n.length;r++)i(n[r]);return i}({1:[function(_,e){"use strict";e.exports=_("./lib")},{"./lib":3}],2:[function(_,e){"use strict";function t(_){var e=this;this.__filters_in__=[],this.__filters_out__=[],this.__subscriptions__=[],this.__node_id__=Math.floor(1e10*Math.random())+1,this.__last_message_cnt__=0,this.__ignore_list__={},this.__router__=_.router,this.__router__.onmessage(function(_,t){e.__onmessage__(_,t)})}var n=_("./utils");t.prototype.emit=function(_,e,t){var i=this,s={id:this.__node_id__+"_"+this.__last_message_cnt__++,node_id:this.__node_id__,data:e};t||(this.__ignore_list__[s.id]=!0),n.asyncEach(this.__filters_out__,_,s,function(_,e){i.__router__.broadcast(_,e)})},t.prototype.on=function(_,e){return this.__subscriptions__.push({channel:_,handler:e}),this.emit("!sys.channels.add",{channel:_}),this},t.prototype.off=function(_,e){var t=this;this.__subscriptions__=this.__subscriptions__.reduce(function(n,i){return i.channel!==_||e&&e!==i.handler?(n.push(i),n):(t.emit("!sys.channels.remove",{channel:_}),n)},[])},t.prototype.filterIn=function(_){return this.__filters_in__.push(_),this},t.prototype.filterOut=function(_){return this.__filters_out__.push(_),this},t.prototype.__onmessage__=function(_,e){var t=this;n.asyncEach(this.__filters_in__,_,e,function(_,e){t.__ignore_list__[e.id]||t.__subscriptions__.forEach(function(t){t.channel===_&&t.handler(e.data,_)})})},e.exports=t},{"./utils":7}],3:[function(_,e){"use strict";var t=_("./router"),n=_("./client"),i=_("./tunnel"),s={},r={_:{}};r._.Router=t,r._.Client=n,r._.Tunnel=i,r.client=function(_){_=_||{};var e,r=_.namespace||"tabex_default_";return _.iframe?e=new i.TunnelClient(_):(s[r]||(s[r]=new t({namespace:r})),e=s[r]),new n({router:e})},r.router=function(_){_=_||{};var e=_.namespace||"tabex_default_";return s[e]||(s[e]=new t({namespace:e})),new i.TunnelRouter({router:s[e],origin:_.origin}),s[e]},e.exports=r},{"./client":2,"./router":5,"./tunnel":6}],4:[function(_,e){"use strict";function t(){}var n=window.localStorage,i={},s=function(){if(!n)return!1;try{n.setItem("live_local_storage_is_writable_test",""),n.removeItem("live_local_storage_is_writable_test")}catch(_){return!1}return!0}();Object.defineProperty(t.prototype,"length",{get:function(){return s?n.length:Object.keys(i).length}}),t.prototype.getItem=function(_){return s?n.getItem(_):i.hasOwnProperty(_)?i[_]:null},t.prototype.setItem=function(_,e){s?n.setItem(_,e):i[_]=e},t.prototype.removeItem=function(_){s?n.removeItem(_):i[_]=null},t.prototype.key=function(_){return s?n.key(_):Object.keys(i)[_]},e.exports=t},{}],5:[function(_,e){"use strict";function t(_){var e=this;_=_||{},this.__namespace__=_.namespace||"tabex_default_",this.__node_id__=Math.floor(1e10*Math.random())+1,this.__last_message_cnt__=0,this.__handlers__=[],this.__router_id_prefix__=this.__namespace__+"router_",this.__router_channels_prefix__=this.__namespace__+"subscribed_",this.__router_channels__={},this.__ls__=new n,this.__master_id__=null,window.addEventListener("storage",function(_){setTimeout(function(){e.__on_changed__(_)},1)}),this.__destroyed__=!1,window.addEventListener("beforeunload",this.__destroy__.bind(this)),window.addEventListener("unload",this.__destroy__.bind(this)),this.__check_master__(),setInterval(this.__check_master__.bind(this),s)}var n=_("./local_storage"),i=4e3,s=i/4;t.prototype.broadcast=function(_,e){return"!sys.channels.add"===_?(this.__router_channels__[e.data.channel]=this.__router_channels__[e.data.channel]||0,this.__router_channels__[e.data.channel]++,void this.__update_channels_list__()):"!sys.channels.remove"===_?(this.__router_channels__[e.data.channel]=this.__router_channels__[e.data.channel]||0,this.__router_channels__[e.data.channel]--,void this.__update_channels_list__()):(this.__ls__.setItem(this.__namespace__+"broadcast",JSON.stringify({channel:_,message:e,random:Math.floor(1e10*Math.random())})),void this.__handlers__.forEach(function(t){t(_,e)}))},t.prototype.onmessage=function(_){var e=this;this.__handlers__.push(_),setTimeout(function(){_("!sys.master",{data:{node_id:e.__node_id__,master_id:e.__master_id__},node_id:e.__node_id__,id:e.__node_id__+"_"+e.__last_message_cnt__++}),e.__on_channels_list_changed__()},0)},t.prototype.__on_master_changed__=function(_){var e=this;return _?(this.__master_id__=+_,void this.__handlers__.forEach(function(_){_("!sys.master",{data:{node_id:e.__node_id__,master_id:e.__master_id__},node_id:e.__node_id__,id:e.__node_id__+"_"+e.__last_message_cnt__++})})):void(this.__get_alive_router_ids__().sort()[0]===this.__node_id__&&(this.__ls__.setItem(this.__namespace__+"master",this.__node_id__),this.__on_master_changed__(this.__node_id__)))},t.prototype.__on_data_changed__=function(_){var e=JSON.parse(_);this.__receive_message__(e.channel,e.message)},t.prototype.__on_changed__=function(_){if(_.key===this.__namespace__+"master"&&this.__on_master_changed__(_.newValue),_.key===this.__namespace__+"message"&&this.__on_data_changed__(_.newValue),0===_.key.indexOf(this.__router_channels_prefix__)&&this.__on_channels_list_changed__(),_.key===this.__namespace__+"broadcast"){var e=JSON.parse(_.newValue);this.__handlers__.forEach(function(_){_(e.channel,e.message)})}},t.prototype.__destroy__=function(){this.__destroyed__||(this.__destroyed__=!0,this.__ls__.removeItem(this.__router_id_prefix__+this.__node_id__),this.__ls__.removeItem(this.__router_channels_prefix__+this.__node_id__),this.__master_id__===this.__node_id__&&this.__ls__.removeItem(this.__namespace__+"master"))},t.prototype.__get_alive_router_ids__=function(){for(var _,e,t=Date.now()-i,n=[],s=0;s<this.__ls__.length;s++)e=this.__ls__.key(s),0===e.indexOf(this.__router_id_prefix__)&&(_=+e.substr(this.__router_id_prefix__.length),this.__ls__.getItem(e)<t?(this.__ls__.removeItem(e),this.__ls__.removeItem(this.__router_channels_prefix__+_)):n.push(_));return n},t.prototype.__update_channels_list__=function(){var _=this,e=[];Object.keys(this.__router_channels__).forEach(function(t){_.__router_channels__[t]>0&&e.push(t)});var t=JSON.stringify(e.sort());this.__ls__.getItem(this.__router_channels_prefix__+this.__node_id__)!==t&&(this.__ls__.setItem(this.__router_channels_prefix__+this.__node_id__,t),this.__on_channels_list_changed__())},t.prototype.__on_channels_list_changed__=function(){for(var _,e=this,t=[],n=0;n<this.__ls__.length;n++)_=this.__ls__.key(n),0===_.indexOf(this.__router_channels_prefix__)&&(t=t.concat(JSON.parse(this.__ls__.getItem(_))));t=t.reduce(function(_,e){return-1===_.indexOf(e)&&_.push(e),_},[]),this.__handlers__.forEach(function(_){_("!sys.channels.refresh",{id:e.__node_id__+"_"+e.__last_message_cnt__++,node_id:e.__node_id__,data:{channels:t}})})},t.prototype.__check_master__=function(){this.__ls__.setItem(this.__router_id_prefix__+this.__node_id__,Date.now()),this.__master_id__=+this.__ls__.getItem(this.__namespace__+"master"),-1===this.__get_alive_router_ids__().indexOf(this.__master_id__)&&(this.__ls__.setItem(this.__namespace__+"master",this.__node_id__),this.__on_master_changed__(this.__node_id__))},e.exports=t},{"./local_storage":4}],6:[function(_,e,t){"use strict";function n(_){var e=this;this.__namespace__=_.namespace||"tabex_default_",this.__handlers__=[],this.__iframe_url__=_.iframe,this.__iframe_done__=!1,this.__pending__=[],this.__iframe__=document.createElement("iframe"),this.__iframe__.style.left="-1000px",this.__iframe__.style.position="absolute",this.__iframe__.onload=function(){e.__iframe__.contentWindow.postMessage({origin:window.location.origin,namespace:e.__namespace__},e.__iframe_url__),e.__iframe_done__=!0,e.__pending__.forEach(function(_){e.__iframe__.contentWindow.postMessage(_,e.__iframe_url__)}),e.__pending__=null},window.addEventListener("message",function(_){0===e.__iframe_url__.indexOf(_.origin)&&_.data.namespace===e.__namespace__&&e.__handlers__.forEach(function(e){e(_.data.channel,_.data.message)})}),this.__iframe__.src=this.__iframe_url__,document.addEventListener("DOMContentLoaded",function(){document.querySelector("body").appendChild(e.__iframe__)})}function i(_){var e,t=this;for(this.__namespace__=_.namespace||"tabex_default_",this.__origin_first_check__=_.origin||window.location.origin,Array.isArray(this.__origin_first_check__)||(this.__origin_first_check__=[this.__origin_first_check__]),e=0;e<this.__origin_first_check__.length;e++)this.__origin_first_check__[e]=this.__origin_first_check__[e].replace(/[-\/\\^$+?.()|[\]{}]/g,"\\$&"),this.__origin_first_check__[e]=this.__origin_first_check__[e].replace(/[*]/g,".+?"),this.__origin_first_check__[e]=new RegExp(this.__origin_first_check__[e]);this.__origin__=null,this.__router__=_.router,window.addEventListener("message",function(_){var n=!1;if(!t.__origin__||t.__origin__!==_.origin){for(e=0;e<t.__origin_first_check__.length;e++)if(t.__origin_first_check__[e].test(_.origin)){n=!0;break}if(!n)return}if(_.data.namespace===t.__namespace__)return!t.__origin__&&_.data.origin?(t.__origin__=_.data.origin,void t.__router__.onmessage(function(_,e){window.parent.postMessage({channel:_,message:e,namespace:t.__namespace__},t.__origin__)})):void t.__router__.broadcast(_.data.channel,_.data.message)})}n.prototype.broadcast=function(_,e){this.__iframe_done__?this.__iframe__.contentWindow.postMessage({channel:_,message:e,namespace:this.__namespace__},this.__iframe_url__):this.__pending__.push({channel:_,message:e,namespace:this.__namespace__})},n.prototype.onmessage=function(_){this.__handlers__.push(_)},t.TunnelClient=n,t.TunnelRouter=i},{}],7:[function(_,e,t){"use strict";t.asyncEach=function(_){function e(){if(0===_.length)return void t.apply(this,arguments);var n=_.shift();n.apply(this,Array.prototype.slice.call(arguments,0).concat(e))}_=_.slice(0);var t=arguments[arguments.length-1],n=Array.prototype.slice.call(arguments,1);n.pop(),e.apply(this,n)}},{}]},{},[1])(1)});
/*! tabex 1.0.1 https://github.com//nodeca/tabex @license MIT */
!function(_){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=_();else if("function"==typeof define&&define.amd)define([],_);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.tabex=_()}}(function(){return function _(e,t,n){function i(r,o){if(!t[r]){if(!e[r]){var a="function"==typeof require&&require;if(!o&&a)return a(r,!0);if(s)return s(r,!0);var h=new Error("Cannot find module '"+r+"'");throw h.code="MODULE_NOT_FOUND",h}var c=t[r]={exports:{}};e[r][0].call(c.exports,function(_){var t=e[r][1][_];return i(t?t:_)},c,c.exports,_,e,t,n)}return t[r].exports}for(var s="function"==typeof require&&require,r=0;r<n.length;r++)i(n[r]);return i}({1:[function(_,e){"use strict";e.exports=_("./lib")},{"./lib":3}],2:[function(_,e){"use strict";function t(_){var e=this;this.__filters_in__=[],this.__filters_out__=[],this.__subscriptions__=[],this.__node_id__=Math.floor(1e10*Math.random())+1,this.__last_message_cnt__=0,this.__ignore_list__={},this.__router__=_.router,this.__router__.onmessage(function(_,t){e.__onmessage__(_,t)})}var n=_("./utils");t.prototype.emit=function(_,e,t){var i=this,s={id:this.__node_id__+"_"+this.__last_message_cnt__++,node_id:this.__node_id__,data:e};t||(this.__ignore_list__[s.id]=!0),n.asyncEach(this.__filters_out__,_,s,function(_,e){i.__router__.broadcast(_,e)})},t.prototype.on=function(_,e){return this.__subscriptions__.push({channel:_,handler:e}),this.emit("!sys.channels.add",{channel:_}),this},t.prototype.off=function(_,e){var t=this;this.__subscriptions__=this.__subscriptions__.reduce(function(n,i){return i.channel!==_||e&&e!==i.handler?(n.push(i),n):(t.emit("!sys.channels.remove",{channel:_}),n)},[])},t.prototype.filterIn=function(_){return this.__filters_in__.push(_),this},t.prototype.filterOut=function(_){return this.__filters_out__.push(_),this},t.prototype.__onmessage__=function(_,e){var t=this;n.asyncEach(this.__filters_in__,_,e,function(_,e){t.__ignore_list__[e.id]||t.__subscriptions__.forEach(function(t){t.channel===_&&t.handler(e.data,_)})})},e.exports=t},{"./utils":7}],3:[function(_,e){"use strict";var t=_("./router"),n=_("./client"),i=_("./tunnel"),s={},r={_:{}};r._.Router=t,r._.Client=n,r._.Tunnel=i,r.client=function(_){_=_||{};var e,r=_.namespace||"tabex_default_";return _.iframe?e=new i.TunnelClient(_):(s[r]||(s[r]=new t({namespace:r})),e=s[r]),new n({router:e})},r.router=function(_){_=_||{};var e=_.namespace||"tabex_default_";return s[e]||(s[e]=new t({namespace:e})),new i.TunnelRouter({router:s[e],namespace:e,origin:_.origin}),s[e]},e.exports=r},{"./client":2,"./router":5,"./tunnel":6}],4:[function(_,e){"use strict";function t(){}var n=window.localStorage,i={},s=function(){if(document.documentMode&&document.documentMode<9)return!1;if(!n)return!1;try{n.setItem("live_local_storage_is_writable_test",""),n.removeItem("live_local_storage_is_writable_test")}catch(_){return!1}return!0}();Object.defineProperty(t.prototype,"length",{get:function(){return s?n.length:Object.keys(i).length}}),t.prototype.getItem=function(_){return s?n.getItem(_):i.hasOwnProperty(_)?i[_]:null},t.prototype.setItem=function(_,e){s?n.setItem(_,e):i[_]=e},t.prototype.removeItem=function(_){s?n.removeItem(_):i[_]=null},t.prototype.key=function(_){return s?n.key(_):Object.keys(i)[_]},e.exports=t},{}],5:[function(_,e){"use strict";function t(_){var e=this;_=_||{},this.__namespace__=_.namespace||"tabex_default_",this.__node_id__=Math.floor(1e10*Math.random())+1,this.__last_message_cnt__=0,this.__handlers__=[],this.__router_id_prefix__=this.__namespace__+"router_",this.__router_channels_prefix__=this.__namespace__+"subscribed_",this.__router_channels__={},this.__storage_events_filter__=[];for(var t=0;100>t;t++)this.__storage_events_filter__.push("");this.__ls__=new n,this.__master_id__=null,i.addEvent(window,"storage",function(_){setTimeout(function(){e.__on_changed__(_)},1)}),this.__destroyed__=!1,i.addEvent(window,"beforeunload",function(){e.__destroy__()}),i.addEvent(window,"unload",function(){e.__destroy__()}),this.__check_master__(),setInterval(function(){e.__check_master__()},r)}var n=_("./local_storage"),i=_("./utils"),s=4e3,r=s/4;t.prototype.broadcast=function(_,e){if("!sys.channels.add"===_)return this.__router_channels__[e.data.channel]=this.__router_channels__[e.data.channel]||0,this.__router_channels__[e.data.channel]++,void this.__update_channels_list__();if("!sys.channels.remove"===_)return this.__router_channels__[e.data.channel]=this.__router_channels__[e.data.channel]||0,this.__router_channels__[e.data.channel]--,void this.__update_channels_list__();var t=JSON.stringify({channel:_,message:e,random:Math.floor(1e10*Math.random())});this.__storage_events_filter__.shift(),this.__storage_events_filter__.push(this.__namespace__+"broadcast_"+t),this.__ls__.setItem(this.__namespace__+"broadcast",t),this.__handlers__.forEach(function(t){t(_,e)})},t.prototype.onmessage=function(_){var e=this;this.__handlers__.push(_),setTimeout(function(){_("!sys.master",{data:{node_id:e.__node_id__,master_id:e.__master_id__},node_id:e.__node_id__,id:e.__node_id__+"_"+e.__last_message_cnt__++}),e.__on_channels_list_changed__()},0)},t.prototype.__on_master_changed__=function(_){var e=this;return _?(this.__master_id__=+_,void this.__handlers__.forEach(function(_){_("!sys.master",{data:{node_id:e.__node_id__,master_id:e.__master_id__},node_id:e.__node_id__,id:e.__node_id__+"_"+e.__last_message_cnt__++})})):void(this.__get_alive_router_ids__().sort()[0]===this.__node_id__&&(this.__storage_events_filter__.pop(),this.__storage_events_filter__.push(this.__namespace__+"master_"+this.__node_id__),this.__ls__.setItem(this.__namespace__+"master",this.__node_id__),this.__on_master_changed__(this.__node_id__)))},t.prototype.__on_changed__=function(_){if(-1===this.__storage_events_filter__.indexOf(_.key+"_"+_.newValue)&&(_.key===this.__namespace__+"master"&&this.__on_master_changed__(_.newValue),0===_.key.indexOf(this.__router_channels_prefix__)&&this.__on_channels_list_changed__(),_.key===this.__namespace__+"broadcast")){var e=JSON.parse(_.newValue);this.__handlers__.forEach(function(_){_(e.channel,e.message)})}},t.prototype.__destroy__=function(){this.__destroyed__||(this.__destroyed__=!0,this.__ls__.removeItem(this.__router_id_prefix__+this.__node_id__),this.__ls__.removeItem(this.__router_channels_prefix__+this.__node_id__),this.__master_id__===this.__node_id__&&this.__ls__.removeItem(this.__namespace__+"master"))},t.prototype.__get_alive_router_ids__=function(){for(var _,e,t=Date.now()-s,n=[],i=0;i<this.__ls__.length;i++)e=this.__ls__.key(i),0===e.indexOf(this.__router_id_prefix__)&&(_=+e.substr(this.__router_id_prefix__.length),this.__ls__.getItem(e)<t?(this.__ls__.removeItem(e),this.__ls__.removeItem(this.__router_channels_prefix__+_)):n.push(_));return n},t.prototype.__update_channels_list__=function(){var _=this,e=[];Object.keys(this.__router_channels__).forEach(function(t){_.__router_channels__[t]>0&&e.push(t)});var t=JSON.stringify(e.sort());this.__ls__.getItem(this.__router_channels_prefix__+this.__node_id__)!==t&&(this.__storage_events_filter__.pop(),this.__storage_events_filter__.push(this.__router_channels_prefix__+this.__node_id__+"_"+t),this.__ls__.setItem(this.__router_channels_prefix__+this.__node_id__,t),this.__on_channels_list_changed__())},t.prototype.__on_channels_list_changed__=function(){for(var _,e=this,t=[],n=0;n<this.__ls__.length;n++)_=this.__ls__.key(n),0===_.indexOf(this.__router_channels_prefix__)&&(t=t.concat(JSON.parse(this.__ls__.getItem(_))));t=t.reduce(function(_,e){return-1===_.indexOf(e)&&_.push(e),_},[]),this.__handlers__.forEach(function(_){_("!sys.channels.refresh",{id:e.__node_id__+"_"+e.__last_message_cnt__++,node_id:e.__node_id__,data:{channels:t}})})},t.prototype.__check_master__=function(){this.__ls__.setItem(this.__router_id_prefix__+this.__node_id__,Date.now()),this.__master_id__=+this.__ls__.getItem(this.__namespace__+"master"),-1===this.__get_alive_router_ids__().indexOf(this.__master_id__)&&(this.__storage_events_filter__.pop(),this.__storage_events_filter__.push(this.__namespace__+"master_"+this.__node_id__),this.__ls__.setItem(this.__namespace__+"master",this.__node_id__),this.__on_master_changed__(this.__node_id__))},e.exports=t},{"./local_storage":4,"./utils":7}],6:[function(_,e,t){"use strict";function n(_){var e=this;this.__namespace__=_.namespace||"tabex_default_",this.__handlers__=[],this.__iframe_url__=_.iframe,this.__iframe_done__=!1,this.__pending__=[],this.__iframe__=document.createElement("iframe"),this.__iframe__.style.left="-1000px",this.__iframe__.style.position="absolute",this.__iframe__.onload=function(){e.__iframe__.contentWindow.postMessage(JSON.stringify({origin:window.location.origin||window.location.protocol+"//"+window.location.host,namespace:e.__namespace__}),e.__iframe_url__),e.__iframe_done__=!0,e.__pending__.forEach(function(_){e.__iframe__.contentWindow.postMessage(JSON.stringify(_),e.__iframe_url__)}),e.__pending__=null},s.addEvent(window,"message",function(_){if(0===e.__iframe_url__.indexOf(_.origin)){var t;try{t=JSON.parse(_.data)}catch(n){return}t.namespace===e.__namespace__&&e.__handlers__.forEach(function(_){_(t.channel,t.message)})}}),this.__iframe__.src=this.__iframe_url__,s.addEvent(document,"DOMContentLoaded",function(){document.querySelector("body").appendChild(e.__iframe__)})}function i(_){var e,t=this;for(this.__namespace__=_.namespace||"tabex_default_",this.__origin_first_check__=_.origin||window.location.origin||window.location.protocol+"//"+window.location.host,Array.isArray(this.__origin_first_check__)||(this.__origin_first_check__=[this.__origin_first_check__]),e=0;e<this.__origin_first_check__.length;e++)this.__origin_first_check__[e]=this.__origin_first_check__[e].replace(/[-\/\\^$+?.()|[\]{}]/g,"\\$&"),this.__origin_first_check__[e]=this.__origin_first_check__[e].replace(/[*]/g,".+?"),this.__origin_first_check__[e]=new RegExp(this.__origin_first_check__[e]);this.__origin__=null,this.__router__=_.router,s.addEvent(window,"message",function(_){var n=!1;if(!t.__origin__||t.__origin__!==_.origin){for(e=0;e<t.__origin_first_check__.length;e++)if(t.__origin_first_check__[e].test(_.origin)){n=!0;break}if(!n)return}var i;try{i=JSON.parse(_.data)}catch(s){return}if(i.namespace===t.__namespace__)return!t.__origin__&&i.origin?(t.__origin__=i.origin,void t.__router__.onmessage(function(_,e){window.parent.postMessage(JSON.stringify({channel:_,message:e,namespace:t.__namespace__}),t.__origin__)})):void t.__router__.broadcast(i.channel,i.message)})}var s=_("./utils");n.prototype.broadcast=function(_,e){this.__iframe_done__?this.__iframe__.contentWindow.postMessage(JSON.stringify({channel:_,message:e,namespace:this.__namespace__}),this.__iframe_url__):this.__pending__.push({channel:_,message:e,namespace:this.__namespace__})},n.prototype.onmessage=function(_){this.__handlers__.push(_)},t.TunnelClient=n,t.TunnelRouter=i},{"./utils":7}],7:[function(_,e,t){"use strict";t.asyncEach=function(_){function e(){if(0===_.length)return void t.apply(this,arguments);var n=_.shift();n.apply(this,Array.prototype.slice.call(arguments,0).concat(e))}_=_.slice(0);var t=arguments[arguments.length-1],n=Array.prototype.slice.call(arguments,1);n.pop(),e.apply(this,n)},t.addEvent=function(_,e,t){return document.addEventListener?void _.addEventListener(e,t):void _.attachEvent("on"+e,t)}},{}]},{},[1])(1)});

@@ -68,2 +68,3 @@ 'use strict';

router: routerInstances[namespace],
namespace: namespace,
origin: options.origin

@@ -70,0 +71,0 @@ });

@@ -6,3 +6,3 @@ // localStorage wrapper with fallback to memory emulation

/* global window */
/* global document, window */
var localStorage = window.localStorage;

@@ -16,2 +16,5 @@

var LS_OK = (function () {
// IE 8 does not send `key` and `newValue` in event
if (document.documentMode && document.documentMode < 9) { return false; }
if (!localStorage) { return false; }

@@ -18,0 +21,0 @@

@@ -8,2 +8,3 @@ // LocalStorage router

var LocalStorage = require('./local_storage');
var $$ = require('./utils');

@@ -34,2 +35,9 @@

// IE broadcasts storage events also to the same window, we should filter that messages
this.__storage_events_filter__ = [];
for (var i = 0; i < 100; i++) {
this.__storage_events_filter__.push('');
}
this.__ls__ = new LocalStorage();

@@ -41,3 +49,3 @@

// Handle `localStorage` update
window.addEventListener('storage', function (e) {
$$.addEvent(window, 'storage', function (e) {
// In IE 9 without delay `e.newValue` will be broken

@@ -54,8 +62,14 @@ // http://stackoverflow.com/questions/9292576/localstorage-getitem-returns-old-data-in-ie-9

this.__destroyed__ = false;
window.addEventListener('beforeunload', this.__destroy__.bind(this));
window.addEventListener('unload', this.__destroy__.bind(this));
$$.addEvent(window, 'beforeunload', function () {
self.__destroy__();
});
$$.addEvent(window, 'unload', function () {
self.__destroy__();
});
// Update current tab info and check master alive
this.__check_master__();
setInterval(this.__check_master__.bind(this), UPDATE_INTERVAL);
setInterval(function () {
self.__check_master__();
}, UPDATE_INTERVAL);
}

@@ -88,4 +102,3 @@

// Add message to `localStorage` to distribute over Router instances
this.__ls__.setItem(this.__namespace__ + 'broadcast', JSON.stringify({
var serializedMessage = JSON.stringify({
channel: channel,

@@ -96,4 +109,9 @@ message: message,

random: Math.floor(Math.random() * 1e10)
}));
});
// Add message to `localStorage` to distribute over Router instances
this.__storage_events_filter__.shift();
this.__storage_events_filter__.push(this.__namespace__ + 'broadcast' + '_' + serializedMessage);
this.__ls__.setItem(this.__namespace__ + 'broadcast', serializedMessage);
// Emit message for all clients and proxies registered on this router

@@ -140,2 +158,4 @@ this.__handlers__.forEach(function (handler) {

if (this.__get_alive_router_ids__().sort()[0] === this.__node_id__) {
this.__storage_events_filter__.pop();
this.__storage_events_filter__.push(this.__namespace__ + 'master' + '_' + this.__node_id__);
this.__ls__.setItem(this.__namespace__ + 'master', this.__node_id__);

@@ -162,14 +182,11 @@ this.__on_master_changed__(this.__node_id__);

// Receive resended message from master and send it to tab subscribers
// localStorage change handler. Updates master ID, receive subscribe requests
//
Router.prototype.__on_data_changed__ = function (serializedData) {
var data = JSON.parse(serializedData);
Router.prototype.__on_changed__ = function (e) {
this.__receive_message__(data.channel, data.message);
};
// IE broadcasts storage events also to the same window, we should filter that messages
if (this.__storage_events_filter__.indexOf(e.key + '_' + e.newValue) !== -1) {
return;
}
// localStorage change handler. Updates master ID, receive subscribe requests
//
Router.prototype.__on_changed__ = function (e) {
// Master changed

@@ -180,7 +197,2 @@ if (e.key === this.__namespace__ + 'master') {

// Receive message from master
if (e.key === this.__namespace__ + 'message') {
this.__on_data_changed__(e.newValue);
}
// Channels list changed

@@ -267,2 +279,4 @@ if (e.key.indexOf(this.__router_channels_prefix__) === 0) {

if (this.__ls__.getItem(this.__router_channels_prefix__ + this.__node_id__) !== serializedChannels) {
this.__storage_events_filter__.pop();
this.__storage_events_filter__.push(this.__router_channels_prefix__ + this.__node_id__ + '_' + serializedChannels);
this.__ls__.setItem(this.__router_channels_prefix__ + this.__node_id__, serializedChannels);

@@ -322,2 +336,4 @@ this.__on_channels_list_changed__();

if (this.__get_alive_router_ids__().indexOf(this.__master_id__) === -1) {
this.__storage_events_filter__.pop();
this.__storage_events_filter__.push(this.__namespace__ + 'master' + '_' + this.__node_id__);
this.__ls__.setItem(this.__namespace__ + 'master', this.__node_id__);

@@ -324,0 +340,0 @@ this.__on_master_changed__(this.__node_id__);

@@ -7,2 +7,3 @@ // Tunnel to communicate between client in root window and router in iframe

/* global document, window */
var $$ = require('./utils');

@@ -39,6 +40,7 @@

// Setup target for messages from iframe (we should not use `*` for security reasons)
self.__iframe__.contentWindow.postMessage({
origin: window.location.origin,
self.__iframe__.contentWindow.postMessage(JSON.stringify({
// `window.location.origin` available from IE 11
origin: window.location.origin || window.location.protocol + '//' + window.location.host,
namespace: self.__namespace__
}, self.__iframe_url__);
}), self.__iframe_url__);

@@ -49,3 +51,3 @@ self.__iframe_done__ = true;

self.__pending__.forEach(function (data) {
self.__iframe__.contentWindow.postMessage(data, self.__iframe_url__);
self.__iframe__.contentWindow.postMessage(JSON.stringify(data), self.__iframe_url__);
});

@@ -57,3 +59,3 @@

// Listen messages from iframe
window.addEventListener('message', function (event) {
$$.addEvent(window, 'message', function (event) {
// Check sender origin

@@ -64,4 +66,12 @@ if (self.__iframe_url__.indexOf(event.origin) !== 0) {

var data;
try {
data = JSON.parse(event.data);
} catch (__) {
return;
}
// Ignore messages from another namespace (and messages from other possible senders)
if (event.data.namespace !== self.__namespace__) {
if (data.namespace !== self.__namespace__) {
return;

@@ -71,3 +81,3 @@ }

self.__handlers__.forEach(function (handler) {
handler(event.data.channel, event.data.message);
handler(data.channel, data.message);
});

@@ -78,3 +88,3 @@ });

document.addEventListener('DOMContentLoaded', function () {
$$.addEvent(document, 'DOMContentLoaded', function () {
document.querySelector('body').appendChild(self.__iframe__);

@@ -97,7 +107,7 @@ });

} else {
this.__iframe__.contentWindow.postMessage({
this.__iframe__.contentWindow.postMessage(JSON.stringify({
channel: channel,
message: message,
namespace: this.__namespace__
}, this.__iframe_url__);
}), this.__iframe_url__);
}

@@ -129,4 +139,7 @@ };

this.__namespace__ = options.namespace || 'tabex_default_';
this.__origin_first_check__ = options.origin || window.location.origin;
// `window.location.origin` available from IE 11
this.__origin_first_check__ = options.origin ||
(window.location.origin || window.location.protocol + '//' + window.location.host);
// Always convert origin list to array

@@ -151,3 +164,3 @@ if (!Array.isArray(this.__origin_first_check__)) {

// Handle messages from parent window
window.addEventListener('message', function (event) {
$$.addEvent(window, 'message', function (event) {
var isOriginValid = false;

@@ -171,4 +184,12 @@

var data;
try {
data = JSON.parse(event.data);
} catch (__) {
return;
}
// Ignore messages from another namespace (and messages from other possible senders)
if (event.data.namespace !== self.__namespace__) {
if (data.namespace !== self.__namespace__) {
return;

@@ -178,11 +199,11 @@ }

// Save real origin from parent window and start routing
if (!self.__origin__ && event.data.origin) {
self.__origin__ = event.data.origin;
if (!self.__origin__ && data.origin) {
self.__origin__ = data.origin;
self.__router__.onmessage(function (channel, message) {
window.parent.postMessage({
window.parent.postMessage(JSON.stringify({
channel: channel,
message: message,
namespace: self.__namespace__
}, self.__origin__);
}), self.__origin__);
});

@@ -193,3 +214,3 @@

self.__router__.broadcast(event.data.channel, event.data.message);
self.__router__.broadcast(data.channel, data.message);
});

@@ -196,0 +217,0 @@ }

'use strict';
/* global document */
// Run each function with params and callback after all

@@ -32,1 +35,13 @@ //

};
// `addEventListener` not supported in IE <= 8, fallback to `attachEvent`
//
exports.addEvent = function (target, type, listener) {
if (document.addEventListener) {
target.addEventListener(type, listener);
return;
}
target.attachEvent('on' + type, listener);
};
{
"name": "tabex",
"version": "1.0.0",
"version": "1.0.1",
"description": "Cross-tab message bus for browsers.",

@@ -21,3 +21,2 @@ "keywords": [

"devDependencies": {
"es5-shim": "^4.1.4",
"browserify": "^10.2.1",

@@ -30,4 +29,7 @@ "uglifyjs": "^2.4.10",

"mocha-browser": "^0.2.0",
"phantomjs": "^1.9.17"
"phantomjs": "^1.9.17",
"autoprefixer-stylus": "^0.7.0",
"jade": "^1.10.0",
"stylus": "^0.51.1"
}
}

@@ -11,3 +11,3 @@ tabex

>
> - Send messages (including cross-domain) between browser tabs and windows.
> - Send messages between browser tabs and windows.
> - Share single websocket connection when multiple tabs open (save server

@@ -17,2 +17,4 @@ > resources).

[Demo](http://nodeca.github.io/tabex/)
__Supported browser:__

@@ -25,9 +27,11 @@

__Known issues__
__Known issues:__
- Safary in private mode will fallback to legacy, because it prohibits
`localStorage` write.
- Cross-domain mode is not available in safary by default, because of
[security settings](http://stackoverflow.com/questions/20401751/). Single
domain mode will work without problems.
- Cross-domain messaging is not recommended due serious unfixable problems
in browsers:
- will not work in safary by default, because of
[security settings](http://stackoverflow.com/questions/20401751/).
- will not work in IE11 due multiple bugs.

@@ -168,3 +172,8 @@

window.tabex.router({
origin: [ '*://*.yourdomain.com', '*://yourdomain.com' ]
origin: [
'http://yourdomain.com',
'https://yourdomain.com',
'http://forum.yourdomain.com',
'https://forum.yourdomain.com'
]
});

@@ -184,7 +193,4 @@ ```

- __!sys.master__ - emitted when router in tab become master. Message data:
- `node_id` - id of "local" router node
- `master_id` - id of node that become master
- __!sys.channels.refresh__ - emitted when any tab changes list of subscribed
channels and after `!sys.master` event. Message data:
- __!sys.channels.refresh__ - emitted when list of subscribed channels changed
(or in specific case, when master tab switched). Message data:
- `channels` - array of all channels subscribed in all tabs

@@ -198,4 +204,11 @@ - __!sys.channels.add__ - emitted by `tabex.client` to notify router about new

- __!sys.error__ - emitted on internal errors, for debug.
- __!sys.master__ - sepecific for localStorage-based router. Emitted when tab
become master. Message data:
- `node_id` - id of "local" router node
- `master_id` - id of node that become master
__Note.__ `!sys.master` event is broadcasted only when `localStorage` router
used. You should NOT rely on it in your general application logic.
### Sharing single server connection (faye)

@@ -202,0 +215,0 @@