Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial Commit

  • Loading branch information...
commit 94887d85247fa27426081ccc93e75444042b52cc 0 parents
Rob Righter authored
13 .gitmodules
@@ -0,0 +1,13 @@
+[submodule "lib/Socket.IO"]
+ path = lib/Socket.IO
+ url = http://github.com/LearnBoost/Socket.IO.git
+[submodule "lib/Socket.IO-node"]
+ path = lib/Socket.IO-node
+ url = http://github.com/LearnBoost/Socket.IO-node.git
+[submodule "lib/express"]
+ path = lib/express
+ url = http://github.com/visionmedia/express.git
+
+[submodule "lib/html5-boilerplate"]
+ path = lib/html5-boilerplate
+ url = http://github.com/robrighter/html5-boilerplate.git
1  lib/Socket.IO
@@ -0,0 +1 @@
+Subproject commit cd30cbf046592f38c4f458a36319b4dbd306aa87
1  lib/Socket.IO-node
@@ -0,0 +1 @@
+Subproject commit 7b7270d5aea3015f45856601bfd42fe679e4ad2c
1  lib/express
@@ -0,0 +1 @@
+Subproject commit baa423b45a983d1a6c44b7476bb4e9b0c42b33c8
1  lib/html5-boilerplate
@@ -0,0 +1 @@
+Subproject commit c6451851c93379290f6914286e50611d53d71bd7
72 lib/setup.js
@@ -0,0 +1,72 @@
+//Setup.js created by Ben Weaver (http://gist.github.com/508314)
+
+var fs = require('fs'),
+ path = require('path');
+
+exports.app = app;
+exports.lib = lib;
+exports.ext = ext;
+exports.run = run;
+
+
+/// --- Methods
+
+var run = require;
+
+// A shortcut for adding `lib' and `ext' subfolders, then running a
+// main program.
+function app(base, main) {
+ lib(path.join(base, 'lib'));
+ ext(path.join(base, 'ext'));
+ return main ? run(path.join(base, main)) : exports;
+}
+
+// Local libraries
+function lib(folder) {
+ if (exists(folder))
+ require.paths.unshift(folder);
+ return exports;
+}
+
+// Third-party libraries
+function ext(folder) {
+ if (!exists(folder))
+ return exports;
+
+ // Some programmers refer to third-party libraries in a fully-qualified manner.
+ require.paths.unshift(folder);
+
+ fs.readdirSync(folder).forEach(function(name) {
+ var base = path.join(folder, name),
+ linked = false;
+
+ // Pure-JS packages have a `lib' folder with LIBRARY.js files in it.
+ // Packages with C++ bindings will have a `build/default' folder
+ // with LIBRARY.node files in it after running node-waf.
+ [path.join(base, '/build/default'), path.join(base, '/lib')]
+ .forEach(function(folder) {
+ if (exists(folder)) {
+ require.paths.unshift(folder);
+ linked = true;
+ }
+ });
+
+ // If neither `lib' or `build' were found, fallback to linking the
+ // folder itself.
+ if (!linked)
+ require.paths.unshift(base);
+ });
+ return exports;
+}
+
+
+/// --- Aux
+
+function exists(filename) {
+ try {
+ fs.statSync(filename);
+ return true;
+ } catch (x) {
+ return false;
+ }
+}
94 server.js
@@ -0,0 +1,94 @@
+//setup Dependencies
+require(__dirname + "/lib/setup").ext( __dirname + "/lib").ext( __dirname + "/lib/express/support");
+var connect = require('connect')
+ , express = require('express')
+ , sys = require('sys')
+ , io = require('Socket.IO-node')
+ , port = 8081;
+
+//Setup Express
+var server = express.createServer();
+server.configure(function(){
+ server.set('views', __dirname + '/views');
+ server.use(connect.bodyDecoder());
+ server.use(connect.staticProvider(__dirname + '/static'));
+ server.use(server.router);
+});
+
+//setup the errors
+server.error(function(err, req, res, next){
+ if (err instanceof NotFound) {
+ res.render('404.ejs', { locals: {
+ header: '#Header#'
+ ,footer: '#Footer#'
+ ,title : '404 - Not Found'
+ ,description: ''
+ ,author: ''
+ ,analyticssiteid: 'XXXXXXX'
+ } });
+ } else {
+ res.render('500.ejs', { locals: {
+ header: '#Header#'
+ ,footer: '#Footer#'
+ ,title : 'The Server Encountered an Error'
+ ,description: ''
+ ,author: ''
+ ,analyticssiteid: 'XXXXXXX'
+ ,error: err
+ } });
+ }
+});
+server.listen( port);
+
+//Setup Socket.IO
+var io = io.listen(server);
+io.on('connection', function(client){
+ console.log('Client Connected');
+ client.on('message', function(message){
+ client.broadcast(message);
+ client.send(message);
+ });
+ client.on('disconnect', function(){
+ console.log('Client Disconnected.');
+ });
+});
+
+
+///////////////////////////////////////////
+// Routes //
+///////////////////////////////////////////
+
+/////// ADD ALL YOUR ROUTES HERE /////////
+
+server.get('/', function(req,res){
+ res.render('index.ejs', {
+ locals : {
+ header: '#Header#'
+ ,footer: '#Footer#'
+ ,title : 'Page Title'
+ ,description: 'Page Description'
+ ,author: 'Your Name'
+ ,analyticssiteid: 'XXXXXXX'
+ }
+ });
+});
+
+
+//A Route for Creating a 500 Error (Useful to keep around)
+server.get('/500', function(req, res){
+ throw new Error('This is a 500 Error');
+});
+
+//The 404 Route (ALWAYS Keep this as the last route)
+server.get('/*', function(req, res){
+ throw new NotFound;
+});
+
+function NotFound(msg){
+ this.name = 'NotFound';
+ Error.call(this, msg);
+ Error.captureStackTrace(this, arguments.callee);
+}
+
+
+console.log('Listening on http://0.0.0.0:' + port );
7 static/css/handheld.css
@@ -0,0 +1,7 @@
+
+* {
+ float: none; /* Screens are not big enough to account for floats */
+ font-size: 80%; /* Slightly reducing font size to reduce need to scroll */
+ background: #fff; /* As much contrast as possible */
+ color: #000;
+}
264 static/css/style.css
@@ -0,0 +1,264 @@
+/*
+ style.css contains a reset, font normalization and some base styles.
+
+ credit is left where credit is due.
+ additionally, much inspiration was taken from these projects:
+ yui.yahooapis.com/2.8.1/build/base/base.css
+ camendesign.com/design/
+ praegnanz.de/weblog/htmlcssjs-kickstart
+*/
+
+/*
+ html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline)
+ v1.4 2009-07-27 | Authors: Eric Meyer & Richard Clark
+ html5doctor.com/html-5-reset-stylesheet/
+*/
+
+html, body, div, span, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+abbr, address, cite, code,
+del, dfn, em, img, ins, kbd, q, samp,
+small, strong, sub, sup, var,
+b, i,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, figure, footer, header,
+hgroup, menu, nav, section, menu,
+time, mark, audio, video {
+ margin:0;
+ padding:0;
+ border:0;
+ outline:0;
+ font-size:100%;
+ vertical-align:baseline;
+ background:transparent;
+}
+
+article, aside, figure, footer, header,
+hgroup, nav, section { display:block; }
+
+nav ul { list-style:none; }
+
+blockquote, q { quotes:none; }
+
+blockquote:before, blockquote:after,
+q:before, q:after { content:''; content:none; }
+
+a { margin:0; padding:0; font-size:100%; vertical-align:baseline; background:transparent; }
+
+ins { background-color:#ff9; color:#000; text-decoration:none; }
+
+mark { background-color:#ff9; color:#000; font-style:italic; font-weight:bold; }
+
+del { text-decoration: line-through; }
+
+abbr[title], dfn[title] { border-bottom:1px dotted #000; cursor:help; }
+
+/* tables still need cellspacing="0" in the markup */
+table { border-collapse:collapse; border-spacing:0; }
+
+hr { display:block; height:1px; border:0; border-top:1px solid #ccc; margin:1em 0; padding:0; }
+
+input, select { vertical-align:middle; }
+/* END RESET CSS */
+
+
+/*
+fonts.css from the YUI Library: developer.yahoo.com/yui/
+ Please refer to developer.yahoo.com/yui/fonts/ for font sizing percentages
+
+There are three custom edits:
+ * remove arial, helvetica from explicit font stack
+ * make the line-height relative and unit-less
+ * remove the pre, code styles
+*/
+body { font: 13px sans-serif; *font-size:small; *font:x-small; line-height:1.22; }
+
+table { font-size:inherit; font: 100%; }
+
+select, input, textarea { font: 99% sans-serif; }
+
+
+/* normalize monospace sizing
+ * en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome
+ */
+pre, code, kbd, samp { font-family: monospace, sans-serif; }
+
+
+
+/*
+ * minimal base styles
+ */
+
+
+/* #444 looks better than black: twitter.com/H_FJ/statuses/11800719859 */
+body, select, input, textarea { color: #444; }
+
+/* Headers (h1,h2,etc) have no default font-size or margin,
+ you'll want to define those yourself. */
+
+/* www.aestheticallyloyal.com/public/optimize-legibility/ */
+h1,h2,h3,h4,h5,h6 { font-weight: bold; text-rendering: optimizeLegibility; }
+
+html {
+ /* maxvoltar.com/archive/-webkit-font-smoothing */
+ -webkit-font-smoothing: antialiased;
+ /* always force a scrollbar in non-IE */
+ overflow-y: scroll;
+}
+
+
+/* Accessible focus treatment: people.opera.com/patrickl/experiments/keyboard/test */
+a:hover, a:active { outline: none; }
+
+a, a:active, a:visited { color: #607890; }
+a:hover { color: #036; }
+
+
+ul { margin-left: 30px; }
+ol { margin-left: 30px; list-style-type: decimal; }
+
+small { font-size: 85%; }
+strong, th { font-weight: bold; }
+
+td, td img { vertical-align: top; }
+
+sub { vertical-align: sub; font-size: smaller; }
+sup { vertical-align: super; font-size: smaller; }
+
+pre {
+ padding: 15px;
+
+ /* www.pathf.com/blogs/2008/05/formatting-quoted-code-in-blog-posts-css21-white-space-pre-wrap/ */
+ white-space: pre; /* CSS2 */
+ white-space: pre-wrap; /* CSS 2.1 */
+ white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
+ word-wrap: break-word; /* IE */
+}
+
+/* align checkboxes, radios, text inputs with their label
+ by: Thierry Koblentz tjkdesign.com/ez-css/css/base.css */
+input[type="radio"] { vertical-align: text-bottom; }
+input[type="checkbox"] { vertical-align: bottom; *vertical-align: baseline; }
+.ie6 input { vertical-align: text-bottom; }
+
+/* hand cursor on clickable input elements */
+label, input[type=button], input[type=submit], button { cursor: pointer; }
+
+
+/* These selection declarations have to be separate.
+ No text-shadow: twitter.com/miketaylr/status/12228805301
+ Also: hot pink. */
+::-moz-selection{ background: #FF5E99; color:#fff; text-shadow: none; }
+::selection { background:#FF5E99; color:#fff; text-shadow: none; }
+
+/* j.mp/webkit-tap-highlight-color */
+a:link { -webkit-tap-highlight-color: #FF5E99; }
+
+/* make buttons play nice in IE:
+ www.viget.com/inspire/styling-the-button-element-in-internet-explorer/ */
+button { width: auto; overflow: visible; }
+
+/* bicubic resizing for non-native sized IMG:
+ code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ */
+.ie7 img { -ms-interpolation-mode: bicubic; }
+
+
+
+/*
+ * Non-semantic helper classes
+ */
+
+/* for image replacement */
+.ir { display: block; text-indent: -999em; overflow: hidden; background-repeat: no-repeat; }
+
+/* Hide for both screenreaders and browsers
+ css-discuss.incutio.com/wiki/Screenreader_Visibility */
+.hidden { display: none; visibility: hidden; }
+
+/* Hide only visually, but have it available for screenreaders
+ www.webaim.org/techniques/css/invisiblecontent/
+ Solution from: j.mp/visuallyhidden - Thanks Jonathan Neal! */
+.visuallyhidden { position: absolute !important;
+ clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
+ clip: rect(1px, 1px, 1px, 1px); }
+
+/* Hide visually and from screenreaders, but maintain layout */
+.invisible { visibility: hidden; }
+
+/* >> The Magnificent CLEARFIX << */
+.clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.clearfix { display: inline-block; }
+* html .clearfix { height: 1%; } /* Hides from IE-mac \*/
+.clearfix { display: block; }
+
+
+
+
+
+ /* Primary Styles
+ Author:
+ */
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * print styles
+ * inlined to avoid required HTTP connection www.phpied.com/delay-loading-your-print-css/
+ */
+@media print {
+ * { background: transparent !important; color: #444 !important; text-shadow: none !important; }
+
+ a, a:visited { color: #444 !important; text-decoration: underline; }
+
+ a:after { content: " (" attr(href) ")"; }
+
+ abbr:after { content: " (" attr(title) ")"; }
+
+ .ir a:after { content: ""; } /* Don't show links for images */
+
+ pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
+
+ img { page-break-inside: avoid; }
+
+ @page { margin: 0.5cm; }
+
+ p, h2, h3 { orphans: 3; widows: 3; }
+
+ h2, h3{ page-break-after: avoid; }
+}
+
+
+
+/*
+ * Media queries for responsive design
+ */
+
+@media all and (orientation:portrait) {
+ /* Style adjustments for portrait mode goes here */
+
+}
+
+@media all and (orientation:landscape) {
+ /* Style adjustments for landscape mode goes here */
+
+}
+
+/* Grade-A Mobile Browsers (Opera Mobile, iPhone Safari, Android Chrome)
+ Consider this: www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/ */
+@media screen and (max-device-width: 480px) {
+
+
+ /* Prevent iOS, WinMobile from adjusting font size */
+ html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; }
+}
+
1  static/js/dd_belatedpng.js
1  static/js/jquery-1.4.2.min.js
1  static/js/modernizr-1.5.min.js
40 static/js/plugins.js
@@ -0,0 +1,40 @@
+
+// remap jQuery to $
+(function($){
+
+
+
+
+
+
+
+
+
+
+
+})(window.jQuery);
+
+
+
+// usage: log('inside coolFunc',this,arguments);
+// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
+window.log = function(){
+ log.history = log.history || []; // store logs to an array for reference
+ log.history.push(arguments);
+ if(this.console){
+ console.log( Array.prototype.slice.call(arguments) );
+ }
+};
+
+
+
+// catch all document.write() calls
+(function(doc){
+ var write = doc.write;
+ doc.write = function(q){
+ log('document.write(): ',arguments);
+ if (/docwriteregexwhitelist/.test(q)) write.apply(doc,arguments);
+ };
+})(document);
+
+
1  static/js/profiling
44 static/js/script.js
@@ -0,0 +1,44 @@
+/* Author:
+
+*/
+
+$(document).ready(function() {
+
+ io.setPath('/client/');
+ socket = new io.Socket(null, {
+ port: 8081
+ ,transports: ['websocket', 'htmlfile', 'xhr-multipart', 'xhr-polling']
+ });
+ socket.connect();
+
+ $('#sender').bind('click', function() {
+ socket.send("Message Sent on " + new Date());
+ });
+
+ socket.on('message', function(data){
+ $('#reciever').append('<li>' + data + '</li>');
+ });
+
+ });
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1  static/js/socket.io.js
694 static/js/underscore.js
@@ -0,0 +1,694 @@
+// Underscore.js
+// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the terms of the MIT license.
+// Portions of Underscore are inspired by or borrowed from Prototype.js,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
+
+(function() {
+ // ------------------------- Baseline setup ---------------------------------
+
+ // Establish the root object, "window" in the browser, or "global" on the server.
+ var root = this;
+
+ // Save the previous value of the "_" variable.
+ var previousUnderscore = root._;
+
+ // Establish the object that gets thrown to break out of a loop iteration.
+ var breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__';
+
+ // Quick regexp-escaping function, because JS doesn't have RegExp.escape().
+ var escapeRegExp = function(s) { return s.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); };
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var slice = ArrayProto.slice,
+ unshift = ArrayProto.unshift,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty,
+ propertyIsEnumerable = ObjProto.propertyIsEnumerable;
+
+ // All ECMA5 native implementations we hope to use are declared here.
+ var
+ nativeForEach = ArrayProto.forEach,
+ nativeMap = ArrayProto.map,
+ nativeReduce = ArrayProto.reduce,
+ nativeReduceRight = ArrayProto.reduceRight,
+ nativeFilter = ArrayProto.filter,
+ nativeEvery = ArrayProto.every,
+ nativeSome = ArrayProto.some,
+ nativeIndexOf = ArrayProto.indexOf,
+ nativeLastIndexOf = ArrayProto.lastIndexOf,
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys;
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) { return new wrapper(obj); };
+
+ // Export the Underscore object for CommonJS.
+ if (typeof exports !== 'undefined') exports._ = _;
+
+ // Export underscore to global scope.
+ root._ = _;
+
+ // Current version.
+ _.VERSION = '1.0.3';
+
+ // ------------------------ Collection Functions: ---------------------------
+
+ // The cornerstone, an each implementation.
+ // Handles objects implementing forEach, arrays, and raw objects.
+ // Delegates to JavaScript 1.6's native forEach if available.
+ var each = _.forEach = function(obj, iterator, context) {
+ try {
+ if (nativeForEach && obj.forEach === nativeForEach) {
+ obj.forEach(iterator, context);
+ } else if (_.isNumber(obj.length)) {
+ for (var i = 0, l = obj.length; i < l; i++) iterator.call(context, obj[i], i, obj);
+ } else {
+ for (var key in obj) {
+ if (hasOwnProperty.call(obj, key)) iterator.call(context, obj[key], key, obj);
+ }
+ }
+ } catch(e) {
+ if (e != breaker) throw e;
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iterator to each element.
+ // Delegates to JavaScript 1.6's native map if available.
+ _.map = function(obj, iterator, context) {
+ if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+ var results = [];
+ each(obj, function(value, index, list) {
+ results.push(iterator.call(context, value, index, list));
+ });
+ return results;
+ };
+
+ // Reduce builds up a single result from a list of values, aka inject, or foldl.
+ // Delegates to JavaScript 1.8's native reduce if available.
+ _.reduce = function(obj, memo, iterator, context) {
+ if (nativeReduce && obj.reduce === nativeReduce) return obj.reduce(_.bind(iterator, context), memo);
+ each(obj, function(value, index, list) {
+ memo = iterator.call(context, memo, value, index, list);
+ });
+ return memo;
+ };
+
+ // The right-associative version of reduce, also known as foldr. Uses
+ // Delegates to JavaScript 1.8's native reduceRight if available.
+ _.reduceRight = function(obj, memo, iterator, context) {
+ if (nativeReduceRight && obj.reduceRight === nativeReduceRight) return obj.reduceRight(_.bind(iterator, context), memo);
+ var reversed = _.clone(_.toArray(obj)).reverse();
+ return _.reduce(reversed, memo, iterator, context);
+ };
+
+ // Return the first value which passes a truth test.
+ _.detect = function(obj, iterator, context) {
+ var result;
+ each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ _.breakLoop();
+ }
+ });
+ return result;
+ };
+
+ // Return all the elements that pass a truth test.
+ // Delegates to JavaScript 1.6's native filter if available.
+ _.filter = function(obj, iterator, context) {
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+ var results = [];
+ each(obj, function(value, index, list) {
+ iterator.call(context, value, index, list) && results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, iterator, context) {
+ var results = [];
+ each(obj, function(value, index, list) {
+ !iterator.call(context, value, index, list) && results.push(value);
+ });
+ return results;
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Delegates to JavaScript 1.6's native every if available.
+ _.every = function(obj, iterator, context) {
+ iterator = iterator || _.identity;
+ if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+ var result = true;
+ each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
+ });
+ return result;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Delegates to JavaScript 1.6's native some if available.
+ _.some = function(obj, iterator, context) {
+ iterator = iterator || _.identity;
+ if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+ var result = false;
+ each(obj, function(value, index, list) {
+ if (result = iterator.call(context, value, index, list)) _.breakLoop();
+ });
+ return result;
+ };
+
+ // Determine if a given value is included in the array or object using '==='.
+ _.include = function(obj, target) {
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+ var found = false;
+ each(obj, function(value) {
+ if (found = value === target) _.breakLoop();
+ });
+ return found;
+ };
+
+ // Invoke a method with arguments on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = _.rest(arguments, 2);
+ return _.map(obj, function(value) {
+ return (method ? value[method] : value).apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of map: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+
+ // Return the maximum item or (item-based computation).
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
+ var result = {computed : -Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
+ var result = {computed : Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Sort the object's values by a criterion produced by an iterator.
+ _.sortBy = function(obj, iterator, context) {
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }), 'value');
+ };
+
+ // Use a comparator function to figure out at what index an object should
+ // be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator) {
+ iterator = iterator || _.identity;
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >> 1;
+ iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+
+ // Convert anything iterable into a real, live array.
+ _.toArray = function(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ if (_.isArray(iterable)) return iterable;
+ if (_.isArguments(iterable)) return slice.call(iterable);
+ return _.values(iterable);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ return _.toArray(obj).length;
+ };
+
+ // -------------------------- Array Functions: ------------------------------
+
+ // Get the first element of an array. Passing "n" will return the first N
+ // values in the array. Aliased as "head". The "guard" check allows it to work
+ // with _.map.
+ _.first = function(array, n, guard) {
+ return n && !guard ? slice.call(array, 0, n) : array[0];
+ };
+
+ // Returns everything but the first entry of the array. Aliased as "tail".
+ // Especially useful on the arguments object. Passing an "index" will return
+ // the rest of the values in the array from that index onward. The "guard"
+ //check allows it to work with _.map.
+ _.rest = function(array, index, guard) {
+ return slice.call(array, _.isUndefined(index) || guard ? 1 : index);
+ };
+
+ // Get the last element of an array.
+ _.last = function(array) {
+ return array[array.length - 1];
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, function(value){ return !!value; });
+ };
+
+ // Return a completely flattened version of an array.
+ _.flatten = function(array) {
+ return _.reduce(array, [], function(memo, value) {
+ if (_.isArray(value)) return memo.concat(_.flatten(value));
+ memo.push(value);
+ return memo;
+ });
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ var values = _.rest(arguments);
+ return _.filter(array, function(value){ return !_.include(values, value); });
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ _.uniq = function(array, isSorted) {
+ return _.reduce(array, [], function(memo, el, i) {
+ if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
+ return memo;
+ });
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersect = function(array) {
+ var rest = _.rest(arguments);
+ return _.filter(_.uniq(array), function(item) {
+ return _.every(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ var args = _.toArray(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i = 0; i < length; i++) results[i] = _.pluck(args, String(i));
+ return results;
+ };
+
+ // If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
+ // we need this function. Return the position of the first occurence of an
+ // item in an array, or -1 if the item is not included in the array.
+ // Delegates to JavaScript 1.8's native indexOf if available.
+ _.indexOf = function(array, item) {
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
+ for (var i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
+ return -1;
+ };
+
+
+ // Delegates to JavaScript 1.6's native lastIndexOf if available.
+ _.lastIndexOf = function(array, item) {
+ if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
+ var i = array.length;
+ while (i--) if (array[i] === item) return i;
+ return -1;
+ };
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python range() function. See:
+ // http://docs.python.org/library/functions.html#range
+ _.range = function(start, stop, step) {
+ var a = _.toArray(arguments);
+ var solo = a.length <= 1;
+ var start = solo ? 0 : a[0], stop = solo ? a[0] : a[1], step = a[2] || 1;
+ var len = Math.ceil((stop - start) / step);
+ if (len <= 0) return [];
+ var range = new Array(len);
+ for (var i = start, idx = 0; true; i += step) {
+ if ((step > 0 ? i - stop : stop - i) >= 0) return range;
+ range[idx++] = i;
+ }
+ };
+
+ // ----------------------- Function Functions: ------------------------------
+
+ // Create a function bound to a given object (assigning 'this', and arguments,
+ // optionally). Binding with arguments is also known as 'curry'.
+ _.bind = function(func, obj) {
+ var args = _.rest(arguments, 2);
+ return function() {
+ return func.apply(obj || {}, args.concat(_.toArray(arguments)));
+ };
+ };
+
+ // Bind all of an object's methods to that object. Useful for ensuring that
+ // all callbacks defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var funcs = _.rest(arguments);
+ if (funcs.length == 0) funcs = _.functions(obj);
+ each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ return obj;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = _.rest(arguments, 2);
+ return setTimeout(function(){ return func.apply(func, args); }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(_.rest(arguments)));
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return function() {
+ var args = [func].concat(_.toArray(arguments));
+ return wrapper.apply(wrapper, args);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var funcs = _.toArray(arguments);
+ return function() {
+ var args = _.toArray(arguments);
+ for (var i=funcs.length-1; i >= 0; i--) {
+ args = [funcs[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ };
+
+ // ------------------------- Object Functions: ------------------------------
+
+ // Retrieve the names of an object's properties.
+ // Delegates to ECMA5's native Object.keys
+ _.keys = nativeKeys || function(obj) {
+ if (_.isArray(obj)) return _.range(0, obj.length);
+ var keys = [];
+ for (var key in obj) if (hasOwnProperty.call(obj, key)) keys.push(key);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ return _.map(obj, _.identity);
+ };
+
+ // Return a sorted list of the function names available on the object.
+ _.functions = function(obj) {
+ return _.filter(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = function(obj) {
+ each(_.rest(arguments), function(source) {
+ for (var prop in source) obj[prop] = source[prop];
+ });
+ return obj;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (_.isArray(obj)) return obj.slice(0);
+ return _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ // Check object identity.
+ if (a === b) return true;
+ // Different types?
+ var atype = typeof(a), btype = typeof(b);
+ if (atype != btype) return false;
+ // Basic equality test (watch out for coercions).
+ if (a == b) return true;
+ // One is falsy and the other truthy.
+ if ((!a && b) || (a && !b)) return false;
+ // One of them implements an isEqual()?
+ if (a.isEqual) return a.isEqual(b);
+ // Check dates' integer values.
+ if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
+ // Both are NaN?
+ if (_.isNaN(a) && _.isNaN(b)) return false;
+ // Compare regular expressions.
+ if (_.isRegExp(a) && _.isRegExp(b))
+ return a.source === b.source &&
+ a.global === b.global &&
+ a.ignoreCase === b.ignoreCase &&
+ a.multiline === b.multiline;
+ // If a is not an object by this point, we can't handle it.
+ if (atype !== 'object') return false;
+ // Check for different array lengths before comparing contents.
+ if (a.length && (a.length !== b.length)) return false;
+ // Nothing else worked, deep compare the contents.
+ var aKeys = _.keys(a), bKeys = _.keys(b);
+ // Different object sizes?
+ if (aKeys.length != bKeys.length) return false;
+ // Recursive comparison of contents.
+ for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
+ return true;
+ };
+
+ // Is a given array or object empty?
+ _.isEmpty = function(obj) {
+ if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+ for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
+ return true;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType == 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return !!(obj && obj.concat && obj.unshift && !obj.callee);
+ };
+
+ // Is a given variable an arguments object?
+ _.isArguments = function(obj) {
+ return obj && obj.callee;
+ };
+
+ // Is a given value a function?
+ _.isFunction = function(obj) {
+ return !!(obj && obj.constructor && obj.call && obj.apply);
+ };
+
+ // Is a given value a string?
+ _.isString = function(obj) {
+ return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
+ };
+
+ // Is a given value a number?
+ _.isNumber = function(obj) {
+ return (obj === +obj) || (toString.call(obj) === '[object Number]');
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false;
+ };
+
+ // Is a given value a date?
+ _.isDate = function(obj) {
+ return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
+ };
+
+ // Is the given value a regular expression?
+ _.isRegExp = function(obj) {
+ return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
+ };
+
+ // Is the given value NaN -- this one is interesting. NaN != NaN, and
+ // isNaN(undefined) == true, so we make sure it's a number first.
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && isNaN(obj);
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return typeof obj == 'undefined';
+ };
+
+ // -------------------------- Utility Functions: ----------------------------
+
+ // Run Underscore.js in noConflict mode, returning the '_' variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iterators.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Run a function n times.
+ _.times = function (n, iterator, context) {
+ for (var i = 0; i < n; i++) iterator.call(context, i);
+ };
+
+ // Break out of the middle of an iteration.
+ _.breakLoop = function() {
+ throw breaker;
+ };
+
+ // Add your own custom functions to the Underscore object, ensuring that
+ // they're correctly added to the OOP wrapper as well.
+ _.mixin = function(obj) {
+ each(_.functions(obj), function(name){
+ addToWrapper(name, _[name] = obj[name]);
+ });
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = idCounter++;
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ start : '<%',
+ end : '%>',
+ interpolate : /<%=(.+?)%>/g
+ };
+
+ // JavaScript templating a-la ERB, pilfered from John Resig's
+ // "Secrets of the JavaScript Ninja", page 83.
+ // Single-quote fix from Rick Strahl's version.
+ // With alterations for arbitrary delimiters.
+ _.template = function(str, data) {
+ var c = _.templateSettings;
+ var endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g");
+ var fn = new Function('obj',
+ 'var p=[],print=function(){p.push.apply(p,arguments);};' +
+ 'with(obj){p.push(\'' +
+ str.replace(/[\r\t\n]/g, " ")
+ .replace(endMatch,"\t")
+ .split("'").join("\\'")
+ .split("\t").join("'")
+ .replace(c.interpolate, "',$1,'")
+ .split(c.start).join("');")
+ .split(c.end).join("p.push('")
+ + "');}return p.join('');");
+ return data ? fn(data) : fn;
+ };
+
+ // ------------------------------- Aliases ----------------------------------
+
+ _.each = _.forEach;
+ _.foldl = _.inject = _.reduce;
+ _.foldr = _.reduceRight;
+ _.select = _.filter;
+ _.all = _.every;
+ _.any = _.some;
+ _.head = _.first;
+ _.tail = _.rest;
+ _.methods = _.functions;
+
+ // ------------------------ Setup the OOP Wrapper: --------------------------
+
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+ var wrapper = function(obj) { this._wrapped = obj; };
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(obj, chain) {
+ return chain ? _(obj).chain() : obj;
+ };
+
+ // A method to easily add functions to the OOP wrapper.
+ var addToWrapper = function(name, func) {
+ wrapper.prototype[name] = function() {
+ var args = _.toArray(arguments);
+ unshift.call(args, this._wrapped);
+ return result(func.apply(_, args), this._chain);
+ };
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ wrapper.prototype[name] = function() {
+ method.apply(this._wrapped, arguments);
+ return result(this._wrapped, this._chain);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ wrapper.prototype[name] = function() {
+ return result(method.apply(this._wrapped, arguments), this._chain);
+ };
+ });
+
+ // Start chaining a wrapped Underscore object.
+ wrapper.prototype.chain = function() {
+ this._chain = true;
+ return this;
+ };
+
+ // Extracts the result from a wrapped and chained object.
+ wrapper.prototype.value = function() {
+ return this._wrapped;
+ };
+
+})();
5 static/robots.txt
@@ -0,0 +1,5 @@
+# www.robotstxt.org/
+# www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449
+
+User-agent: *
+
19 views/404.ejs
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>not found</title>
+
+<style>
+body { text-align: center;}
+h1 { font-size: 50px; }
+body { font: 20px Constantia, 'Hoefler Text', "Adobe Caslon Pro", Baskerville, Georgia, Times, serif; color: #999; text-shadow: 2px 2px 2px rgba(200, 200, 200, 0.5); }
+a { color: rgb(36, 109, 56); text-decoration:none; }
+a:hover { color: rgb(96, 73, 141) ; text-shadow: 2px 2px 2px rgba(36, 109, 56, 0.5); }
+span[frown] { transform: rotate(90deg); display:inline-block; color: #bbb; }
+</style>
+
+
+
+
+<details>
+ <summary><h1>Not found</h1></summary>
+ <p><span frown>:(</span></p>
+</details>
22 views/500.ejs
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>The Server Encountered an Error</title>
+
+<style>
+body { text-align: center;}
+h1 { font-size: 50px; }
+body { font: 20px Constantia, 'Hoefler Text', "Adobe Caslon Pro", Baskerville, Georgia, Times, serif; color: #999; text-shadow: 2px 2px 2px rgba(200, 200, 200, 0.5); }
+a { color: rgb(36, 109, 56); text-decoration:none; }
+a:hover { color: rgb(96, 73, 141) ; text-shadow: 2px 2px 2px rgba(36, 109, 56, 0.5); }
+span[frown] { transform: rotate(90deg); display:inline-block; color: #bbb; }
+</style>
+
+
+
+
+<details>
+ <summary><h1>The Server Encountered and Error</h1></summary>
+ <p><span frown>:(</span></p>
+ <div>
+ <%= error %>
+ </div>
+</details>
4 views/index.ejs
@@ -0,0 +1,4 @@
+<div>
+ <a id="sender">send a message</a>
+ <ul id="reciever"></ul>
+</div>
101 views/layout.ejs
@@ -0,0 +1,101 @@
+<!doctype html>
+<html lang="en" class="no-js">
+<head>
+ <meta charset="utf-8">
+
+ <!-- www.phpied.com/conditional-comments-block-downloads/ -->
+ <!--[if IE]><![endif]-->
+
+ <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
+ Remove this if you use the .htaccess -->
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+
+ <title><%= title %></title>
+ <meta name="description" content="<%= description %>">
+ <meta name="author" content="<%= author %>">
+
+ <!-- Mobile Viewport Fix
+ j.mp/mobileviewport & davidbcalhoun.com/2010/viewport-metatag
+ device-width : Occupy full width of the screen in its current orientation
+ initial-scale = 1.0 retains dimensions instead of zooming out if page height > device height
+ maximum-scale = 1.0 retains dimensions instead of zooming in if page width < device width
+ -->
+ <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;">
+
+
+ <!-- Place favicon.ico and apple-touch-icon.png in the root of your domain and delete these references -->
+ <link rel="shortcut icon" href="/favicon.ico">
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png">
+
+
+ <!-- CSS : implied media="all" -->
+ <link rel="stylesheet" href="/css/style.css?v=1">
+
+ <!-- For the less-enabled mobile browsers like Opera Mini -->
+ <link rel="stylesheet" media="handheld" href="/css/handheld.css?v=1">
+
+
+ <!-- All JavaScript at the bottom, except for Modernizr which enables HTML5 elements & feature detects -->
+ <script src="js/modernizr-1.5.min.js"></script>
+
+</head>
+
+<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
+
+<!--[if lt IE 7 ]> <body class="ie6"> <![endif]-->
+<!--[if IE 7 ]> <body class="ie7"> <![endif]-->
+<!--[if IE 8 ]> <body class="ie8"> <![endif]-->
+<!--[if IE 9 ]> <body class="ie9"> <![endif]-->
+<!--[if (gt IE 9)|!(IE)]><!--> <body> <!--<![endif]-->
+
+ <div id="container">
+ <header>
+ <%= header %>
+ </header>
+
+ <div id="main">
+ <%- body %>
+ </div>
+
+ <footer>
+ <%= footer %>
+ </footer>
+ </div> <!--! end of #container -->
+
+
+ <!-- Javascript at the bottom for fast page loading -->
+
+ <!-- Grab Google CDN's jQuery. fall back to local if necessary -->
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
+ <script>!window.jQuery && document.write('<script src="js/jquery-1.4.2.min.js"><\/script>')</script>
+
+ <script src="/js/socket.io.js"></script>
+ <script src="/js/plugins.js?v=1"></script>
+ <script src="/js/script.js?v=1"></script>
+
+ <!--[if lt IE 7 ]>
+ <script src="js/dd_belatedpng.js?v=1"></script>
+ <![endif]-->
+
+
+ <!-- yui profiler and profileviewer - remove for production -->
+ <script src="/js/profiling/yahoo-profiling.min.js?v=1"></script>
+ <script src="/js/profiling/config.js?v=1"></script>
+ <!-- end profiling code -->
+
+
+ <!-- asynchronous google analytics: mathiasbynens.be/notes/async-analytics-snippet
+ change the UA-XXXXX-X to be your site's ID -->
+ <script>
+ var _gaq = [['_setAccount', '<%= analyticssiteid %>'], ['_trackPageview']];
+ (function(d, t) {
+ var g = d.createElement(t),
+ s = d.getElementsByTagName(t)[0];
+ g.async = true;
+ g.src = '//www.google-analytics.com/ga.js';
+ s.parentNode.insertBefore(g, s);
+ })(document, 'script');
+ </script>
+
+</body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.