Congratulations to my Twin Sister!

With honors, I am truly proud.
I have been working on this during some unexpected (but much needed!!) downtime…
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, "'"); 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) : " ") + "</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.
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.
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!

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!
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!
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:

Recent Comments