Posts Tagged ‘javascript’

Share Validating Credit Card Numbers

Wednesday, August 18th, 2010

The easiest way to pre-verify a credit card value is entered correctly is to use the Luhn algorithm to check for mistakes. This is commonly referred to as a mod-10, mod10 or mod 10 check. It’s always important when handling user data to ensure it validates not only on the client, saving a trip to the server, but also server side should the client not support JavaScript. For that reason, we test on both ends.

There are more “elegant” implementations of this algorithm – see the Wikipedia entry referenced above – but they will likely be more difficult for a novice developer to understand. Further, the functions provided here are tolerant of common data entry conventions, such as using spaces and dashes to delimit blocks of numbers as is common with credit card numbers.

View Code JAVASCRIPT
function mod10_check(val){
	var nondigits = new RegExp(/[^0-9]+/g);
	var number = val.replace(nondigits,'');
	var pos, digit, i, sub_total, sum = 0;
	var strlen = number.length;
	if(strlen < 13){ return false; }
	for(i=0;i<strlen;i++){
		pos = strlen - i;
		digit = parseInt(number.substring(pos - 1, pos));
		if(i % 2 == 1){
			sub_total = digit * 2;
			if(sub_total > 9){
				sub_total = 1 + (sub_total - 10);
			}
		} else {
			sub_total = digit;
		}
		sum += sub_total;
	}
	if(sum > 0 && sum % 10 == 0){
		return true;
	}
	return false;
}

You can use the JavaScript version to validate a field on any javascript event. The following snippet illustrates how you might use the onblur event to notify the user the card number appears to be invalid with jQuery.

...
<input type="text" 
	name="cc_number" 
	onblur="if(mod10_check(this.value)){$('#cc_error').hide(); } else { $('#cc_error').show(); }" 
	value="" />
<span id="cc_error" style="display:none;">The card number is invalid.</span>
...

You can then use the following test in PHP to validate the data once it gets to your server.

function mod10_check($val){
	$number = preg_replace('/[^0-9]+/', '', $val);
	$sum = 0;
	$strlen = strlen($number);
	if($strlen < 13){ return false; }
	for($i=0;$i<$strlen;$i++){
		$digit = substr($number, $strlen - $i - 1, 1);
		if($i % 2 == 1){
			$sub_total = $digit * 2;
			if($sub_total > 9){
				$sub_total = 1 + ($sub_total - 10);
			}
		} else {
			$sub_total = $digit;
		}
		$sum += $sub_total;
	}
	if($sum > 0 && $sum % 10 == 0){ 
		return true; 
	}
	return false;
}

You can see the JavaScript implementation in action here. The only difference from the above example is the addition of an onkeyup event and the inclusion of a valid card message.

The card number appears to be invalid.

Some card numbers you can use to test the code.

1234-5678-9012-3456 - Invalid
4111 1111 1111 1111 - Valid (MC/Visa Like)
3111 111111 11117 - Valid (Amex Like)
6011111111111117 - Valid (Discover Like)

Share Using jQuery UI’s Autocomplete to Populate a Form

Wednesday, May 12th, 2010

It’s been a year and a half since I last posted about jQuery autocomplete. It’s come a long long way since then. In fact it’s really incredible now. The jQuery UI team has provided event hooks throughout the entire process while still providing a really robust experience if you just use it out of the box. For my case, I wanted to pre-populate more than just the current field with data. Using the “select” event, I was able to provide a custom handler that used the auto-suggest data to update other fields. This is very simple to implement and yields a really nice bump in the usability.

The use case is simple. A user starts to enter a city name, “san”. We use the text fragment and make a request for city / state / zip matches from the database or other source. We then present those to the user as an autocomplete option. If they select one, we update the city, state and zip fields with the selected data.

To implement this, you’ll want to generate an ajax handler that can generate JSON data. You can use a local array as your data source, however, the real power of auto-suggest is bringing the full weight of your database to bear. In many projects the data is too large to load into a static array. Since I use PHP mostly in my daily work, that’s what the example here is in. However, this could be done in any language. The two required fields, when using an object are “label” and “value”. The label is the text that will be shown to the user and “value” is the data that will be set in the current field. I generate an array of result data on the fly and then use PHP’s built in json_encode() function to bundle it up and return it to the user. This truncated example, shows the data being returned from my handler. Notice that I’m also passing back “city”, “state” and “zip” in addition to the “label” and “value” fields.

View Code JAVASCRIPT
[{"city":"San Diego","state":"CA","zip":"92101","value":"San Diego","label":"San Diego, CA 92101"}]

With the additional data in the response, I can assign these structured values to other fields in the form. This solved the main gripe I had with the autocomplete feature before, simple handling of JSON. While it was feasible under the old model, it required far more effort and development. This is all built into the core jQuery UI library. As you can see in the example below, it is insanely simple to write robust forms that can auto-populate based off the data in a single field.

This of course just scratches the surface of what you can really do with the autocomplete feature though. The jQuery UI team has done a great job of providing hooks to all the events, which really allows you to go nuts with the functionality. For example, using a function instead of an ajax file or local variable, you could serialize the entire form and send it via ajax. Then as your callback, pass the data to generate the suggestions to the user. Take a few minutes and read over the entire documentation, it’s really very powerful. You also have a wide variety of visual themes available, including the option to build your own. I’m using the default theme generated by the jQuery themeroller tool here.

Working Demo

Try entering, “sa”, “ch” or “ph” into the City field to see it in action. In this case, I look for a string match in the city name, but you could just as easily include the state, zip and so on.

The Code

You can see in the javascript below, I’m providing a handler for the “select” event that updates the other fields. I find that sometimes the event doesn’t properly update the fields essentially leaving the source field, city, with whatever text fragment I’ve entered. This seems to happen more often on mouse events but I haven’t spent much time tracking the cause down. If you happen to see what the issue is, please leave it in the comments!

<link rel="stylesheet" href="http://static.jquery.com/ui/css/base2.css" type="text/css" media="all" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript">
 
$(document).ready(function(){
	var ac_config = {
		source: "/ajax/demo_cities.php",
		select: function(event, ui){
			$("#city").val(ui.item.city);
			$("#state").val(ui.item.state);
			$("#zip").val(ui.item.zip);
		},
		minLength:1
	};
	$("#city").autocomplete(ac_config);
});
</script>
<form action="#" method="post">
	 <p><label for="city">City</label><br />
		 <input type="text" name="city" id="city" value="" /></p>
	 <p><label for="state">State</label><br />
		 <input type="text" name="state" id="state" value="" /></p>
	 <p><label for="zip">Zip</label><br />
	 	 <input type="text" name="zip" id="zip" value="" /></p>
</form>

An over simplified callback script that does a simple text match on the data entered into the field.

<?php
 
// Data could be pulled from a DB or other source
$cities = array(
	array('city'=>'New York', state=>'NY', zip=>'10001'),
	array('city'=>'Los Angeles', state=>'CA', zip=>'90001'),
	array('city'=>'Chicago', state=>'IL', zip=>'60601'),
	array('city'=>'Houston', state=>'TX', zip=>'77001'),
	array('city'=>'Phoenix', state=>'AZ', zip=>'85001'),
	array('city'=>'Philadelphia', state=>'PA', zip=>'19019'),
	array('city'=>'San Antonio', state=>'TX', zip=>'78201'),
	array('city'=>'Dallas', state=>'TX', zip=>'75201'),
	array('city'=>'San Diego', state=>'CA', zip=>'92101'),
	array('city'=>'San Jose', state=>'CA', zip=>'95101'),
	array('city'=>'Detroit', state=>'MI', zip=>'48201'),
	array('city'=>'San Francisco', state=>'CA', zip=>'94101'),
	array('city'=>'Jacksonville', state=>'FL', zip=>'32099'),
	array('city'=>'Indianapolis', state=>'IN', zip=>'46201'),
	array('city'=>'Austin', state=>'TX', zip=>'73301'),
	array('city'=>'Columbus', state=>'OH', zip=>'43085'),
	array('city'=>'Fort Worth', state=>'TX', zip=>'76101'),
	array('city'=>'Charlotte', state=>'NC', zip=>'28201'),
	array('city'=>'Memphis', state=>'TN', zip=>'37501'),
	array('city'=>'Baltimore', state=>'MD', zip=>'21201'),
);	
 
// Cleaning up the term
$term = trim(strip_tags($_GET['term']));
 
// Rudimentary search
$matches = array();
foreach($cities as $city){
	if(stripos($city['city'], $term) !== false){
		// Add the necessary "value" and "label" fields and append to result set
		$city['value'] = $city['city'];
		$city['label'] = "{$city['city']}, {$city['state']} {$city['zip']}";
		$matches[] = $city;
	}
}
 
// Truncate, encode and return the results
$matches = array_slice($matches, 0, 5);
print json_encode($matches);

Share Graphing Without Flash

Monday, May 10th, 2010

I put this deck together to explore SlideShare in more depth. Of course, meaningful content is always more helpful so this slideshow has a number of excellent tools for creating dynamic graphs without using Adobe Flash which is not supported by some devices.

The content from the slideshow, should anyone want to check out some of these really awesome tools.

SOLUTIONS
Generate Images Dynamically

Creating an image dynamically from your source data on the fly as the browser requests it. Lacking in interactivity but supported by any device that supports images.

HTML5 Canvas Tag

Not natively supported by IE, although support can be enabled through use of the ExplorerCanvas project. http://code.google.com/p/explorercanvas

SVG (Scaleable Vector Graphics)

Allows for rich user experiences while remaining lightweight. Native support in IE 9, plugins available for 8 and lower. Supported by all other major browser lines.

Create Images Dynamically
Hosted: Google Chart API http://code.google.com/apis/charttools
PHP: GraPHPite http://graphpite.sourceforge.net
PHP: pChart http://pchart.sourceforge.net
Python: Pychart http://home.gna.org/pychart
Java: EasyCharts http://www.objectplanet.com/easycharts
Java: ElegantJ Charts http://www.elegantjcharts.com
Java: JFreeChart http://www.jfree.org/jfreechart
.NET: Microsoft .net Chart Controls 
http://www.microsoft.com/downloads/details.aspx?FamilyID=130f7986-bf49-4fe5-9ca8-910ae6ea442c
.NET: .net Charting http://www.dotnetcharting.com
Silverlight: Microsoft Silverlight Toolkit http://www.silverlight.net

HTML5 Canvas: Some of these support SVG too
JS Charts http://www.jscharts.com
PlotKit http://www.liquidx.net/plotkit
Processing.js http://processingjs.org
Dojo Toolkit http://www.dojotoolkit.org
Bluff http://bluff.jcoglan.com
Canvas 3D Graph http://dragan.yourtree.org/code/canvas-3d-graph
TufteGraph (jQuery Based) http://xaviershay.github.com/tufte-graph
Emprise JavaScript Charts http://www.ejschart.com
Canvas Pie Chart with Tooltips (Mootools Based) 
http://blog.greghoustondesign.com/canvas-pie-chart-with-tooltips
MooChart (Mootools Based) http://moochart.coneri.se
InfoVis Toolkit http://thejit.org
Highcharts http://www.highcharts.com
Flot http://code.google.com/p/flot
Flotr Javascript Plotting Library (Prototype Based) 
http://solutoire.com/flotr
Graphico (Prototype + Raphael Based) http://grafico.kilianvalkhof.com

SVG
Raphael Javascript Library http://raphaeljs.com
SVG Kit http://svgkit.sourceforge.net
SVG Web http://code.google.com/p/svgweb
ProtoVis http://vis.stanford.edu/protovis

Share Keyboard Event Handling with FBJS

Thursday, February 19th, 2009

FBJS event handling does not follow the default Facebook JavaScript event handling model exactly. Facebook re-writes the event object as a far more limited object, meaning you have access to less information than you would in a true Javascript environment. If you’re looking for information on how browsers handle the onKey* events, quirksmode is a fantastic reference, albeit Windows centric. I ran into this yesterday while looking to improve a user interface. This following illustrates some of the potential gotchas to keep an eye out for.

Test Code

The following code will capture all events related to that form element and send them to the console log. This is going to be a whole lot of information, so note where you can dial it back as needed. For my project I was able to modify the str return value to just include the fields I was concerned with.

<script type="text/javascript">
function captureKeyboardEvent(e){
	var evt = e || window.event;
	var str = evt.type;
	// to make this less verbose - comment out the following 3 lines
	for (var property in evt){
		str += "\n  -" + property + " = " + evt[property];
	}
	console.log(str);
}
</script>
<form>
<input type="text" 
		onKeyPress="logEvent(event);" 
		onKeyDown="logEvent(event);"
		onKeyUp = "logEvent(event);"
		onFocus = "logEvent(event);"
		onBlur = "logEvent(event);"
	/>
</form>

Using Safari on a Mac produces the following output. What struck me as curious was the presence of pageX and pageY. As you can see the keyCode value is returned but not the charCode, timestamp or many other values as illustrated by the same code run without the benefit of the FBML parser.

keydown
 -type = keydown
 -ctrlKey = false
 -keyCode = 65
 -metaKey = false
 -shiftKey = false
 -target = [object Object]
 -pageX = NaN
 -pageY = NaN
 -__priv = 3
 -preventDefault = function () 
{
  var data = fbjs_private.get(this);
    ...
  data.return_value = false;
}
 -stopPropagation = function () 
{
  var event = fbjs_private.get(this).event;
    ...
    }
}
keydown
  -keyLocation = 0
  -ctrlKey = false
  -shiftKey = false
  -keyIdentifier = U+0041
  -altKey = false
  -metaKey = false
  -altGraphKey = false
  -pageY = 0
  -layerY = 0
  -pageX = 0
  -charCode = 0
  -view = [object DOMWindow]
  -which = 65
  -keyCode = 65
  -detail = 0
  -layerX = 0
  -returnValue = true
  -timeStamp = 1235049247482
  -eventPhase = 2
  -target = [object HTMLInputElement]
  -srcElement = [object HTMLInputElement]
  -type = keydown
  -clipboardData = undefined
  -cancelable = true
  -currentTarget = [object HTMLInputElement]
  -bubbles = true
  -cancelBubble = false
  -initKeyboardEvent = function initKeyboardEvent() {
    [native code]
}
  -initUIEvent = function initUIEvent() {
    [native code]
}
  -preventDefault = function preventDefault() {
    [native code]
}
  -initEvent = function initEvent() {
    [native code]
}
  -stopPropagation = function stopPropagation() {
    [native code]
}
  -MOUSEOUT = 8
  -FOCUS = 4096
  -CHANGE = 32768
  -MOUSEMOVE = 16
  -AT_TARGET = 2
  -SELECT = 16384
  -BLUR = 8192
  -KEYUP = 512
  -MOUSEDOWN = 1
  -MOUSEDRAG = 32
  -BUBBLING_PHASE = 3
  -MOUSEUP = 2
  -CAPTURING_PHASE = 1
  -MOUSEOVER = 4
  -CLICK = 64
  -DBLCLICK = 128
  -KEYDOWN = 256
  -KEYPRESS = 1024
  -DRAGDROP = 2048

Why does this matter?

If your creating code that looks at keypress input, there are some differences between browser implementations, what values are stored within the keyCode value and how Facebook passes those events on. In IE, Firefox and Safari, when a key is pressed down a keydown event is fired. When that key is released, a keyup event is fired. Pretty straightforward right? Here’s where it gets complicated.

As pointed out on Quirksmode, browsers handle the repeating event differently. Some place data in the charCode or keyCode values depending on context. Additionally, other modifier keys such as function and control keys are passed as boolean fields. However, we only get keyCode in FBJS. Furthermore, Safari and IE don’t ever raise the repeating keypress event like Firefox does, instead raising the keydown event only! However, Firefox does not raise the keydown event and the keypress event only passes back a keyCode of ’0′.

Share ‘Tis the Season of the New TV

Friday, December 12th, 2008

Classic Television Televisions are always a hot topic for holiday purchases and this year is no different. I was reviewing my Google Analytics numbers for AF-Design this morning and saw the annual spike in traffic to my television size calculator. This calculator is something I cobbled together one afternoon 3 or 4 years ago when trying to determine the amount of space a screen was going to take up. Surprisingly, every November and December, this page becomes one of the most visited pages on AF-Design. This year the spike is a little higher, probably due to the impending digital TV conversion. As such, I’ve created a minor update to the page to include optimal viewing distance for the screen size being calculated. Calculators of this nature are hardly complex to write, but apparently there’s a market for explaining them. Perhaps one day I’ll re-write the calculator to make it more flexible. Until then, enjoy shopping for that new set.

Share So That’s What Broke!

Thursday, November 27th, 2008

MySpace has a good post explaining why you can’t use relative links within OpenSocial applications. If you’re building for the OpenSocial container and trying to make valid HTML apps, watch out for this one. I’ve written the following in a lot of applications and suspect that others have as well. The #na below will cause problems, despite being valid markup.

<a href="#na" onClick="doJavascriptCall();">Click Me</a>

Consider the following ways to invoke functionality instead:

<a href="javascript:;" onClick="doJavascriptCall();">Click Me</a>
<div onClick="doJavascriptCall();">Click Me</div>

Share jQuery Autocomplete Plugin

Monday, October 20th, 2008

jQuery Logo jQuery users, take a look at the autocomplete plugin which is shipping in the UI framework. While there are some serious limitations to the currently plugin, it does provides a drop dead simple way to provide Google Suggest style functionality to your site users without significant overhead. It’s widely supported and weighs in at 78K (without data/css and markup) for the minified components.

My one complaint is the lack of JSON support for remotely fetched results. Currently you must return items for the suggest widget as plain text list. You can, however, currently parse individual lines (which could be objects). I expect the jQuery team will be adding this functionality soon enough. Jörn Zaefferer has built a modified version of the plugin that supports JSON. I’m holding out until it’s merged into the UI trunk to limit my sources of code updates in this instance.

Below is a quick example of the syntax so you can see how easy it is to create. The file, names.php, simply returns a series of names, 1 per line. This might be static or pulled from a database based on the passed “q” get parameter that holds the contents of the input area.

jQuery Autocomplete Plugin Screenshot

jQuery Autocomplete Plugin Screenshot

<link rel="stylesheet" href="css/jquery.autocomplete.css" type="text/css" />
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="ui.core.min.js"></script>
<script type="text/javascript" src="jquery.bgiframe.min.js"></script>
<script type="text/javascript" src="jquery.dimensions.min.js"></script>
<script type="text/javascript" src="ui.autocomplete.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
   $("#name").autocomplete("names.php");
});
</script>
<form>
   Name <input type="text" id="name" name="name" value="" /><input type="button" value="Go" />
</form>

Share Updated JavaScript UUID Generator v.0.3

Friday, September 5th, 2008

The JavaScript UUID Generator class has been refreshed again and is even more efficient than the 0.2 version due largely in part to heavier reliance on built in JavaScript functions. It’s still not a “REAL” UUID, but it’s good enough for most projects. The changes are as follows:

  • A leaner and more efficient returnBase(val, base) method for conversion to base16 strings. The original version from irt.org has been replaced with built in JavaScript methods. Some testing for your target platforms should be performed to ensure compatibility with your engine.
  • The change from randrange(min, max) in v.0.1 to rand(max) in 0.2 introduced a bug where the maximum value provided would never be matched. This has been fixed to correct for that issue.

Special thanks go out to Robert Kieffer for pointing out these issues and providing the updated code for the base 16 conversion.

Download the latest version.

View Code JAVASCRIPT
/*
uuid.js - Version 0.3
JavaScript Class to create a UUID like identifier
 
Copyright (C) 2006-2008, Erik Giberti (AF-Design), All rights reserved.
 
This program is free software; you can redistribute it and/or modify it under 
the terms of the GNU General Public License as published by the Free Software 
Foundation; either version 2 of the License, or (at your option) any later 
version.
 
This program is distributed in the hope that it will be useful, but WITHOUT ANY 
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License along with 
this program; if not, write to the Free Software Foundation, Inc., 59 Temple 
Place, Suite 330, Boston, MA 02111-1307 USA
 
The latest version of this file can be downloaded from
http://www.af-design.com/resources/javascript_uuid.php
 
HISTORY:
6/5/06 	- Initial Release
5/22/08 - Updated code to run faster, removed randrange(min,max) in favor of
          a simpler rand(max) function. Reduced overhead by using getTime() 
          method of date class (suggestion by James Hall).
9/5/08	- Fixed a bug with rand(max) and additional efficiencies pointed out 
	  by Robert Kieffer http://broofa.com/
 
KNOWN ISSUES:
- Still no way to get MAC address in JavaScript
- Research into other versions of UUID show promising possibilities 
  (more research needed)
- Documentation needs improvement
 
*/
 
// On creation of a UUID object, set it's initial value
function UUID(){
	this.id = this.createUUID();
}
 
// When asked what this Object is, lie and return it's value
UUID.prototype.valueOf = function(){ return this.id; }
UUID.prototype.toString = function(){ return this.id; }
 
//
// INSTANCE SPECIFIC METHODS
//
 
UUID.prototype.createUUID = function(){
	//
	// Loose interpretation of the specification DCE 1.1: Remote Procedure Call
	// described at http://www.opengroup.org/onlinepubs/009629399/apdxa.htm#tagtcjh_37
	// since JavaScript doesn't allow access to internal systems, the last 48 bits 
	// of the node section is made up using a series of random numbers (6 octets long).
	//  
	var dg = new Date(1582, 10, 15, 0, 0, 0, 0);
	var dc = new Date();
	var t = dc.getTime() - dg.getTime();
	var h = '-';
	var tl = UUID.getIntegerBits(t,0,31);
	var tm = UUID.getIntegerBits(t,32,47);
	var thv = UUID.getIntegerBits(t,48,59) + '1'; // version 1, security version is 2
	var csar = UUID.getIntegerBits(UUID.rand(4095),0,7);
	var csl = UUID.getIntegerBits(UUID.rand(4095),0,7);
 
	// since detection of anything about the machine/browser is far to buggy, 
	// include some more random numbers here
	// if NIC or an IP can be obtained reliably, that should be put in
	// here instead.
	var n = UUID.getIntegerBits(UUID.rand(8191),0,7) + 
			UUID.getIntegerBits(UUID.rand(8191),8,15) + 
			UUID.getIntegerBits(UUID.rand(8191),0,7) + 
			UUID.getIntegerBits(UUID.rand(8191),8,15) + 
			UUID.getIntegerBits(UUID.rand(8191),0,15); // this last number is two octets long
	return tl + h + tm + h + thv + h + csar + csl + h + n; 
}
 
 
//
// GENERAL METHODS (Not instance specific)
//
 
 
// Pull out only certain bits from a very large integer, used to get the time
// code information for the first part of a UUID. Will return zero's if there 
// aren't enough bits to shift where it needs to.
UUID.getIntegerBits = function(val,start,end){
	var base16 = UUID.returnBase(val,16);
	var quadArray = new Array();
	var quadString = '';
	var i = 0;
	for(i=0;i<base16.length;i++){
		quadArray.push(base16.substring(i,i+1));	
	}
	for(i=Math.floor(start/4);i<=Math.floor(end/4);i++){
		if(!quadArray[i] || quadArray[i] == '') quadString += '0';
		else quadString += quadArray[i];
	}
	return quadString;
}
 
// Replaced from the original function to leverage the built in methods in
// JavaScript. Thanks to Robert Kieffer for pointing this one out
UUID.returnBase = function(number, base){
	return (number).toString(base).toUpperCase();
}
 
// pick a random number within a range of numbers
// int b rand(int a); where 0 <= b <= a
UUID.rand = function(max){
	return Math.floor(Math.random() * (max + 1));
}
 
// end of UUID class file

Share Documentation of JavaScript DOM

Tuesday, August 5th, 2008

Just found this excellent resource outlining the DOM in JavaScript. It’s clear and to the point spelling out what methods and properties are supported by the major browsers. Thanks Mark for putting it together.

Share JavaScript UUID Generator v. 0.2

Thursday, May 22nd, 2008

Nearly 2 years ago I crafted some JavaScript code to create a properly formatted UUID in JavaScript. Full compliance with specification for version 1 UUID’s still isn’t possible. However, in the interest of keeping the project updated, I’ve made some changes to the code to make it more reliable and more efficient.

  • It now use getTime() from the date object. This reduced the time spent calculating unnecessary values for the timestamp (idea came from James Hall’s canonical name function).
  • The randrange() function was replaced with one that more evenly distributes the random number values while additionally reducing complexity.

Get the download here.

I’d also like to give a shout to some of the folks who have mentioned it in forums, ported it to different libraries, linked to it from Wikipedia, blogs etc and have generally made my efforts worth while. Thank You!

View Code JAVASCRIPT
/*
 
uuid.js - Version 0.2
JavaScript Class to create a UUID like identifier
 
Copyright (C) 2006-2008, Erik Giberti (AF-Design), All rights reserved.
 
This program is free software; you can redistribute it and/or modify it under 
the terms of the GNU General Public License as published by the Free Software 
Foundation; either version 2 of the License, or (at your option) any later 
version.
 
This program is distributed in the hope that it will be useful, but WITHOUT ANY 
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License along with 
this program; if not, write to the Free Software Foundation, Inc., 59 Temple 
Place, Suite 330, Boston, MA 02111-1307 USA
 
The latest version of this file can be downloaded from
http://www.af-design.com/resources/javascript_uuid.php
 
HISTORY:
6/5/06 	- Initial Release
5/22/08 - Updated code to run faster, removed randrange(min,max) in favor of
          a simpler rand(max) function. Reduced overhead by using getTime() 
          method of date class (suggestion by James Hall).
 
KNOWN ISSUES:
- Still no way to get MAC address in JavaScript
- Research into other versions of UUID show promising possibilities 
  (more research needed)
- Documentation needs improvement
 
*/
 
// On creation of a UUID object, set it's initial value
function UUID(){
	this.id = this.createUUID();
}
 
// When asked what this Object is, lie and return it's value
UUID.prototype.valueOf = function(){ return this.id; }
UUID.prototype.toString = function(){ return this.id; }
 
//
// INSTANCE SPECIFIC METHODS
//
 
UUID.prototype.createUUID = function(){
	//
	// Loose interpretation of the specification DCE 1.1: Remote Procedure Call
	// described at http://www.opengroup.org/onlinepubs/009629399/apdxa.htm#tagtcjh_37
	// since JavaScript doesn't allow access to internal systems, the last 48 bits 
	// of the node section is made up using a series of random numbers (6 octets long).
	//  
	var dg = new Date(1582, 10, 15, 0, 0, 0, 0);
	var dc = new Date();
	var t = dc.getTime() - dg.getTime();
	var h = '-';
	var tl = UUID.getIntegerBits(t,0,31);
	var tm = UUID.getIntegerBits(t,32,47);
	var thv = UUID.getIntegerBits(t,48,59) + '1'; // version 1, security version is 2
	var csar = UUID.getIntegerBits(UUID.rand(4095),0,7);
	var csl = UUID.getIntegerBits(UUID.rand(4095),0,7);
 
	// since detection of anything about the machine/browser is far to buggy, 
	// include some more random numbers here
	// if NIC or an IP can be obtained reliably, that should be put in
	// here instead.
	var n = UUID.getIntegerBits(UUID.rand(8191),0,7) + 
			UUID.getIntegerBits(UUID.rand(8191),8,15) + 
			UUID.getIntegerBits(UUID.rand(8191),0,7) + 
			UUID.getIntegerBits(UUID.rand(8191),8,15) + 
			UUID.getIntegerBits(UUID.rand(8191),0,15); // this last number is two octets long
	return tl + h + tm + h + thv + h + csar + csl + h + n; 
}
 
 
//
// GENERAL METHODS (Not instance specific)
//
 
 
// Pull out only certain bits from a very large integer, used to get the time
// code information for the first part of a UUID. Will return zero's if there 
// aren't enough bits to shift where it needs to.
UUID.getIntegerBits = function(val,start,end){
	var base16 = UUID.returnBase(val,16);
	var quadArray = new Array();
	var quadString = '';
	var i = 0;
	for(i=0;i<base16.length;i++){
		quadArray.push(base16.substring(i,i+1));	
	}
	for(i=Math.floor(start/4);i<=Math.floor(end/4);i++){
		if(!quadArray[i] || quadArray[i] == '') quadString += '0';
		else quadString += quadArray[i];
	}
	return quadString;
}
 
// Numeric Base Conversion algorithm from irt.org
// In base 16: 0=0, 5=5, 10=A, 15=F
UUID.returnBase = function(number, base){
	//
	// Copyright 1996-2006 irt.org, All Rights Reserved.	
	//
	// Downloaded from: http://www.irt.org/script/146.htm	
	// modified to work in this class by Erik Giberti
	var convert = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
    if (number < base) var output = convert[number];
    else {
        var MSD = '' + Math.floor(number / base);
        var LSD = number - MSD*base;
        if (MSD >= base) var output = this.returnBase(MSD,base) + convert[LSD];
        else var output = convert[MSD] + convert[LSD];
    }
    return output;
}
 
// pick a random number within a range of numbers
// int b rand(int a); where 0 <= b <= a
UUID.rand = function(max){
	return Math.floor(Math.random() * max);
}
 
// end of UUID class file
© 1998-2008 AF-Design, All rights reserved.