├── .gitignore ├── public ├── favicon.ico ├── favicon.png ├── assets │ └── images │ │ └── joke.png ├── javascripts │ ├── socket.io │ │ ├── lib │ │ │ ├── io.js │ │ │ ├── util.js │ │ │ ├── transports │ │ │ │ ├── xhr-multipart.js │ │ │ │ ├── xhr-polling.js │ │ │ │ ├── flashsocket.js │ │ │ │ ├── websocket.js │ │ │ │ ├── htmlfile.js │ │ │ │ └── xhr.js │ │ │ ├── transport.js │ │ │ └── socket.js │ │ └── socket.io.js │ └── enterprise.js └── stylesheets │ └── enterprise.css ├── views ├── index.jade └── layout.jade ├── README.md ├── app.js └── tips.js /.gitignore: -------------------------------------------------------------------------------- 1 | logs/* 2 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/enterprise-js/master/public/favicon.ico -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/enterprise-js/master/public/favicon.png -------------------------------------------------------------------------------- /public/assets/images/joke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/enterprise-js/master/public/assets/images/joke.png -------------------------------------------------------------------------------- /views/index.jade: -------------------------------------------------------------------------------- 1 | header 2 | #prefix.shadowed.split.upper 3 | a.special(href="/")="Enterprise JavaScript" 4 | =" Is:" 5 | #refresh.split 6 | a(href="/")="Refresh" 7 | #message.shadowed.upper!=tip.message 8 | - if (tip.example) 9 | pre#example!=tip.example 10 | footer 11 | p#author.split="Submitted by: " 12 | a.special(href="http://twitter.com/#/" + tip.author)=tip.author 13 | p#permalink.split 14 | a(href="/" + index)="Permalink" 15 | -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/io.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | this.io = { 10 | version: '0.5.3', 11 | 12 | setPath: function(path){ 13 | this.path = /\/$/.test(path) ? path : path + '/'; 14 | 15 | // this is temporary until we get a fix for injecting Flash WebSocket javascript files dynamically, 16 | // as io.js shouldn't be aware of specific transports. 17 | if ('WebSocket' in window){ 18 | WebSocket.__swfLocation = path + 'lib/vendor/web-socket-js/WebSocketMain.swf'; 19 | } 20 | } 21 | }; 22 | 23 | if ('jQuery' in this) jQuery.io = this.io; -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | io.util = { 10 | 11 | inherit: function(ctor, superCtor){ 12 | // no support for `instanceof` for now 13 | for (var i in superCtor.prototype){ 14 | ctor.prototype[i] = superCtor.prototype[i]; 15 | } 16 | }, 17 | 18 | indexOf: function(arr, item, from){ 19 | for (var l = arr.length, i = (from < 0) ? Math.max(0, l + from) : from || 0; i < l; i++){ 20 | if (arr[i] === item) return i; 21 | } 22 | return -1; 23 | }, 24 | 25 | isArray: function(obj){ 26 | return Object.prototype.toString.call(obj) === '[object Array]'; 27 | } 28 | 29 | }; -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/transports/xhr-multipart.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | (function(){ 10 | 11 | var XHRMultipart = io.Transport['xhr-multipart'] = function(){ 12 | io.Transport.XHR.apply(this, arguments); 13 | }; 14 | 15 | io.util.inherit(XHRMultipart, io.Transport.XHR); 16 | 17 | XHRMultipart.prototype.type = 'xhr-multipart'; 18 | 19 | XHRMultipart.prototype._get = function(){ 20 | var self = this; 21 | this._xhr = this._request('', 'GET', true); 22 | this._xhr.onreadystatechange = function(){ 23 | if (self._xhr.readyState == 3) self._onData(self._xhr.responseText); 24 | }; 25 | this._xhr.send(); 26 | }; 27 | 28 | XHRMultipart.check = function(){ 29 | return 'XMLHttpRequest' in window && 'multipart' in XMLHttpRequest.prototype; 30 | }; 31 | 32 | XHRMultipart.xdomainCheck = function(){ 33 | return true; 34 | }; 35 | 36 | })(); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Enterprise JavaScript 2 | ===================== 3 | 4 | If you’re someone that runs an enterprise-level website (>100 hits per day), you’ve probably had to deal with the pains of scaling and maintaining your code. 5 | 6 | Enterprises have dealt with these problems for years — this is an attempt at gathering all of that knowledge and to share it with the world. 7 | 8 | ## Dependencies 9 | 10 | * [Connect 0.2.6](http://senchalabs.github.com/connect/) (`npm install connect`) 11 | * [Express 1.0.0rc4](http://expressjs.com/) (`npm install express`) 12 | * [Highlight 0.1.0](http://github.com/andris9/highlight/) (`npm install highlight`) 13 | * [Jade 0.5.3](http://jade-lang.com/) (`npm install jade`) 14 | * [Socket.IO 0.5.3](http://socket.io/) (`npm install socket.io`) 15 | 16 | ## Adding Your Own Tips 17 | 18 | Add your own tips to `tips.js` by appending to the `tips` array: 19 | 20 | tips.push({ 21 | author: 'your_twitter_handle', 22 | message: 'Your Tip Message', 23 | example: [ 24 | '
', 25 | 'Code Example', 26 | '
' 27 | ] 28 | }); 29 | 30 | Once committed, send a pull request and I’ll be sure to get it up on 31 | [enterprise-js.com](http://enterprise-js.com/). -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/transports/xhr-polling.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | (function(){ 10 | 11 | var empty = new Function(), 12 | 13 | XHRPolling = io.Transport['xhr-polling'] = function(){ 14 | io.Transport.XHR.apply(this, arguments); 15 | }; 16 | 17 | io.util.inherit(XHRPolling, io.Transport.XHR); 18 | 19 | XHRPolling.prototype.type = 'xhr-polling'; 20 | 21 | XHRPolling.prototype._get = function(){ 22 | var self = this; 23 | this._xhr = this._request(+ new Date, 'GET'); 24 | if ('onload' in this._xhr){ 25 | this._xhr.onload = function(){ 26 | if (this.responseText.length) self._onData(this.responseText); 27 | self.connect(); 28 | }; 29 | } else { 30 | this._xhr.onreadystatechange = function(){ 31 | var status; 32 | if (self._xhr.readyState == 4){ 33 | self._xhr.onreadystatechange = empty; 34 | try { status = self._xhr.status; } catch(e){} 35 | if (status == 200){ 36 | if (self._xhr.responseText.length) self._onData(self._xhr.responseText); 37 | self.connect(); 38 | } 39 | } 40 | }; 41 | } 42 | this._xhr.send(); 43 | }; 44 | 45 | XHRPolling.check = function(){ 46 | return io.Transport.XHR.check(); 47 | }; 48 | 49 | XHRPolling.xdomainCheck = function(){ 50 | return 'XDomainRequest' in window || 'XMLHttpRequest' in window; 51 | }; 52 | 53 | })(); -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/transports/flashsocket.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | (function(){ 10 | 11 | var Flashsocket = io.Transport.flashsocket = function(){ 12 | io.Transport.websocket.apply(this, arguments); 13 | }; 14 | 15 | io.util.inherit(Flashsocket, io.Transport.websocket); 16 | 17 | Flashsocket.prototype.type = 'flashsocket'; 18 | 19 | Flashsocket.prototype._onClose = function(){ 20 | if (!this.base.connected){ 21 | // something failed, we might be behind a proxy, so we'll try another transport 22 | this.base.options.transports.splice(io.util.indexOf(this.base.options.transports, 'flashsocket'), 1); 23 | this.base.transport = this.base.getTransport(); 24 | this.base.connect(); 25 | return; 26 | } 27 | return io.Transport.websocket.prototype._onClose.call(this); 28 | }; 29 | 30 | Flashsocket.check = function(){ 31 | if (!('path' in io)) throw new Error('The `flashsocket` transport requires that you call io.setPath() with the path to the socket.io client dir.'); 32 | if ('navigator' in window && 'plugins' in navigator && navigator.plugins['Shockwave Flash']){ 33 | return !!navigator.plugins['Shockwave Flash'].description; 34 | } 35 | if ('ActiveXObject' in window) { 36 | try { 37 | return !!new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); 38 | } catch (e) {} 39 | } 40 | return false; 41 | }; 42 | 43 | Flashsocket.xdomainCheck = function(){ 44 | return true; 45 | }; 46 | 47 | })(); -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/transports/websocket.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | (function(){ 10 | 11 | var WS = io.Transport.websocket = function(){ 12 | io.Transport.apply(this, arguments); 13 | }; 14 | 15 | io.util.inherit(WS, io.Transport); 16 | 17 | WS.prototype.type = 'websocket'; 18 | 19 | WS.prototype.connect = function(){ 20 | var self = this; 21 | this.socket = new WebSocket(this._prepareUrl()); 22 | this.socket.onmessage = function(ev){ self._onData(ev.data); }; 23 | this.socket.onclose = function(ev){ self._onClose(); }; 24 | return this; 25 | }; 26 | 27 | WS.prototype.send = function(data){ 28 | this.socket.send(this._encode(data)); 29 | return this; 30 | } 31 | 32 | WS.prototype.disconnect = function(){ 33 | this.socket.close(); 34 | return this; 35 | }; 36 | 37 | WS.prototype._onClose = function(){ 38 | this._onDisconnect(); 39 | return this; 40 | }; 41 | 42 | WS.prototype._prepareUrl = function(){ 43 | return (this.base.options.secure ? 'wss' : 'ws') 44 | + '://' + this.base.host 45 | + ':' + this.base.options.port 46 | + '/' + this.base.options.resource 47 | + '/' + this.type 48 | + (this.sessionid ? ('/' + this.sessionid) : ''); 49 | }; 50 | 51 | WS.check = function(){ 52 | // we make sure WebSocket is not confounded with a previously loaded flash WebSocket 53 | return 'WebSocket' in window && !('__initialize' in WebSocket); 54 | }; 55 | 56 | WS.xdomainCheck = function(){ 57 | return true; 58 | }; 59 | 60 | })(); -------------------------------------------------------------------------------- /views/layout.jade: -------------------------------------------------------------------------------- 1 | !!!5 2 | html 3 | head 4 | meta(charset='utf-8') 5 | meta(http-equiv='X-UA-Compatible', content='chrome=1') 6 | meta(name='description', content='Learn the secrets to successful Enterprise JavaScript.') 7 | link(rel='icon', href='/favicon.png', type='image/png') 8 | link(rel='shortcut icon', href='/favicon.ico', type='image/x-icon') 9 | title="Enterprise JavaScript - Provides proven high performance, enterprise-level and scalable JavaScript tips and best practices." 10 | link(href='/stylesheets/enterprise.css?v6', rel='stylesheet') 11 | style#special 12 | | a, em, .special, #moar a:hover { color: ##{color}; } 13 | body 14 | #container!=body 15 | ul#moar 16 | li 17 | a(href='http://enterprise-html.com/')='HTML' 18 | li 19 | a(href='http://enterprise-css.com/')='CSS' 20 | li 21 | a(href='http://enterprise-js.com/')='JS' 22 | p#contribute 23 | ="If you'd like to add your own enterprise tips, " 24 | a(href="http://github.com/bentruyman/enterprise-js")="fork this project" 25 | =" on GitHub." 26 | #joke 27 | img(src="/assets/images/joke.png", alt="This is a joke.", height="149", width="149") 28 | a#fork(href="http://github.com/bentruyman/enterprise-js") 29 | img(src="http://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png", alt="Fork me on GitHub", height="149", width="149") 30 | script(src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js") 31 | script(src="/javascripts/socket.io/socket.io.js") 32 | script(src="/javascripts/enterprise.js") 33 | script 34 | | var _gaq=_gaq||[];_gaq.push(["_setAccount","UA-19149649-1"]);_gaq.push(["_trackPageview"]);(function(){var a=document.createElement("script");a.type="text/javascript";a.async=true;a.src=("https:"==document.location.protocol?"https://ssl":"http://www")+".google-analytics.com/ga.js";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b)})(); 35 | -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/transports/htmlfile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | (function(){ 10 | 11 | var HTMLFile = io.Transport.htmlfile = function(){ 12 | io.Transport.XHR.apply(this, arguments); 13 | }; 14 | 15 | io.util.inherit(HTMLFile, io.Transport.XHR); 16 | 17 | HTMLFile.prototype.type = 'htmlfile'; 18 | 19 | HTMLFile.prototype._get = function(){ 20 | var self = this; 21 | this._open(); 22 | window.attachEvent('onunload', function(){ self._destroy(); }); 23 | }; 24 | 25 | HTMLFile.prototype._open = function(){ 26 | this._doc = new ActiveXObject('htmlfile'); 27 | this._doc.open(); 28 | this._doc.write(''); 29 | this._doc.parentWindow.s = this; 30 | this._doc.close(); 31 | 32 | var _iframeC = this._doc.createElement('div'); 33 | this._doc.body.appendChild(_iframeC); 34 | this._iframe = this._doc.createElement('iframe'); 35 | _iframeC.appendChild(this._iframe); 36 | this._iframe.src = this._prepareUrl() + '/' + (+ new Date); 37 | }; 38 | 39 | HTMLFile.prototype._ = function(data, doc){ 40 | this._onData(data); 41 | var script = doc.getElementsByTagName('script')[0]; 42 | script.parentNode.removeChild(script); 43 | }; 44 | 45 | HTMLFile.prototype._destroy = function(){ 46 | this._iframe.src = 'about:blank'; 47 | this._doc = null; 48 | CollectGarbage(); 49 | }; 50 | 51 | HTMLFile.prototype.disconnect = function(){ 52 | this._destroy(); 53 | return io.Transport.XHR.prototype.disconnect.call(this); 54 | }; 55 | 56 | HTMLFile.check = function(){ 57 | if ('ActiveXObject' in window){ 58 | try { 59 | var a = new ActiveXObject('htmlfile'); 60 | return a && io.Transport.XHR.check(); 61 | } catch(e){} 62 | } 63 | return false; 64 | }; 65 | 66 | HTMLFile.xdomainCheck = function(){ 67 | return false; // send() is not cross domain. we need to POST to an iframe to fix it 68 | }; 69 | 70 | })(); -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | process.chdir(__dirname); 2 | require.paths.push('/usr/local/lib/node'); 3 | 4 | var express = require('express') 5 | , hl = require("highlight").Highlight 6 | , io = require('socket.io'); 7 | 8 | var app = express.createServer() 9 | , socket = io.listen(app); 10 | 11 | app.configure(function () { 12 | app.use(express.methodOverride()); 13 | app.use(express.bodyDecoder()); 14 | app.use(app.router); 15 | app.use(express.staticProvider(__dirname + '/public')); 16 | }); 17 | 18 | // Colors 19 | var colors = 'ff0090,ffff00,0bff00,08e3ff,ff460d'.split(','); 20 | 21 | // Tips 22 | var tips = require('./tips'); 23 | 24 | // Make 'em sexy 25 | tips.forEach(function (tip) { 26 | if (tip.example) { 27 | // Wrap it in script tags to trigger JavaScript highlighting...sigh 28 | tip.example = hl(''); 29 | // Unwrap (hax) 30 | tip.example = tip.example.replace('<script>', ''); 31 | tip.example = tip.example.replace('</script>', ''); 32 | } 33 | }); 34 | 35 | // Routes 36 | app.get('/', function (req, res) { 37 | showTip(req, res, generateRandomIndex()); 38 | }); 39 | 40 | app.get('/:permalink', function (req, res) { 41 | var index = req.params.permalink; 42 | 43 | if (tips[index - 1]) { 44 | showTip(req, res, index); 45 | } else { 46 | res.redirect('/'); 47 | } 48 | }); 49 | 50 | // WebSocket 51 | socket.on('connection', function(client){ 52 | client.on('message', function (action) { 53 | if (action === 'refresh') { 54 | client.send(JSON.stringify(generateTip(generateRandomIndex()))); 55 | } 56 | }); 57 | }); 58 | 59 | // Utilities 60 | function showTip (req, res, index) { 61 | res.render('index.jade', { 62 | locals: { 63 | tip: tips[index - 1], 64 | color: colors[Math.floor(Math.random() * colors.length)], 65 | index: index 66 | } 67 | }); 68 | } 69 | 70 | function generateTip (index) { 71 | return { 72 | tip: tips[index - 1], 73 | color: colors[Math.floor(Math.random() * colors.length)], 74 | index: index 75 | }; 76 | } 77 | 78 | function generateRandomIndex() { 79 | return Math.ceil(Math.random() * tips.length); 80 | } 81 | 82 | app.listen(3002); 83 | -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/transports/xhr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | (function(){ 10 | 11 | var empty = new Function, 12 | 13 | request = function(xdomain){ 14 | if ('XDomainRequest' in window && xdomain) return new XDomainRequest(); 15 | if ('XMLHttpRequest' in window) return new XMLHttpRequest(); 16 | 17 | try { 18 | var a = new ActiveXObject('MSXML2.XMLHTTP'); 19 | return a; 20 | } catch(e){} 21 | 22 | try { 23 | var b = new ActiveXObject('Microsoft.XMLHTTP'); 24 | return b; 25 | } catch(e){} 26 | 27 | return false; 28 | }, 29 | 30 | XHR = io.Transport.XHR = function(){ 31 | io.Transport.apply(this, arguments); 32 | }; 33 | 34 | io.util.inherit(XHR, io.Transport); 35 | 36 | XHR.prototype.connect = function(){ 37 | if (!('_sendBuffer' in this)) this._sendBuffer = []; 38 | this._get(); 39 | return this; 40 | }; 41 | 42 | XHR.prototype._checkSend = function(){ 43 | if (!this._posting && this._sendBuffer.length){ 44 | var encoded = this._encode(this._sendBuffer); 45 | this._sendBuffer = []; 46 | this._send(encoded); 47 | } 48 | }; 49 | 50 | XHR.prototype.send = function(data){ 51 | if (io.util.isArray(data)){ 52 | this._sendBuffer.push.apply(this._sendBuffer, data); 53 | } else { 54 | this._sendBuffer.push(data); 55 | } 56 | this._checkSend(); 57 | return this; 58 | }; 59 | 60 | XHR.prototype._send = function(data){ 61 | var self = this; 62 | this._posting = true; 63 | this._sendXhr = this._request('send', 'POST'); 64 | this._sendXhr.send('data=' + encodeURIComponent(data)); 65 | this._sendXhr.onreadystatechange = function(){ 66 | var status; 67 | if (self._sendXhr.readyState == 4){ 68 | self._sendXhr.onreadystatechange = empty; 69 | try { status = self._sendXhr.status; } catch(e){} 70 | if (status == 200){ 71 | self._posting = false; 72 | self._checkSend(); 73 | } 74 | } 75 | }; 76 | }, 77 | 78 | XHR.prototype.disconnect = function(){ 79 | if (this._xhr){ 80 | this._xhr.onreadystatechange = this._xhr.onload = empty; 81 | this._xhr.abort(); 82 | } 83 | if (this._sendXhr){ 84 | this._sendXhr.onreadystatechange = this._sendXhr.onload = empty; 85 | this._sendXhr.abort(); 86 | } 87 | this._onClose(); 88 | this._onDisconnect(); 89 | return this; 90 | } 91 | 92 | XHR.prototype._request = function(url, method, multipart){ 93 | var req = request(this.base._isXDomain()); 94 | if (multipart) req.multipart = true; 95 | req.open(method || 'GET', this._prepareUrl() + (url ? '/' + url : '')); 96 | if (method == 'POST'){ 97 | req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8'); 98 | } 99 | return req; 100 | }; 101 | 102 | XHR.check = function(){ 103 | try { 104 | if (request()) return true; 105 | } catch(e){} 106 | return false; 107 | }; 108 | 109 | XHR.request = request; 110 | 111 | })(); -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/transport.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | // abstract 10 | 11 | (function(){ 12 | 13 | var frame = '~m~', 14 | 15 | Transport = io.Transport = function(base, options){ 16 | this.base = base; 17 | this.options = options; 18 | }; 19 | 20 | Transport.prototype.send = function(){ 21 | throw new Error('Missing send() implementation'); 22 | }; 23 | 24 | Transport.prototype.connect = function(){ 25 | throw new Error('Missing connect() implementation'); 26 | }; 27 | 28 | Transport.prototype.disconnect = function(){ 29 | throw new Error('Missing disconnect() implementation'); 30 | }; 31 | 32 | Transport.prototype._encode = function(messages){ 33 | var ret = '', message, 34 | messages = io.util.isArray(messages) ? messages : [messages]; 35 | for (var i = 0, l = messages.length; i < l; i++){ 36 | message = messages[i] === null || messages[i] === undefined ? '' : String(messages[i]); 37 | ret += frame + message.length + frame + message; 38 | } 39 | return ret; 40 | }; 41 | 42 | Transport.prototype._decode = function(data){ 43 | var messages = [], number, n; 44 | do { 45 | if (data.substr(0, 3) !== frame) return messages; 46 | data = data.substr(3); 47 | number = '', n = ''; 48 | for (var i = 0, l = data.length; i < l; i++){ 49 | n = Number(data.substr(i, 1)); 50 | if (data.substr(i, 1) == n){ 51 | number += n; 52 | } else { 53 | data = data.substr(number.length + frame.length) 54 | number = Number(number); 55 | break; 56 | } 57 | } 58 | messages.push(data.substr(0, number)); // here 59 | data = data.substr(number); 60 | } while(data !== ''); 61 | return messages; 62 | }; 63 | 64 | Transport.prototype._onData = function(data){ 65 | var msgs = this._decode(data); 66 | if (msgs){ 67 | for (var i = 0, l = msgs.length; i < l; i++){ 68 | this._onMessage(msgs[i]); 69 | } 70 | } 71 | }; 72 | 73 | Transport.prototype._onMessage = function(message){ 74 | if (!('sessionid' in this)){ 75 | this.sessionid = message; 76 | this._onConnect(); 77 | } else if (message.substr(0, 3) == '~h~'){ 78 | this._onHeartbeat(message.substr(3)); 79 | } else { 80 | this.base._onMessage(message); 81 | } 82 | }, 83 | 84 | Transport.prototype._onHeartbeat = function(heartbeat){ 85 | this.send('~h~' + heartbeat); // echo 86 | }; 87 | 88 | Transport.prototype._onConnect = function(){ 89 | this.connected = true; 90 | this.base._onConnect(); 91 | }; 92 | 93 | Transport.prototype._onDisconnect = function(){ 94 | if (!this.connected) return; 95 | this.connected = false; 96 | this.base._onDisconnect(); 97 | }; 98 | 99 | Transport.prototype._prepareUrl = function(){ 100 | return (this.base.options.secure ? 'https' : 'http') 101 | + '://' + this.base.host 102 | + ':' + this.base.options.port 103 | + '/' + this.base.options.resource 104 | + '/' + this.type 105 | + (this.sessionid ? ('/' + this.sessionid) : '/'); 106 | }; 107 | 108 | })(); -------------------------------------------------------------------------------- /public/javascripts/enterprise.js: -------------------------------------------------------------------------------- 1 | /* json2.js 2 | * 2008-01-17 3 | * Public Domain 4 | * No warranty expressed or implied. Use at your own risk. 5 | * See http://www.JSON.org/js.html 6 | */ 7 | if(!this.JSON)this.JSON={}; 8 | (function(){function l(b){return b<10?"0"+b:b}function o(b){p.lastIndex=0;return p.test(b)?'"'+b.replace(p,function(f){var c=r[f];return typeof c==="string"?c:"\\u"+("0000"+f.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+b+'"'}function m(b,f){var c,d,g,j,i=h,e,a=f[b];if(a&&typeof a==="object"&&typeof a.toJSON==="function")a=a.toJSON(b);if(typeof k==="function")a=k.call(f,b,a);switch(typeof a){case "string":return o(a);case "number":return isFinite(a)?String(a):"null";case "boolean":case "null":return String(a); 9 | case "object":if(!a)return"null";h+=n;e=[];if(Object.prototype.toString.apply(a)==="[object Array]"){j=a.length;for(c=0;c').insertAfter('#message'); 36 | } 37 | 38 | if (!response.tip.example) { 39 | $('#example').hide(); 40 | } else { 41 | $('#example').show(); 42 | } 43 | 44 | $('#example').html($.trim(response.tip.example)); 45 | $('#author a').attr('href', 'http://twitter.com/#/' + response.tip.author).text(response.tip.author); 46 | $('#permalink a').attr('href', '/' + response.index); 47 | 48 | var $special = $('#special'); 49 | $special.text($special.text().replace(/#[a-f0-9]+;/, '#' + response.color + ';')); 50 | 51 | _gaq.push(["_trackPageview"]); 52 | }); 53 | -------------------------------------------------------------------------------- /public/javascripts/socket.io/lib/socket.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Socket.IO client 3 | * 4 | * @author Guillermo Rauch 5 | * @license The MIT license. 6 | * @copyright Copyright (c) 2010 LearnBoost 7 | */ 8 | 9 | (function(){ 10 | 11 | var Socket = io.Socket = function(host, options){ 12 | this.host = host || document.domain; 13 | this.options = { 14 | secure: false, 15 | document: document, 16 | heartbeatInterval: 4000, 17 | port: document.location.port || 80, 18 | resource: 'socket.io', 19 | transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling'], 20 | transportOptions: {}, 21 | rememberTransport: false 22 | }; 23 | for (var i in options) this.options[i] = options[i]; 24 | this.connected = false; 25 | this.connecting = false; 26 | this._events = {}; 27 | this.transport = this.getTransport(); 28 | if (!this.transport && 'console' in window) console.error('No transport available'); 29 | }; 30 | 31 | Socket.prototype.getTransport = function(){ 32 | var transports = this.options.transports, match; 33 | if (this.options.rememberTransport){ 34 | match = this.options.document.cookie.match('(?:^|;)\\s*socket\.io=([^;]*)'); 35 | if (match) transports = [decodeURIComponent(match[1])]; 36 | } 37 | for (var i = 0, transport; transport = transports[i]; i++){ 38 | if (io.Transport[transport] 39 | && io.Transport[transport].check() 40 | && (!this._isXDomain() || io.Transport[transport].xdomainCheck())){ 41 | return new io.Transport[transport](this, this.options.transportOptions[transport] || {}); 42 | } 43 | } 44 | return null; 45 | }; 46 | 47 | Socket.prototype.connect = function(){ 48 | if (this.transport && !this.connected && !this.connecting){ 49 | this.connecting = true; 50 | this.transport.connect(); 51 | } 52 | return this; 53 | }; 54 | 55 | Socket.prototype.send = function(data){ 56 | if (!this.transport || !this.transport.connected) return this._queue(data); 57 | this.transport.send(data); 58 | return this; 59 | }; 60 | 61 | Socket.prototype.disconnect = function(){ 62 | this.transport.disconnect(); 63 | return this; 64 | }; 65 | 66 | Socket.prototype.on = function(name, fn){ 67 | if (!(name in this._events)) this._events[name] = []; 68 | this._events[name].push(fn); 69 | return this; 70 | }; 71 | 72 | Socket.prototype.fire = function(name, args){ 73 | if (name in this._events){ 74 | for (var i in this._events[name]) 75 | this._events[name][i].apply(this, args); 76 | } 77 | return this; 78 | }; 79 | 80 | Socket.prototype.removeEvent = function(name, fn){ 81 | if (name in this._events){ 82 | for (var i in this._events[name]){ 83 | for (var a = 0, l = this._events[name].length; a < l; a++) 84 | if (this._events[name][a] == fn) this._events[name].splice(a, 1); 85 | } 86 | } 87 | return this; 88 | }; 89 | 90 | Socket.prototype._queue = function(message){ 91 | if (!('_queueStack' in this)) this._queueStack = []; 92 | this._queueStack.push(message); 93 | return this; 94 | }; 95 | 96 | Socket.prototype._doQueue = function(){ 97 | if (!('_queueStack' in this) || !this._queueStack.length) return this; 98 | this.transport.send(this._queueStack); 99 | this._queueStack = []; 100 | return this; 101 | }; 102 | 103 | Socket.prototype._isXDomain = function(){ 104 | return this.host !== document.domain; 105 | }; 106 | 107 | Socket.prototype._onConnect = function(){ 108 | this.connected = true; 109 | this.connecting = false; 110 | this._doQueue(); 111 | if (this.options.rememberTransport) this.options.document.cookie = 'socket.io=' + encodeURIComponent(this.transport.type); 112 | this.fire('connect'); 113 | }; 114 | 115 | Socket.prototype._onMessage = function(data){ 116 | this.fire('message', [data]); 117 | }; 118 | 119 | Socket.prototype._onDisconnect = function(){ 120 | this.fire('disconnect'); 121 | }; 122 | 123 | Socket.prototype.addListener = Socket.prototype.addEvent = Socket.prototype.addEventListener = Socket.prototype.on; 124 | 125 | })(); -------------------------------------------------------------------------------- /tips.js: -------------------------------------------------------------------------------- 1 | var tips = []; 2 | 3 | tips.push({ 4 | author: 'bentruyman', 5 | message: 'Never Using Literals or Lazy Shorthand', 6 | example: [ 7 | 'var integer = new Number(5);', 8 | 'var myString = new String("Hello World");', 9 | 'var foo = new Object();', 10 | 'var arrayOfFoo = new Array(5);', 11 | 'if (status === new Boolean(true)) {', 12 | ' ...', 13 | '}' 14 | ] 15 | }); 16 | 17 | tips.push({ 18 | author: 'bentruyman', 19 | message: 'Extremely Descriptive Self-Documenting Variable Names', 20 | example: [ 21 | 'function CatObjectThatInheritsAnimal() {', 22 | ' this.yellowFurColorString = "yellow";', 23 | ' this.animalsAgeInYears = 10;', 24 | '}', 25 | '', 26 | 'CatObjectThatInheritsAnimal.prototype = new AnimalObjectThatInheritsNothing;' 27 | ] 28 | }); 29 | 30 | tips.push({ 31 | author: 'bentruyman', 32 | message: 'Using Constants to Keep Everything Abstract', 33 | example: [ 34 | 'var FALSE = new Boolean(false);', 35 | 'var TRUE = new Boolean(true);', 36 | 'var ONE = new Number(1);', 37 | '', 38 | 'function IF_STATEMENT(condition, callback) {', 39 | ' if (condition == TRUE) {', 40 | ' callback.call(this);', 41 | ' }', 42 | '}' 43 | ] 44 | }); 45 | 46 | tips.push({ 47 | author: 'bentruyman', 48 | message: 'Ensuring Lines Are Terminated With Multiple Semicolons So the JavaSript Parser Really Knows when a Line Is Ending', 49 | example: [ 50 | 'var helloWorld = function (message) {', 51 | ' if (!message) {', 52 | ' message = "Hello World";;;;;;', 53 | ' }', 54 | '', 55 | ' alert(message);;;;;;;;;;;;;;;;;;;', 56 | '', 57 | '};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;' 58 | ] 59 | }); 60 | 61 | tips.push({ 62 | author: 'bentruyman', 63 | message: 'Creating Really Random Numbers', 64 | example: [ 65 | 'var reallyRandom = Math.pow(Math.random(), Math.random());' 66 | ] 67 | }); 68 | 69 | tips.push({ 70 | author: 'rwaldron', 71 | message: "Make sure you explicitly declare EVERY VARIABLE on its own line, that way your team will know they are all variables", 72 | example: [ 73 | 'var li = "
  • ";', 74 | 'var div = "
    "+li+"
    ";', 75 | 'var num1 = 4;', 76 | 'var num2 = 5;', 77 | 'var total = num1 + num2;', 78 | 'var rounded = Math.round(total);' 79 | ] 80 | }); 81 | 82 | tips.push({ 83 | author: 'paulca', 84 | message: "Use HTML5 to link links to functions that link to links.", 85 | example: [ 86 | 'Homepage' 87 | ] 88 | }); 89 | 90 | tips.push({ 91 | author: 'karbassi', 92 | message: "Use tabs and spaces to indent your code.", 93 | example: [ 94 | 'var x = 3;', 95 | 'var y = 4;', 96 | 'var z = 0;', 97 | ' z = x+y;' 98 | ] 99 | }); 100 | 101 | tips.push({ 102 | author: 'karbassi', 103 | message: "Use one space for all your indentation.", 104 | example: [ 105 | 'function(x,y){', 106 | ' if(x=3)', 107 | ' if(y!=3)', 108 | ' if(y+x>3)', 109 | ' return true;', 110 | '}' 111 | ] 112 | }); 113 | 114 | tips.push({ 115 | author: 'rwaldron', 116 | message: "Declaring your functions globally ensures they are accessible throughout your entire script. This ensures they always take precedence!", 117 | example: [ 118 | 'function postMessage(message) {', 119 | ' $.post("/helloworld.php", "message="+message)', 120 | '};' 121 | ] 122 | }); 123 | 124 | 125 | tips.push({ 126 | author: 'rwaldron', 127 | message: "Put your commas at the beginning of the line, because thats what they do in some other Enterprise languages", 128 | example: [ 129 | 'var CommaBomb = {', 130 | ' defaults: "" ', 131 | ' , options: "" ', 132 | ' , settings: "" ', 133 | ' , methods: { ', 134 | ' getOptions: function () { ', 135 | ' } ', 136 | ' , setOptions: function () { ', 137 | ' } ', 138 | ' , getSettings: function () { ', 139 | ' } ', 140 | ' , setSettings: function () { ', 141 | ' } ', 142 | ' }', 143 | '};' 144 | ] 145 | }); 146 | 147 | tips.push({ 148 | author: 'erichynds', 149 | message: "For ultimate code reuse, declare a wrapper function for everything", 150 | example: [ 151 | 'function createInformationWindow(message){', 152 | ' alert(message);', 153 | '}', 154 | '', 155 | 'function incrementVariable(variable,byHowMany){', 156 | ' return variable + byHowMany;', 157 | '}', 158 | '', 159 | 'function alertIfOnePlusTwoEqualsThree(){', 160 | ' if( incrementVariable(1, 2) === 3 ){', 161 | ' createInformationWindow("LOLWAT?");', 162 | ' }', 163 | '}' 164 | ] 165 | }); 166 | 167 | tips.push({ 168 | author: 'mrgnrdrck', 169 | message: "Use bitwise operators for array bounds checks", 170 | example: [ 171 | 'if (index !== +index >>> 0 || index >= elements.length){', 172 | ' alert("fail!")', 173 | '}' 174 | ] 175 | }); 176 | 177 | tips.push({ 178 | author: 'rwaldron', 179 | message: "Wrap open source libraries in descriptive 'in-house namespaces'.", 180 | example: [ 181 | 'var InitechCoreJQuery = jQuery', 182 | '', 183 | 'InitechCoreJQuery( function () {', 184 | ' InitechCoreJQuery(document).click(function () {', 185 | ' //... ', 186 | ' })', 187 | '})' 188 | ] 189 | }); 190 | 191 | tips.push({ 192 | author: 'F1LT3R', 193 | message: "Always add more comments, especially where they are most important... in the middle of statements.", 194 | example: [ 195 | 'var myString = /* Setting of the string happens after this comment. */ "The string was set."; // The string was set before this comment.' 196 | ] 197 | }); 198 | 199 | tips.push({ 200 | author: 'yonkeltron', 201 | message: 'Namespace code into a "proper package structure" to make backend devs feel at home.', 202 | example: [ 203 | 'var com = {,', 204 | ' AwesomeCo: {', 205 | ' util: {', 206 | ' info: function ( message) {', 207 | ' alert(message);', 208 | ' return message;', 209 | ' }', 210 | ' }', 211 | ' }', 212 | '};', 213 | '', 214 | 'com.AwesomeCo.util.info("SRSLY!?");' 215 | ] 216 | }); 217 | 218 | tips.push({ 219 | author: 'n1k0', 220 | message: 'Use a modern, multipurpose, introspection aware, evented debugging and notification system.', 221 | example: [ 222 | 'alert(foo);' 223 | ] 224 | }); 225 | 226 | tips.push({ 227 | author: 'n1k0', 228 | message: 'Always name variables, objects, methods and every single piece of code in your mother language, in order to thwart any offshoring attempt and make the documentation actually scale.', 229 | example: [ 230 | 'var ModelisationDuProcessusDeFacturation = function() {', 231 | ' var facturerTousLesUtilisateursOuiMaisLesquels = function(utilisateurs) {', 232 | ' for (var utilisateur in utilisateurs) {', 233 | ' var facture = new FacturationUtilisateur(utilisateur);', 234 | ' facture.envoyerEtVerifierLesSous();', 235 | ' }', 236 | ' };', 237 | '};' 238 | ] 239 | }); 240 | 241 | tips.push({ 242 | author: 'JakeWharton', 243 | message: 'A fully dynamic layout management framework', 244 | example: [ 245 | 'divErrors.style.top = 105;', 246 | 'divErrors.style.left = 115;', 247 | 'divErrors.style.width = 885;', 248 | 'if (divErrors.offsetHeight <= 20) {', 249 | ' hdrStatus.style.top = 105;', 250 | '} else {', 251 | ' hdrStatus.style.top = divErrors.offsetTop + divErrors.offsetHeight + 20;', 252 | '}', 253 | 'hdrStatus.style.left = divErrors.offsetLeft;', 254 | 'hdrStatus.style.width = divErrors.offsetWidth;', 255 | 'tblStatus.style.top = hdrStatus.offsetTop + hdrStatus.offsetHeight + 5;', 256 | 'tblStatus.style.left = hdrStatus.offsetLeft;', 257 | 'tblStatus.style.width = divErrors.offsetWidth;', 258 | 'hdrKeyDates.style.top = tblStatus.offsetTop + tblStatus.offsetHeight + 5;', 259 | 'hdrKeyDates.style.left = hdrStatus.offsetLeft;', 260 | 'hdrKeyDates.style.width = hdrStatus.offsetWidth;', 261 | 'tblKeyDates1.style.top = hdrKeyDates.offsetTop + hdrKeyDates.offsetHeight + 5;', 262 | 'tblKeyDates2.style.top = hdrKeyDates.offsetTop + hdrKeyDates.offsetHeight + 5;', 263 | 'tblKeyDates3.style.top = hdrKeyDates.offsetTop + hdrKeyDates.offsetHeight + 5;', 264 | 'tblTransit.style.top = tblKeyDates1.offsetTop + tblKeyDates1.offsetHeight + 5;', 265 | 'tblTransit.style.left = hdrStatus.offsetLeft;', 266 | 'hdrShipParams.style.top = tblKeyDates1.offsetTop + tblKeyDates1.offsetHeight + 30;', 267 | 'hdrShipParams.style.left = hdrStatus.offsetLeft;', 268 | 'tblShipParams.style.top = hdrShipParams.offsetTop + hdrShipParams.offsetHeight + 5;', 269 | 'tblShipParams.style.left = hdrShipParams.offsetLeft;', 270 | 'tblShipParams.style.width = hdrShipParams.offsetWidth - 200;', 271 | 'tblFormWidgets2.style.top = tblShipParams.offsetTop + tblShipParams.offsetHeight - 35;', 272 | 'tblFormWidgets2.style.left = tblShipParams.offsetLeft + 680;', 273 | 'tblFormWidgets2.style.width = 200;', 274 | 'hdrSpecs.style.top = tblShipParams.offsetTop + tblShipParams.offsetHeight + 5;', 275 | 'hdrSpecs.style.left = hdrStatus.offsetLeft;', 276 | 'tblSpecsLeft.style.top = hdrSpecs.offsetTop + hdrSpecs.offsetHeight + 5;', 277 | 'tblSpecsLeft.style.left = hdrSpecs.offsetLeft;', 278 | 'tblSpecsRight.style.top = tblSpecsLeft.offsetTop', 279 | 'tblSpecsRight.style.left = tblSpecsLeft.offsetLeft + tblSpecsLeft.offsetWidth + 25;', 280 | 'tblSpecsRight.style.width = hdrSpecs.offsetLeft + hdrSpecs.offsetWidth - tblSpecsRight.offsetLeft;', 281 | 'hdrServices.style.top = tblSpecsRight.offsetTop + tblSpecsRight.offsetHeight + 10;', 282 | 'hdrServices.style.left = hdrStatus.offsetLeft;', 283 | 'hdrServices.style.width = hdrSpecs.offsetWidth;', 284 | 'tblServices.style.top = hdrServices.offsetTop + hdrServices.offsetHeight + 5;', 285 | 'tblServices.style.left = hdrSpecs.offsetLeft;', 286 | 'tblServices.style.width = hdrSpecs.offsetWidth;', 287 | 'hdrAddresses.style.top = tblServices.offsetTop + tblServices.offsetHeight + 10;', 288 | 'hdrAddresses.style.left = hdrStatus.offsetLeft;', 289 | 'tblAddresses.style.top = hdrAddresses.offsetTop + hdrAddresses.offsetHeight + 10;', 290 | 'tblAddresses.style.left = hdrAddresses.offsetLeft + 10;', 291 | 'tblAddresses.style.width = hdrAddresses.offsetWidth - 10;', 292 | 'hdrShipperInfo.style.top = tblAddresses.offsetTop + tblAddresses.offsetHeight + 25;', 293 | 'tblShipperInfo.style.top = hdrShipperInfo.offsetTop + hdrShipperInfo.offsetHeight + 10;', 294 | 'tblShipperInfo.style.left = tblAddresses.offsetLeft;', 295 | 'tblShipperInfo.style.width = tblAddresses.offsetWidth;', 296 | 'hdrPets.style.top = tblShipperInfo.offsetTop + tblShipperInfo.offsetHeight + 25;', 297 | 'tblPets.style.top = hdrPets.offsetTop + hdrPets.offsetHeight + 10;', 298 | 'tblPets.style.left = tblShipperInfo.offsetLeft;', 299 | 'tblPets.style.width = tblShipperInfo.offsetWidth;', 300 | 'divFooter.style.top = tblPets.offsetTop + tblPets.offsetHeight + 20;', 301 | 'divFooter.style.left = tblPets.offsetLeft;' 302 | ] 303 | }); 304 | 305 | tips.push({ 306 | author: 'restlessdesign', 307 | message: 'Handling your exception handling', 308 | example: [ 309 | 'try {', 310 | ' try {', 311 | ' myArray.push(el);', 312 | ' }', 313 | ' catch(e) {', 314 | ' alert(e.message)', 315 | ' }', 316 | '}', 317 | 'catch (e) {', 318 | ' alert(\'Failed at trying\');', 319 | '}' 320 | ] 321 | }); 322 | 323 | tips.push({ 324 | author: 'dansnetwork', 325 | message: 'Maintaining a Sufficient Amount of Preceding White Space', 326 | example: [ 327 | ' ', 328 | ' ', 329 | ' // <- plenty of room for comments here', 330 | ' ', 331 | ' ', 332 | ' ', 333 | ' ', 334 | 'function highleveluncompressedcorporatestuff(){document.getElementById(\'anchortag\').href="iheartie6.asp";}' 335 | ] 336 | }); 337 | 338 | tips.push({ 339 | author: 'foobarfighter', 340 | message: 'Computer cycles are cheaper than developer cycles: Include your favorite javascript framework to maximize productivity regardless of whats already included on the page.', 341 | example: [ 342 | '$.fail()' 343 | ] 344 | }); 345 | 346 | tips.push({ 347 | author: 'KevBurnsJr', 348 | message: 'Initializing your layout', 349 | example: [ 350 | 'var ops = {', 351 | ' layout : {', 352 | ' init : function() {', 353 | ' window.$layout = { ', 354 | ' win : $(window),', 355 | ' head : $(\'head\'),', 356 | ' body : $(\'body\'),', 357 | ' a : $(\'a\'),', 358 | ' cont : $(\'#content\'),', 359 | ' wrapper : $(\'div.wrapper\'),', 360 | ' wrappad : $(\'div.wrapper-pad\'),', 361 | ' td : $(\'div.td\'),', 362 | ' loader : $(\'div.loader\'),', 363 | ' tog : $(\'dt.tog\'),', 364 | ' prop : $(\'.prop\'),', 365 | ' jmail : $(\'.jmail\'),', 366 | ' fb : $(\'.form-button\'),', 367 | ' items : $(\'.items\'),', 368 | ' item : $(\'.item\'),', 369 | ' price : $(\'.price\'),', 370 | ' box_round : $(\'.blue-box-full, .grey-box-full\'),', 371 | ' corners : $(\'.error-box-full, dd.element-description span, .modal\'),', 372 | ' top_round : $(\'.blue-box, .grey-box\'),', 373 | ' bot_round : $(\'.blue-box-bottom, .grey-box-bottom\'),', 374 | ' bot : $(\'.bottom\'),', 375 | ' mg : $(\'.items\').find(\'.minigutter\'),', 376 | ' modal : $(\'#modal\'),', 377 | ' tt : $(\'#tooltip\'),', 378 | ' widget : $(\'div.widget\'),', 379 | ' panes : $(\'ul.panes\'),', 380 | ' panesli : $(\'ul.panes li\'),', 381 | ' pane : $(\'div.pane\'),', 382 | ' panea : $(\'div.pane a\'),', 383 | ' truncrev : $(\'.truncrev\'),', 384 | ' ctrev : $(\'.click-truncrev\'),', 385 | ' oplayer : $(\'a.overlay-player\'),', 386 | ' bundles : $(\'tbody.bundles\'),', 387 | ' cform : $(\'#contact_form\'),', 388 | ' pform : $(\'#porder_form\'),', 389 | ' reset : $(\'#reset\'),', 390 | ' confirm : $(\'#confirm\'),', 391 | ' pconfirm : $(\'#pconfirm\'),', 392 | ' ptotal : $(\'#ptotal\'),', 393 | ' ntotal : $(\'#ntotal\'),', 394 | ' tncs_label : $(\'#tncs_cb-label\'),', 395 | ' tncscb : $(\'#tncs_cb\'),', 396 | ' delight : $(\'dd.element-description\'),', 397 | ' highlight : $(\'.highlight\'),', 398 | ' selreveal : $(\'.select-reveal\'),', 399 | ' cb : $(\'.checkbox\'),', 400 | ' cbradio : $(\'.cbradio\'),', 401 | ' crnrs : $(\'.corners\'),', 402 | ' cccpng : $(\'.cccpng\'),', 403 | ' cbupdate : $(\'.cbupdate\'),', 404 | ' qty : $(\'.qty\'),', 405 | ' is_default : $(\'.is_default\'),', 406 | ' corners : $(\'.text, .select, .textarea\')', 407 | ' };', 408 | ' }', 409 | ' }', 410 | '};', 411 | '', 412 | 'ops.layout.init();' 413 | ] 414 | }); 415 | 416 | tips.push({ 417 | author: 'bentruyman', 418 | message: 'Prefixing Variable Names With an Abbreviation of Their Type', 419 | example: [ 420 | 'var strFoo = \'foo\'', 421 | 'var arrItems = [strFoo, \'bar\', \'baz\', \'qux\'];', 422 | 'var objNamespace = {', 423 | ' items: arrItems', 424 | '};' 425 | ] 426 | }); 427 | 428 | tips.push({ 429 | author: 'rmehner', 430 | message: 'Avoiding if / else under any circumstances', 431 | example: [ 432 | 'switch(true) {', 433 | ' case element.hasClass(\'foo\'):', 434 | ' foo();', 435 | ' break;', 436 | ' default:', 437 | ' bar();', 438 | ' break;', 439 | '}' 440 | ] 441 | }); 442 | 443 | 444 | tips.push({ 445 | author: 'shazmo', 446 | message: 'No more tabs. Use contextual indentation. That\'s what FORTUNE 500 companies do.', 447 | example: [ 448 | '$("#header").html("A Fortune 500 Company").show("slow").click(function () ', 449 | ' {', 450 | ' window.location="http://www.a-fortune-500-company.com/"', 451 | ' });', 452 | 'var isStandalone = checkIfStandalone();', 453 | '$("#modal").unbind("click").bind("click", function (e)', 454 | ' {', 455 | ' if(getConfig().attachCloseEvent)', 456 | ' {', 457 | ' var targetObj= $(e.target);', 458 | ' (isStandalone ? close({', 459 | ' element: args.element', 460 | ' }) : close();', 461 | ' }', 462 | ' return false;', 463 | ' });', 464 | '$("#overlay").unbind("keydown").bind("keydown", function (e)', 465 | ' {', 466 | ' if(e.keyCode === 27)', 467 | ' {', 468 | ' var targetObj= $(e.target);', 469 | ' (isStandalone) ? close({', 470 | ' element: args.element', 471 | ' }) : close();', 472 | ' return false;', 473 | ' }', 474 | ' });' 475 | ] 476 | }); 477 | 478 | tips.push({ 479 | author: 'miketaylr', 480 | message: 'Using agressive caching methods on your jQuery selectors', 481 | example: [ 482 | 'var listContainer = \'#list\'; //cached', 483 | '', 484 | 'for (var i = 0; i < 9001; i++) {', 485 | ' $(listContainer).append(\'
  • Product #\' + i + \'
  • \');', 486 | '}' 487 | ] 488 | }); 489 | 490 | tips.push({ 491 | author: 'bentruyman', 492 | message: 'Utilizing vapor.js to Its Fullest Extent', 493 | example: [''] 494 | }); 495 | 496 | tips.push({ 497 | author: 'cowboy', 498 | message: 'Never, ever, EVER serializing JSON properly', 499 | example: [ 500 | 'function buildJSONObject( key, value ) {', 501 | ' return "{\\"" + key.replace(/"/g,"\\\\\\"") + "\\": \\"" + value.replace(/"/g,"\\\\\\"") + "\\"}";', 502 | '}' 503 | ] 504 | }); 505 | 506 | tips.push({ 507 | author: 'mathias', 508 | message: 'Using advanced protection techniques to stop people from viewing the source code', 509 | example: [ 510 | 'window.oncontextmenu = function() {', 511 | ' alert(\'Copyright © 1990 Initech - All Rights Reserved\');', 512 | ' return false;', 513 | '};' 514 | ] 515 | }); 516 | 517 | module.exports = tips; 518 | -------------------------------------------------------------------------------- /public/stylesheets/enterprise.css: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz&subset=latin); 2 | @import url(http://fonts.googleapis.com/css?family=Inconsolata&subset=latin); 3 | 4 | :focus { 5 | outline: none; 6 | } 7 | 8 | body, p { 9 | margin: 0; 10 | } 11 | 12 | html { 13 | background-image: url(data:image/png;base64,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); 14 | color: #f3f3f3; 15 | font-family: 'Yanone Kaffeesatz', arial, serif; 16 | } 17 | 18 | body { 19 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0, 0, 0, 0.8)), color-stop(1, transparent)); 20 | background-repeat: repeat-x; 21 | margin-bottom: 60px; 22 | padding-top: 149px; 23 | } 24 | 25 | a { 26 | color: #ae81ff; 27 | } 28 | 29 | em { 30 | font-style: normal; 31 | } 32 | 33 | header, 34 | footer { 35 | display: block; 36 | height: 36px; 37 | } 38 | 39 | img { 40 | border: 0; 41 | } 42 | 43 | li { 44 | list-style: none; 45 | } 46 | 47 | ul { 48 | margin: 0; 49 | padding: 0; 50 | } 51 | 52 | .shadowed { 53 | text-shadow: 3px 3px 0 #000; 54 | } 55 | 56 | .split { 57 | display: inline-block; 58 | float: left; 59 | } 60 | 61 | header .split { 62 | width: 460px; 63 | } 64 | 65 | footer .split { 66 | width: 440px; 67 | } 68 | 69 | .upper { 70 | text-transform: uppercase; 71 | } 72 | 73 | #container { 74 | margin: auto; 75 | width: 920px; 76 | } 77 | 78 | #prefix { 79 | color: #999; 80 | font-size: 24px; 81 | } 82 | 83 | #prefix a { 84 | text-decoration: none; 85 | } 86 | 87 | #refresh { 88 | text-align: right; 89 | } 90 | 91 | #refresh a { 92 | background-image: -moz-linear-gradient(top, #eee, #aaa); 93 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #eee), color-stop(1, #aaa)); 94 | -moz-border-radius: 10px; 95 | -webkit-border-radius: 10px; 96 | border-radius: 10px; 97 | color: #333; 98 | display: inline-block; 99 | padding: 6px 16px; 100 | text-decoration: none; 101 | text-shadow: 0 1px 0 #fff; 102 | } 103 | 104 | #refresh a:hover { 105 | color: #666; 106 | } 107 | 108 | #refresh a:active { 109 | background-image: -moz-linear-gradient(top, #aaa, #eee); 110 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #aaa), color-stop(1, #eee)); 111 | } 112 | 113 | #message { 114 | font-size: 82px; 115 | } 116 | 117 | #example { 118 | background-color: #fff; 119 | background-image: -moz-linear-gradient(top, #fff, #eee); 120 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(1, #eee)); 121 | -moz-border-radius: 20px; 122 | -webkit-border-radius: 20px; 123 | border-radius: 20px; 124 | -moz-box-shadow: 0px 0px 15px #000; 125 | -webkit-box-shadow: 0px 0px 15px #000; 126 | box-shadow: 0px 0px 15px #000; 127 | color: #333; 128 | font-family: 'Inconsolata', courier, monospace; 129 | overflow: auto; 130 | padding: 20px; 131 | } 132 | 133 | #author { 134 | margin-left: 20px; 135 | } 136 | 137 | #permalink { 138 | margin-right: 20px; 139 | text-align: right; 140 | } 141 | 142 | #moar { 143 | margin: 40px 0; 144 | text-align: center; 145 | } 146 | 147 | #moar li { 148 | display: inline-block; 149 | padding: 0 5px; 150 | text-align: center; 151 | width: 100px; 152 | } 153 | 154 | #moar a { 155 | color: #222; 156 | font-size: 46px; 157 | text-decoration: none; 158 | -webkit-transition: color 0.25s ease-in-out; 159 | } 160 | 161 | #contribute { 162 | text-align: center; 163 | } 164 | 165 | #joke, #fork { 166 | position: absolute; 167 | top: 0; 168 | } 169 | 170 | #joke { 171 | left: 0; 172 | } 173 | 174 | #fork { 175 | right: 0; 176 | -webkit-transition: opacity 0.25s ease-in-out; 177 | } 178 | 179 | #fork:hover { 180 | opacity: 0.75; 181 | } 182 | 183 | pre .built_in { color: #ae81ff; } 184 | pre .comment { color: #999; } 185 | pre .function .title { color: #86c20e; } 186 | pre .function .params { color: #fd971f; } 187 | pre .keyword { color: #44a0ef; } 188 | pre .literal { color: #ae81ff; } 189 | pre .number { color: #ae81ff; } 190 | pre .string { color: #c6bb54; } 191 | -------------------------------------------------------------------------------- /public/javascripts/socket.io/socket.io.js: -------------------------------------------------------------------------------- 1 | /** Socket.IO 0.5.3 - Built with build.js */ 2 | /** 3 | * Socket.IO client 4 | * 5 | * @author Guillermo Rauch 6 | * @license The MIT license. 7 | * @copyright Copyright (c) 2010 LearnBoost 8 | */ 9 | 10 | this.io = { 11 | version: '0.5.3', 12 | 13 | setPath: function(path){ 14 | this.path = /\/$/.test(path) ? path : path + '/'; 15 | 16 | // this is temporary until we get a fix for injecting Flash WebSocket javascript files dynamically, 17 | // as io.js shouldn't be aware of specific transports. 18 | if ('WebSocket' in window){ 19 | WebSocket.__swfLocation = path + 'lib/vendor/web-socket-js/WebSocketMain.swf'; 20 | } 21 | } 22 | }; 23 | 24 | if ('jQuery' in this) jQuery.io = this.io; 25 | /** 26 | * Socket.IO client 27 | * 28 | * @author Guillermo Rauch 29 | * @license The MIT license. 30 | * @copyright Copyright (c) 2010 LearnBoost 31 | */ 32 | 33 | io.util = { 34 | 35 | inherit: function(ctor, superCtor){ 36 | // no support for `instanceof` for now 37 | for (var i in superCtor.prototype){ 38 | ctor.prototype[i] = superCtor.prototype[i]; 39 | } 40 | }, 41 | 42 | indexOf: function(arr, item, from){ 43 | for (var l = arr.length, i = (from < 0) ? Math.max(0, l + from) : from || 0; i < l; i++){ 44 | if (arr[i] === item) return i; 45 | } 46 | return -1; 47 | }, 48 | 49 | isArray: function(obj){ 50 | return Object.prototype.toString.call(obj) === '[object Array]'; 51 | } 52 | 53 | }; 54 | /** 55 | * Socket.IO client 56 | * 57 | * @author Guillermo Rauch 58 | * @license The MIT license. 59 | * @copyright Copyright (c) 2010 LearnBoost 60 | */ 61 | 62 | // abstract 63 | 64 | (function(){ 65 | 66 | var frame = '~m~', 67 | 68 | Transport = io.Transport = function(base, options){ 69 | this.base = base; 70 | this.options = options; 71 | }; 72 | 73 | Transport.prototype.send = function(){ 74 | throw new Error('Missing send() implementation'); 75 | }; 76 | 77 | Transport.prototype.connect = function(){ 78 | throw new Error('Missing connect() implementation'); 79 | }; 80 | 81 | Transport.prototype.disconnect = function(){ 82 | throw new Error('Missing disconnect() implementation'); 83 | }; 84 | 85 | Transport.prototype._encode = function(messages){ 86 | var ret = '', message, 87 | messages = io.util.isArray(messages) ? messages : [messages]; 88 | for (var i = 0, l = messages.length; i < l; i++){ 89 | message = messages[i] === null || messages[i] === undefined ? '' : String(messages[i]); 90 | ret += frame + message.length + frame + message; 91 | } 92 | return ret; 93 | }; 94 | 95 | Transport.prototype._decode = function(data){ 96 | var messages = [], number, n; 97 | do { 98 | if (data.substr(0, 3) !== frame) return messages; 99 | data = data.substr(3); 100 | number = '', n = ''; 101 | for (var i = 0, l = data.length; i < l; i++){ 102 | n = Number(data.substr(i, 1)); 103 | if (data.substr(i, 1) == n){ 104 | number += n; 105 | } else { 106 | data = data.substr(number.length + frame.length) 107 | number = Number(number); 108 | break; 109 | } 110 | } 111 | messages.push(data.substr(0, number)); // here 112 | data = data.substr(number); 113 | } while(data !== ''); 114 | return messages; 115 | }; 116 | 117 | Transport.prototype._onData = function(data){ 118 | var msgs = this._decode(data); 119 | if (msgs){ 120 | for (var i = 0, l = msgs.length; i < l; i++){ 121 | this._onMessage(msgs[i]); 122 | } 123 | } 124 | }; 125 | 126 | Transport.prototype._onMessage = function(message){ 127 | if (!('sessionid' in this)){ 128 | this.sessionid = message; 129 | this._onConnect(); 130 | } else if (message.substr(0, 3) == '~h~'){ 131 | this._onHeartbeat(message.substr(3)); 132 | } else { 133 | this.base._onMessage(message); 134 | } 135 | }, 136 | 137 | Transport.prototype._onHeartbeat = function(heartbeat){ 138 | this.send('~h~' + heartbeat); // echo 139 | }; 140 | 141 | Transport.prototype._onConnect = function(){ 142 | this.connected = true; 143 | this.base._onConnect(); 144 | }; 145 | 146 | Transport.prototype._onDisconnect = function(){ 147 | if (!this.connected) return; 148 | this.connected = false; 149 | this.base._onDisconnect(); 150 | }; 151 | 152 | Transport.prototype._prepareUrl = function(){ 153 | return (this.base.options.secure ? 'https' : 'http') 154 | + '://' + this.base.host 155 | + ':' + this.base.options.port 156 | + '/' + this.base.options.resource 157 | + '/' + this.type 158 | + (this.sessionid ? ('/' + this.sessionid) : '/'); 159 | }; 160 | 161 | })(); 162 | /** 163 | * Socket.IO client 164 | * 165 | * @author Guillermo Rauch 166 | * @license The MIT license. 167 | * @copyright Copyright (c) 2010 LearnBoost 168 | */ 169 | 170 | (function(){ 171 | 172 | var empty = new Function, 173 | 174 | request = function(xdomain){ 175 | if ('XDomainRequest' in window && xdomain) return new XDomainRequest(); 176 | if ('XMLHttpRequest' in window) return new XMLHttpRequest(); 177 | 178 | try { 179 | var a = new ActiveXObject('MSXML2.XMLHTTP'); 180 | return a; 181 | } catch(e){} 182 | 183 | try { 184 | var b = new ActiveXObject('Microsoft.XMLHTTP'); 185 | return b; 186 | } catch(e){} 187 | 188 | return false; 189 | }, 190 | 191 | XHR = io.Transport.XHR = function(){ 192 | io.Transport.apply(this, arguments); 193 | }; 194 | 195 | io.util.inherit(XHR, io.Transport); 196 | 197 | XHR.prototype.connect = function(){ 198 | if (!('_sendBuffer' in this)) this._sendBuffer = []; 199 | this._get(); 200 | return this; 201 | }; 202 | 203 | XHR.prototype._checkSend = function(){ 204 | if (!this._posting && this._sendBuffer.length){ 205 | var encoded = this._encode(this._sendBuffer); 206 | this._sendBuffer = []; 207 | this._send(encoded); 208 | } 209 | }; 210 | 211 | XHR.prototype.send = function(data){ 212 | if (io.util.isArray(data)){ 213 | this._sendBuffer.push.apply(this._sendBuffer, data); 214 | } else { 215 | this._sendBuffer.push(data); 216 | } 217 | this._checkSend(); 218 | return this; 219 | }; 220 | 221 | XHR.prototype._send = function(data){ 222 | var self = this; 223 | this._posting = true; 224 | this._sendXhr = this._request('send', 'POST'); 225 | this._sendXhr.send('data=' + encodeURIComponent(data)); 226 | this._sendXhr.onreadystatechange = function(){ 227 | var status; 228 | if (self._sendXhr.readyState == 4){ 229 | self._sendXhr.onreadystatechange = empty; 230 | try { status = self._sendXhr.status; } catch(e){} 231 | if (status == 200){ 232 | self._posting = false; 233 | self._checkSend(); 234 | } 235 | } 236 | }; 237 | }, 238 | 239 | XHR.prototype.disconnect = function(){ 240 | if (this._xhr){ 241 | this._xhr.onreadystatechange = this._xhr.onload = empty; 242 | this._xhr.abort(); 243 | } 244 | if (this._sendXhr){ 245 | this._sendXhr.onreadystatechange = this._sendXhr.onload = empty; 246 | this._sendXhr.abort(); 247 | } 248 | this._onClose(); 249 | this._onDisconnect(); 250 | return this; 251 | } 252 | 253 | XHR.prototype._request = function(url, method, multipart){ 254 | var req = request(this.base._isXDomain()); 255 | if (multipart) req.multipart = true; 256 | req.open(method || 'GET', this._prepareUrl() + (url ? '/' + url : '')); 257 | if (method == 'POST'){ 258 | req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8'); 259 | } 260 | return req; 261 | }; 262 | 263 | XHR.check = function(){ 264 | try { 265 | if (request()) return true; 266 | } catch(e){} 267 | return false; 268 | }; 269 | 270 | XHR.request = request; 271 | 272 | })(); 273 | /** 274 | * Socket.IO client 275 | * 276 | * @author Guillermo Rauch 277 | * @license The MIT license. 278 | * @copyright Copyright (c) 2010 LearnBoost 279 | */ 280 | 281 | (function(){ 282 | 283 | var WS = io.Transport.websocket = function(){ 284 | io.Transport.apply(this, arguments); 285 | }; 286 | 287 | io.util.inherit(WS, io.Transport); 288 | 289 | WS.prototype.type = 'websocket'; 290 | 291 | WS.prototype.connect = function(){ 292 | var self = this; 293 | this.socket = new WebSocket(this._prepareUrl()); 294 | this.socket.onmessage = function(ev){ self._onData(ev.data); }; 295 | this.socket.onclose = function(ev){ self._onClose(); }; 296 | return this; 297 | }; 298 | 299 | WS.prototype.send = function(data){ 300 | this.socket.send(this._encode(data)); 301 | return this; 302 | } 303 | 304 | WS.prototype.disconnect = function(){ 305 | this.socket.close(); 306 | return this; 307 | }; 308 | 309 | WS.prototype._onClose = function(){ 310 | this._onDisconnect(); 311 | return this; 312 | }; 313 | 314 | WS.prototype._prepareUrl = function(){ 315 | return (this.base.options.secure ? 'wss' : 'ws') 316 | + '://' + this.base.host 317 | + ':' + this.base.options.port 318 | + '/' + this.base.options.resource 319 | + '/' + this.type 320 | + (this.sessionid ? ('/' + this.sessionid) : ''); 321 | }; 322 | 323 | WS.check = function(){ 324 | // we make sure WebSocket is not confounded with a previously loaded flash WebSocket 325 | return 'WebSocket' in window && !('__initialize' in WebSocket); 326 | }; 327 | 328 | WS.xdomainCheck = function(){ 329 | return true; 330 | }; 331 | 332 | })(); 333 | /** 334 | * Socket.IO client 335 | * 336 | * @author Guillermo Rauch 337 | * @license The MIT license. 338 | * @copyright Copyright (c) 2010 LearnBoost 339 | */ 340 | 341 | (function(){ 342 | 343 | var Flashsocket = io.Transport.flashsocket = function(){ 344 | io.Transport.websocket.apply(this, arguments); 345 | }; 346 | 347 | io.util.inherit(Flashsocket, io.Transport.websocket); 348 | 349 | Flashsocket.prototype.type = 'flashsocket'; 350 | 351 | Flashsocket.prototype._onClose = function(){ 352 | if (!this.base.connected){ 353 | // something failed, we might be behind a proxy, so we'll try another transport 354 | this.base.options.transports.splice(io.util.indexOf(this.base.options.transports, 'flashsocket'), 1); 355 | this.base.transport = this.base.getTransport(); 356 | this.base.connect(); 357 | return; 358 | } 359 | return io.Transport.websocket.prototype._onClose.call(this); 360 | }; 361 | 362 | Flashsocket.check = function(){ 363 | if (!('path' in io)) throw new Error('The `flashsocket` transport requires that you call io.setPath() with the path to the socket.io client dir.'); 364 | if ('navigator' in window && 'plugins' in navigator && navigator.plugins['Shockwave Flash']){ 365 | return !!navigator.plugins['Shockwave Flash'].description; 366 | } 367 | if ('ActiveXObject' in window) { 368 | try { 369 | return !!new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); 370 | } catch (e) {} 371 | } 372 | return false; 373 | }; 374 | 375 | Flashsocket.xdomainCheck = function(){ 376 | return true; 377 | }; 378 | 379 | })(); 380 | /** 381 | * Socket.IO client 382 | * 383 | * @author Guillermo Rauch 384 | * @license The MIT license. 385 | * @copyright Copyright (c) 2010 LearnBoost 386 | */ 387 | 388 | (function(){ 389 | 390 | var HTMLFile = io.Transport.htmlfile = function(){ 391 | io.Transport.XHR.apply(this, arguments); 392 | }; 393 | 394 | io.util.inherit(HTMLFile, io.Transport.XHR); 395 | 396 | HTMLFile.prototype.type = 'htmlfile'; 397 | 398 | HTMLFile.prototype._get = function(){ 399 | var self = this; 400 | this._open(); 401 | window.attachEvent('onunload', function(){ self._destroy(); }); 402 | }; 403 | 404 | HTMLFile.prototype._open = function(){ 405 | this._doc = new ActiveXObject('htmlfile'); 406 | this._doc.open(); 407 | this._doc.write(''); 408 | this._doc.parentWindow.s = this; 409 | this._doc.close(); 410 | 411 | var _iframeC = this._doc.createElement('div'); 412 | this._doc.body.appendChild(_iframeC); 413 | this._iframe = this._doc.createElement('iframe'); 414 | _iframeC.appendChild(this._iframe); 415 | this._iframe.src = this._prepareUrl() + '/' + (+ new Date); 416 | }; 417 | 418 | HTMLFile.prototype._ = function(data, doc){ 419 | this._onData(data); 420 | var script = doc.getElementsByTagName('script')[0]; 421 | script.parentNode.removeChild(script); 422 | }; 423 | 424 | HTMLFile.prototype._destroy = function(){ 425 | this._iframe.src = 'about:blank'; 426 | this._doc = null; 427 | CollectGarbage(); 428 | }; 429 | 430 | HTMLFile.prototype.disconnect = function(){ 431 | this._destroy(); 432 | return io.Transport.XHR.prototype.disconnect.call(this); 433 | }; 434 | 435 | HTMLFile.check = function(){ 436 | if ('ActiveXObject' in window){ 437 | try { 438 | var a = new ActiveXObject('htmlfile'); 439 | return a && io.Transport.XHR.check(); 440 | } catch(e){} 441 | } 442 | return false; 443 | }; 444 | 445 | HTMLFile.xdomainCheck = function(){ 446 | return false; // send() is not cross domain. we need to POST to an iframe to fix it 447 | }; 448 | 449 | })(); 450 | /** 451 | * Socket.IO client 452 | * 453 | * @author Guillermo Rauch 454 | * @license The MIT license. 455 | * @copyright Copyright (c) 2010 LearnBoost 456 | */ 457 | 458 | (function(){ 459 | 460 | var XHRMultipart = io.Transport['xhr-multipart'] = function(){ 461 | io.Transport.XHR.apply(this, arguments); 462 | }; 463 | 464 | io.util.inherit(XHRMultipart, io.Transport.XHR); 465 | 466 | XHRMultipart.prototype.type = 'xhr-multipart'; 467 | 468 | XHRMultipart.prototype._get = function(){ 469 | var self = this; 470 | this._xhr = this._request('', 'GET', true); 471 | this._xhr.onreadystatechange = function(){ 472 | if (self._xhr.readyState == 3) self._onData(self._xhr.responseText); 473 | }; 474 | this._xhr.send(); 475 | }; 476 | 477 | XHRMultipart.check = function(){ 478 | return 'XMLHttpRequest' in window && 'multipart' in XMLHttpRequest.prototype; 479 | }; 480 | 481 | XHRMultipart.xdomainCheck = function(){ 482 | return true; 483 | }; 484 | 485 | })(); 486 | /** 487 | * Socket.IO client 488 | * 489 | * @author Guillermo Rauch 490 | * @license The MIT license. 491 | * @copyright Copyright (c) 2010 LearnBoost 492 | */ 493 | 494 | (function(){ 495 | 496 | var empty = new Function(), 497 | 498 | XHRPolling = io.Transport['xhr-polling'] = function(){ 499 | io.Transport.XHR.apply(this, arguments); 500 | }; 501 | 502 | io.util.inherit(XHRPolling, io.Transport.XHR); 503 | 504 | XHRPolling.prototype.type = 'xhr-polling'; 505 | 506 | XHRPolling.prototype._get = function(){ 507 | var self = this; 508 | this._xhr = this._request(+ new Date, 'GET'); 509 | if ('onload' in this._xhr){ 510 | this._xhr.onload = function(){ 511 | if (this.responseText.length) self._onData(this.responseText); 512 | self.connect(); 513 | }; 514 | } else { 515 | this._xhr.onreadystatechange = function(){ 516 | var status; 517 | if (self._xhr.readyState == 4){ 518 | self._xhr.onreadystatechange = empty; 519 | try { status = self._xhr.status; } catch(e){} 520 | if (status == 200){ 521 | if (self._xhr.responseText.length) self._onData(self._xhr.responseText); 522 | self.connect(); 523 | } 524 | } 525 | }; 526 | } 527 | this._xhr.send(); 528 | }; 529 | 530 | XHRPolling.check = function(){ 531 | return io.Transport.XHR.check(); 532 | }; 533 | 534 | XHRPolling.xdomainCheck = function(){ 535 | return 'XDomainRequest' in window || 'XMLHttpRequest' in window; 536 | }; 537 | 538 | })(); 539 | /** 540 | * Socket.IO client 541 | * 542 | * @author Guillermo Rauch 543 | * @license The MIT license. 544 | * @copyright Copyright (c) 2010 LearnBoost 545 | */ 546 | 547 | (function(){ 548 | 549 | var Socket = io.Socket = function(host, options){ 550 | this.host = host || document.domain; 551 | this.options = { 552 | secure: false, 553 | document: document, 554 | heartbeatInterval: 4000, 555 | port: document.location.port || 80, 556 | resource: 'socket.io', 557 | transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling'], 558 | transportOptions: {}, 559 | rememberTransport: false 560 | }; 561 | for (var i in options) this.options[i] = options[i]; 562 | this.connected = false; 563 | this.connecting = false; 564 | this._events = {}; 565 | this.transport = this.getTransport(); 566 | if (!this.transport && 'console' in window) console.error('No transport available'); 567 | }; 568 | 569 | Socket.prototype.getTransport = function(){ 570 | var transports = this.options.transports, match; 571 | if (this.options.rememberTransport){ 572 | match = this.options.document.cookie.match('(?:^|;)\\s*socket\.io=([^;]*)'); 573 | if (match) transports = [decodeURIComponent(match[1])]; 574 | } 575 | for (var i = 0, transport; transport = transports[i]; i++){ 576 | if (io.Transport[transport] 577 | && io.Transport[transport].check() 578 | && (!this._isXDomain() || io.Transport[transport].xdomainCheck())){ 579 | return new io.Transport[transport](this, this.options.transportOptions[transport] || {}); 580 | } 581 | } 582 | return null; 583 | }; 584 | 585 | Socket.prototype.connect = function(){ 586 | if (this.transport && !this.connected && !this.connecting){ 587 | this.connecting = true; 588 | this.transport.connect(); 589 | } 590 | return this; 591 | }; 592 | 593 | Socket.prototype.send = function(data){ 594 | if (!this.transport || !this.transport.connected) return this._queue(data); 595 | this.transport.send(data); 596 | return this; 597 | }; 598 | 599 | Socket.prototype.disconnect = function(){ 600 | this.transport.disconnect(); 601 | return this; 602 | }; 603 | 604 | Socket.prototype.on = function(name, fn){ 605 | if (!(name in this._events)) this._events[name] = []; 606 | this._events[name].push(fn); 607 | return this; 608 | }; 609 | 610 | Socket.prototype.fire = function(name, args){ 611 | if (name in this._events){ 612 | for (var i in this._events[name]) 613 | this._events[name][i].apply(this, args); 614 | } 615 | return this; 616 | }; 617 | 618 | Socket.prototype.removeEvent = function(name, fn){ 619 | if (name in this._events){ 620 | for (var i in this._events[name]){ 621 | for (var a = 0, l = this._events[name].length; a < l; a++) 622 | if (this._events[name][a] == fn) this._events[name].splice(a, 1); 623 | } 624 | } 625 | return this; 626 | }; 627 | 628 | Socket.prototype._queue = function(message){ 629 | if (!('_queueStack' in this)) this._queueStack = []; 630 | this._queueStack.push(message); 631 | return this; 632 | }; 633 | 634 | Socket.prototype._doQueue = function(){ 635 | if (!('_queueStack' in this) || !this._queueStack.length) return this; 636 | this.transport.send(this._queueStack); 637 | this._queueStack = []; 638 | return this; 639 | }; 640 | 641 | Socket.prototype._isXDomain = function(){ 642 | return this.host !== document.domain; 643 | }; 644 | 645 | Socket.prototype._onConnect = function(){ 646 | this.connected = true; 647 | this.connecting = false; 648 | this._doQueue(); 649 | if (this.options.rememberTransport) this.options.document.cookie = 'socket.io=' + encodeURIComponent(this.transport.type); 650 | this.fire('connect'); 651 | }; 652 | 653 | Socket.prototype._onMessage = function(data){ 654 | this.fire('message', [data]); 655 | }; 656 | 657 | Socket.prototype._onDisconnect = function(){ 658 | this.fire('disconnect'); 659 | }; 660 | 661 | Socket.prototype.addListener = Socket.prototype.addEvent = Socket.prototype.addEventListener = Socket.prototype.on; 662 | 663 | })(); 664 | /* SWFObject v2.2 665 | is released under the MIT License 666 | */ 667 | var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='"+af+"";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab 0) { 777 | for (var i = 0; i < ol; i++) { 778 | if (typeof objects[i].SetVariable != "undefined") { 779 | activeObjects[activeObjects.length] = objects[i]; 780 | } 781 | } 782 | } 783 | var embeds = document.getElementsByTagName("embed"); 784 | var el = embeds.length; 785 | var activeEmbeds = []; 786 | if (el > 0) { 787 | for (var j = 0; j < el; j++) { 788 | if (typeof embeds[j].SetVariable != "undefined") { 789 | activeEmbeds[activeEmbeds.length] = embeds[j]; 790 | } 791 | } 792 | } 793 | var aol = activeObjects.length; 794 | var ael = activeEmbeds.length; 795 | var searchStr = "bridgeName="+ bridgeName; 796 | if ((aol == 1 && !ael) || (aol == 1 && ael == 1)) { 797 | FABridge.attachBridge(activeObjects[0], bridgeName); 798 | } 799 | else if (ael == 1 && !aol) { 800 | FABridge.attachBridge(activeEmbeds[0], bridgeName); 801 | } 802 | else { 803 | var flash_found = false; 804 | if (aol > 1) { 805 | for (var k = 0; k < aol; k++) { 806 | var params = activeObjects[k].childNodes; 807 | for (var l = 0; l < params.length; l++) { 808 | var param = params[l]; 809 | if (param.nodeType == 1 && param.tagName.toLowerCase() == "param" && param["name"].toLowerCase() == "flashvars" && param["value"].indexOf(searchStr) >= 0) { 810 | FABridge.attachBridge(activeObjects[k], bridgeName); 811 | flash_found = true; 812 | break; 813 | } 814 | } 815 | if (flash_found) { 816 | break; 817 | } 818 | } 819 | } 820 | if (!flash_found && ael > 1) { 821 | for (var m = 0; m < ael; m++) { 822 | var flashVars = activeEmbeds[m].attributes.getNamedItem("flashVars").nodeValue; 823 | if (flashVars.indexOf(searchStr) >= 0) { 824 | FABridge.attachBridge(activeEmbeds[m], bridgeName); 825 | break; 826 | } 827 | } 828 | } 829 | } 830 | return true; 831 | } 832 | 833 | // used to track multiple bridge instances, since callbacks from AS are global across the page. 834 | 835 | FABridge.nextBridgeID = 0; 836 | FABridge.instances = {}; 837 | FABridge.idMap = {}; 838 | FABridge.refCount = 0; 839 | 840 | FABridge.extractBridgeFromID = function(id) 841 | { 842 | var bridgeID = (id >> 16); 843 | return FABridge.idMap[bridgeID]; 844 | } 845 | 846 | FABridge.attachBridge = function(instance, bridgeName) 847 | { 848 | var newBridgeInstance = new FABridge(instance, bridgeName); 849 | 850 | FABridge[bridgeName] = newBridgeInstance; 851 | 852 | /* FABridge[bridgeName] = function() { 853 | return newBridgeInstance.root(); 854 | } 855 | */ 856 | var callbacks = FABridge.initCallbacks[bridgeName]; 857 | if (callbacks == null) 858 | { 859 | return; 860 | } 861 | for (var i = 0; i < callbacks.length; i++) 862 | { 863 | callbacks[i].call(newBridgeInstance); 864 | } 865 | delete FABridge.initCallbacks[bridgeName] 866 | } 867 | 868 | // some methods can't be proxied. You can use the explicit get,set, and call methods if necessary. 869 | 870 | FABridge.blockedMethods = 871 | { 872 | toString: true, 873 | get: true, 874 | set: true, 875 | call: true 876 | }; 877 | 878 | FABridge.prototype = 879 | { 880 | 881 | 882 | // bootstrapping 883 | 884 | root: function() 885 | { 886 | return this.deserialize(this.target.getRoot()); 887 | }, 888 | //clears all of the AS objects in the cache maps 889 | releaseASObjects: function() 890 | { 891 | return this.target.releaseASObjects(); 892 | }, 893 | //clears a specific object in AS from the type maps 894 | releaseNamedASObject: function(value) 895 | { 896 | if(typeof(value) != "object") 897 | { 898 | return false; 899 | } 900 | else 901 | { 902 | var ret = this.target.releaseNamedASObject(value.fb_instance_id); 903 | return ret; 904 | } 905 | }, 906 | //create a new AS Object 907 | create: function(className) 908 | { 909 | return this.deserialize(this.target.create(className)); 910 | }, 911 | 912 | 913 | // utilities 914 | 915 | makeID: function(token) 916 | { 917 | return (this.bridgeID << 16) + token; 918 | }, 919 | 920 | 921 | // low level access to the flash object 922 | 923 | //get a named property from an AS object 924 | getPropertyFromAS: function(objRef, propName) 925 | { 926 | if (FABridge.refCount > 0) 927 | { 928 | throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround."); 929 | } 930 | else 931 | { 932 | FABridge.refCount++; 933 | retVal = this.target.getPropFromAS(objRef, propName); 934 | retVal = this.handleError(retVal); 935 | FABridge.refCount--; 936 | return retVal; 937 | } 938 | }, 939 | //set a named property on an AS object 940 | setPropertyInAS: function(objRef,propName, value) 941 | { 942 | if (FABridge.refCount > 0) 943 | { 944 | throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround."); 945 | } 946 | else 947 | { 948 | FABridge.refCount++; 949 | retVal = this.target.setPropInAS(objRef,propName, this.serialize(value)); 950 | retVal = this.handleError(retVal); 951 | FABridge.refCount--; 952 | return retVal; 953 | } 954 | }, 955 | 956 | //call an AS function 957 | callASFunction: function(funcID, args) 958 | { 959 | if (FABridge.refCount > 0) 960 | { 961 | throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround."); 962 | } 963 | else 964 | { 965 | FABridge.refCount++; 966 | retVal = this.target.invokeASFunction(funcID, this.serialize(args)); 967 | retVal = this.handleError(retVal); 968 | FABridge.refCount--; 969 | return retVal; 970 | } 971 | }, 972 | //call a method on an AS object 973 | callASMethod: function(objID, funcName, args) 974 | { 975 | if (FABridge.refCount > 0) 976 | { 977 | throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround."); 978 | } 979 | else 980 | { 981 | FABridge.refCount++; 982 | args = this.serialize(args); 983 | retVal = this.target.invokeASMethod(objID, funcName, args); 984 | retVal = this.handleError(retVal); 985 | FABridge.refCount--; 986 | return retVal; 987 | } 988 | }, 989 | 990 | // responders to remote calls from flash 991 | 992 | //callback from flash that executes a local JS function 993 | //used mostly when setting js functions as callbacks on events 994 | invokeLocalFunction: function(funcID, args) 995 | { 996 | var result; 997 | var func = this.localFunctionCache[funcID]; 998 | 999 | if(func != undefined) 1000 | { 1001 | result = this.serialize(func.apply(null, this.deserialize(args))); 1002 | } 1003 | 1004 | return result; 1005 | }, 1006 | 1007 | // Object Types and Proxies 1008 | 1009 | // accepts an object reference, returns a type object matching the obj reference. 1010 | getTypeFromName: function(objTypeName) 1011 | { 1012 | return this.remoteTypeCache[objTypeName]; 1013 | }, 1014 | //create an AS proxy for the given object ID and type 1015 | createProxy: function(objID, typeName) 1016 | { 1017 | var objType = this.getTypeFromName(typeName); 1018 | instanceFactory.prototype = objType; 1019 | var instance = new instanceFactory(objID); 1020 | this.remoteInstanceCache[objID] = instance; 1021 | return instance; 1022 | }, 1023 | //return the proxy associated with the given object ID 1024 | getProxy: function(objID) 1025 | { 1026 | return this.remoteInstanceCache[objID]; 1027 | }, 1028 | 1029 | // accepts a type structure, returns a constructed type 1030 | addTypeDataToCache: function(typeData) 1031 | { 1032 | newType = new ASProxy(this, typeData.name); 1033 | var accessors = typeData.accessors; 1034 | for (var i = 0; i < accessors.length; i++) 1035 | { 1036 | this.addPropertyToType(newType, accessors[i]); 1037 | } 1038 | 1039 | var methods = typeData.methods; 1040 | for (var i = 0; i < methods.length; i++) 1041 | { 1042 | if (FABridge.blockedMethods[methods[i]] == undefined) 1043 | { 1044 | this.addMethodToType(newType, methods[i]); 1045 | } 1046 | } 1047 | 1048 | 1049 | this.remoteTypeCache[newType.typeName] = newType; 1050 | return newType; 1051 | }, 1052 | 1053 | //add a property to a typename; used to define the properties that can be called on an AS proxied object 1054 | addPropertyToType: function(ty, propName) 1055 | { 1056 | var c = propName.charAt(0); 1057 | var setterName; 1058 | var getterName; 1059 | if(c >= "a" && c <= "z") 1060 | { 1061 | getterName = "get" + c.toUpperCase() + propName.substr(1); 1062 | setterName = "set" + c.toUpperCase() + propName.substr(1); 1063 | } 1064 | else 1065 | { 1066 | getterName = "get" + propName; 1067 | setterName = "set" + propName; 1068 | } 1069 | ty[setterName] = function(val) 1070 | { 1071 | this.bridge.setPropertyInAS(this.fb_instance_id, propName, val); 1072 | } 1073 | ty[getterName] = function() 1074 | { 1075 | return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName)); 1076 | } 1077 | }, 1078 | 1079 | //add a method to a typename; used to define the methods that can be callefd on an AS proxied object 1080 | addMethodToType: function(ty, methodName) 1081 | { 1082 | ty[methodName] = function() 1083 | { 1084 | return this.bridge.deserialize(this.bridge.callASMethod(this.fb_instance_id, methodName, FABridge.argsToArray(arguments))); 1085 | } 1086 | }, 1087 | 1088 | // Function Proxies 1089 | 1090 | //returns the AS proxy for the specified function ID 1091 | getFunctionProxy: function(funcID) 1092 | { 1093 | var bridge = this; 1094 | if (this.remoteFunctionCache[funcID] == null) 1095 | { 1096 | this.remoteFunctionCache[funcID] = function() 1097 | { 1098 | bridge.callASFunction(funcID, FABridge.argsToArray(arguments)); 1099 | } 1100 | } 1101 | return this.remoteFunctionCache[funcID]; 1102 | }, 1103 | 1104 | //reutrns the ID of the given function; if it doesnt exist it is created and added to the local cache 1105 | getFunctionID: function(func) 1106 | { 1107 | if (func.__bridge_id__ == undefined) 1108 | { 1109 | func.__bridge_id__ = this.makeID(this.nextLocalFuncID++); 1110 | this.localFunctionCache[func.__bridge_id__] = func; 1111 | } 1112 | return func.__bridge_id__; 1113 | }, 1114 | 1115 | // serialization / deserialization 1116 | 1117 | serialize: function(value) 1118 | { 1119 | var result = {}; 1120 | 1121 | var t = typeof(value); 1122 | //primitives are kept as such 1123 | if (t == "number" || t == "string" || t == "boolean" || t == null || t == undefined) 1124 | { 1125 | result = value; 1126 | } 1127 | else if (value instanceof Array) 1128 | { 1129 | //arrays are serializesd recursively 1130 | result = []; 1131 | for (var i = 0; i < value.length; i++) 1132 | { 1133 | result[i] = this.serialize(value[i]); 1134 | } 1135 | } 1136 | else if (t == "function") 1137 | { 1138 | //js functions are assigned an ID and stored in the local cache 1139 | result.type = FABridge.TYPE_JSFUNCTION; 1140 | result.value = this.getFunctionID(value); 1141 | } 1142 | else if (value instanceof ASProxy) 1143 | { 1144 | result.type = FABridge.TYPE_ASINSTANCE; 1145 | result.value = value.fb_instance_id; 1146 | } 1147 | else 1148 | { 1149 | result.type = FABridge.TYPE_ANONYMOUS; 1150 | result.value = value; 1151 | } 1152 | 1153 | return result; 1154 | }, 1155 | 1156 | //on deserialization we always check the return for the specific error code that is used to marshall NPE's into JS errors 1157 | // the unpacking is done by returning the value on each pachet for objects/arrays 1158 | deserialize: function(packedValue) 1159 | { 1160 | 1161 | var result; 1162 | 1163 | var t = typeof(packedValue); 1164 | if (t == "number" || t == "string" || t == "boolean" || packedValue == null || packedValue == undefined) 1165 | { 1166 | result = this.handleError(packedValue); 1167 | } 1168 | else if (packedValue instanceof Array) 1169 | { 1170 | result = []; 1171 | for (var i = 0; i < packedValue.length; i++) 1172 | { 1173 | result[i] = this.deserialize(packedValue[i]); 1174 | } 1175 | } 1176 | else if (t == "object") 1177 | { 1178 | for(var i = 0; i < packedValue.newTypes.length; i++) 1179 | { 1180 | this.addTypeDataToCache(packedValue.newTypes[i]); 1181 | } 1182 | for (var aRefID in packedValue.newRefs) 1183 | { 1184 | this.createProxy(aRefID, packedValue.newRefs[aRefID]); 1185 | } 1186 | if (packedValue.type == FABridge.TYPE_PRIMITIVE) 1187 | { 1188 | result = packedValue.value; 1189 | } 1190 | else if (packedValue.type == FABridge.TYPE_ASFUNCTION) 1191 | { 1192 | result = this.getFunctionProxy(packedValue.value); 1193 | } 1194 | else if (packedValue.type == FABridge.TYPE_ASINSTANCE) 1195 | { 1196 | result = this.getProxy(packedValue.value); 1197 | } 1198 | else if (packedValue.type == FABridge.TYPE_ANONYMOUS) 1199 | { 1200 | result = packedValue.value; 1201 | } 1202 | } 1203 | return result; 1204 | }, 1205 | //increases the reference count for the given object 1206 | addRef: function(obj) 1207 | { 1208 | this.target.incRef(obj.fb_instance_id); 1209 | }, 1210 | //decrease the reference count for the given object and release it if needed 1211 | release:function(obj) 1212 | { 1213 | this.target.releaseRef(obj.fb_instance_id); 1214 | }, 1215 | 1216 | // check the given value for the components of the hard-coded error code : __FLASHERROR 1217 | // used to marshall NPE's into flash 1218 | 1219 | handleError: function(value) 1220 | { 1221 | if (typeof(value)=="string" && value.indexOf("__FLASHERROR")==0) 1222 | { 1223 | var myErrorMessage = value.split("||"); 1224 | if(FABridge.refCount > 0 ) 1225 | { 1226 | FABridge.refCount--; 1227 | } 1228 | throw new Error(myErrorMessage[1]); 1229 | return value; 1230 | } 1231 | else 1232 | { 1233 | return value; 1234 | } 1235 | } 1236 | }; 1237 | 1238 | // The root ASProxy class that facades a flash object 1239 | 1240 | ASProxy = function(bridge, typeName) 1241 | { 1242 | this.bridge = bridge; 1243 | this.typeName = typeName; 1244 | return this; 1245 | }; 1246 | //methods available on each ASProxy object 1247 | ASProxy.prototype = 1248 | { 1249 | get: function(propName) 1250 | { 1251 | return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName)); 1252 | }, 1253 | 1254 | set: function(propName, value) 1255 | { 1256 | this.bridge.setPropertyInAS(this.fb_instance_id, propName, value); 1257 | }, 1258 | 1259 | call: function(funcName, args) 1260 | { 1261 | this.bridge.callASMethod(this.fb_instance_id, funcName, args); 1262 | }, 1263 | 1264 | addRef: function() { 1265 | this.bridge.addRef(this); 1266 | }, 1267 | 1268 | release: function() { 1269 | this.bridge.release(this); 1270 | } 1271 | }; 1272 | 1273 | // Copyright: Hiroshi Ichikawa 1274 | // License: New BSD License 1275 | // Reference: http://dev.w3.org/html5/websockets/ 1276 | // Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol 1277 | 1278 | (function() { 1279 | 1280 | if (window.WebSocket) return; 1281 | 1282 | var console = window.console; 1283 | if (!console) console = {log: function(){ }, error: function(){ }}; 1284 | 1285 | function hasFlash() { 1286 | if ('navigator' in window && 'plugins' in navigator && navigator.plugins['Shockwave Flash']) { 1287 | return !!navigator.plugins['Shockwave Flash'].description; 1288 | } 1289 | if ('ActiveXObject' in window) { 1290 | try { 1291 | return !!new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); 1292 | } catch (e) {} 1293 | } 1294 | return false; 1295 | } 1296 | 1297 | if (!hasFlash()) { 1298 | console.error("Flash Player is not installed."); 1299 | return; 1300 | } 1301 | console.log(location.protocol); 1302 | if (location.protocol == "file:") { 1303 | console.error( 1304 | "web-socket-js doesn't work in file:///... URL (without special configuration). " + 1305 | "Open the page via Web server i.e. http://..."); 1306 | } 1307 | 1308 | WebSocket = function(url, protocol, proxyHost, proxyPort, headers) { 1309 | var self = this; 1310 | self.readyState = WebSocket.CONNECTING; 1311 | self.bufferedAmount = 0; 1312 | // Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc. 1313 | // Otherwise, when onopen fires immediately, onopen is called before it is set. 1314 | setTimeout(function() { 1315 | WebSocket.__addTask(function() { 1316 | self.__createFlash(url, protocol, proxyHost, proxyPort, headers); 1317 | }); 1318 | }, 1); 1319 | } 1320 | 1321 | WebSocket.prototype.__createFlash = function(url, protocol, proxyHost, proxyPort, headers) { 1322 | var self = this; 1323 | self.__flash = 1324 | WebSocket.__flash.create(url, protocol, proxyHost || null, proxyPort || 0, headers || null); 1325 | 1326 | self.__flash.addEventListener("open", function(fe) { 1327 | try { 1328 | self.readyState = self.__flash.getReadyState(); 1329 | if (self.__timer) clearInterval(self.__timer); 1330 | if (window.opera) { 1331 | // Workaround for weird behavior of Opera which sometimes drops events. 1332 | self.__timer = setInterval(function () { 1333 | self.__handleMessages(); 1334 | }, 500); 1335 | } 1336 | if (self.onopen) self.onopen(); 1337 | } catch (e) { 1338 | console.error(e.toString()); 1339 | } 1340 | }); 1341 | 1342 | self.__flash.addEventListener("close", function(fe) { 1343 | try { 1344 | self.readyState = self.__flash.getReadyState(); 1345 | if (self.__timer) clearInterval(self.__timer); 1346 | if (self.onclose) self.onclose(); 1347 | } catch (e) { 1348 | console.error(e.toString()); 1349 | } 1350 | }); 1351 | 1352 | self.__flash.addEventListener("message", function() { 1353 | try { 1354 | self.__handleMessages(); 1355 | } catch (e) { 1356 | console.error(e.toString()); 1357 | } 1358 | }); 1359 | 1360 | self.__flash.addEventListener("error", function(fe) { 1361 | try { 1362 | if (self.__timer) clearInterval(self.__timer); 1363 | if (self.onerror) self.onerror(); 1364 | } catch (e) { 1365 | console.error(e.toString()); 1366 | } 1367 | }); 1368 | 1369 | self.__flash.addEventListener("stateChange", function(fe) { 1370 | try { 1371 | self.readyState = self.__flash.getReadyState(); 1372 | self.bufferedAmount = fe.getBufferedAmount(); 1373 | } catch (e) { 1374 | console.error(e.toString()); 1375 | } 1376 | }); 1377 | 1378 | //console.log("[WebSocket] Flash object is ready"); 1379 | }; 1380 | 1381 | WebSocket.prototype.send = function(data) { 1382 | if (this.__flash) { 1383 | this.readyState = this.__flash.getReadyState(); 1384 | } 1385 | if (!this.__flash || this.readyState == WebSocket.CONNECTING) { 1386 | throw "INVALID_STATE_ERR: Web Socket connection has not been established"; 1387 | } 1388 | var result = this.__flash.send(encodeURIComponent(data)); 1389 | if (result < 0) { // success 1390 | return true; 1391 | } else { 1392 | this.bufferedAmount = result; 1393 | return false; 1394 | } 1395 | }; 1396 | 1397 | WebSocket.prototype.close = function() { 1398 | if (!this.__flash) return; 1399 | this.readyState = this.__flash.getReadyState(); 1400 | if (this.readyState != WebSocket.OPEN) return; 1401 | this.__flash.close(); 1402 | // Sets/calls them manually here because Flash WebSocketConnection.close cannot fire events 1403 | // which causes weird error: 1404 | // > You are trying to call recursively into the Flash Player which is not allowed. 1405 | this.readyState = WebSocket.CLOSED; 1406 | if (this.__timer) clearInterval(this.__timer); 1407 | if (this.onclose) this.onclose(); 1408 | }; 1409 | 1410 | /** 1411 | * Implementation of {@link DOM 2 EventTarget Interface} 1412 | * 1413 | * @param {string} type 1414 | * @param {function} listener 1415 | * @param {boolean} useCapture !NB Not implemented yet 1416 | * @return void 1417 | */ 1418 | WebSocket.prototype.addEventListener = function(type, listener, useCapture) { 1419 | if (!('__events' in this)) { 1420 | this.__events = {}; 1421 | } 1422 | if (!(type in this.__events)) { 1423 | this.__events[type] = []; 1424 | if ('function' == typeof this['on' + type]) { 1425 | this.__events[type].defaultHandler = this['on' + type]; 1426 | this['on' + type] = this.__createEventHandler(this, type); 1427 | } 1428 | } 1429 | this.__events[type].push(listener); 1430 | }; 1431 | 1432 | /** 1433 | * Implementation of {@link DOM 2 EventTarget Interface} 1434 | * 1435 | * @param {string} type 1436 | * @param {function} listener 1437 | * @param {boolean} useCapture NB! Not implemented yet 1438 | * @return void 1439 | */ 1440 | WebSocket.prototype.removeEventListener = function(type, listener, useCapture) { 1441 | if (!('__events' in this)) { 1442 | this.__events = {}; 1443 | } 1444 | if (!(type in this.__events)) return; 1445 | for (var i = this.__events.length; i > -1; --i) { 1446 | if (listener === this.__events[type][i]) { 1447 | this.__events[type].splice(i, 1); 1448 | break; 1449 | } 1450 | } 1451 | }; 1452 | 1453 | /** 1454 | * Implementation of {@link DOM 2 EventTarget Interface} 1455 | * 1456 | * @param {WebSocketEvent} event 1457 | * @return void 1458 | */ 1459 | WebSocket.prototype.dispatchEvent = function(event) { 1460 | if (!('__events' in this)) throw 'UNSPECIFIED_EVENT_TYPE_ERR'; 1461 | if (!(event.type in this.__events)) throw 'UNSPECIFIED_EVENT_TYPE_ERR'; 1462 | 1463 | for (var i = 0, l = this.__events[event.type].length; i < l; ++ i) { 1464 | this.__events[event.type][i](event); 1465 | if (event.cancelBubble) break; 1466 | } 1467 | 1468 | if (false !== event.returnValue && 1469 | 'function' == typeof this.__events[event.type].defaultHandler) 1470 | { 1471 | this.__events[event.type].defaultHandler(event); 1472 | } 1473 | }; 1474 | 1475 | WebSocket.prototype.__handleMessages = function() { 1476 | // Gets data using readSocketData() instead of getting it from event object 1477 | // of Flash event. This is to make sure to keep message order. 1478 | // It seems sometimes Flash events don't arrive in the same order as they are sent. 1479 | var arr = this.__flash.readSocketData(); 1480 | for (var i = 0; i < arr.length; i++) { 1481 | var data = decodeURIComponent(arr[i]); 1482 | try { 1483 | if (this.onmessage) { 1484 | var e; 1485 | if (window.MessageEvent) { 1486 | e = document.createEvent("MessageEvent"); 1487 | e.initMessageEvent("message", false, false, data, null, null, window, null); 1488 | } else { // IE 1489 | e = {data: data}; 1490 | } 1491 | this.onmessage(e); 1492 | } 1493 | } catch (e) { 1494 | console.error(e.toString()); 1495 | } 1496 | } 1497 | }; 1498 | 1499 | /** 1500 | * @param {object} object 1501 | * @param {string} type 1502 | */ 1503 | WebSocket.prototype.__createEventHandler = function(object, type) { 1504 | return function(data) { 1505 | var event = new WebSocketEvent(); 1506 | event.initEvent(type, true, true); 1507 | event.target = event.currentTarget = object; 1508 | for (var key in data) { 1509 | event[key] = data[key]; 1510 | } 1511 | object.dispatchEvent(event, arguments); 1512 | }; 1513 | } 1514 | 1515 | /** 1516 | * Basic implementation of {@link DOM 2 EventInterface} 1517 | * 1518 | * @class 1519 | * @constructor 1520 | */ 1521 | function WebSocketEvent(){} 1522 | 1523 | /** 1524 | * 1525 | * @type boolean 1526 | */ 1527 | WebSocketEvent.prototype.cancelable = true; 1528 | 1529 | /** 1530 | * 1531 | * @type boolean 1532 | */ 1533 | WebSocketEvent.prototype.cancelBubble = false; 1534 | 1535 | /** 1536 | * 1537 | * @return void 1538 | */ 1539 | WebSocketEvent.prototype.preventDefault = function() { 1540 | if (this.cancelable) { 1541 | this.returnValue = false; 1542 | } 1543 | }; 1544 | 1545 | /** 1546 | * 1547 | * @return void 1548 | */ 1549 | WebSocketEvent.prototype.stopPropagation = function() { 1550 | this.cancelBubble = true; 1551 | }; 1552 | 1553 | /** 1554 | * 1555 | * @param {string} eventTypeArg 1556 | * @param {boolean} canBubbleArg 1557 | * @param {boolean} cancelableArg 1558 | * @return void 1559 | */ 1560 | WebSocketEvent.prototype.initEvent = function(eventTypeArg, canBubbleArg, cancelableArg) { 1561 | this.type = eventTypeArg; 1562 | this.cancelable = cancelableArg; 1563 | this.timeStamp = new Date(); 1564 | }; 1565 | 1566 | 1567 | WebSocket.CONNECTING = 0; 1568 | WebSocket.OPEN = 1; 1569 | WebSocket.CLOSING = 2; 1570 | WebSocket.CLOSED = 3; 1571 | 1572 | WebSocket.__tasks = []; 1573 | 1574 | WebSocket.__initialize = function() { 1575 | if (WebSocket.__swfLocation) { 1576 | // For backword compatibility. 1577 | window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation; 1578 | } 1579 | if (!window.WEB_SOCKET_SWF_LOCATION) { 1580 | console.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf"); 1581 | return; 1582 | } 1583 | var container = document.createElement("div"); 1584 | container.id = "webSocketContainer"; 1585 | // Puts the Flash out of the window. Note that we cannot use display: none or visibility: hidden 1586 | // here because it prevents Flash from loading at least in IE. 1587 | container.style.position = "absolute"; 1588 | container.style.left = "-100px"; 1589 | container.style.top = "-100px"; 1590 | var holder = document.createElement("div"); 1591 | holder.id = "webSocketFlash"; 1592 | container.appendChild(holder); 1593 | document.body.appendChild(container); 1594 | swfobject.embedSWF( 1595 | WEB_SOCKET_SWF_LOCATION, "webSocketFlash", "8", "8", "9.0.0", 1596 | null, {bridgeName: "webSocket"}, null, null, 1597 | function(e) { 1598 | if (!e.success) console.error("[WebSocket] swfobject.embedSWF failed"); 1599 | } 1600 | ); 1601 | FABridge.addInitializationCallback("webSocket", function() { 1602 | try { 1603 | //console.log("[WebSocket] FABridge initializad"); 1604 | WebSocket.__flash = FABridge.webSocket.root(); 1605 | WebSocket.__flash.setCallerUrl(location.href); 1606 | WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG); 1607 | for (var i = 0; i < WebSocket.__tasks.length; ++i) { 1608 | WebSocket.__tasks[i](); 1609 | } 1610 | WebSocket.__tasks = []; 1611 | } catch (e) { 1612 | console.error("[WebSocket] " + e.toString()); 1613 | } 1614 | }); 1615 | }; 1616 | 1617 | WebSocket.__addTask = function(task) { 1618 | if (WebSocket.__flash) { 1619 | task(); 1620 | } else { 1621 | WebSocket.__tasks.push(task); 1622 | } 1623 | } 1624 | 1625 | // called from Flash 1626 | window.webSocketLog = function(message) { 1627 | console.log(decodeURIComponent(message)); 1628 | }; 1629 | 1630 | // called from Flash 1631 | window.webSocketError = function(message) { 1632 | console.error(decodeURIComponent(message)); 1633 | }; 1634 | 1635 | if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) { 1636 | if (window.addEventListener) { 1637 | window.addEventListener("load", WebSocket.__initialize, false); 1638 | } else { 1639 | window.attachEvent("onload", WebSocket.__initialize); 1640 | } 1641 | } 1642 | 1643 | })(); 1644 | 1645 | --------------------------------------------------------------------------------