May 2 2012

Congratulations to my Twin Sister!

With honors, I am truly proud.


May 2 2012

Announcing: TARStack

TARStack



I have been working on this during some unexpected (but much needed!!) downtime…


Apr 22 2012

Way to Go GOL!!!


Apr 17 2012

Channel 5 WPTV – Discovery Flight


Jun 10 2011

JQuery Calendar Code

Of all the code floating around the web calendar drawing code is usually messy, hard to maintain, and inflexible. A while back I got permission to open-source calendar drawing code that I wrote. It’s client-side JavaScript code as a JQuery plug-in but I plan to port it to both PHP and C# (the first version used Prototype’s psuedo object oriented framework so porting to classical OO languages will be a cinch).


 
/*global jQuery: false */
/*jslint undef: true, nomen: true, bitwise: true, regexp: true, strict: true, newcap: true */
"use strict";
(function ($) {
 
//
// jqCal
//
$.fn.jqCal = function(options) {
	// build main options before element iteration
	var opts = $.extend({}, $.fn.jqCal.defaults, options);
 
	function optDateEqual(d1, d2) {
		return d1[0] == d2[0] &&
				d1[1] == d2[1] &&
				d1[2] == d2[2];
	}
 
	function dateHasAppts(date) {
		for (var i=0; i<opts.events.length; i++) {
			if (opts.events[i].date == null) continue;
			if (optDateEqual(opts.events[i].date, date)) {
				return true;
			}
		}
		return false;
	}
 
	function getDateAppts(date, baseClasses) {
		switch (opts.mode) {
		case $.fn.jqCal.modes.Big :
			var apptsHtml = "";
			for (var i=0; i<opts.events.length; i++) {
				if (opts.events[i].date == null) continue;
				if (optDateEqual(opts.events[i].date, date)) {
					apptsHtml += "<a href='" + opts.events[i].url + "' class='AppointmentLink' target='_new" + opts.events[i].key + "'>" +
						"<div class='Appointment'>" +
						opts.events[i].desc + "</div></a>";
				}
			}
			return apptsHtml;
		case $.fn.jqCal.modes.Print :
			var apptsHtml = "<table width='100%'>";
			for (var i=0; i<opts.events.length; i++) {
				if (opts.events[i].date == null) continue;
				if (optDateEqual(opts.events[i].date, date)) {
					apptsHtml += "<tr><td><div class='" + this.CSS_ApptPrint + "'>" + opts.events[i].desc + "</div></td></tr>";
				}
			}
			apptsHtml += "</table>";
			return apptsHtml;
		case $.fn.jqCal.modes.Tiny :
			var appts = 0;
			var toolTipText = "";
			var cssClass = baseClasses;
			for (var i=0; i<opts.events.length; i++) {
				if (opts.events[i].date == null) continue;
				if (optDateEqual(opts.events[i].date, date)) {
					appts++;
					if (appts > 1) toolTipText += " | ";
					toolTipText += opts.events[i].desc.replace(/<[^>]*>/g, " ").replace(/'/g, "&apos;");
					cssClass += " TinyAppointment";
				}
			}
			if (appts > 1) cssClass += this.CSS_MultiA;
			return " class='" + cssClass + "' title='" + toolTipText + "' ";
		case $.fn.jqCal.modes.Collective :
			var apptsHtml = "<table width='100%'>";
			for (var i=0; i<opts.events.length; i++) {
				if (opts.events[i].date == null) continue;
				if (optDateEqual(opts.events[i].date, date)) {
					apptsHtml += "<tr><td class='" + this.CSS_Appointment + "'>" + opts.events[i].desc + "</td></tr>";
				}
			}
			apptsHtml += "</table>";
			return apptsHtml;
		}
	}
 
 
	function dateIsHoliday(date) {
		for (var i=0; i<opts.holidays.length; i++) {
			if (opts.holidays[i].date == null) continue;
			if (optDateEqual(opts.holidays[i].date, date)) {
				return true;
			}
		}
		return false;
	}
 
	// iterate each matched element
	return this.each(function() {
		var $this = $(this);
 
		// build element specific options
		//var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
		var o = opts;
 
		var date = o.date ? new Date(o.date.valueOf()) : new Date((new Date()).getFullYear(), (new Date()).getMonth(), 1);
		date.setDate(1);
 
		var currentDate = new Date();
		var currentDate = [currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate()];
 
		var calHtml = ["<table class='" + o.cssClasses.CalClass + 
			((o.mode === $.fn.jqCal.modes.Tiny) ? " " + o.cssClasses.CalClass + "Tiny" : "") + "'>" +
			((o.monthYear) ? "<tr><td class='" + o.cssClasses.MonthYear + 
				((o.mode === $.fn.jqCal.modes.Tiny) ? " " + o.cssClasses.MonthYear + "Tiny" : "") + "' colspan=7>" + 
			o.months[date.getMonth()] + ", " + date.getFullYear() + "</td></tr><tr>" : "")];
		for (var i=0; i<7; i++) {
			calHtml[calHtml.length] = "<td class='" + o.cssClasses.Weekday + "' align='center'>" + 
				((o.mode !== $.fn.jqCal.modes.Tiny) ? o.days[i] : o.daysTiny[i]) + "</td>";
		}
		calHtml[calHtml.length] = "</tr>";
		calHtml[calHtml.length] = "<tr>";
		var dayClass, numClass, isHoliday, hasAppts;
		$.fn.jqCal.calDays(date, function(iter) {
			dayClass = iter.during ? o.cssClasses.DayReg : o.cssClasses.DayEmpty;
			dayClass += ((o.mode === $.fn.jqCal.modes.Tiny) ? " " + o.cssClasses.Day + "Tiny" : "");
			dayClass += optDateEqual(currentDate, iter.optDate) ? " today" : "";
			numClass = iter.during ? o.cssClasses.DayRegNum : o.cssClasses.DayEmptyNum;
			hasAppts = dateHasAppts(iter.optDate);
			isHoliday = dateIsHoliday(iter.optDate);
			if (iter.newRow) {
				calHtml[calHtml.length] = "<tr>";
			}
			if (o.mode != $.fn.jqCal.modes.Tiny) {
				calHtml[calHtml.length] = 
					"<td class='" + o.cssClasses.Day + " " + dayClass + "' id='" + iter.idStr + "' width='14%'>" +
//					((isHoliday) ? "<table cellpadding='0' cellspacing='0' width='100%' height='100%'>" +
//					"<tr><td valign='top'>" : "") +
					iter.dayNum +
//					((isHoliday) ? "</td></tr><tr><td valign='bottom'>" + this.getHolidays(iter.curDate) + 
//					"</td></tr></table>" : "") +
					"" + ((hasAppts) ? getDateAppts(iter.optDate) : "&nbsp;") + 
					"</td>";
			} else {
				calHtml[calHtml.length] = 
					"<td" + getDateAppts(iter.optDate, o.cssClasses.Day + " " + dayClass) + " width='14%'>" + iter.dayNum + "</td>";
			}
			if (iter.endRow === 6) {
				calHtml[calHtml.length] = "</tr>";
			}
		});
		calHtml[calHtml.length] = "</tr></table>";
 
		$this.html(calHtml.join(""));
	});
};
 
$.fn.jqCal.modes = {
Tiny : 0,
Big : 1,
Print : 2,
Collective : 3
};
 
//
// plugin defaults
//
$.fn.jqCal.defaults = {
mode : $.fn.jqCal.modes.Tiny,
events : [],
holidays : [],
monthYear : true,
months : ["January", "February", "March", "April", "May", "June", "July", "August",
	"September", "October", "November", "December"],
monthsTiny : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
	"Sep", "Oct", "Nov", "Dec"],
days : ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"],
daysTiny : ["S", "M", "T", "W", "T", "F", "S"],
cssClasses : {
	CalClass : "CalClass",
	MonthYear : "MonthYear",
	Weekday : "Weekday",
	Day : "CalDay",
	DayEmpty : "DayEmpty",
	DayEmptyNum : "DayEmptyNum",
	Appointment : "Appointment",
	ApptDay : "ApptDay",
	ApptDesc : "ApptDesc",
	MultiA : "MultiAppt",
	DayReg : "DayReg",
	DayRegNum : "DayRegNum",
	Holiday : "Holiday",
	ApptPrint : "ApptPrint",
	Hover : "CalDateHover"
		}
};
 
$.fn.jqCal.calDays = function(date, callback) {
	var calendarDate = new Date(date.valueOf());
	var calendarDateDay = calendarDate.getDay();
	var curDate = new Date(date.valueOf());
	curDate.setDate(curDate.getDate() - (curDate.getDay() + 1));
 
	var calendarMonth = calendarDate.getMonth();
	var calendarYear = calendarDate.getFullYear();
 
	var beforeMonth = curDate.getMonth() !== calendarMonth;
	var duringMonth = curDate.getMonth() === calendarMonth;
	var afterMonth = false;
 
	var idStrBase = "cal-" + calendarMonth + "-" + calendarYear + "-";
 
	var dayMs = 1000 * 60 * 60 * 24;
 
	var lastDayMs = new Date(calendarYear, calendarMonth + 1, 1).valueOf() - dayMs;
	var numDays = (new Date(lastDayMs)).getDate();
 
	var before=0, day=0, after=0;
 
	function dayNum() {
		if (duringMonth) {
			return day;
		} else {
			return curDate.getDate();
		}
	}
 
	function month() {
		var ret;
		if (duringMonth) {
			ret = calendarMonth;
		} else if (beforeMonth) {
			ret = calendarMonth - 1;
			if (ret === -1) {
				ret = 11;
			}
		} else {
			ret = calendarMonth + 1;
			if (ret === 12) {
				ret = 0;
			}
		}
		return ret;
	}
 
	function year() {
		if (duringMonth) {
			return calendarYear;
		} else {
			return curDate.getFullYear();
		}
	}
 
	function doDay() {
		var showDay = dayNum();
		var weekDay = curDate.getDay();
		callback({
			day : curDate, 
			during : duringMonth,
			before : beforeMonth, 
			after : afterMonth,
			dayNum : showDay,
			idStr : idStrBase + month() + "-" + showDay + "-" + year(),
			newRow : weekDay === 0,
			endRow : weekDay === 6,
			optDate : [year(), month(), showDay]
				});
	}
 
	while (true) {
		if (beforeMonth) {
			if (before < calendarDateDay) {
				curDate.setDate(curDate.getDate() + 1);
				before++;
				doDay();
				continue;
			} else {
				beforeMonth = false;
				duringMonth = true;
			}
		}
		if (duringMonth) {
			if (day < numDays) {
				curDate.setDate(curDate.getDate() + 1);
				day++;
				doDay();
				continue;
			}
			after = curDate.getDay();
			if (after === 6) {
				return;
			} else {
				duringMonth = false;
				afterMonth = true;
			}
		}
		if (afterMonth) {
			if (after < 6) {
				curDate.setDate(curDate.getDate() + 1);
				after++;
				doDay();
				continue;
			} else {
				return;
			}
		}
	}
 
};
 
 
})(jQuery);

The PHP and C# versions will be up here soon.


Dec 20 2009

Everything is Amazing & Nobody is Happy

Must Watch!


Dec 19 2009

Caring Labs

In the process of incorporating Keyring Labs, my company. Also launching a new effort which I thought of during a conversation with someone who works at a non-profit (as I do). Caring Labs is going to be a sister corporation of Keyring Labs, offering pro-bono consulting, products and services to any non-profit needing any of that.

The idea is that the non-profit I work for has more resources than most non-profits, and a very good CTO who has gotten the organization ahead of the game technology-wise in most ways, but even for us some of things we do are a little backwards (only in dealing with technology). There are a lot of non-profits fighting for things of great value to this world that have even less resources than the organization I work for. If there was an organization that could come into a place, look at how they are using technology, and either point them in the right direction or do the actual work to get them operating far more efficiently, well, hopefully enough has been said and you all get the picture. Will update on the progress here often.

Caring Labs


Dec 18 2009

Blueprint CSS Framework

I stumbled on the BluePrint CSS framework, seeing it used in another blog’s template. I had no idea there was such a thing as a CSS framework. So I’ve been playing around with it this morning.


I first wanted to try it out on a very simple page, and the public end of the bbpointofsale.com site is very simple but uses a lot of floats which are replaced in the framework with the concept of a “grid.” It makes things a lot simpler.


There was one tricky part, the content of bbpointofsale.com is centered ala most Google pages. In screen.css there is a container class that you use when you want to use grid layouts. The default width is 950px so it doesn’t center at all. I was only using 18 columns in my grid and the math for width of columns is columns * 40 – 10 = width so I changed it to this:

.container {width:710px;margin:0 auto;}

Viola! Centered content with the magic of grid layouts!


bbpos


My initial impression is that the Blueprint CSS Framework is well worth learning and using for reduced development time and great simplicity and easier maintenance. Two thumbs up!


Dec 9 2009

battlerc.com

I checked the stats for battlerc.com this morning. Turns out I’ve actually created a google search:
battle rc
rc plane laser tag
laser tag rc airplanes
jet laser tag
laser tag plane
rc laser aircraft
battlerc
laser tag airplanes
laser remote control
1 real laser tag
1 laser tag remote control
battlerc island

Nobody was searching for these things before, they’re all directly related to battlerc.com being up. Looks like there is some buzz. It’s about time for a mailing list send!


Dec 2 2009

Card Swipe for BlackBerry

It’s been a good morning. I took the code from the manufacturer’s website and hooked it all in so that a BlackBerry should theoretically connect to the device and read card information. Now that I know the code is, well, sane, I can actually get the device with no worry that it’ll be a nightmare to interface with it from Java code. When I have it working with the device I’ll post an update here.

Here’s what the BlackBerry will show when no P25M is connected:
bbpointofsale.com P25M not connected