Archive for the ‘Programming’ Category
A dead simple, lightweight javascript calendar
I recently needed a good light weight javascript calendar but couldn’t find it. The problem is that online I could find many calendars, but they all suffered from one of two problems: they were either too heavy, or they were badly written (aka coding like it’s 1999).
I hereby present a very lightweight javascript calendar object. It can be used anywhere where you need to select a date.
It features the following:
- no library. That’s right, it does NOT use mootools, it does NOT use jQuery.
- clean code. Yes it can be improved, but that would make it a heavy calendar again.
- it does not do Date magic. If you want date magic I can recommend date.js. (oh, and that means things like ‘3 days ago’ etc.)
- it’s lightweight, mainly because it doesn’t do magic and it doesn’t have a library. It’s 2K uncompressed, 1.5K using dean edwards packer.
- no popup windows. All
Download
Usage
var cal = new MBCalendar('inp', 'btn', 'click');
Where
- inp is the id of the input that will be retrieving the calendar, and
- btn is the id of the element that will trigger the calendar to show, and
- click is the name of the event that will trigger the calendar
- in the onload script, in this example ‘out’ is the id of the element that will hold the calendar.
This way it can be used as a date picker, but it can also be used as a visible calendar with navigation (static). Basically the output is simply the HTML, so you can use it anywhere.
All dates van be individually styled, since they all get a unique id. Also all dates get class names so you can style either a certain year, month, or day of the month. E.g. ‘.y2009′ will style every date in 2009, ‘.m3′ will style every march, and ‘.y2009.m3′ will style every day in March, 2009.
Source code
Now for the code
/*(c) Michiel van der Blonk 2009 - license: http://www.opensource.org/licenses/mit-license.php*/
function MBCalendar(m, y)
{
this.m = m;
this.y = y;
this.weekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
}
MBCalendar.prototype.$ = function(s) {return document.getElementById(s)};
// export as array
MBCalendar.prototype.toArray = function() {
var d;
var dates = [];
for (var i=1;i<32;i++)
{
d = new Date(this.y,this.m-1, i);
if (d.getMonth() == this.m-1)
dates.push(d);
}
return dates;
};
// export as html
MBCalendar.prototype.toHTML = function() {
var i;
var ret, dayId, dayClass;
ret = dayId = dayClass = '';
var dates = this.toArray();
ret += '
<table class="cal">' + '
<tr>';
for (i in [0,1,2,3,4,5,6])
ret += '
<th>' + this.weekDays[parseInt(dates[i].getDay())].substr(0,1) + '</th>
';
ret += '</tr>
<tr>';
for (i in dates)
{
var d = dates[i];
if ((parseInt(i) % 7) == 0)
ret += '</tr>
';
if ((parseInt(i)+1 % 7==0) && i<dates .length)
ret += '
<tr>';
dayClass = 'y'+d.getFullYear() + ' m' +(d.getMonth()+1) + ' d' + d.getDate();
dayId = 'day-' + parseInt(d.getTime()/86400000);
ret += '
<td id="' + dayId + '" class="' + dayClass +'">' + dates[i].getDate() + '</td>
';
}
ret = ret + '</dates></table>
';
return ret;
};
window.onload = function() {
var $ = function(s) {return document.getElementById(s)};
var c;
$('showCal').onclick = function() {
var y = $('year').value;
var m = $('month').value;
c = new MBCalendar(m, y);
$('out').innerHTML = c.toHTML();
};
$('prev').onclick = function() {
var d = new Date(c.y,c.m-2,1);
c = new MBCalendar(d.getMonth()+1, d.getFullYear());
$('out').innerHTML = c.toHTML();
}
$('next').onclick = function() {
var d = new Date(c.y,c.m,1);
c = new MBCalendar(d.getMonth()+1, d.getFullYear());
$('out').innerHTML = c.toHTML();
}
};
If you like you can integrate the prev, next and show methods in the Calendar object itself of course. I invite all javascript experts to crunch the code even more, without making it unreadable!
If you don’t integrate that code, you will need to add some standard HTML in a page to get a functional Calendar demonstration:
<input type="text" id="year" value="" /> <input type="text" id="month" value="" /> <button type="button" id="showCal">Show Calendar</button> <button type="button" id="prev">prev</button> <button type="button" id="next">next</button>
Some alternative calendars you might like:
- Aeron’s Mootools calendar. Check the 1.2 modified version.
- The Vista Like Ajax calendar (vla). The only problem I have with this one is it doesn’t work properly in IE8
update: there was still some debug code in there, it’s removed now. Also it seems wordpress messes up the code when I paste it. Change line 16 to have the ‘<’ char instead of <
Awesome list of mootools resources
Check that out, if ever I need anything mootools I will find it here.
http://www.w3avenue.com/2009/07/28/list-of-really-useful-plugins-and-resources-for-mootools/
Stack Overflow
-
if you cannot find it here, you cannot find it anywhere. StackOverflow is a site by programmers for programmers. Try to answer one of those questions, they’re hard.
How to shuffle an array
This is a very common programming problem, e.g. when you wish to show some images in random order, when you want to show a random quote, etc. I will show you a solution in JavaScript, but it can be ported to other languages easily.
The common solution to shuffling is to swap random elements, but swapping means you have to constantly work with two elements, and it can be done by using only one. Also, it’s common to randomly swap e.g. 1000 elements, but that wouldn’t work well for very large arrays.
All you have to do is follow a couple of simple steps:
- First, of course you start with a simple array, which you have in a specified order.
- You place a random element in the output array, and remove the element
- Repeat step 2 until the array is empty
Here’s the full code
function shuffle(r) {
var pos;
var out = [];
while (r.length > 0) {
pos = parseInt(Math.random()*r.length);
out.push(r[pos]);
r = r.slice(0,pos).concat(r.slice(pos+1, r.length));
}
return out;
}
Let’s examine the parts. First, the variables pos and out are defined, and out is initialized to an empty array.
var pos; var out = [];
No we “loop” through the array. But, do note that this is not a real loop, in fact we’re constantly going to remove elements until the array is empty. So the simple check on length is enough here.
while (r.length > 0) {
We find a random element. For large arrays the Math.random() method can be considered unreliable, but then I mean really large.
pos = parseInt(Math.random()*r.length);
Next, we add the random element to the output array, using push. Then we remove the element from the original array. This is done in three parts:
- get everything on the left of the element
- get everything on the right of the element
- concat these two arrays to form a new array
That is a really difficult way of removing just one element, but deleting an element from an array is not a native javascript method. John Resig wrote another version of delete…
out.push(r[pos]); r = r.slice(0,pos).concat(r.slice(pos+1, r.length));
And last but not least we return the new array:
} return out; }
Example
Here’s an example of calling the function, shuffling 52 integers
var r=[];
i=52;
while (i--)
r.push(i);
alert(shuffle(r).join(','));
Extending Array
If you feel so inclined you can make it an extension of the Array object in javascript, like so:
Array.prototype.shuffle = function() {
var r=this;
... //rest of code
}
Note the additional "r=this" line.
Drawbacks
There are some drawbacks and warnings to take note of:
- It can be slow for huge arrays, I would recommend it for arrays under 1000 items
- It takes up additional space, since it creates a new array
- The delete can be improved, by using e.g. John Resig’s version
A shorter ‘hack’
The following is a short hack that can most definitely suit one time needs. It’s a form of sorting randomly, which sounds weird, and it is, but it works. However, if the random value is not seeded again, the next time you run it you end up with the exact same sequence.
function shuffle(r) {
r.sort(function() { return Math.random() } );
}
For more background see e.g. the Fisher Yates shuffle method (which by the way this is not, but this is).
Convert Excel Tables To Lists
In a dark past I was an Excel instructor (among other things). I have trained countless people in the art of Excel number wizardry. I have then become a certified Excel VBA specialist, and I must say, in my years being a professional programmer, this is the skill that has set me apart from all other programmers around me. Sure, people can do Regular Expressions… So can I. Sure, people can do Object Orientation. So can I. But what programmer fancies dumb jumbling of data, and programming a language that has the word ‘basic’ in it? Right. Most programmers I knew were Linux bashers (pun intended) that had no idea something good was hidden up the sleeve of Microsoft. But ok, sometimes I was able to show them some awesome things, and they would instantly recognize that their world view (Excelll is for end-users) was a grave mistake.
What fun it was to teach people Excel, and more so, VBA! To me, it’s the tool of all tools, and it can greatly help anyone who ever works with data (ehm, anyone). So in this first part of a long long series (I hope) I will show you, the humble ignorant user how to convert an Excel table to a list.
Why? Many times I have gone to companies and helped them with some particular problem. Usually it started out with an analyst/marketer/ceo showing me a bunch of data. The data was always presented as a table, with column headings and row headings, with the data in the middle. That seems like a nice way to present data, yes, it is in fact. The first thing I would do is then convert this table to an ugly list.
So why would you convert it to a list?
Because Excel is in love with lists. Excel craves lists, it’s like Access’ little brother, but it can speak five languages and juggle 4 balls. It’s no database tool (maximum of 65535 rows, 1M in Excel 2007)… but it can transform any list into a deep, deep analysis.
The way this analysis is done later on is with Pivot Tables. I wrote those capitals on purpose. Pivot Tables are so powerful that you can basically give it any data list and it can tell you what’s missing, what’s wrong, what’s unique, what’s the total, what’s the average, you name it. But more on that later on.
Let’s convert!
Warning: code ahead…
A table consists of three parts:
- The row headings (left)
- The column headings (top)
- The data (center)
We will loop through the data cell by cell, and create a row in a new list for each. That’s the basic idea (pun intended).
Before we start, we check some preconditions. We have to make sure that we are inside a set of data, formed into a table. All we do is just check if we have at least two rows and two columns (not the ultimate, but it works).
Sub TableToList() If ActiveCell.CurrentRegion.Rows.Count < 2 Then Exit Sub End If If ActiveCell.CurrentRegion.Columns.Count < 2 Then Exit Sub End If
Then we will need some variables to refer to the various sections of the table
Dim table As Range Dim rngColHead As Range Dim rngRowHead As Range Dim rngData As Range Dim rngCurrCell As Range
Next. we will need some variables for the data itself
Dim rowVal As Variant Dim colVal As Variant Dim val As Variant
Now, we will start pointing our variables to the data, row headings and column headings, like so
Set table = ActiveCell.CurrentRegion Set rngColHead = table.Rows(1) Set rngRowHead = table.Columns(1) Set rngData = table.Offset(1, 1) Set rngData = rngData.Resize(rngData.Rows.Count - 1, rngData.Columns.Count - 1)
Note that “currentregion” is a handy tool that expands any cell into a surrounding of non-empty cells. So this way your selected cell could be anywhere inside the table when you run the macro. The data part is a bit harder, line 4 and 5 together shift and resize the original table to form the right bottom part, where all the data resides.
Dim shList As Worksheet Set shList = ThisWorkbook.Worksheets.Add
Next, we create a new sheet in the workbook, to hold the list.
ActiveCell.Value = "Row#" ActiveCell.Offset(0, 1).Value = "RowValue" ActiveCell.Offset(0, 2).Value = "ColValue" ActiveCell.Offset(0, 3).Value = "Data" ActiveCell.Offset(1, 0).Select
In this sheet, we create a first row, “manually”, where we name the column headings for our list. These column headings are very important for sorting, analysis, pivot tables, export and such. The last statement instantly moves the current cell selection one row down. Notice we’re inserting a special column for Row Number. This is not always necessary, but it doesn’t hurt, and it helps you to always be able to restore the original order of the list.
Now it’s time for the actual grunt work, looping through the table
Dim n As Long For Each rngCurrCell In rngData colVal = rngColHead.Cells(rngCurrCell.Column - table.Column + 1) rowVal = rngRowHead.Cells(rngCurrCell.Row - table.Row + 1)
The “for each rngCurrCell in” is a real beauty in VBA. It just runs through any selection, without worries of overflows, row and column numbers, or calculations. In the loop, we set the value of the current column and row. Note that the rngCurrCell.column and rngCurrCell.row are not relative, it’s the actual number of the column/row. So if the tables starts at C3, the first cel is having column=3 and row=3.
n = n + 1 ActiveCell.Value = n
Here, we upped counter ‘n’ and put it in the list.
ActiveCell.Offset(0, 1).Value = rowVal ActiveCell.Offset(0, 2).Value = colVal ActiveCell.Offset(0, 3).Value = rngCurrCell.Value ActiveCell.Offset(1, 0).Select
We do the same trick again to put a new row in the data list on our new sheet. As you can see this part of code is repeated from the part where we created the header. A small improvement would be to create a function named ‘newRow(n, rv, cv, dv)’ to insert a new row with these values.
Next End Sub
Well, that’s it!
When you are done with your code, run it and look at the list. You can try sorting, filtering, analyzing, totalling, and… pivot tables. A pivot table is a dynamically updating table which automatically totals values from a list, and presents them in… a table. Here’s how to re-create the original table from the list:”
- Choose Data > Pivot Table
- Choose Finish
- Drag ColumnValues to the ‘column fields’
- Drag RowValues to the ‘row fields’
- Drag Data into ‘Drop data items here’
Voila, the list is back. That is, if it was a list of numbers. Pivot Tables are for numeric operations, if you had text in there, it won’t show anything (anything good).
The file(s)
Download the file here:
Table2List.xla
Note: to install an XLA you need to go to Tools > AddIns and select the file
JavaScript arrays, functions and objects
In javascript arrays and functions are very much alike. They are more like brother and sister than like neighbors. Arrays can hold values, which can include objects and functions. Functions can also hold these in their properties, but in addition can act as Class templates to create new objects. They are both objects by the way.
Let’s look at some data viewed in various incarnations, to illustrate the concept:
An array
var fruit = new Array(); fruit['first']='apple'; fruit['second']='banana'; fruit['third']='cherry';
Note that this uses strings as index values, creating a so-called Hash or Dictionary. It is different from a traditional array, which uses numbers as index values, as in:
var fruit = new Array();
fruit.push('apple');
fruit.push('banana');
fruit.push('cherry');
or
fruit = ['apple', 'banana', 'cherry'];
A function
var fruit = function()
{
this.first = 'apple';
this.second = 'banana';
this.third = 'cherry';
}
It’s important to note that there is a major difference between a function and an object. When a function is created it can act like a constructor (class template), creating new objects with the ‘new’ keyword. Objects cannot do this themselves.
An object
var fruit = new Object(); fruit.first = 'apple'; fruit.second = 'banana'; fruit.third = 'cherry';
this can be rephrased as
fruit = {first:'apple', second:'banana'; third:'cherry'};
Note the weird ending of the line with “;};” which is correct in this case.
sIFR reloaded
sIFR (scalable inman flash replacement for the outsiders) is a technique to embed custom fonts in a webpage. You know, traditionally web pages can only show a couple of fonts reliably – the ubiquitous Arial, Times, and a couple of others.
When sIFR was introduced I was pretty psyched out about it. Showing any font, and still accessible, selectable, etc. However, it’s giving me nothing but headaches. Let’s recap some of those:
- sIFR needs Flash. At a certain point there was a security issue and I had to disable Flash. No more sIFR.
- Lots of people block Flash, because of the ads.
- Special characters weren’t showing. It appeared my font didn’t even have these defined. Well that’s not sIFR to blame, but still
- It’s almost doing a good job presenting the CSS correctly. Almost.
- Documentation? Don’t get me started. Besides a collection of pages on several blogs, that are badly maintained, there’s absolutely nothing.
- Every time you install a new version you have to recreate your font files. Now that’s annoying!
Here are some alternatives I found today
TrueFontFamily
trademarks: JS, PHP, CSS, commercial.
Server side generating is of course a good idea, but I can’t see if the textimages are cached, it looks like not.
Facelift
trademarks: JS, PHP, hosted, commercial
This one seems very good, but a bit too commercial. Hosted? No thank you.
TypeFace
trademarks: JS, SVG/VML, free
Typeface is a diamond among these, so it seems, if it doesn’t suffer from the lack of documentation that is. But if it’s really good it doesn’t need documentation.
The wampapache service terminated with service-specific error 1 (0×1)
Many people must have seen this error. I just installed WampServer 2, and got it. An analysis of the problem results in the following possible causes:
- a misconfiguration in your httpd.conf. This is the most common. To resolve it, go to the command line (Start > Run > CMD), and enter “httpd.exe –S” in the apache\bin folder.
- port 80 is already in use. This can happen because you have another application, e.g. IIS running on port 80. Actually there is no reason you shouldn’t be able to use both, just not at the same time. From the Wamp menu you can choose Apache > Test port 80 and it will tell you which service is using it. To stop IIS you will have to go to Control Panel > Adminstrative Tools > Services and stop the World Wide Web Publishing service.
- your firewall is blocking port 80. All firewalls are different. First, just stop the firewall to test if it’s the cause of the problem. If it is, you need to add 127.0.0.1 to the ‘safe list’.
- Update: I recently found the ‘IIS management service’. This can also interfere with apache, so stop it if you don’t need it.
- Update2: Thanks, Anil, for the Skype issue. I had that one as well actually.. So, guys, just stop Skype (right click in the task bar, and exit the app). Then start Wampserver and you can restart Skype. Or change the Skype port numbers. See the Skype support page.
I hope this helps anyone, since I couldn’t find anything online.
The javascript Date object and how to add days to a date variable
JavaScript is not an object oriented language, it’s a prototype based language. This means that you can extend any existing object by just writing a new function for it on-the-fly. Here’s an example:
// add n number of days
Date.prototype.goto = function(n) {
this.setTime(this.getTime()+n*86400000);
return this;
};
Yes I know… GOTO is considered harmful. But so is Edsger Dijkstra. Anyway, this nifty little function will add, or subtract(!), any number of days with an easy to use syntax:
// add n number of days d = new Date; // today d.goto(7); // move it to next week d.goto(-365); // move to last year (well if it isn't leap) };
Try it yourself, it’s fun. Now to make things more interesting, you can make a generic function (erm.. method?!) that will calculate the number of days since the Epoch
Date.prototype.days = function() { return parseInt(this.getTime() / (1000*24*60*60)); };
This makes stuff like comparing dates and calculating differences way easier. E.g. check out this one for calculating the number of working days between two dates:
Date.prototype.workdays = function(d2) {
var start = new Date(this);
var end = d2;
var ret = 0;
var diff = end.days() - start.days();
if (diff > 0)
// up to 1 year
while (start.days() < end.days() && ret < 3650)
{
start.goto(1); // move to next day
if (start.getDay() != 0 && start.getDay() != 6)
ret++;
}
return ret;
};
Comments (4)
Leave a Comment
Leave a Comment

