UNPKG

6.38 kBJavaScriptView Raw
1
2/**
3 * socket.io
4 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
5 * MIT Licensed
6 */
7
8(function (exports) {
9
10 /**
11 * Utilities namespace.
12 *
13 * @namespace
14 */
15
16 var util = exports.util = {};
17
18 /**
19 * Parses an URI
20 *
21 * @author Steven Levithan <stevenlevithan.com> (MIT license)
22 * @api public
23 */
24
25 var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
26
27 var parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password',
28 'host', 'port', 'relative', 'path', 'directory', 'file', 'query',
29 'anchor'];
30
31 util.parseUri = function (str) {
32 var m = re.exec(str || '')
33 , uri = {}
34 , i = 14;
35
36 while (i--) {
37 uri[parts[i]] = m[i] || '';
38 }
39
40 return uri;
41 };
42
43 /**
44 * Produces a unique url that identifies a Socket.IO connection.
45 *
46 * @param {Object} uri
47 * @api public
48 */
49
50 util.uniqueUri = function (uri) {
51 var protocol = uri.protocol
52 , host = uri.host
53 , port = uri.port;
54
55 if ('undefined' != typeof document) {
56 host = host || document.domain;
57 port = port || (protocol == 'https'
58 && document.location.protocol !== 'https:' ? 443 : document.location.port);
59 } else {
60 host = host || 'localhost';
61
62 if (!port && protocol == 'https') {
63 port = 443;
64 }
65 }
66
67 return (protocol || 'http') + '://' + host + ':' + (port || 80);
68 };
69
70 /**
71 * Executes the given function when the page is loaded.
72 *
73 * io.util.load(function () { console.log('page loaded'); });
74 *
75 * @param {Function} fn
76 * @api public
77 */
78
79 var pageLoaded = false;
80
81 util.load = function (fn) {
82 if (document.readyState === 'complete' || pageLoaded) {
83 return fn();
84 }
85
86 util.on(window, 'load', fn, false);
87 };
88
89 /**
90 * Adds an event.
91 *
92 * @api private
93 */
94
95 util.on = function (element, event, fn, capture) {
96 if (element.attachEvent) {
97 element.attachEvent('on' + event, fn);
98 } else {
99 element.addEventListener(event, fn, capture);
100 }
101 };
102
103 /**
104 * Generates the correct `XMLHttpRequest` for regular and cross domain requests.
105 *
106 * @param {Boolean} [xdomain] Create a request that can be used cross domain.
107 * @returns {XMLHttpRequest|false} If we can create a XMLHttpRequest.
108 * @api private
109 */
110
111 util.request = function (xdomain) {
112 if ('undefined' != typeof window) {
113 if (xdomain && window.XDomainRequest) {
114 return new XDomainRequest();
115 };
116
117 if (window.XMLHttpRequest && (!xdomain || util.ua.hasCORS)) {
118 return new XMLHttpRequest();
119 };
120
121 if (!xdomain) {
122 try {
123 return new window.ActiveXObject('Microsoft.XMLHTTP');
124 } catch(e) { }
125 }
126 }
127
128 return null;
129 };
130
131 /**
132 * XHR based transport constructor.
133 *
134 * @constructor
135 * @api public
136 */
137
138 /**
139 * Change the internal pageLoaded value.
140 */
141
142 if ('undefined' != typeof window) {
143 util.load(function () {
144 pageLoaded = true;
145 });
146 }
147
148 /**
149 * Defers a function to ensure a spinner is not displayed by the browser
150 *
151 * @param {Function} fn
152 * @api public
153 */
154
155 util.defer = function (fn) {
156 if (!util.ua.webkit) {
157 return fn();
158 }
159
160 util.load(function () {
161 setTimeout(fn, 100);
162 });
163 };
164
165 /**
166 * Merges two objects.
167 *
168 * @api public
169 */
170
171 util.merge = function merge (target, additional, deep, lastseen) {
172 var seen = lastseen || []
173 , depth = typeof deep == 'undefined' ? 2 : deep
174 , prop;
175
176 for (prop in additional) {
177 if (additional.hasOwnProperty(prop) && util.indexOf(seen, prop) < 0) {
178 if (typeof target[prop] !== 'object' || !depth) {
179 target[prop] = additional[prop];
180 seen.push(additional[prop]);
181 } else {
182 util.merge(target[prop], additional[prop], depth - 1, seen);
183 }
184 }
185 }
186
187 return target;
188 };
189
190 /**
191 * Merges prototypes from objects
192 *
193 * @api public
194 */
195
196 util.mixin = function (ctor, ctor2) {
197 util.merge(ctor.prototype, ctor2.prototype);
198 };
199
200 /**
201 * Shortcut for prototypical and static inheritance.
202 *
203 * @api private
204 */
205
206 util.inherit = function (ctor, ctor2) {
207 ctor.prototype = new ctor2;
208 util.merge(ctor, ctor2);
209 };
210
211 /**
212 * Checks if the given object is an Array.
213 *
214 * io.util.isArray([]); // true
215 * io.util.isArray({}); // false
216 *
217 * @param Object obj
218 * @api public
219 */
220
221 util.isArray = Array.isArray || function (obj) {
222 return Object.prototype.toString.call(obj) === '[object Array]';
223 };
224
225 /**
226 * Intersects values of two arrays into a third
227 *
228 * @api public
229 */
230
231 util.intersect = function (arr, arr2) {
232 var ret = []
233 , longest = arr.length > arr2.length ? arr : arr2
234 , shortest = arr.length > arr2.length ? arr2 : arr
235
236 for (var i = 0, l = shortest.length; i < l; i++) {
237 if (~util.indexOf(longest, shortest[i]))
238 ret.push(shortest[i]);
239 }
240
241 return ret;
242 }
243
244 /**
245 * Array indexOf compatibility.
246 *
247 * @see bit.ly/a5Dxa2
248 * @api public
249 */
250
251 util.indexOf = function (arr, o, i) {
252 if (Array.prototype.indexOf) {
253 return Array.prototype.indexOf.call(arr, o, i);
254 }
255
256 for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0
257 ; i < j && arr[i] !== o; i++);
258
259 return j <= i ? -1 : i;
260 };
261
262 /**
263 * Converts enumerables to array.
264 *
265 * @api public
266 */
267
268 util.toArray = function (enu) {
269 var arr = [];
270
271 for (var i = 0, l = enu.length; i < l; i++)
272 arr.push(enu[i]);
273
274 return arr;
275 };
276
277 /**
278 * UA / engines detection namespace.
279 *
280 * @namespace
281 */
282
283 util.ua = {};
284
285 /**
286 * Whether the UA supports CORS for XHR.
287 *
288 * @api public
289 */
290
291 util.ua.hasCORS = 'undefined' != typeof window && window.XMLHttpRequest &&
292 (function () {
293 try {
294 var a = new XMLHttpRequest();
295 } catch (e) {
296 return false;
297 }
298
299 return a.withCredentials != undefined;
300 })();
301
302 /**
303 * Detect webkit.
304 *
305 * @api public
306 */
307
308 util.ua.webkit = 'undefined' != typeof navigator
309 && /webkit/i.test(navigator.userAgent);
310
311})('undefined' != typeof window ? io : module.exports);