/** * socket.io * Copyright(c) 2011 LearnBoost * MIT Licensed */ (function (exports) { /** * Utilities namespace. * * @namespace */ var util = exports.util = {}; /** * Parses an URI * * @author Steven Levithan (MIT license) * @api public */ var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; var parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor']; util.parseUri = function (str) { var m = re.exec(str || '') , uri = {} , i = 14; while (i--) { uri[parts[i]] = m[i] || ''; } return uri; }; /** * Produces a unique url that identifies a Socket.IO connection. * * @param {Object} uri * @api public */ util.uniqueUri = function (uri) { var protocol = uri.protocol , host = uri.host , port = uri.port; if ('undefined' != typeof document) { host = host || document.domain; port = port || document.location.port; } else { host = host || 'localhost'; } return (protocol || 'http') + '://' + host + ':' + (port || protocol && protocol === 'https' ? 443 : 80); }; /** * Executes the given function when the page is loaded. * * io.util.load(function () { console.log('page loaded'); }); * * @param {Function} fn * @api public */ var pageLoaded = false; util.load = function (fn) { if (document.readyState === 'complete' || pageLoaded) { return fn(); } util.on(window, 'load', fn, false); }; /** * Adds an event. * * @api private */ util.on = function (element, event, fn, capture) { if (element.attachEvent) { element.attachEvent('on' + event, fn); } else { element.addEventListener(event, fn, capture); } }; /** * Generates the correct `XMLHttpRequest` for regular and cross domain requests. * * @param {Boolean} [xdomain] Create a request that can be used cross domain. * @returns {XMLHttpRequest|false} If we can create a XMLHttpRequest. * @api private */ var hasCORS = 'undefined' != typeof window && window.XMLHttpRequest && (function () { var a = new XMLHttpRequest(); return a.withCredentials != undefined; })(); util.request = function (xdomain) { if ('undefined' != typeof window) { if (xdomain && window.XDomainRequest) { return new XDomainRequest(); }; if (window.XMLHttpRequest && (!xdomain || hasCORS)) { return new XMLHttpRequest(); }; if (!xdomain) { try { return new window.ActiveXObject('Microsoft.XMLHTTP'); } catch(e) { } } } return null; }; /** * XHR based transport constructor. * * @constructor * @api public */ /** * Change the internal pageLoaded value. */ if ('undefined' != typeof window) { util.load(function () { pageLoaded = true; }); } /** * Defers a function to ensure a spinner is not displayed by the browser * * @param {Function} fn * @api public */ util.defer = function (fn) { if (!util.ua.webkit) { return fn(); } util.load(function () { setTimeout(fn, 100); }); }; /** * Merges two objects. * * @api public */ util.merge = function merge(target, additional, deep, lastseen){ var seen = lastseen || [] , depth = typeof deep == 'undefined' ? 2 : deep , prop; for (prop in additional){ if (additional.hasOwnProperty(prop) && this.indexOf(seen, prop) < 0){ if (typeof target[prop] !== 'object' || !depth){ target[prop] = additional[prop]; seen.push(additional[prop]); } else { this.merge(target[prop], additional[prop], depth - 1, seen); } } } return target; }; /** * Merges prototypes from objects * * @api public */ util.mixin = function (ctor, ctor2) { util.merge(ctor.prototype, ctor2.prototype); }; /** * Shortcut for prototypical and static inheritance. * * @api private */ util.inherit = function (ctor, ctor2) { ctor.prototype = new ctor2; util.merge(ctor, ctor2); }; /** * Checks if the given object is an Array. * * io.util.isArray([]); // true * io.util.isArray({}); // false * * @param Object obj * @api public */ util.isArray = Array.isArray || function (obj) { return Object.prototype.toString.call(obj) === '[object Array]'; }; /** * Intersects values of two arrays into a third * * @api public */ util.intersect = function (arr, arr2) { var ret = [] , longest = arr.length > arr2.length ? arr : arr2 , shortest = arr.length > arr2.length ? arr2 : arr for (var i = 0, l = shortest.length; i < l; i++) { if (~util.indexOf(longest, shortest[i])) ret.push(shortest[i]); } return ret; } /** * Array indexOf compatibility. * * @see bit.ly/a5Dxa2 * @api public */ util.indexOf = function (arr, o, i) { if (Array.prototype.indexOf) { return Array.prototype.indexOf.call(arr, o, i); } for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0 ; i < j && arr[i] !== o; i++); return j <= i ? -1 : i; }; /** * UA / engines detection namespace. * * @namespace */ util.ua = {}; /** * Detect webkit. * * @api public */ util.ua.webkit = 'undefined' != typeof navigator && /webkit/i.test(navigator.userAgent); })('undefined' != typeof window ? io : module.exports);