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 987651c1f82f62f6074e63b30dcf354b0c38b8f7 0 parents
@creationix authored
1  README.markdown
@@ -0,0 +1 @@
+This is a collection of various small projects that I don't want to lose.
71 json-ext.js
@@ -0,0 +1,71 @@
+// Add ruby-like JSON ability to the standard JSON code.
+(function () {
+
+ // A recursive function that traverses the raw object looking for special
+ // serialized objects to be de-serialized. Used by `JSON.load`
+ var json_object_load = function (obj) {
+ var key;
+ if (typeof obj.json_class === 'string') {
+ return (eval(obj.json_class)).jsonCreate(obj);
+ }
+ if (typeof obj === 'object') {
+ for (key in obj) {
+ obj[key] = json_object_load(obj[key]);
+ }
+ }
+ return obj;
+ };
+
+ // dump is just an alias of stringify since the needed `toJSON` hook is
+ // already in the stringify implementation.
+ JSON.dump = JSON.stringify;
+
+ // Works like JSON.parse, but then filters the output looking for object
+ // hooks. Allows custom objects to be de-serialized.
+ JSON.load = function (text) { return json_object_load(JSON.parse(text)); };
+
+ // Adds generic object hooks to about any object constructor.
+ JSON.extend = function (class) {
+
+ // Unserializes an object from JSON
+ class.jsonCreate = function(o) {
+ var obj, data, O, prototype;
+ O = function () {};
+ obj = new O();
+ prototype = class.prototype;
+ for (key in prototype) {
+ if (prototype.hasOwnProperty(key)) {
+ O.prototype[key] = prototype[key];
+ }
+ }
+ O.name = class.name;
+ obj.constructor = class;
+ data = o.data;
+ for (key in data) {
+ if (data.hasOwnProperty(key)) {
+ obj[key] = data[key];
+ }
+ }
+ return obj;
+ };
+
+ // Serialize any object to JSON
+ class.prototype.toJSON = function() {
+ var data = {};
+ if (this.constructor.name === 'Object') {
+ return this;
+ }
+ for (key in this) {
+ if (this.hasOwnProperty(key) && typeof this[key] !== 'function') {
+ data[key] = this[key];
+ }
+ }
+ return {
+ 'json_class': this.constructor.name,
+ 'data': data
+ };
+ };
+ };
+
+
+}());
150 mazemaker.js
@@ -0,0 +1,150 @@
+#!/usr/local/bin/node
+
+Array.prototype.shuffle = function () {
+ var i, j, tempi, tempj;
+ i = this.length;
+ if ( i === 0 ) {
+ return false;
+ }
+ while ( --i ) {
+ j = Math.floor( Math.random() * ( i + 1 ) );
+ tempi = this[i];
+ tempj = this[j];
+ this[i] = tempj;
+ this[j] = tempi;
+ }
+};
+
+Number.prototype.times = function (fn) {
+ for (var i = 0; i < this; i += 1) {
+ fn(i);
+ }
+};
+
+var Maze;
+
+(function () {
+
+ function get_root(node) {
+ if (node.parent) {
+ return get_root(node.parent);
+ }
+ return node;
+ }
+
+ function check_wall(first, second) {
+ var first_root, second_root;
+ first_root = get_root(first);
+ second_root = get_root(second);
+ if (first_root === second_root) {
+ return true;
+ }
+ first_root.parent = second_root;
+ return false;
+ }
+
+ Maze = function (width, height) {
+ var sets = [];
+ var order = [];
+ for (var i = 0; i < width * height; i += 1) {
+ sets.push({});
+ order.push(i * 2);
+ order.push(i * 2 + 1);
+ }
+ order.shuffle();
+
+ order.forEach(function (i) {
+ var first, second;
+ if (i >= sets.length) {
+ // Right Wall
+ first = sets[i - sets.length];
+ if (i % width === width - 1) {
+ first.right = true;
+ // Skip right wall for last column of cells
+ return;
+ }
+ second = sets[i - sets.length + 1];
+ first.right = check_wall(first, second);
+ } else {
+ // Bottom Wall
+ first = sets[i];
+ if (Math.floor(i / width) === height - 1) {
+ first.bottom = true;
+ // Skip bottom wall for last row of cells
+ return;
+ }
+ second = sets[i + width];
+ first.bottom = check_wall(first, second);
+ }
+ });
+
+ this.width = width;
+ this.height = height;
+ this.sets = sets;
+ }
+
+ Maze.prototype.display = function () {
+ var x, y, map, item, grid, line;
+ grid = [];
+ map = "██";
+ line = [1];
+ for (x = 0; x < this.width; x += 1) {
+ map += "████";
+ line.push(1);
+ line.push(1);
+ }
+ grid.push(line);
+ for (y = 0; y < this.height; y += 1) {
+ map += "\n██";
+ line = [1];
+ for (x = 0; x < this.width; x += 1) {
+ item = this.sets[y * this.width + x];
+ map += item.right ? " ██" : " ";
+ line.push(0);
+ line.push(item.right ? 1 : 0);
+ }
+ grid.push(line);
+ map += "\n██";
+ line = [1];
+ for (x = 0; x < this.width; x += 1) {
+ item = this.sets[y * this.width + x];
+ var itemr = this.sets[y * this.width + x + 1];
+ var itemb = this.sets[y * this.width + x + this.width];
+ map += item.bottom ? "██" : " ";
+ line.push(item.bottom ? 1 : 0);
+ map += (item.right || item.bottom || itemr.bottom || itemb.right) ? "██" : " ";
+ line.push((item.right || item.bottom || itemr.bottom || itemb.right) ? 1 : 0);
+ }
+ grid.push(line);
+ }
+ map += "\n";
+ // sys.p(grid);
+ return map;
+ };
+
+}());
+if (__filename === process.ARGV[1]) {
+ var sys = require('sys');
+ var width, height;
+ // Check that there are two extra arguments and that they are both non-zero numbers
+ if (process.ARGV.length == 4 && (width = parseInt(process.ARGV[2])) && (height = parseInt(process.ARGV[3]))) {
+ sys.print((new Maze(width, height)).display());
+ } else {
+ sys.puts("USAGE:\n\t" + process.ARGV[1] + " width height")
+ }
+}
+
+
+// Sample output for a 5x5 maze
+// ██████████████████████
+// ██ ██ ██
+// ██ ██████ ██ ██████
+// ██ ██ ██
+// ██ ██████ ██ ██████
+// ██ ██ ██ ██
+// ██ ██████████████ ██
+// ██ ██ ██
+// ██ ██████ ██████ ██
+// ██ ██ ██ ██
+// ██████████████████████
+
37 smtp.js
@@ -0,0 +1,37 @@
+function wordwrap(str) {
+ var m = 80;
+ var b = "\r\n";
+ var c = false;
+ var i, j, l, s, r;
+ str += '';
+ if (m < 1) {
+ return str;
+ }
+ for (i = -1, l = (r = str.split(/\r\n|\n|\r/)).length; ++i < l; r[i] += s) {
+ for(s = r[i], r[i] = ""; s.length > m; r[i] += s.slice(0, j) + ((s = s.slice(j)).length ? b : "")){
+ j = c == 2 || (j = s.slice(0, m + 1).match(/\S*(\s)?$/))[1] ? m : j.input.length - j[0].length || c == 1 && m || j.input.length + (j = s.slice(m).match(/^\S*/)).input.length;
+ }
+ }
+ return r.join("\n");
+}
+
+
+exports.sendmail = function (from, to, subject, body) {
+ var connection = process.tcp.createConnection(25);
+ connection.addListener("connect", function (socket) {
+ connection.send("helo localhost\r\n");
+ connection.send("mail from: " + from + "\r\n");
+ connection.send("rcpt to: " + to + "\r\n");
+ connection.send("data\r\n");
+ connection.send("To: " + to + "\r\n");
+ connection.send("Subject: " + subject + "\r\n");
+ connection.send("Content-Type: text/html\r\n");
+ connection.send(wordwrap(body) + "\r\n");
+ connection.send(".\r\n");
+ connection.send("quit\r\n");
+ connection.close();
+ });
+};
+
+
+
197 turtle.js
@@ -0,0 +1,197 @@
+
+// Add some ruby-like methods to some of the builtins
+Object.prototype.instance_eval = function (block) {
+ // Convert the function to a string so that we can rebind it
+ if (typeof block === 'function') {
+ block = "(" + block + ").call(this)";
+ }
+ // Eval using "this" as the "with" scope
+ return eval("with(this) { " + block + "}");
+};
+Object.prototype.keys = function () {
+ var key, keys = [];
+ for (key in this) {
+ if (this.hasOwnProperty(key)) {
+ keys.push(key);
+ }
+ }
+ return keys;
+};
+Number.prototype.times = function (block) {
+ for (var i = 0; i < this; i += 1) {
+ block(i);
+ }
+};
+Number.prototype.is_even = function () {
+ return (this % 2) === 0;
+};
+Number.prototype.upto = function (other, block) {
+ for (var i = this; i <= other; i+= 1) {
+ block(i);
+ }
+};
+Array.prototype.minmax = function () {
+ var min, max;
+ this.forEach(function (item) {
+ if (min === undefined || item < min) {
+ min = item;
+ }
+ if (max === undefined || item > max) {
+ max = item;
+ }
+ });
+ return [min, max];
+};
+
+function Turtle() {
+ // directions: 0 = E, 1 = S, 2 = W, 3 = N
+ // axis: 0 = x, 1 = y
+ this.board = {};
+ this.x = 0;
+ this.y = 0;
+ this.direction = 0;
+ this.pen_up();
+}
+Turtle.prototype = {
+ pen_up: function () {
+ this.is_pen_down = false;
+ },
+ pen_down: function () {
+ this.is_pen_down = true;
+ this.mark_current_location();
+ },
+ forward: function (n) {
+ with(this) {
+ if (n === undefined) {
+ n = 1;
+ }
+ n.times(function () {
+ move();
+ });
+ }
+ },
+ left: function () {
+ this.direction -= 1;
+ if (this.direction < 0) {
+ this.direction = 3;
+ }
+ },
+ right: function () {
+ this.direction += 1;
+ if (this.direction > 3) {
+ this.direction = 0;
+ }
+ },
+ walk: function (block) {
+ this.instance_eval(block);
+ },
+ draw: function () {
+ var xrange, yrange,
+ puts = require('sys').puts;
+ with (this) {
+ xrange = board.keys().map(function (key) {
+ return parseInt(key.split(',')[0]);
+ }).minmax();
+ yrange = board.keys().map(function (key) {
+ return parseInt(key.split(',')[1]);
+ }).minmax();
+ yrange[0].upto(yrange[1], function (y) {
+ var row = "";
+ xrange[0].upto(xrange[1], function (x) {
+ row += board[[x,y]] || " ";
+ });
+ puts(row);
+ });
+ }
+ },
+ move: function () {
+ var increment = this.direction > 1 ? -1 : 1;
+ if (this.direction.is_even()) {
+ this.x += increment;
+ } else {
+ this.y += increment;
+ }
+ this.mark_current_location();
+ },
+ mark_current_location: function () {
+ if (this.is_pen_down) {
+ this.board[[this.x, this.y]] = "#";
+ }
+ }
+};
+
+
+// Use the dsl (Domain Specific Language)
+var turtle = new Turtle();
+
+turtle.walk(function () {
+ pen_down();
+ left();
+ forward(4);
+ right();
+ (4).times(function () {
+ forward(1);
+ right();
+ forward(1);
+ left();
+ });
+ left();
+ forward(4);
+ right();
+ pen_up();
+ forward(4);
+ pen_down();
+ (4).times(function () {
+ forward(4);
+ right();
+ });
+ pen_up();
+ forward(8);
+ pen_down();
+ forward(3);
+ right();
+ forward(1);
+ left();
+ forward(1);
+ right();
+ forward(2);
+ right();
+ forward(1);
+ left();
+ forward(1);
+ right();
+ forward(3);
+ right();
+ forward(4);
+ right();
+ pen_up();
+ // E
+ forward(12);
+ right();
+ right();
+ pen_down();
+ forward(4);
+ left();
+ forward(4);
+ left();
+ forward(4);
+ pen_up();
+ left();
+ forward(2);
+ left();
+ forward(1);
+ pen_down();
+ forward(3);
+
+});
+
+turtle.draw();
+
+// Here's the output if you don't have node
+
+// Timothy-Caswells-MacBook-Pro:Desktop tim$ node turtle.js
+// ##### ##### #####
+// # # # # # #
+// # # # # # #
+// # # # # # #
+// ##### ##### #####
289 ui.menu.js
@@ -0,0 +1,289 @@
+(function($) {
+$.widget("ui.menu", {
+ active: false,
+ last_activated: null,
+ last_menu_level: null,
+ last_level: null,
+ timer_id: null,
+ _init: function() {
+ this._menufy();
+ },
+
+ deactivate: function () {
+ this.$sub_menus.addClass('ui-helper-hidden');
+ this.$lis.removeClass('ui-state-active');
+ this.active = false;
+ this.last_activated = null;
+ },
+
+ activate: function(li, force) {
+ if (force) {
+ this.active = true;
+ }
+ if (!this.active) {
+ return;
+ }
+ var submenu = li.submenu;
+ if (!submenu) {
+ return;
+ }
+ if (this.last_activated == li) {this.last_level = null; return;}
+ this.last_activated = li;
+ this.last_level = submenu.level;
+ this.last_menu_level = submenu.level;
+ var menu_entry = $(li);
+ if (submenu.level == 0)
+ {
+ this.deactivate();
+ this.active = true;
+ menu_entry.addClass('ui-state-active');
+ submenu.css('left', (menu_entry.offset().left-1)+"px");
+ submenu.css('top', (menu_entry.offset().top+menu_entry.outerHeight()+1)+"px");
+ }
+ else
+ {
+ this.$sub_menus.each(function (i, sub_menu) {
+ if (sub_menu.level >= submenu.level)
+ $(sub_menu).addClass('ui-helper-hidden');
+ });
+ var parent_menu = $(li.parentNode);
+ submenu.css('left', (parent_menu.offset().left+parent_menu.outerWidth()-1)+"px");
+ submenu.css('top', (menu_entry.offset().top-1)+"px");
+ }
+ // IE6 hack for first level submenu widths being way off
+ if (submenu.outerWidth() > 500 || submenu.outerWidth() < 10)
+ {
+ submenu.css('width', "0px");
+ }
+ submenu.css('width', submenu.innerWidth() + "px");
+ submenu.removeClass('ui-helper-hidden');
+ },
+
+ _menufy: function() {
+ this.top_level = this.element.children('ul:first, ol:first').eq(0);
+ this.$lis = $('li', this.top_level);
+ this.$sub_menus = $([]);
+
+ var self = this, o = this.options;
+
+ function getSubmenus($lis, level)
+ {
+ if ($lis.length == 0) return;
+ var menu = $($lis[0].parentNode);
+
+ // Main menu entries are buttons
+ var addState = function(state, el) {
+ if (el.is(':not(.ui-state-disabled)')) {
+ el.addClass('ui-state-' + state);
+ }
+ };
+ var removeState = function(state, el) {
+ el.removeClass('ui-state-' + state);
+ };
+ if (level == 0)
+ {
+ $lis.addClass('ui-state-default');
+ $lis.eq($lis.length-1).addClass('ui-corner-right');
+
+ $lis.bind('mouseover', function() {
+ addState('hover', $(this));
+ });
+ $lis.bind('mouseout', function() {
+ removeState('hover', $(this));
+ });
+ }
+ else
+ {
+ $lis.bind('mouseover.menu', function() {
+ addState('hover', $(this));
+ });
+ $lis.bind('mouseout.menu', function() {
+ removeState('hover', $(this));
+ });
+ }
+
+ var has_images = false;
+ // Make empty li elements to be separators
+ $lis.each(function (i, li) {
+ if (li.innerHTML == '')
+ {
+ $(li).addClass('ui-menu-separator ui-widget-content');
+ $(li).unbind('.menu');
+ }
+ var $imgs = $('img', li);
+ if ($imgs.length)
+ {
+ $imgs.addClass('ui-helper-reset');
+ has_images = true;
+ }
+
+ $(li).attr('depth', level - 1);
+ });
+ if (has_images && level > 0)
+ menu.addClass('ui-menu-submenu-images');
+
+ var $ids = $lis.map(function() { return $('a', this)[0]; });
+ var has_children = false;
+ $ids.each(function(i, a) {
+
+ var href = $(a).attr('href');
+ var target = $(a).attr('target');
+ var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
+ // For dynamically created HTML that contains a hash as href IE < 8 expands
+ // such href to the full page url with hash and then misinterprets tab as ajax.
+ // Same consideration applies for an added tab with a fragment identifier
+ // since a[href=#fragment-identifier] does unexpectedly not match.
+ // Thus normalize href attribute...
+ if (href.split('#')[0] == location.toString().split('#')[0]) {
+ href = a.hash;
+ }
+
+ //added to make full bar clickable! -Kyle M.
+ if(href.indexOf('#') !== 0 && target != '_blank')
+ {
+ var li = a.parentNode;
+ li.onclick = function(){window.location=href;};
+ li.style.cursor = 'pointer';
+ }
+
+ // submenu
+ if (fragmentId.test(href)) {
+ var li = a.parentNode;
+ // Nuke the anchor tag
+ li.innerHTML = a.innerHTML;
+ li.href = href;
+ li.target = target;
+
+ var selector = self._sanitizeSelector(href);
+ self.$sub_menus = self.$sub_menus.add(selector);
+ var submenu = $(selector);
+ li.submenu = submenu;
+ submenu[0].level = level;
+ submenu.level = level;
+ submenu.addClass('ui-helper-hidden');
+
+ // Add arrow if there is a submenu.
+ var row = $(li);
+ var arrow = $('<div class="ui-icon ui-icon-triangle-1-e"></div>');
+ row.prepend(arrow);
+ if (level > 0)
+ {
+ has_children = true;
+ }
+ else
+ {
+ var item = $(li);
+ $(li).css('padding-right', '30px');
+ var arrow = $('div', item);
+ arrow.css('left', (item.innerWidth()-52) + "px");
+ }
+ getSubmenus($('li', submenu), level + 1);
+ }
+ });
+ if (has_children && level > 0)
+ menu.addClass('ui-menu-submenu-children');
+
+ if (level == 0)
+ {/*
+ $lis.bind('click.tabs', function(e) {
+ e.stopPropagation();
+ if (self.active)
+ self.deactivate();
+ else
+ self.activate(this, true);
+ });*/
+
+ $lis.bind('mouseover.tabs', function() {
+ if(self.timer_id != null)
+ {
+ clearTimeout(self.timer_id);
+ self.timer_id = null;
+ }
+
+ self.activate(this, true);
+ });
+
+
+ self.$lis.bind('mouseout.tabs', function(e) {
+
+ if(self.timer_id != null)
+ {
+ clearTimeout(self.timer_id);
+ self.timer_id = null;
+ }
+
+ self.timer_id = setTimeout(function () { self.deactivate(); }, 500);
+ });
+
+ }
+ else
+ {
+ $lis.bind('mouseover.tabs', function(e) {
+
+ if(self.timer_id != null)
+ {
+
+ clearTimeout(self.timer_id);
+ self.timer_id = null;
+ }
+
+ var depth = $(this).attr('depth');
+ self.activate(this, true);
+
+ if(this.submenu)
+ {
+ this.submenu.removeClass('ui-helper-hidden');
+ }
+ else
+ {
+ self.$sub_menus.each(function (i, sub_menu) {
+ if (sub_menu.level > depth)
+ {
+ $(sub_menu).addClass('ui-helper-hidden');
+ }
+ });
+ }
+ }
+
+ );
+
+
+ self.$sub_menus.bind('mouseout.tabs', function(e) {
+
+ if(self.timer_id != null)
+ {
+ clearTimeout(self.timer_id);
+ self.timer_id = null;
+ }
+
+ self.timer_id = setTimeout(function () { self.deactivate(); }, 500);
+ });
+ }
+
+
+ }
+
+ // attach necessary classes for styling
+ this.element.addClass('ui-menu ui-widget');
+ this.top_level.addClass('ui-menu-toplevel ui-widget-header ui-helper-reset ui-helper-clearfix');
+
+ // Start the recursive processing
+ getSubmenus(this.$lis, 0);
+
+ this.$sub_menus.addClass('ui-helper-reset ui-menu-submenu ui-widget ui-widget-content');
+
+ // deactivate the menu when the page is clicked anywhere
+ $(document).bind('click', function (e) {
+ // Only catch left clicks
+ if (e.button > 0) return;
+ e.stopPropagation();
+ self.deactivate();
+ });
+
+ },
+ _sanitizeSelector: function(hash) {
+ return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
+ }
+ });
+
+})(jQuery);
Please sign in to comment.
Something went wrong with that request. Please try again.