var GUID = function() {
    try {
		// for IE users, we can use a built-in ActiveX object to retrive a GUID and trim it to 38 characters to more closely resemble a GUID.
		if( window.ActiveXObject ) {
			this.id = (new ActiveXObject('Scriptlet.TypeLib').GUID).substr(1, 36);
		} else {
			this.id = this.createGUID();
		}		
	} catch (e) {
		// on creation of a GUID object, set it's initial value
		this.id = this.createGUID();
	}
}
GUID.prototype.valueOf = function(){ return this.id; };
GUID.prototype.toString = function(){ return this.id; };
GUID.prototype.createGUID = function() {
  	var dg = new Date(1582, 10, 15, 0, 0, 0, 0).getTime();
  	var dc = new Date().getTime();
  	var t = (dg < 0) ? Math.abs(dg) + dc : dc - dg;
  	var h = '-';
  	var tl = GUID.getIntegerBits(t, 0, 31);
  	var tm = GUID.getIntegerBits(t, 32, 47);
  	var thv = GUID.getIntegerBits(t, 48, 59) + '1'; // version 1, security version is 2
  	var csar = GUID.getIntegerBits(Math.randRange(0, 4095), 0, 7);
  	var csl = GUID.getIntegerBits(Math.randRange(0, 4095), 0, 7);
  
  	var n = GUID.getIntegerBits(Math.randRange(0, 8191), 0, 7) + 
  			GUID.getIntegerBits(Math.randRange(0, 8191), 8, 15) + 
  			GUID.getIntegerBits(Math.randRange(0, 8191), 0, 7) + 
  			GUID.getIntegerBits(Math.randRange(0, 8191), 8, 15) + 
  			GUID.getIntegerBits(Math.randRange(0, 8191), 0, 15); // this last number is two octets long
  	return tl + h + tm + h + thv + h + csar + csl + h + n; 
}

GUID.getIntegerBits = function(val, start, end) {
    var base16 = GUID.returnBase(val, 16);
    var quadArray = base16.split('');
    var quadString = '';
    var i = 0;
    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;
}

// In base 16: 0=0, 5=5, 10=A, 15=F
GUID.returnBase = function(number, base) {
    return number.toString(base).toUpperCase();
}

Math.randRange = function(min, max) {
	return Math.max(Math.min(Math.round(Math.random() * max), max), min);
};