




$(document).ready(function(){

	$('div.okmsg').each(coolReveal);
	$('div.errormsg').each(coolReveal);
	$('tr.justupdated td').animate({ color: "black" }, 3000);




	initializeDatePickers();
	


	$('span.qDelivery').qtip({
	   	content: '<strong>Delivery Date Information:</strong><ul><li>At least two delivery dates are required.</li><li>If a date is inactive on the calendar then it is no longer available as a delivery date option.</li><li>For earlier delivery choices please choice the Priority, Express or Same Day Delivery Method.</li></ul>',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	$('span.qtax').qtip({
	   	content: 'Effective 06/01/2009, Nassau & Suffolk County have imposed a 2.5% tax on residential fuel delivery services and products. Further details are available at www.tax.state.ny.us.',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});

	$('a.qtipComingSoon').qtip({
	   	content: 'Coming Sept. 1st',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	$('span.qwoodtype').qtip({
	   	content: '<strong style="text-decoration:underline;">Kiln Dried :</strong><ul><li>Dried in lumber kilns (ovens).</li><li>Optimal moisture content of 10 to 18%.</li><li>True BTU ratings (= heat).</li><li>Store indoors or cover outside.</li></ul><br /><strong style="text-decoration:underline;">Air Dried :</strong><ul><li>Dried outdoors naturally via sun and wind.</li><li>Moisture content 20 to 40%.</li><li>BTU ratings less than full.</li><li>Cover top (for rain) & expose on sides.</li></ul><br /><strong style="text-decoration:underline;">Green :</strong><ul><li>Fresh split wood.</li><li>Moisture content above 40%.</li><li>Not ready for burning.</li><li>Will require full seasoning.</li></ul>',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	$('span.qspecies').qtip({
	   	content: '<strong style="text-decoration:underline;">Mixed Hardwoods :</strong><ul><li>Consists of various hardwood species.</li><li>% of species will change according to availability.</li></ul><br /><strong style="text-decoration:underline;">100 % (species) :</strong><ul><li>One single type of wood.</li><li>Our list of available species varies throughout the season.</li></ul>',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	$('span.qbtu').qtip({
	   	content: '<strong style="text-decoration:underline;">BTU Rating :</strong><ul><li><strong>B</strong>ritish <strong>T</strong>hermal <strong>U</strong>nit for measuring heat.</li><li>Optimal moisture content (< 20%) required for full BTU output.</li><li>Softwoods measure from 12 to 17</li><li>Hardwoods measure from 15 to 27</li></ul>',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});

	$('span.qsd').qtip({
	   	content: '<strong style="text-decoration:underline;">Split Diameter :</strong><ul><li>Info coming soon.</li></ul>',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	$('span.qru').qtip({
	   	content: '<strong style="text-decoration:underline;">Recommended Use :</strong><ul><li>Info coming soon.</li></ul>',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
		
	$('span.qlength').qtip({
	   	content: '<strong style="text-decoration:underline;">Length :</strong><ul><li>Industry standard is 15 to 16 inches.</li><li>Stove cut is 12 to 14 inches.</li><li>Fireplace cut is 24" or more inches.</li></ul>',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	$('span.qvolume').qtip({
	   	content: '<strong style="text-decoration:underline;">Volume :</strong><ul><li>Measure of (length) x (width) x (height) when wood is stacked loosely.</li><li>A defined legal cord is 128 cu ft.</li><li>A "face" cord should be 42 cu ft.</li><li>A store bought bundle or bag is 0.75 cu ft.</li></ul>',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	$('span.qpackaging').qtip({
	   	content: '<strong style="text-decoration:underline;">Loose :</strong><ul><li>The wood has not been packaged and will be delivered in a pile.</li></ul><strong style="text-decoration:underline;">Wrapped Pallet</strong><ul><li>The wood has been stacked on a pallet and then wrapped.</li><li>Pricing includes dumping the wood loose off the pallet.</li><li>For an additional fee the intact unit will be offloaded onto any level hard surface.</li></ul><strong style="text-decoration:underline;">Polypro Bag :</strong><ul><li>This breathable opaque bag can be opened and reclosed.</li><li>Can be stored up to 6 months.</li><li>The bag is very durable and reusable.</li></ul><strong style="text-decoration:underline;">Polyeth Bag :</strong><ul><li>Clear plastic bag with handle.</li><li>May be stored up to 1 year.</li><li>Disposable one time use.</li></ul><strong style="text-decoration:underline;">Bundle :</strong><ul><li>Wrapped on ends with handle affixed.</li><li>Can be stored indefinitely.</li><li>One time use, less waste.</li></ul><strong style="text-decoration:underline;">Container :</strong><ul><li>Poly nursery container.</li><li>Used for measurement &amp; delivery.</li><li>Can be purchased for additional fee.</li></ul>',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	
	
	
	
	
	
	$('span.qpaytype').qtip({
	   	content: 'We currently accept payment by Visa and MasterCard through our online order system.',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	$('span.qcvv2').qtip({
	   	content: 'The CVV2 Security Code appears as a 3 digit code in the signature strip on the back of a Visa, MasterCard, or Discover Card. For Amex Cards the CVV2 Security Code appears as a 4 digit code on the front of the card.',
		style: {
			      	border: {
				         width: 3,
				         radius: 8,
				         color: '#edde84'
			      	},
			      	tip: 'topLeft'			
			}
	});
	
	
	
	
	
	/*
	$('div.cat div.hider').slideToggle(1000);
	$('div.cat h3 a.hidertogglelink').click(function() {
		oLink = $(this);
		oHiderDiv = oLink.parent().parent().find('div.hider');
		
		sCurHtml = oLink.html();
		iProdCount = oLink.attr('rel');
		if (sCurHtml.indexOf('hide') === -1) {
			oLink.html('[&ndash;] hide extra items');
		} else {
			oLink.html('[+] view all ' + iProdCount + ' items');
		}
		
		oHiderDiv.slideToggle(1000);
		return false;
	});
	$('div.cat h3 a.hidertogglelinkMain').click(function() {
		oLink = $(this);
		oOtherLink = oLink.parent().find('a.hidertogglelink');
		oHiderDiv = oLink.parent().parent().find('div.hider');
		
		sCurHtml = oOtherLink.html();
		iProdCount = oOtherLink.attr('rel');
		if (sCurHtml.indexOf('hide') === -1) {
			oOtherLink.html('[&ndash;] hide extra items');
		} else {
			oOtherLink.html('[+] view all ' + iProdCount + ' items');
		}
		
		oHiderDiv.slideToggle(1000);
		return false;
	});
	*/
	
	
	
			
	
	initLightbox();
	
	$('A[rel="external"]').click( function() {
		window.open( $(this).attr('href') );
		return false;
	});	
	
});

function coolReveal()
{
	$(this).hide();
	$(this).slideDown('slow');
}





function initializeDatePickers()
{
	iDAYS_STAN = iSTD_DELIVERY_NUM_DAYS; // this value is populated in javascript code in the hamptons-firewood-checkout.php file
	iDAYS_PRIO = 2;
	iDAYS_NEXT = 1;
	iDAYS_SAME = 0;
	
	sDeliveryMethod = $('select#sDeliveryMethod').val();
	iDaysFromCurrentToPrevent = iDAYS_STAN;
	
	if (sDeliveryMethod == 'Standard')
	{
		iDaysFromCurrentToPrevent = iDAYS_STAN;
	}
	else if (sDeliveryMethod == 'Priority')
	{
		iDaysFromCurrentToPrevent = iDAYS_PRIO;
	}
	else if (sDeliveryMethod == 'Next Day')
	{
		iDaysFromCurrentToPrevent = iDAYS_NEXT;
	}
	else if (sDeliveryMethod == 'Same Day')
	{
		iDaysFromCurrentToPrevent = iDAYS_SAME;
	}	
	
	defaultDate = new Date(2009, 9-1, 18);
	properDate = new Date();
	properDate.setDate(properDate.getDate() + iDaysFromCurrentToPrevent);
	if (properDate > defaultDate)
	{
		defaultDate = properDate;
	}
	
	$("#sDeliveryDay1").datepicker('destroy').datepicker({ beforeShowDay: checkDays, defaultDate: defaultDate, minDate: '+' + iDaysFromCurrentToPrevent + 'D', maxDate: '+6M'});
	$("#sDeliveryDay2").datepicker('destroy').datepicker({ beforeShowDay: checkDays, defaultDate: defaultDate, minDate: '+' + iDaysFromCurrentToPrevent + 'D', maxDate: '+6M'});
	$("#sDeliveryDay3").datepicker('destroy').datepicker({ beforeShowDay: checkDays, defaultDate: defaultDate, minDate: '+' + iDaysFromCurrentToPrevent + 'D', maxDate: '+6M'});	
}




function handleDeliveryMethodChange()
{
	sDeliveryMethod = $('select#sDeliveryMethod').val();
	
	fPriceSub = $('input#checkoutform_PriceSub').val();
	fPriceDel = $('input#checkoutform_PriceDelivery').val();
	fPriceDelBase = $('input#checkoutform_PriceDeliveryBase').val();
	fPriceTax = $('input#checkoutform_PriceTax').val();
	fPriceGrand = $('input#checkoutform_PriceGrand').val();
	
	//alert('...' + fPriceSub + '...' + fPriceDel + '...' + fPriceDelBase + '...' + fPriceTax + '...' + fPriceGrand + '...');
	
	iAdjustDel = 0;
	if (sDeliveryMethod == 'Standard')
	{
		iAdjustDel = 0;
	}
	else if (sDeliveryMethod == 'Priority')
	{
		iAdjustDel = fCHARGE_SHIP_METHOD_PRIO;
	}
	else if (sDeliveryMethod == 'Next Day')
	{
		iAdjustDel = fCHARGE_SHIP_METHOD_NEXT;
	}
	else if (sDeliveryMethod == 'Same Day')
	{
		iAdjustDel = fCHARGE_SHIP_METHOD_SAME;
	}
	
	fPriceNewDel = parseFloat(fPriceDelBase) + parseFloat(iAdjustDel);
	fPriceNewGrand = parseFloat(fPriceSub) + parseFloat(fPriceNewDel) + parseFloat(fPriceTax);

	//alert('...' + fPriceNewDel + '...' + fPriceNewGrand + '...');
		
	oPriceMainDelivery = $('span.PriceMainDelivery');
	oPriceMainGrand = $('span.PriceMainGrand');
	oPriceSpotlightGrand = $('span.PriceSpotlightGrand');
	
	oPriceMainDelivery.html('$' + CurrencyFormatted(fPriceNewDel));
	oPriceMainGrand.html('$' + CurrencyFormatted(fPriceNewGrand));
	oPriceSpotlightGrand.html('$' + CurrencyFormatted(fPriceNewGrand));
	
	initializeDatePickers();
}



function CurrencyFormatted(amount)
{
	var i = parseFloat(amount);
	if(isNaN(i)) { i = 0.00; }
	var minus = '';
	if(i < 0) { minus = '-'; }
	i = Math.abs(i);
	i = parseInt((i + .005) * 100);
	i = i / 100;
	s = new String(i);
	if(s.indexOf('.') < 0) { s += '.00'; }
	if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
	s = minus + s;
	return s;
}



function checkDays(date)
{
	iTheDateYear = date.getYear() + 1900;
	iTheDateMonth = date.getMonth() + 1;
	iTheDateDay = date.getDate();
	iTheDayOfWeek = date.getDay();
	myDays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
	sTheDayOfWeek = myDays[iTheDayOfWeek];

	currentDate = new Date();
	currentYear = currentDate.getYear() + 1900;
	currentMonth = currentDate.getMonth() + 1;
	currentDay = currentDate.getDate();
	
	futureDate = new Date();
	futureDate.setMonth(futureDate.getMonth() + 4);
		
	//alert('...' + date + '...' + iTheDateYear + '...' + iTheDateMonth + '...' + iTheDateDay + '...');
	
	if (iTheDateYear < 2009)
	{
		// before 2009
		return [false, ''];
	}
	/*
	else if (iTheDateYear == 2009 && iTheDateMonth < 9)
	{
		// before september 2009
		return [false, ''];
	}
	else if (iTheDateYear == 2009 && iTheDateMonth == 9 && iTheDateDay < 18)
	{
		// before september 18 2009
		return [false, ''];
	}
	else if (date < currentDate)
	{
		// before current date
		return [false, ''];
	}
	else if (date > futureDate)
	{
		// more than 3 months in the future
		return [false, ''];	
	}
	*/
	else if (iTheDateMonth == 12 && iTheDateDay == 25)
	{
		// christmas
		return [false, ''];
	}
	else if (iTheDateMonth == 11 && iTheDateDay == findThanksgivingDayByYear(iTheDateYear))
	{
		// thanksgiving
		return [false, ''];
	}
	else if (isDateOnBlackoutList(iTheDateMonth + '/' + iTheDateDay + '/' + iTheDateYear))
	{
		// date is in blackout list
		return [false, ''];
	}
	/*
	else if (!( sTheDayOfWeek == 'Tuesday' || sTheDayOfWeek == 'Thursday' || sTheDayOfWeek == 'Sunday' ))
	{
		// date is not one of the supported days of the week
		return [false, ''];
	}
	*/

	return [true, ''];
}

function findThanksgivingDayByYear(year)
{
	var delta = year - 1900;
	var doomsday = delta % 12;
	doomsday = (doomsday + Math.floor(doomsday/4) + Math.floor(delta/12)) % 7;
	return (doomsday == 0)? 28 : (29 - doomsday);
}



function handleFinalClick()
{
	return true;
}

function handleZipClick()
{
	oHidZip = $('input#cartform_zip');
	oHidZip.val('true');
	return true;
}

function handleCheckoutClick()
{
	oHidCheckout = $('input#cartform_checkout');
	oHidCheckout.val('true');
	return true;
}

function handleRemoveClick(oThis)
{
	oHidRemove = $('input#cartform_remove');
	oClickedInput = $(oThis);
	iProdId = oClickedInput.attr('name').substring(7);
	oHidRemove.val(iProdId);
	return true;
}

function handleContinueClick()
{
	document.location = '/hamptons-firewood.php';
	return false;
}

function hideShowDeliveryDateRows()
{
	//var oRows1 = $('.deliveryDayRow1');
	var oRows2 = $('.deliveryDayRow2');
	var oRows3 = $('.deliveryDayRow3');
	var sDeliveryMethod = $('#sDeliveryMethod').val();
	
	oRows2.show();
	oRows3.show();
	
	if (sDeliveryMethod == 'Priority')
	{
		oRows2.hide();
		oRows3.hide();
	}
	else if (sDeliveryMethod == 'Next Day')
	{
		oRows2.hide();
		oRows3.hide();
	}
	else if (sDeliveryMethod == 'Same Day')
	{
		oRows2.hide();
		oRows3.hide();
	}
}




	function strtotime (str, now) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Caio Ariede (http://caioariede.com)
	    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +      input by: David
	    // +   improved by: Caio Ariede (http://caioariede.com)
	    // +   improved by: Brett Zamir (http://brett-zamir.me)
	    // +   bugfixed by: Wagner B. Soares
	    // +   bugfixed by: Artur Tchernychev
	    // %        note 1: Examples all have a fixed timestamp to prevent tests to fail because of variable time(zones)
	    // *     example 1: strtotime('+1 day', 1129633200);
	    // *     returns 1: 1129719600
	    // *     example 2: strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200);
	    // *     returns 2: 1130425202
	    // *     example 3: strtotime('last month', 1129633200);
	    // *     returns 3: 1127041200
	    // *     example 4: strtotime('2009-05-04 08:30:00');
	    // *     returns 4: 1241418600
	 
	    var i, match, s, strTmp = '', parse = '';
	 
	    strTmp = str;
	    strTmp = strTmp.replace(/\s{2,}|^\s|\s$/g, ' '); // unecessary spaces
	    strTmp = strTmp.replace(/[\t\r\n]/g, ''); // unecessary chars
	 
	    if (strTmp == 'now') {
	        return (new Date()).getTime()/1000; // Return seconds, not milli-seconds
	    } else if (!isNaN(parse = Date.parse(strTmp))) {
	        return (parse/1000);
	    } else if (now) {
	        now = new Date(now*1000); // Accept PHP-style seconds
	    } else {
	        now = new Date();
	    }
	 
	    strTmp = strTmp.toLowerCase();
	 
	    var __is =
	    {
	        day:
	        {
	            'sun': 0,
	            'mon': 1,
	            'tue': 2,
	            'wed': 3,
	            'thu': 4,
	            'fri': 5,
	            'sat': 6
	        },
	        mon:
	        {
	            'jan': 0,
	            'feb': 1,
	            'mar': 2,
	            'apr': 3,
	            'may': 4,
	            'jun': 5,
	            'jul': 6,
	            'aug': 7,
	            'sep': 8,
	            'oct': 9,
	            'nov': 10,
	            'dec': 11
	        }
	    };
	 
	    var process = function (m) {
	        var ago = (m[2] && m[2] == 'ago');
	        var num = (num = m[0] == 'last' ? -1 : 1) * (ago ? -1 : 1);
	 
	        switch (m[0]) {
	            case 'last':
	            case 'next':
	                switch (m[1].substring(0, 3)) {
	                    case 'yea':
	                        now.setFullYear(now.getFullYear() + num);
	                        break;
	                    case 'mon':
	                        now.setMonth(now.getMonth() + num);
	                        break;
	                    case 'wee':
	                        now.setDate(now.getDate() + (num * 7));
	                        break;
	                    case 'day':
	                        now.setDate(now.getDate() + num);
	                        break;
	                    case 'hou':
	                        now.setHours(now.getHours() + num);
	                        break;
	                    case 'min':
	                        now.setMinutes(now.getMinutes() + num);
	                        break;
	                    case 'sec':
	                        now.setSeconds(now.getSeconds() + num);
	                        break;
	                    default:
	                        var day;
	                        if (typeof (day = __is.day[m[1].substring(0, 3)]) != 'undefined') {
	                            var diff = day - now.getDay();
	                            if (diff == 0) {
	                                diff = 7 * num;
	                            } else if (diff > 0) {
	                                if (m[0] == 'last') {diff -= 7;}
	                            } else {
	                                if (m[0] == 'next') {diff += 7;}
	                            }
	                            now.setDate(now.getDate() + diff);
	                        }
	                }
	                break;
	 
	            default:
	                if (/\d+/.test(m[0])) {
	                    num *= parseInt(m[0], 10);
	 
	                    switch (m[1].substring(0, 3)) {
	                        case 'yea':
	                            now.setFullYear(now.getFullYear() + num);
	                            break;
	                        case 'mon':
	                            now.setMonth(now.getMonth() + num);
	                            break;
	                        case 'wee':
	                            now.setDate(now.getDate() + (num * 7));
	                            break;
	                        case 'day':
	                            now.setDate(now.getDate() + num);
	                            break;
	                        case 'hou':
	                            now.setHours(now.getHours() + num);
	                            break;
	                        case 'min':
	                            now.setMinutes(now.getMinutes() + num);
	                            break;
	                        case 'sec':
	                            now.setSeconds(now.getSeconds() + num);
	                            break;
	                    }
	                } else {
	                    return false;
	                }
	                break;
	        }
	        return true;
	    };
	 
	    match = strTmp.match(/^(\d{2,4}-\d{2}-\d{2})(?:\s(\d{1,2}:\d{2}(:\d{2})?)?(?:\.(\d+))?)?$/);
	    if (match != null) {
	        if (!match[2]) {
	            match[2] = '00:00:00';
	        } else if (!match[3]) {
	            match[2] += ':00';
	        }
	 
	        s = match[1].split(/-/g);
	 
	        for (i in __is.mon) {
	            if (__is.mon[i] == s[1] - 1) {
	                s[1] = i;
	            }
	        }
	        s[0] = parseInt(s[0], 10);
	 
	        s[0] = (s[0] >= 0 && s[0] <= 69) ? '20'+(s[0] < 10 ? '0'+s[0] : s[0]+'') : (s[0] >= 70 && s[0] <= 99) ? '19'+s[0] : s[0]+'';
	        return parseInt(this.strtotime(s[2] + ' ' + s[1] + ' ' + s[0] + ' ' + match[2])+(match[4] ? match[4]/1000 : ''), 10);
	    }
	 
	    var regex = '([+-]?\\d+\\s'+
	        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
	        '|sun\.?|sunday|mon\.?|monday|tue\.?|tuesday|wed\.?|wednesday'+
	        '|thu\.?|thursday|fri\.?|friday|sat\.?|saturday)'+
	        '|(last|next)\\s'+
	        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
	        '|sun\.?|sunday|mon\.?|monday|tue\.?|tuesday|wed\.?|wednesday'+
	        '|thu\.?|thursday|fri\.?|friday|sat\.?|saturday))'+
	        '(\\sago)?';
	 
	    match = strTmp.match(new RegExp(regex, 'g'));
	    if (match == null) {
	        return false;
	    }
	 
	    for (i = 0; i < match.length; i++) {
	        if (!process(match[i].split(' '))) {
	            return false;
	        }
	    }
	 
	    return (now.getTime()/1000);
	}	

function trim(str)
{
	return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}	

var dateFormat = function () {
	var	token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
		timezoneClip = /[^-+\dA-Z]/g,
		pad = function (val, len) {
			val = String(val);
			len = len || 2;
			while (val.length < len) val = "0" + val;
			return val;
		};

	// Regexes and supporting functions are cached through closure
	return function (date, mask, utc) {
		var dF = dateFormat;

		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
		if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
			mask = date;
			date = undefined;
		}

		// Passing date through Date applies Date.parse, if necessary
		date = date ? new Date(date) : new Date;
		if (isNaN(date)) throw SyntaxError("invalid date");

		mask = String(dF.masks[mask] || mask || dF.masks["default"]);

		// Allow setting the utc argument via the mask
		if (mask.slice(0, 4) == "UTC:") {
			mask = mask.slice(4);
			utc = true;
		}

		var	_ = utc ? "getUTC" : "get",
			d = date[_ + "Date"](),
			D = date[_ + "Day"](),
			m = date[_ + "Month"](),
			y = date[_ + "FullYear"](),
			H = date[_ + "Hours"](),
			M = date[_ + "Minutes"](),
			s = date[_ + "Seconds"](),
			L = date[_ + "Milliseconds"](),
			o = utc ? 0 : date.getTimezoneOffset(),
			flags = {
				d:    d,
				dd:   pad(d),
				ddd:  dF.i18n.dayNames[D],
				dddd: dF.i18n.dayNames[D + 7],
				m:    m + 1,
				mm:   pad(m + 1),
				mmm:  dF.i18n.monthNames[m],
				mmmm: dF.i18n.monthNames[m + 12],
				yy:   String(y).slice(2),
				yyyy: y,
				h:    H % 12 || 12,
				hh:   pad(H % 12 || 12),
				H:    H,
				HH:   pad(H),
				M:    M,
				MM:   pad(M),
				s:    s,
				ss:   pad(s),
				l:    pad(L, 3),
				L:    pad(L > 99 ? Math.round(L / 10) : L),
				t:    H < 12 ? "a"  : "p",
				tt:   H < 12 ? "am" : "pm",
				T:    H < 12 ? "A"  : "P",
				TT:   H < 12 ? "AM" : "PM",
				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
			};

		return mask.replace(token, function ($0) {
			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
		});
	};
}();

// Some common format strings
dateFormat.masks = {
	"default":      "ddd mmm dd yyyy HH:MM:ss",
	shortDate:      "m/d/yy",
	mediumDate:     "mmm d, yyyy",
	longDate:       "mmmm d, yyyy",
	fullDate:       "dddd, mmmm d, yyyy",
	shortTime:      "h:MM TT",
	mediumTime:     "h:MM:ss TT",
	longTime:       "h:MM:ss TT Z",
	isoDate:        "yyyy-mm-dd",
	isoTime:        "HH:MM:ss",
	isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
	isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};

// Internationalization strings
dateFormat.i18n = {
	dayNames: [
		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
	],
	monthNames: [
		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
	]
};

// For convenience...
Date.prototype.format = function (mask, utc) {
	return dateFormat(this, mask, utc);
};


	
	
