spudly.shuoink.com

the best way to predict the future is to implement it

Entries Comments


Date.add(), Date.subtract(), & Date.truncate()

4 July, 2008 (07:36) | JavaScript | 7 comments

If you’ve ever worked extensively with dates in javascript, you may have missed methods like these. These methods allow you to add or subtract time from a Date object. Truncate forces your date object into a specified precision. Here’s some examples:

var d = new Date();
//=> Fri Jul 04 2008 07:48:53 GMT-0600 (MDT)
d.add( "years", 1 );
//=> Fri Jul 04 2009 07:48:53 GMT-0600 (MDT)
d.subtract( "minutes", 38 );
//=> Fri Jul 04 2009 07:10:53 GMT-0600 (MDT)
d.truncate( "minute" );
//=> Fri Jul 04 2009 07:10:00 GMT-0600 (MDT)
d.truncate( "day" );
//=> Fri Jul 04 2009 00:00:00 GMT-0600 (MDT)
d.truncate( "year" );
//=> Thu Jan 01 2009 00:00:00 GMT-0600 (MDT)

Beware, however, of adding months. Because months have variable lengths, it’s difficult to know what should happen if you’re on the tail-end of a longer month. My script has the same behavior as native JavaScript, that is, if you are on day 31 of a given month, and the next month has less than 31 days then when you add 1 month to it, you’ll end up with the first day of the third month.

Here’s the code:

Date.prototype.add = function( /**String*/unit, /**Number*/value ) {

   unit = unit.replace( /s$/ ).toLowerCase();

   switch ( unit ) {
      case "year":
         this.setYear( this.getYear() + value );
         break;
      case "month":
         this.setMonth( this.getMonth() + value );
         break;
      case "week":
         this.setTime( this.getTime() + value * 604800000 );
         break;
      case "day":
         this.setTime( this.getTime() + value * 86400000 );
         break;
      case "hour":
         this.setTime( this.getTime() + value * 3600000 );
         break;
      case "minute":
         this.setTime( this.getTime() + value * 60000 );
         break;
      case "second":
         this.setTime( this.getTime() + value * 1000 );
         break;
      case "nanosecond":
         // Fall Through
      default:
         this.setTime( this.getTime() + value );
         break;
   }

   return this;
};

Date.prototype.subtract = function( /**String*/unit, /**Number*/value ) {

   unit = unit.replace( /s$/ ).toLowerCase();

   switch ( unit ) {
      case "year":
         this.setYear( this.getYear() - value );
         break;
      case "month":
         this.setMonth( this.getMonth() - value );
         break;
      case "week":
         this.setTime( this.getTime() - value * 604800000 );
         break;
      case "day":
         this.setTime( this.getTime() - value * 86400000 );
         break;
      case "hour":
         this.setTime( this.getTime() - value * 3600000 );
         break;
      case "minute":
         this.setTime( this.getTime() - value * 60000 );
         break;
      case "second":
         this.setTime( this.getTime() - value * 1000 );
         break;
      case "nanosecond":
         // Fall Through
      default:
         this.setTime( this.getTime() - value );
         break;
   }
};

Date.prototype.truncate = function( /**String*/to ) {

   unit = unit.replace( /s$/ ).toLowerCase();

   switch ( unit ) {
      case "year":
         this.setMonth( 0, 1 );
         this.setHours( 0, 0, 0, 0 );
         break;
      case "month":
         this.setDate( 1 );
         this.setHours( 0, 0, 0, 0 );
         break;
      case "week":
         this.subtract( "day", this.getDay() );
         break;
      case "day":
         this.setMinutes( 0, 0, 0, 0 );
         break;
      case "hour":
         this.setMinutes( 0, 0, 0 );
         break;
      case "minute":
         this.setSeconds( 0, 0 );
         break;
      case "second":
         this.setMilliseconds( 0 );
         break;
      default:
         break;
   }

   return this;
};

assert for javascript

1 July, 2008 (20:26) | JavaScript | No comments

I was looking through a C++ book the other day and realized that javascript doesn’t have any functionality (that I know of at least) to perform assertions.

An assertion allows you to check in your script for things that should never happen, and throw an error if the thing that wasn’t supposed to happen happened. In other words, they throw an exception under certain conditions.

Anyway, I’ve written a very simple javascript function to allow you to use assertions in your code. Here it is:

function assert( test ) {
   if ( test === false ) {
      throw new Error( "Assert failed" );
   }
   return test;
}

It’s really simple, but really quite useful, especially if you’ve got some complex code and you want to make sure it worked properly before continuing.

Here’s a simple example:

var age = calculateAgeBasedOnSomeCrazyRandomAlgorithm();
assert( age > 0 ); // age can never be negative!

At this point, if age is less than or equal to 0, a JavaScript error will be thrown, and the current operation will stop executing.

String.interpolate()

19 June, 2008 (21:39) | JavaScript | 1 comment

Here’s a string prototype that allows you to interpolate variables into a string (ruby style). All you have to do is create your template and call interpolate on it ( with an object literal as a parameter for the vars to interpolate ).

Example:

var template = "The #{foxAdj}, #{foxAdj2} fox jumped over the #{dogAdj} dog.";

// alert "The quick, brown fox jumps over the lazy dog."
alert( template.interpolate( { foxAdj: 'quick', foxAdj2: 'brown', dogAdj: 'lazy' } ) );

You don’t have to use single variables within the template string either. Check these out:

var template = "#{var1} + #{var2} = #{var1 + var2}.";
alert( template.interpolate({ var1: 1, var2: 2 }) ); //prints "1 + 1 = 2"
var template = "Hello #{name()}!";
alert( template.interpolate({ name: function() { return "World"; } } ) ); // alerts "Hello World!"

And heres the code:

String.prototype.interpolate = function() {
   for ( i in arguments[0] ) {
      eval( i + ' = "' + arguments[0][i] + '"' );
   }
   return this.replace( /#\{.*?\}/g, function(match) {
      return eval( match.replace( /^#\{|\}$/g , '') );
   });
};

If anybody can think of a way to do this without eval, I would love to see it. Comments are welcome.

Array.each();

3 June, 2008 (06:48) | General | 3 comments

Here’s my version of the popular array.each method.

Array.prototype.each = function() {

   if ( this.cursor === undefined ) {
      this.cursor = 0;
   } else if ( this.cursor > this.length - 1 ) {
      this.cursor = undefined;
      return;
   }

   this.cursor++;

   return this[ this.cursor - 1 ];
};

Usage:

var myArray = [ 1, 2, 3, 4, 5 ];
while ( value = myArray.each() ) {
   // do something with the value
}

Array.min() && Array.max() && Array.sum()

1 June, 2008 (19:38) | General | 2 comments

Here’s three array methods that might be useful: min(), max(), and sum(). I’m sure you can guess what they do, but I’m going to tell you anyway. Note that for all three functions, the entire array must have only numeric values.

First, we have min(). This finds the smallest number in the array and returns it.

Usage:

var list = [ 1, 2, 3, 4, 5, 6, 7 ];
var min = list.min(); // min is now 1
Array.prototype.min = function() {

   if ( this.length == 0 || typeof this[0] != "number" ) {
      return null; // TODO: how about we throw an error instead, eh?
   }

   var min = this[0];
   for ( var i = 1; i < this.length; i++ ) {
      if ( typeof this[i] != "number" ) {
         return null; // TODO: how about we throw an error instead, eh?
      }
      if ( this[i] < min ) {
         min = this[i];
      }
   }
   return min;
};

Next, we have max(). This finds the largest number in the array and returns it.

Usage:

var list = [ 1, 2, 3, 4, 5, 6, 7 ];
var max = list.max(); // max is now 7
Array.prototype.max = function() {

   if ( this.length == 0 || typeof this[0] != "number" ) {
      return null; // TODO: how about we throw an error instead, eh?
   }

   var max = this[0];
   for ( var i = 1; i < this.length; i++ ) {
      if ( typeof this[i] != "number" ) {
         return null; // TODO: how about we throw an error instead, eh?
      }
      if ( this[i] > max ) {
         max = this[i];
      }
   }
   return max;
};

Lastly, sum() calculates the sum of all the values in the array.

Usage:

var list = [ 1, 2, 3, 4, 5, 6, 7 ];
var sum = list.sum(); // sum is now 28
Array.prototype.sum = function() {

   if ( this.length == 0 ) {
      return;
   }

   var sum = 0;
   for ( var i = 0; i < this.length; i++ ) {
      if ( typeof this[i] != "number" ) {
         return;
      }
      sum += this[i];
   }
   return sum;

};

Array.difference();

31 May, 2008 (17:00) | JavaScript | 2 comments

Here’s a prototyped method for Array that computes the symmetric difference between two arrays. It basically returns all the values that are in one or the other array but not both.

Usage:

var setA = [ 1, 2, 3, 4, 5, 6 ];
var setB = [ 4, 5, 6, 7, 8, 9, 10 ];
var diff = setA.difference( setB ); // diff is now [ 1, 2, 3, 7, 8, 9, 10 ]
Array.prototype.difference = function( setB ) {
   var setA = this;

   var setA_seen = {};
   var setB_seen = {};

   for ( var i = 0; i < setB.length; i++ ) {
      setB_seen[ setB[i] ] = true;
   }
   for ( var i = 0; i < setA.length; i++ ) {
      setA_seen[ setA[i] ] = true;
   }

   var difference = [];
   for ( var i = 0; i < setA.length; i++ ) {
      if ( !setB_seen[ setA[i] ] ) {
         difference.push( setA[i] );
      }
   }
   for ( var i = 0; i < setB.length; i++ ) {
      if ( !setA_seen[ setB[i] ] ) {
         difference.push( setB[i] );
      }
   }
   return difference;
};

Array.complement();

31 May, 2008 (16:51) | JavaScript | No comments

Heres a method to get the relative complement of one array to another. Thus, it will return an array of everything that is in the current array but not in the array you pass in.

Usage:

var setA = [ 1, 2, 3 ];
var setB = [ 3, 4, 5 ];
var setC = setA.complement( setB ); // setC is now [ 1, 2 ]
Array.prototype.complement = function( setB ) {
   var setA = this;

   var setA_seen = {};
   var setB_seen = {};

   for ( var i = 0; i < setB.length; i++ ) {
      setB_seen[ setB[i] ] = true;
   }

   var complement = [];
   for ( var i = 0; i < setA.length; i++ ) {
      if ( !setA_seen[ setA[i] ] ) {
         setA_seen[ setA[i] ] = true;
         if ( !setB_seen[ setA[i] ] ) {
            complement.push( setA[i] );
         }
      }
   }
   return complement;
};

Array.union();

31 May, 2008 (15:36) | JavaScript | No comments

Here’s another set theory prototype for the Array object in JavaScript. This one performs a union of the two arrays.

Usage;

var setA = [ 1, 2, 3, 4, 5, 6 ];
var setB = [ 4, 5, 6, 7, 8 ];
var union = setA.union( setB ); // Now union is [ 1, 2, 3, 4, 5, 6, 7, 8 ];
Array.prototype.union = function( setB ) {
   var setA = this;

   var seen = {};
   var union = [];

   for ( var i = 0; i < setA.length; i++ ) {
      if ( !seen[ setA[i] ] ) {
         union.push( setA[i] );
         seen[ setA[i] ] = true;
      }
   }
   for ( var i = 0; i < setB.length; i++ ) {
      if ( !seen[ setB[i] ] ) {
         union.push( setB[i] );
         seen[ setB[i] ] = true;
      }
   }

   return union;
};

Array.intersection()

31 May, 2008 (14:48) | JavaScript | 1 comment

I’m sure a lot of you know what set theory is if you’re reading a programming blog. Anyway, a big part of set theory is the concept of an intersection between two sets of data. This is essentially the parts of the sets that the two have in common. Here’s an prototype for the intersection of two arrays:

Array.prototype.intersection = function( setB ) {
   var setA = this;

   var setA_seen = {};
   var setB_seen = {};
   for ( var i = 0; i < setB.length; i++ ) {
      setB_seen[ setB[i] ] = true;
   }

   var intersection = [];
   for ( var i = 0; i < setA.length; i++ ) {
      if ( !setA_seen[ setA[i] ] ) {
         setA_seen[ setA[i] ] = true;
         if ( setB_seen[ setA[i] ] ) {
            intersection.push( setA[i] );
         }
      }
   }
   return intersection;
};

Array.grep

31 May, 2008 (14:38) | JavaScript | No comments

Here’s another prototype for the javascript Array class of objects: Array.grep(). This takes either a regular expression object or any other kind of value that can be compared with ===. If a regex is given, it will test the regex against each value. If something else is given, it will simply compare them with ===. The method returns an array of indexes where the pattern or value matched.

Enjoy :)

Array.prototype.grep = function( test ) {
   var matches = [];
   for ( var i = 0; i < this.length; i++ ) {
      if ( ( test.test && test.test(this[i]) ) || this[i] === test ) {
         matches.push(i);
      }
   }
   return matches;
};

« Older entries