spudly.shuoink.com

the best way to predict the future is to implement it

Entries Comments


Array#only

16 January, 2010 (01:05) | JavaScript | No comments

Here’s a function I wish was built into jQuery’s node set object… When you call this function, you’re saying “This array should have exactly one element. Give it to me.” Doing so will not only give you the element of the array (like array[0]), but will also throw an Error if the array is empty or has more than one element.

/*
 * Copyright (c) 2009 Stephen Sorensen, http://www.shuoink.com/
 *
 * Licensed under the MIT license.
 */

/**
 * Returns the first and only element of an {@link Array}. Throws an Error
 * if the array is empty or has more than one element.
 *
 * @throws   {Error} If the array does not have exactly one element
 * @returns  {mixed} The only element in the array
 */
Array.prototype.only = function () {
  if (this.length !== 1) {
    throw new Error();
  }
  return this[0];
};

View the latest version at google code!

Let me know in the comments if you can think of a more elegant solution…

Array#chunk

14 January, 2010 (21:20) | JavaScript | No comments

Here’s a little gem I wrote a while back. Hopefully the jsdoc documentation explains it’s purpose well enough that I won’t have to…

/*
 * Copyright (c) 2009 Stephen Sorensen, http://www.shuoink.com/
 *
 * Licensed under the MIT license.
 */

/**
 * Splits an array into multiple arrays of the given size and returns an array
 * of those arrays
 *
 * @example [1,2,3].split(1) // returns [[1],[2],[3]]
 * @example [1,2,3,4,5,6,7,8].split(3) // returns [[1,2,3],[4,5,6],[7,8]]
 *
 * @param   {Number} [size=3] The number of elements in each chunk.
 * @returns {Array}           An array of arrays of the given size.
 */
Array.prototype.chunk = function (size) {
  size = size || 3;
  var chunks = [], i;
  for (i = 0; i < this.length; i += size) {
    chunks.push(this.slice(i, Math.min(this.length, i + size)));
  }
  return chunks;
};

View the latest version at google code!

Let me know in the comments if you can think of a more elegant solution...

Passing a variable from PHP to JavaScript

29 December, 2009 (19:12) | General | 1 comment

One of my readers recently asked how to pass an array or another variable from PHP to JavaScript. This is a question I’ve seen all over the internet, and the quick and dirty answer is that you can’t… at least not directly. This is because PHP is run on the server-side, and JavaScript is run on the client side (except in rare, experimental cases). You cannot call a JavaScript function, or access a JavaScript variable directly from PHP because they run in completely different locations (among other reasons).

That said, here’s what you can do to share data between PHP and JavaScript:

  • Generate the JavaScript using PHP, just like you do HTML
  • Use AJAX to send data from JavaScript to PHP and vice versa

Neither of these methods fully qualifies as “passing variables” like you would when calling a function with parameters, but they do involve sending and retrieving data, which can be created from and/or parsed into variables for any given language.

Generate the JavaScript with PHP

<script>
  var my_number = <?php echo 123; ?>;
  var my_string  = "<?php echo "foo"; ?>";
  var my_array  = <?php echo json_encode( array( "foo", "bar", "baz" ) ); ?>;
  var my_object = <?php echo json_encode( array( "foo" => "bar" ) ); ?>;
</script>

The code above generates JavaScript variables using PHP. This is the easiest way to control JavaScript using PHP. Numbers and strings are pretty simple. For more complex variables, like arrays, the json_encode function can help. It basically converts a PHP data structure into JavaScript code. This use case isn’t exactly what it was intended for (more on that later), but it’s quite handy in this circumstance.

The php code above will generate the following JavaScript code when executed:

<script>
  var my_number = 123;
  var my_string  = "foo";
  var my_array  = [ "foo", "bar", "baz" ];
  var my_object = { "foo": "bar" };
</script>

As you can see, you now have four JavaScript variables created from data contained in your php script. All you have to do is make sure that you convert your data into valid JavaScript code!

AJAX / Forms / Links

The other (usually better) way to share data between PHP and JavaScript is by using HTTP Requests to send and retrieve information from the web server. Whenever you click a link or submit a form on a web site, a request is sent from the client to the server, and the server sends a response back to the client. Thus, you can send data on a request and receive data from the response. Back in the day, this was done with links and forms only, but now we have AJAX. AJAX is not so much a feature of JavaScript as it is a technique of using the XMLHttpRequest object to send and retrieve data from the server. Basically the idea is that you can send a request using JavaScript, the server sends a response, and the response text is then handed back to the JavaScript code. For more information on AJAX, I highly recommend reviewing the AJAX Tutorial at w3schools.com.

Here’s a sample PHP script that returns a random number between 0 and 100:

<?php echo rand(0,100); ?>

And here’s some JavaScript code that makes a request to the PHP script on the web server (using the jQuery library’s “get” function):

<script>
  // Note: this script sample uses the jQuery library for simplification
  jQuery.get( 'random.php', function ( data ) {
    alert( "here's a random number: " + data );
  });
</script>

The code above makes a GET request to the web server for the random.php script, which is then executed by the server and the response is sent from server to client. When the response is received, the anonymous function is called and passed the response text, which in this case is simply a random number from 0 to 100.

Note: PHP is not the only language these techniques apply to. Any language that can be executed on the server-side applies, my personal favorite being Perl. In addition, there are many formats for data transfer, the most notable being plain text, XML, and JSON.

I’m back…

13 December, 2009 (14:29) | General | 2 comments

Ok, so it’s been a very long time since I posted anything on this blog. I’ve just been too busy to keep up with it. I think it’s time to start up again, however, so I’ll be writing some new posts in coming days. As a part of this “coming back,” I’ve moved all of my code to the svn repositories at google code. Here’s the link: http://code.google.com/p/shuoink

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

4 July, 2008 (07:36) | JavaScript | 9 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;
};

« Older entries