/*
	Date Format 1.1
	(c) 2007 Steven Levithan <stevenlevithan.com>
	MIT license
	With code by Scott Trenda (Z and o flags, and enhanced brevity)
	http://blog.stevenlevithan.com/archives/date-time-format
*/

/*** dateFormat
	Accepts a date, a mask, or a date and a mask.
	Returns a formatted version of the given date.
	The date defaults to the current date/time.
	The mask defaults ``"ddd mmm d yyyy HH:MM:ss"``.
*/
var dateFormat = function () {
	var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloZ]|"[^"]*"|'[^']*'/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 (value, length) {
			value = String(value);
			length = parseInt(length) || 2;
			while (value.length < length)
				value = "0" + value;
			return value;
		};

	// Regexes and supporting functions are cached through closure
	return function (date, mask) {
		// Treat the first argument as a mask if it doesn't contain any numbers
		if (
			arguments.length == 1 &&
			(typeof date == "string" || date instanceof String) &&
			!/\d/.test(date)
		) {
			mask = date;
			date = undefined;
		}

		date = date ? new Date(date) : new Date();
		if(!date) return 'invalid date';

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

		var	d = date.getDate(),
			D = date.getDay(),
			m = date.getMonth(),
			y = date.getFullYear(),
			H = date.getHours(),
			M = date.getMinutes(),
			s = date.getSeconds(),
			L = date.getMilliseconds(),
			o = 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:    (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4)
			};

		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 d 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",
	isoFullDateTime: "yyyy-mm-dd'T'HH:MM:ss.lo"
};

// Internationalization strings
dateFormat.i18n = {
	dayNames: [
		"Sun", "Mon", "Tue", "Wed", "Thr", "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) {
	return dateFormat(this, mask);
}


/**
 * Date Time processor for parsing dates in the form of:
 * Mon, 25 Feb 2008 03:09:22 GMT
 *
 * By default, if a timestamp is within a month, time will be displayed as
 * x days, x months ago. If the timestamp flag is used, it will be either
 * today, tomorrow or a timestamp
 *
 * Possible classes:
 * timestamp  	-  show a timestamp, regardless of when the time was
 * abbr       	-  abbreviates time unit names
 * descr		  	-  append either "ago" or "remaining"
 * notime    	-  ommits time from the display, supported with timestamp
 * timeonly  	-  shows only the time, only works with timestamp
 * printable 	-  adds a span.print version of the time for printable formats
 */
(function() {

	// the units we are using to calculate time differences
	var units = {
		year: 60 * 60 * 24 * 365,
		month: 60 * 60 * 24 * 30,
		week: 60 * 60 * 24 * 7,
		day: 60 * 60 * 24,
		hour: 60 * 60,
		minute: 60,
		second: 1
	};

	// define some abbreviations
	var abbrs = {
		year:'yr', month:'mth', hour:'hr',
		minute:'min', second:'sec'
	};

	// finds the biggest unit possible in the seconds, returns a tuple with
	// the unit, the quantity and the number of seconds to decrement by
	var findBiggestUnit = function(seconds) {
		for (var key in units) {
			var qty = Math.floor(seconds / units[key]);
			if(qty != 0) return [key,qty,units[key] * qty];
		}
	}

	// calculates the time difference between two times
	var timeDifference = function(time1, time2) {
		var elapsed = Math.abs((time2.getTime() - time1.getTime()) / 1000);
		var tokens = [];

		// break into chunks of time, in descending order
		while(!isNaN(elapsed) && (chunk = findBiggestUnit(elapsed))) {
			suffix = chunk[1] > 1 ? 's' : '';
			tokens.push(chunk[1] + ' ' + chunk[0] + suffix);
			elapsed -= chunk[2];
		}

		return tokens;
	}

	// returns true if an element has a particular class
	var hasClass = function(element, className) {
		return (
			element.className &&
			element.className.match( new RegExp( "\\b"+className+"\\b" ) )
			) ? true : false;
	}

	// gets the first text node that is a direct child of the span
	var findSpanTextNode = function(element) {
		for(var i=0; i<element.childNodes.length; i++) {
			if(element.childNodes[i].nodeType == 3) {
				return element.childNodes[i];
			}
		}
	}

	// calculates the difference in two dates in days
	var getDifferenceInDays = function(date1, date2) {
		var date2 = !date2 ? new Date() : date2;
		return (date1.getTime()-date2.getTime()) / (1000 * 60 * 60 * 24);
	}

	// formats the timestamp, optionally uses the dateformat library
	var formatTimestamp = function(time,config) {
		var now = new Date();
		var today = new Date(now.getFullYear(), now.getMonth(),
			now.getDate());
		var yesterday = new Date(now.getFullYear(), now.getMonth(),
			now.getDate()-1);
		var tomorrow = new Date(today.getTime() + 24*3600000);

		// calculate time
		var timetext = ', ' + time.getHours() + ':' +
			((time.getMinutes()>10) ? time.getMinutes() : '0' + time.getMinutes());

		if (!config.formatDate) {
			// display a short time if we can
			if(time.getTime() >= (tomorrow.getTime()+24*3600000)) {
				// do nothing for future times
			} else if(time.getTime() >= tomorrow.getTime()) {
				return 'tomorrow' + (config.notime ? '' : timetext);
			} else if(time.getTime() >= today.getTime()) {
				return 'today' + (config.notime ? '' : timetext);
			} else if(time.getTime() >= yesterday.getTime()) {
				return 'yesterday' + (config.notime ? '' : timetext);
			}
		}

		// fall back to a date string
		if(typeof(dateFormat) == 'function') {
			if(config.notime) {
				var monthMask = config.abbreviate ? 'mmm' : 'mmmm';
				var mask = monthMask + ' d, yyyy';
			} else if(config.timeonly) {
				var mask = 'h:MM tt';
			} else if (config.formatDate) {
				var mask = 'h:MM tt ddd d mmm';
			} else {
				var monthMask = config.abbreviate ? 'mmm' : 'mmmm';
				var mask = monthMask + ' d, yyyy h:MM tt';
			}
			return dateFormat(time, mask);
		} else {
			return time.toLocaleString();
		}
	}

	// gets a date object parsed from the span
	var getSpanDate = function(span) {
		var node = findSpanTextNode(span);
		if(!node) return false;
		return span.gmttime ? span.gmttime : new Date(Date.parse(node.nodeValue));
	}

	// process a span with a class of gmttime
	var formatSpan = function(span) {
		var dateString = '';
		var date = getSpanDate(span);
		if(!date) return false;

		var dayDiff = getDifferenceInDays(date);
		var since = dayDiff < 0;

		var config = {
			relative: !hasClass(span, 'timestamp'),
			abbreviate: !hasClass(span, 'timestamp') && hasClass(span,'abbr'),
			timeonly: hasClass(span, 'timeonly'),
			describe: hasClass(span, 'descr') || hasClass(span, 'desc'),
			notime: hasClass(span, 'notime'),
			print: hasClass(span, 'printable'),
			noSeconds: hasClass(span, 'noseconds'),
			formatDate: hasClass(span, 'formatdate'),
			withTitle: hasClass(span, 'withTitle')
		}


		// override relative if the date is more than 28 days old
		if(Math.abs(dayDiff) > 28) config.relative = false;

		// don't show seconds unit
		if (config.noSeconds) {
			delete units.second;
		}

		if(!config.relative) {
			dateString = formatTimestamp(date, config);
		} else if(config.relative && since) {
			dateString = timeDifference(date, new Date())
				.slice(0,2).join(', ');
		} else {
			dateString = timeDifference(date, new Date())
				.slice(0,2).join(', ');
		}

		if(!dateString) {
			dateString = formatTimestamp(date, config);
		} else if(config.describe && config.relative) {
			dateString += since ? ' ago' : ' remaining';
		}

		// optionally use abbreviations
		if(config.abbreviate) {
			for(var a in abbrs) dateString = dateString.replace(a, abbrs[a]);
		}

		// set the title
		if (config.withTitle) {
			span.title = dateString;
		}
		else {
			span.title = date.toLocaleString();
		}

		span.gmttime = date;

		// replace the value with the formatted time
		var textNode = findSpanTextNode(span);

		screenSpan = document.createElement('span');
		screenSpan.className = 'screen';
		screenSpan.appendChild(document.createTextNode(dateString));
		span.replaceChild(screenSpan,textNode);

		// optionally, add a print only version
		if(config.print) {
			printSpan = document.createElement('span');
			printSpan.className = 'print';
			printSpan.appendChild(document.createTextNode(date.toLocaleString()));
			span.insertBefore(printSpan,screenSpan);
		}
	}

	// function that sets up a span
	var initializeSpan = function(span) {
		// bind some functions to the span
		span.getDate = function() {return getSpanDate(this);}
		span.format = function() {return formatSpan(this);}

		// process the span
		span.format();
	}

	// process span.gmttime
	if(window.jQuery) {

		// add a jQuery plugin
		jQuery.fn.dateTime = function() {
			return this.each(function(){
				initializeSpan(this);
			});
		};

		// process each span
		jQuery('span.gmttime').dateTime();

	// otherwise, do it the old fashioned way
	} else {
		var spans = document.getElementsByTagName('span');
		for(i=0; i<spans.length; i++) {
			if(hasClass(spans[i], 'gmttime')) initializeSpan(spans[i]);
		}
	}

}());
var HMoney = HMoney || {};

// US Timezones
HMoney.EASTERN_STANDARD_TIME_OFFSET = -5;
HMoney.CENTRAL_STANDARD_TIME_OFFSET = -6;
HMoney.MOUNTAIN_STANDARD_TIME_OFFSET = -7;
HMoney.PACIFIC_STANDARD_TIME_OFFSET = -8;
HMoney.ALASKA_STANDARD_TIME_OFFSET = -9;
HMoney.HAWAII_STANDARD_TIME_OFFSET = -10;
HMoney.EASTERN_DAYLIGHT_TIME_OFFSET = -4;
HMoney.CENTRAL_DAYLIGHT_TIME_OFFSET = -5;
HMoney.MOUNTAIN_DAYLIGHT_TIME_OFFSET = -6;
HMoney.PACIFIC_DAYLIGHT_TIME_OFFSET = -7;
HMoney.ALASKA_DAYLIGHT_TIME_OFFSET = -8;
HMoney.HAWAII_DAYLIGHT_TIME_OFFSET = -10; // Hawaii does not observe daylight savings time

// Australian Timezones
HMoney.AUSTRALIAN_EASTERN_STANDARD_TIME_OFFSET = 10;
HMoney.AUSTRALIAN_CENTRAL_STANDARD_TIME_OFFSET = 9.5;
HMoney.AUSTRALIAN_WESTERN_STANDARD_TIME_OFFSET = 8;
HMoney.AUSTRALIAN_EASTERN_DAYLIGHT_TIME_OFFSET = 11;
HMoney.AUSTRALIAN_CENTRAL_DAYLIGHT_TIME_OFFSET = 10.5;
HMoney.AUSTRALIAN_WESTERN_DAYLIGHT_TIME_OFFSET = 8; // Western Australia does not observe daylight savings time

/**
 * @constructor
 */
HMoney.CurrencyTimezone = function(currencyCode, lowOffset, highOffset) {
	this._currencyCode = currencyCode;
	this._lowOffset = lowOffset;
	this._highOffset = lowOffset;
	if(typeof highOffset == "number") {
		this._highOffset = highOffset;
	}
	return this;
};

HMoney.CurrencyTimezone.prototype._currencyCode = null;
HMoney.CurrencyTimezone.prototype._lowOffset = null;
HMoney.CurrencyTimezone.prototype._highOffset = null;

HMoney.CurrencyTimezone.prototype.getCurrencyCode = function() {
	return this._currencyCode;
};

HMoney.CurrencyTimezone.prototype.inTimezone = function() {
	var inTimezone = false;
	var timezoneOffset = this._getUserTimezoneOffset();
	if(timezoneOffset >= this._lowOffset && timezoneOffset <= this._highOffset) {
		inTimezone = true;
	}
	return inTimezone;
};

HMoney.CurrencyTimezone.prototype._getUserTimezoneOffset = function() {
	var now = new Date();
	return now.getTimezoneOffset() / 60 * -1; // getTimezoneOffset returns negative minutes
};

HMoney.Timezones = [
	new HMoney.CurrencyTimezone("USD", HMoney.PACIFIC_STANDARD_TIME_OFFSET, HMoney.EASTERN_DAYLIGHT_TIME_OFFSET)
];

HMoney.RemoveCurrencyCodes = function() {
	var currencyTimezones = HMoney.Timezones;
	var noCurrencyTimezones = currencyTimezones.length;
	for(var i = 0; i < noCurrencyTimezones; i++) {
		var currencyTimezone = currencyTimezones[i];
		if(currencyTimezone.inTimezone()) {
			var currencyCode = currencyTimezone.getCurrencyCode().toUpperCase();
			var elements = jQuery(".hmoney .currency-code").get();
			var noElements = elements.length;
			for(var j = 0; j < noElements; j++) {
				var element = elements[j];
				var thisCurrencyCode = jQuery.trim(jQuery(element).text().toUpperCase());
				if(thisCurrencyCode == currencyCode) {
					jQuery(element).remove();
				}
			}
		}
	}
};

jQuery(function() {
	HMoney.RemoveCurrencyCodes();
});Buttonify = {};
(function($){

	// consts
	var BUTTON_SET = '.button-set'
		BUTTON = '.buttonify'

	Buttonify.Events = {
		click: function(e) {
			if ($(this).hasClass('ui-processing')) {
				e.stopImmediatePropagation();
				e.preventDefault();
			}
		},
		processing: function() {
			$(this).removeClass('ui-processing ui-errors ui-done');
			$(this).addClass('ui-processing');
		},
		done: function() {
			$(this).removeClass('ui-processing ui-errors ui-done');
			$(this).addClass('ui-done');
		},
		error: function() {
			$(this).removeClass('ui-processing ui-errors ui-done');
			$(this).addClass('ui-errors');
		},
		reset: function() {
			$(this).removeClass('ui-processing ui-errors ui-done');
		}
	};

	Buttonify.apply = function(context) {

		// apply button-set styling and event hooks
		$(BUTTON_SET, context).buttonset();

		// apply button styling and event hooks
		$('.buttonify', context).addClass('ui-priority-primary');
		$('.buttonify.secondary', context).removeClass('ui-priority-primary');

		$('a.buttonify, :input.buttonify', context).each(function(){

			var button = $(this)
				.bind('click.buttonify', Buttonify.Events.click)
				.bind('processing.buttonify', Buttonify.Events.processing)
				.bind('done.buttonify', Buttonify.Events.done)
				.bind('error.buttonify', Buttonify.Events.error)
				.bind('reset.buttonify', Buttonify.Events.reset)
				.button();
			
			//Support for when class marked as disabled
			if(button.hasClass('disabled')){
				button.button('option', 'disabled', true);
			}

			button.data('events').click.sort(function(a, b){
				if (a.namespace == 'buttonify')
					return -1;
				if (b.namespace == 'buttonify')
					return 1;
				return 0;
			});

		});
	};

	Buttonify.remove = function(context) {
		$('.buttonify.ui-button', context)
			.unbind('.buttonify')
			.button('destroy');

		// destroy buttonset
	};

	$(function(){
		Buttonify.apply();
	});

})(jQuery);/**
 * Tooltipify v0.1
 *
 * This jQuery 1.4 plugin allows you to activate tooltips via tooltip triggers.
 *
 * Run with:
 * jQuery(".tooltipify-trigger").tooltipify();
 * At present, this tool looks for a "data-tooltipify" attribute on any matched triggers.
 * It assumes this value is the ID of the tooltip it should show.
 *
 * TODO: pass in effects
 * TODO: more control over acertaining tooltip
 *
 * @author Josh Amos
 **/

(function($) {

  $.fn.tooltipify = function(settings) {

    var config = {'pageWidth': 960};
    if (settings) $.extend(config, settings);

	  var newMethods = {
			showTooltip : function(tooltip) {
				$(this).positionTooltip(tooltip);
				tooltip.delay(200).fadeIn('fast');
				return this;
			},
			hideTooltip : function(tooltip) {
				tooltip.delay(200).fadeOut('fast');
				return this;
			},
			ensureNowrap : function() {
				this.css('white-space', 'nowrap');
				return this;
			},
			positionTooltip : function(tooltip) {
				var trigger = $(this);
				var triggerPos = trigger.position();
				var triggerWidth = trigger.width();
				var triggerHeight = trigger.height();
				var tooltipPos = tooltip.offset();
				var tooltipPaddingLeft = parseInt(tooltip.css('padding-left').replace(/px/, ''));
				var tooltipPaddingRight = parseInt(tooltip.css('padding-right').replace(/px/, ''));
				var tooltipWidth = (tooltip.width() + tooltipPaddingLeft + tooltipPaddingRight);

				tooltip.activateTooltipPointer();
				var tooltipPointer = tooltip.getTooltipPointer();
				var tooltipPointerWidth = $(tooltipPointer).css('width').replace(/px/, '');
				var tooltipPointerHeight = $(tooltipPointer).css('height').replace(/px/, '');

				var left = (triggerPos.left - (tooltipWidth/2) + (triggerWidth/2));
				var top = triggerPos.top + triggerHeight  + 7;
				var tooltipPointerLeft = ((tooltipWidth/2) - (tooltipPointerWidth/2));

				//Limit left positioning
				if (left < 0) {
					var left = 0;
					tooltipPointerLeft = triggerPos.left + (triggerWidth/2) + 'px';
				}

				//Limit right positioning
				var rightOffset = left + tooltipWidth;
				if (rightOffset > config.pageWidth) {
					var left = (config.pageWidth - tooltipWidth);
					tooltipPointerLeft = (triggerPos.left + (triggerWidth/2) - left) + 'px';
				}

				tooltip.positionTooltipPointer(tooltipPointerLeft);
				tooltip.css({ "left": left + "px", "top": top + "px" });
				return this;
			},
			addTriggerEvents : function(tooltip) {
				this.mouseenter(
					function(){
						$(this).showTooltip(tooltip);
				});

				this.mouseleave(
					function(){
						$(this).hideTooltip(tooltip);
					});

				return this;
			},
			acertainTooltip : function() {
				return $('#' + $(this).attr('data-tooltipify'));
			},
			getTooltipPointer : function() {
				var tooltipPointer = $('#' + this.attr('id') + ' > .tooltipify-pointer');
				return tooltipPointer;
			},
			activateTooltipPointer : function() {
				if($('#' + this.attr('id')).has('.tooltipify-pointer').length == 0) {
					$('<span class="tooltipify-pointer"></span>').prependTo($('#' + this.attr('id')));
				}
				return this;
			},
			positionTooltipPointer : function(left) {
				$('#' + this.attr('id') + ' > .tooltipify-pointer').css('left', left);
				return this;
			}
	  };

		$.each(newMethods, function(i) {
		    jQuery.fn[i] = this;
		});

    this.each(function() {
			var tooltip = $(this).acertainTooltip();
			$(this).ensureNowrap().addTriggerEvents(tooltip);
    });

    return this;
  };

})(jQuery);(function($) {
	$.fn.ellipsis = function(enableUpdating){
		var s = document.documentElement.style;
		if (!('textOverflow' in s || 'OTextOverflow' in s)) {
			return this.each(function(){
				var el = $(this);
				if(el.css("overflow") == "hidden"){
					var originalText = el.html();
					var w = el.width();

					var t = $(this.cloneNode(true)).hide().css({
                        'position': 'absolute',
                        'width': 'auto',
                        'overflow': 'visible',
                        'max-width': 'inherit'
                    });
					el.after(t);

					var text = originalText;
					while(text.length > 0 && t.width() > el.width()){
						text = text.substr(0, text.length - 1);
						t.html(text + "...");
					}
					el.html(t.html());

					t.remove();

					if(enableUpdating == true){
						var oldW = el.width();
						setInterval(function(){
							if(el.width() != oldW){
								oldW = el.width();
								el.html(originalText);
								el.ellipsis();
							}
						}, 200);
					}
				}
			});
		} else return this;
	};
})(jQuery);/**
* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne <brian@cherne.net>
*/
(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY;};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev]);}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev]);};var handleHover=function(e){var p=(e.type=="mouseover"?e.fromElement:e.toElement)||e.relatedTarget;while(p&&p!=this){try{p=p.parentNode;}catch(e){p=this;}}if(p==this){return false;}var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);}if(e.type=="mouseover"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob);},cfg.timeout);}}};return this.mouseover(handleHover).mouseout(handleHover);};})(jQuery);
/**
 * Provides a zoom effect
 */

(function() {

	var SIZE_NAME = 'stocklarge',
		SIZE_X = 624,
		SIZE_Y = 351;

	var Preview = function(element, previewBox) {
		this.element = element;
		this.previewBox = previewBox;
		this.initialize();
	};

	// bind events and prepare the preview
	Preview.prototype.initialize = function() {
		// add an overlay shim
		this.element.append('<span class="previewoverlay"> </span>');

		var over = function(preview) { return function(e) { preview.load(e); }; }(this);
		var out = function(preview) { return function(e) { preview.hide(e); }; }(this);

		// why does hoverIntent not work on Opera?
		if(jQuery.browser.opera) {
			jQuery(this.element).hover(over,out);
		} else {
			jQuery(this.element).hoverIntent({
				sensitivity: 3,
				interval: 50,
				over: over,
				timeout: 0,
				out: out
			});
		}

		// fire preload on mouseover
		jQuery(this.element).mouseover(
			function(preview) { return function(e) { preview.preload(e); }; }(this));
	};

	// builds an image url from the preview image/link used
	Preview.prototype.getImageUrl = function(size) {
		var thumbImage = this.element.find('img');
		var url = thumbImage.length ? thumbImage.attr('src') : this.element.attr('href');
		return url.replace(/stockthumbnail/, size);
	};

	// preloads an image for later use
	Preview.prototype.preload = function() {
		if(!this.image) {
			var url = this.getImageUrl(SIZE_NAME);
			this.image = new Image();
			this.image.src = url;
		}
	};

	// load the preview image, show the preview when ready
	Preview.prototype.load = function(e) {
		this.previewImage = jQuery(document.createElement('img'));
		this.previewBox.find('img').remove();
		this.previewBox.append(this.previewImage);
		this.previewImage.attr('src',this.getImageUrl(SIZE_NAME));
		this.show();

		this.previewImage.load(function(){
			jQuery('body').trigger('previewload');
		});
	};

	// display the preview box
	Preview.prototype.show = function(e) {
		window.activePreview = this;

		// display the preview
		this.move(window.mouseX,window.mouseY);
		this.previewBox.show();

		this.element.bind('mousemove',function(preview) {
			return function(e) {
				preview.move(e.pageX, e.pageY);
			};
		}(this));
	};

	// hide the preview box
	Preview.prototype.hide = function(e) {
		this.previewBox.hide();
		this.element.unbind('mousemove');
		window.activePreview = false;
	};

	// move the preview to as close to the provided x and y as possible
	Preview.prototype.move = function(x,y) {
		var viewport = {};
		viewport.x = $(window).scrollLeft();
		viewport.y = $(window).scrollTop();
		viewport.cx = $(window).width();
		viewport.cy= $(window).height();
		var height = SIZE_Y + 8;
		var width = SIZE_X + 8;
		var xdiff = (viewport.x + viewport.cx) - (x + width);
		var ydiff = (viewport.y + viewport.cy) - (y + height);

		// handle clashing by flipping image to other side of mouse
		if(xdiff < 0) x = x - width - 50;
		if(ydiff < 0) y = y - height - 20;

		var bodyOffset = jQuery(document.body).offset();
		var left = x - bodyOffset.left + 20;
		var top = y - bodyOffset.top + 20;

		this.previewBox.css('left', left+'px').css('top', top+'px');
	};

	jQuery.fn.imagePreview = function() {
		return this.each(function () {
			new Preview(jQuery(this),jQuery('#previewbox'));
		});
	};

	var px = function (pixels) { return '' + pixels + 'px'; };

	// initialize and bind on ready
	jQuery(document).ready(function(){
		jQuery('body').append(
			jQuery('<div>').attr('id', 'previewbox').css({
				display: 'none',
				width: px(SIZE_X),
				height: px(SIZE_Y)
			}));
		jQuery('.stocklogo .thumbnail a').imagePreview();
	});

	window.activePreview = false;
	jQuery(document).mousemove(function(e){
		window.mouseX = e.pageX;
		window.mouseY = e.pageY;
	});

}());

/**
 * Base library for web services
 */

var Service = Service || {};
Service.Base = {};

(function(Base) {

	Base.ServiceException = function(content) {
		this.message = content.errormessage;
		this.errorcode = content.errorcode;
	};

	/**
	 * Gets the url for a method call
	 */
	Base.urlFor = function(service, version, method) {
		return '/api/'+version+'/rest?service='+
			service+'&format=json&method='+method;
	};

	Base.parseResponse = function(text) {
		// TODO: Remove this function
		if (typeof(text) == 'object') return text;

		var json = eval("("+text+")");
		return json;
	};

	/**
	 * Make a call to the service
	 */
	Base.serviceCall = function(url, params, callback) {
		if(callback) {
			jQuery.post(url,params,function(data){
				callback(Base.parseResponse(data));
			});
		} else {
			var json;
			if (params)
			{
				json = Base.parseResponse(
				jQuery.ajax({type:'POST',url:url,async:false,data:params,dataType:'json'}));
			}
			else
			{
				json = Base.parseResponse(
				jQuery.ajax({type:'POST',url:url,async:false,dataType:'json'}));
			}
			// handle failure
			if(json.status == 'fail') {
				throw new Base.ServiceException(json);
			}

			return json.content;
		}
		return undefined;
	};

	Base.call = function (service, version, method, params, callback) {
		var url = Base.urlFor(service, version, method);
		return Base.serviceCall(url, params, callback);
	};

}(Service.Base));
Service.User = {

	getActiveUser: function (context, callback) {
		if (!context) context = 'default';
		this._call('getActiveUser', { context: context }, function (response) {
			callback(response.content);
		});
	},

	getLaunchCapabilities: function (callback) {
		this._call('getLaunchCapabilities', { }, function (response) {
			callback(response.content);
		});
	},

	_call: function (method, params, callback) {
		if (!callback) callback = function(){}; // prevent synchronous Service.Base.call
		return Service.Base.call('user', 'v1', method, params, callback);
	}

};/**
 * Client for StockFavoriteService.
 * Depends on Service base class being loaded first.
 * Example: Service.StockFavorite.addFavorite(12345);
 */

Service.StockFavorite = {

	_call: function (method, params, callback) {
		if (!callback) callback = function(){}; // prevent synchronous Service.Base.call
		return Service.Base.call('stockfavorite', 'v1', method, params, callback);
	},

	addFavorite: function (stockId, callback) {
		this._call('addFavorite', { stockId: stockId }, callback);
	},

	removeFavorite: function (stockId, callback) {
		this._call('removeFavorite', { stockId: stockId }, callback);
	},

	getFavoriteIds: function (callback) {
		this._call('getFavoriteIds', {}, function(response){
			callback(response.content ? response.content : []);
		});
	},

	getLatestFavorites: function (limit, size, callback) {
		this._call('getLatestFavorites', { limit: limit, size: size }, function (response) {
			callback(response.content ? response.content : []);
		});
	}

};Service.Registration = {
	isAvailable: function (data, callback) {
		this._call('isAvailable', data, callback);
	},

	autoRegister: function (data, callback) {
		data.agreements || (data.agreements = []);
		data.properties || (data.properties = []);
		this._call('autoRegister', data, callback);
	},

	register: function (data, callback) {
		data.agreements || (data.agreements = []);
		data.properties || (data.properties = []);
		this._call('register', data, callback);
	},

	_call: function (method, params, callback) {
		if (!callback) callback = function(){}; // prevent synchronous Service.Base.call
		return Service.Base.call('registration', 'v1', method, params, callback);
	}
};
/**
 * A bitfield-backed collection of flags.
 * Depends on Cookie object from core.js
 * Flag bitmasks must be 2^x, i.e. 1, 2, 4, 8, ...
 * Be careful of (signed?) int sizes beyond the 30th field.
 *
 * @author Paul Annesley
 * @author Richard Bone
 */
FlagCookie = {

	COOKIE: 'flags',
	DAYS: 28,

	FLAGS: {
		'stock-favorite-promo-hide': 1
	},

	// ----------------------------------------

	set: function (flag) {
		this._write(this._bitfield() | this._mask(flag));
	},

	unset: function (flag) {
		this._write(this._bitfield() & ~this._mask(flag));
	},

	isset: function (flag) {
		return this._bitfield() & this._mask(flag) !== 0;
	},

	// ----------------------------------------

	_bitfield: function () {
		return Cookie.get(this.COOKIE) || 0;
	},

	_write: function (value) {
		Cookie.set(this.COOKIE, value, this.DAYS);
	},

	_mask: function (flag) {
		var mask = this.FLAGS[flag];
		if (!mask) throw("Unknown flag: " + flag);
		return mask;
	}

};
/*
 * Copyright (C) 1999-2009 Jive Software. All rights reserved.
 *
 * This software is the proprietary information of Jive Software. Use is subject to license terms.
 */

/*
* $ lightbox_me
* By: Buck Wilson
* Version : 2.2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


(function($) {

    $.fn.lightbox_me = function(options) {

        return this.each(function() {

            var
                opts = $.extend({}, $.fn.lightbox_me.defaults, options),
                $overlay = $('div.' + opts.classPrefix + '_overlay'),
                $self = $(this),
                $iframe = $('iframe#lb_iframe'),
                ie6 = ($.browser.msie && $.browser.version < 7);

            if ($overlay.length > 0) {
                $overlay[0].removeModal(); // if the overlay exists, then a modal probably exists. Ditch it!
            } else {
                $overlay =  $('<div class="' + opts.classPrefix + '_overlay" style="display:none;"/>'); // otherwise just create an all new overlay.
            }

            $iframe = ($iframe.length > 0) ? $iframe : $iframe = $('<iframe id="lb_iframe" style="z-index: ' + (opts.zIndex + 1) + '; display: none; border: none; margin: 0; padding: 0; position: absolute; width: 100%; height: 100%; top: 0; left: 0;"/>');

            /*----------------------------------------------------
               DOM Building
            ---------------------------------------------------- */
            if (ie6) {
                var src = /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank';
                $iframe.attr('src', src);
                $('body').append($iframe);
            } // iframe shim for ie6, to hide select elements

            $('body').append($self).append($overlay);

            /*----------------------------------------------------
               CSS stuffs
            ---------------------------------------------------- */

            // set css of the modal'd window

            setSelfPosition();
            $self.css({left: '50%', marginLeft: ($self.outerWidth() / 2) * -1,  zIndex: (opts.zIndex + 3) });

            // set css of the overlay

            setOverlayHeight(); // pulled this into a function because it is called on window resize.
            $overlay.css({ position: 'absolute', width: '100%', top: 0, left: 0, right: 0, bottom: 0, zIndex: (opts.zIndex + 2) })
                    .css(opts.overlayCSS);

            /*----------------------------------------------------
               Animate it in.
            ---------------------------------------------------- */

            if ($overlay.is(":hidden")) {
                $overlay.fadeIn(opts.overlaySpeed, function() {
                    $self[opts.appearEffect](opts.lightboxSpeed, function() { setOverlayHeight(); opts.onLoad()});
                });
            } else {
                $self[opts.appearEffect](opts.lightboxSpeed, function() { setOverlayHeight(); opts.onLoad()});
            }

            /*----------------------------------------------------
               Bind Events
            ---------------------------------------------------- */

            $(window).resize(setOverlayHeight)
                     .resize(setSelfPosition)
                     .scroll(setSelfPosition)
                     .keydown(observeEscapePress);

            $self.find(opts.closeSelector).click(function() { removeModal(true); return false; });
            $overlay.click(function() { if(opts.closeClick){ removeModal(true); return false;} });


            $self.bind('close', function() { removeModal(true) });
            $self.bind('resize', setSelfPosition);
            $overlay[0].removeModal = removeModal;

            /*----------------------------------------------------------------------------------------------------------------------------------------
              ---------------------------------------------------------------------------------------------------------------------------------------- */

            /*----------------------------------------------------
               Private Functions
            ---------------------------------------------------- */


            function removeModal(removeO) {
                // fades & removes modal, then unbinds events
                $self[opts.disappearEffect](opts.lightboxDisappearSpeed, function() {

                    if (removeO) {
                      removeOverlay();
                    }

                    opts.destroyOnClose ? $self.remove() : $self.hide()


                    $self.find(opts.closeSelector).unbind('click');
                    $self.unbind('close');
                    $self.unbind('resize');
                    $(window).unbind('scroll', setSelfPosition);
                    $(window).unbind('resize', setSelfPosition);


                });
            }


            function removeOverlay() {
                // fades & removes overlay, then unbinds events
                $overlay.fadeOut(opts.overlayDisappearSpeed, function() {
                    $(window).unbind('resize', setOverlayHeight);

                    $overlay.remove();
                    $overlay.unbind('click');


                    opts.onClose();

                })
            }



            /* Function to bind to the window to observe the escape key press */
            function observeEscapePress(e) {
                if((e.keyCode == 27 || (e.DOM_VK_ESCAPE == 27 && e.which==0)) && opts.closeEsc) removeModal(true);
            }

            /* Set the height of the overlay
                    : if the document height is taller than the window, then set the overlay height to the document height.
                    : otherwise, just set overlay height: 100%
            */
            function setOverlayHeight() {
                if ($(window).height() < $(document).height()) {
                    $overlay.css({height: $(document).height() + 'px'});
                } else {
                    $overlay.css({height: '100%'});
                    if (ie6) {$('html,body').css('height','100%'); } // ie6 hack for height: 100%; TODO: handle this in IE7
                }
            }

            /* Set the position of the modal'd window ($self)
                    : if $self is taller than the window, then make it absolutely positioned
                    : otherwise fixed
            */
            function setSelfPosition() {
                var s = $self[0].style;

                if (($self.height() + 80  >= $(window).height()) && ($self.css('position') != 'absolute' || ie6)) {
                    var topOffset = $(document).scrollTop() + 40;
                    $self.css({position: 'absolute', top: topOffset + 'px', marginTop: 0})
                    if (ie6) {
                        s.removeExpression('top');
                    }
                } else if ($self.height()+ 80  < $(window).height()) {
                    if (ie6) {
                        s.position = 'absolute';
                        if (opts.centered) {
                            s.setExpression('top', '(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"')
                            s.marginTop = 0;
                        } else {
                            var top = (opts.modalCSS && opts.modalCSS.top) ? parseInt(opts.modalCSS.top) : 0;
                            s.setExpression('top', '((blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"')
                        }
                    } else {
                        if (opts.centered) {
                            $self.css({ position: 'fixed', top: '50%', marginTop: ($self.outerHeight() / 2) * -1})
                        } else {
                            $self.css({ position: 'fixed'}).css(opts.modalCSS);
                        }
                    }
                }
            }
        });
    };


    $.fn.lightbox_me.defaults = {

        // animation when appears
        appearEffect: "fadeIn",
        overlaySpeed: 300,
        lightboxSpeed: "fast",

        // animation when dissapears
        disappearEffect: "fadeOut",
        overlayDisappearSpeed: 300,
        lightboxDisappearSpeed: "fast",

        // close
        closeSelector: ".close",
        closeClick: true,
        closeEsc: true,

        // behavior
        destroyOnClose: false,

        // callbacks
        onLoad: function() {},
        onClose: function() {},

        // style
        classPrefix: 'lb',
        zIndex: 999,
        centered: false,
        modalCSS: {top: '40px'},
        overlayCSS: {background: 'black', opacity: .6}
    }


})(jQuery);var Favoriting = {
	SIGNUP_CONTEXT: 'stock-favorite',
	LABEL_ADD: 'Add to Favorites',
	LABEL_REMOVE: 'Remove from Favorites',
	_animating: false
};

Favoriting.loadFavorites = function () {
	var buttons = jQuery('form.favorite button');

	buttons
		.removeClass('favorite')
		.addClass('loading')
		.attr('title', Favoriting.LABEL_ADD)
		.find('span').text(Favoriting.LABEL_ADD);

	Service.StockFavorite.getFavoriteIds(function (list) {
		buttons.removeClass('loading');
		for (var i = 0; i < list.length; i++) {
			jQuery('#favorite-' + list[i] + ' button')
				.addClass('favorite')
				.attr('title', Favoriting.LABEL_REMOVE)
				.find('span').text(Favoriting.LABEL_REMOVE);
		}
		UserBar.addCallback(function () {
			Favoriting.updateUserBarCount(list.length);
		});
	});
};

Favoriting.handleLoginLinkClick = function () {
	Favoriting.gaTrackSignup('login', window.location.pathname);
};

Favoriting.handleClick = function (button, isLoggedIn) {
	var stockId = button.parents('form').find('input[name=stockid]').val();
	if (isLoggedIn)
		Favoriting.clickLoggedIn(stockId, button);
	else
		Favoriting.clickLoggedOut(stockId, button);
};

Favoriting.clickLoggedIn = function (stockId, button) {
	if (button.hasClass('favorite')) {
		Service.StockFavorite.removeFavorite(stockId, Favoriting.responseHandler);
		button
			.removeClass('favorite')
			.attr('title', Favoriting.LABEL_ADD)
			.find('span').text(Favoriting.LABEL_ADD);
	} else {
		Service.StockFavorite.addFavorite(stockId, Favoriting.responseHandler);
		button
			.addClass('favorite')
			.attr('title', Favoriting.LABEL_REMOVE)
			.find('span').text(Favoriting.LABEL_REMOVE);
	}
};

Favoriting.clickLoggedOut = function (stockId, button) {
	var lightbox = jQuery('#favoriteregister');

	lightbox
		.addClass('register')
		.removeClass('login');

	lightbox.lightbox_me({
		centered: true,
		overlaySpeed: 'fast',
		closeSelector: '.close-button',
		lightboxDisappearSpeed: 'fast',
		overlayDisappearSpeed: 'fast',
		onLoad: function () {
			lightbox.find('input[name=stockid]').val(stockId);
			lightbox.find('input[name=email]').focus();
			Favoriting.gaTrackSignup("open", "stockid:"+stockId+":"+window.location.pathname);
		},
		onClose: function () {
			Favoriting.gaTrackSignup("close", "stockid:"+stockId+":"+window.location.pathname);
		}
	});
};

Favoriting.submitRegistration = function (form) {
	var email = form.find('input[name=email]').val(),
		stockId = form.find('input[name=stockid]').val(),
		agreementCheckbox = form.find('input[name=agreement]').attr('checked');

	if (!agreementCheckbox) {
		Favoriting.showError("You must accept the 99designs General Services Agreement.");
		return;
	}


	if (/^[^@]+@[^@]+$/.test(email) == false) {
		Favoriting.showError("That email address isn't valid, please check your spelling.");
		return;
	}

	Service.Registration.autoRegister(
		{
			email: email,
			loginType: Favoriting.SIGNUP_CONTEXT,
			agreements: ['general-services']
		},
		function (response) {
			if (response.status == 'ok' && response.content.result === undefined) {
				Service.StockFavorite.addFavorite(stockId, function (response) {
					UserBar.reset().load('#userbar');
					Favoriting.loadFavorites();
				});
				jQuery('#favoriteregister').trigger('close');
				Favoriting.gaTrackSignup("success", "stockid:"+stockId+":"+window.location.pathname);
			} else if (response.content.result !== undefined && response.content.result == 'user-exists') {
				jQuery('#favoriteregister')
					.removeClass('register')
					.addClass('login');
			} else if (response.content.result !== undefined && response.content.result == 'invalid-email') {
				Favoriting.showError("That email address isn't valid, please check your spelling.");
			} else {
				// error occurred: Should let the user know
			}
		}
	);
};

Favoriting.showError = function (errorText, delay) {
	if (delay === undefined)
		delay = 4000;

	var errorField = jQuery('#register-errors');

	if (Favoriting._animating) return;

	Favoriting._animating = true;

	errorField
		.text(errorText)
		.slideDown('fast')
		.delay(4000)
		.slideUp('slow', function () {
			jQuery(this).text('');
			Favoriting._animating = false;
		})
		;
};

Favoriting.updateUserBarCount = function (count) {

	var html = '<span>*</span> Favorites';
	if (count > 0) html += ' <em>' + count + '</em>';

	jQuery('#nav-account .favorites-link')
		.toggleClass('active', count > 0)
		.html(html);
};

Favoriting.responseHandler = function (response) {

	window.StockFavoriteBar && StockFavoriteBar.load();

	if (response.status == "ok" && typeof response.content.count != 'undefined') {
		Favoriting.updateUserBarCount(response.content.count);
	} else {
		Favoriting.loadFavorites();
	}
};

Favoriting.gaTrackSignup = function (action, label) {
	Favoriting.gaTrackEvent("StockFavoritingSignup", action, label);
};

Favoriting.gaTrackEvent = function (category, action, label, value) {
	Analytics.trackEvent(category, action, label, value);
};
StockFavoriteBar = {

	LIMIT: 8,
	IMG_SIZE: 'stockthumbnail',
	IMG_WIDTH: 50,
	IMG_HEIGHT: 28,

	initialize: function () {
		UserBar.addCallback(function (isLoggedIn) {
			if (isLoggedIn) StockFavoriteBar.load();
		});
	},

	open: function () {
		jQuery('#favorites-bar').slideDown('fast');
	},

	close: function () {
		jQuery('#favorites-bar').slideUp('fast');
	},

	clear: function () {
		jQuery('#favorites-bar .thumbnails li').remove();
	},

	load: function () {
		Service.StockFavorite.getLatestFavorites(this.LIMIT, this.IMG_SIZE, function (data) {
			StockFavoriteBar.clear();
			StockFavoriteBar._tally(data.total);
			if (data.items) {
				jQuery.each(data.items.reverse(), function () {
					StockFavoriteBar.addByData(this);
				});
			}
		});
	},

	addById: function (stockId) {
		Service.StockLogo.lookup(stockId, function (data) {
			StockFavoriteBar.addByData(data);
		});
	},

	addByData: function (data) {
		var list = jQuery('#favorites-bar .thumbnails');

		var cutoff = StockFavoriteBar.LIMIT - 1;
		list.find('li:nth-child('+cutoff+') ~ li').remove();

		list.prepend(jQuery('<li>').append(StockFavoriteBar._img(data)));
		StockFavoriteBar.open();
	},

	// ----------------------------------------

	_tally: function (total) {
		if (total === 0) StockFavoriteBar.close();
		var countPrefix = (total > 2) ? 'all ' : '';
		jQuery('#favorites-bar .total').text(countPrefix + total);
		jQuery('#favorites-bar #compare-button').toggle(total >= 2);
	},

	_img: function (data) {
		var img = jQuery('<img>').attr({
			src: data.preview[this.IMG_SIZE],
			width: this.IMG_WIDTH,
			height: this.IMG_HEIGHT,
			title: data.title + ' by ' + data.designer
		});

		return jQuery('<a>').attr('href', data.url).append(img);
	}
};

StockFavoriteBar.initialize();
// setup favoriting
(function () {
	// attempt to load existing favorites immediately
	Favoriting.loadFavorites();

	jQuery('form.favorite button').click(function (event) {
		event.preventDefault();
		var button = jQuery(this);
		UserBar.addCallback(function (isLoggedIn) {
			Favoriting.handleClick(button, isLoggedIn);
		});
	});

	jQuery('#favoriteregister a.login').click(function (event) {
		Favoriting.handleLoginLinkClick();
	});

	var registrationForm = jQuery('#favoriteregister form');
	registrationForm.bind('submit', function (event) {
		event.preventDefault();
		Favoriting.submitRegistration(registrationForm);
	});
}());

// tooltip on each Favorite button.
(function () {
	jQuery('form.favorite button').qtip({
		style: {
			background: '#333',
			color: '#fff',
			border: {
				width: 0,
				radius: 4,
				color: '#333'
			},
			textAlign: 'center',
			tip: {
				corner: 'bottomMiddle',
				size: { x: 14, y: 7 }
			}
		},
		position: {
			corner: {
				target: 'topMiddle',
				tooltip: 'bottomMiddle'
			}
		},
		show: {
			delay: 50
		},
		hide: {
			fixed: true
		}
	});

}());

// Add to Favorites: instructional promotion.
(function () {
	var flag = 'stock-favorite-promo-hide';
	if (FlagCookie.isset(flag)) return;

	var promo = jQuery('#fav-promo');
	jQuery('#results ol.thumbnails li:nth-child(4)').after(promo);
	promo.slideDown();

	jQuery('#fav-promo .close').click(function (event) {
		event.preventDefault();
		promo.slideUp();
		FlagCookie.set(flag);
	});

	jQuery('form.favorite button').click(function () {
		FlagCookie.set(flag);
	});
}());


(function () {
	var form = jQuery('#feedbackform');
	var confirmation = jQuery('#confirm-feedback');
	var message = form.find('#feedback_message');
	var button = form.find('input[type=submit]');
	form.bind('submit', function (event) {
		event.preventDefault();
		button.attr('disabled', 'disabled');
		message.attr('disabled', 'disabled');
		jQuery.ajax({
			type: 'POST',
			url: form.attr('action'),
			data: {'message':message.val()},
			success: function () {
				message.val('');
				message.removeAttr('disabled');
				button.removeAttr('disabled');
				confirmation.fadeIn('fast', function () {
					setTimeout(function () {
						confirmation.fadeOut('slow');
					}, 4000);
				});
			}
		});

	});
});

(function(){

	var currenttarget,
		currentmenu = null,
		options = document.getElementById('search-options');

	document.onclick = function(e)
	{

		if(currentmenu !== null)
		{
			currentmenu.style.display = 'none';
			currentmenu = null;
			currenttarget.className = currenttarget.className.replace(/ pressed/, '');
		}

		var target = e ? e.target : event.srcElement;
		if(target.nodeName == '#text') { target = target.parentNode; }

		if(!target.href || target.parentNode.parentNode != options) { return true; }

		currentmenu = document.getElementById(target.href.split('#')[1]);
		currenttarget = target;
		currentmenu.style.visibility = 'hidden';
		currentmenu.style.display = 'block';

		var position = getPosition(target);
		currentmenu.style.left = (currentmenu.id == 'options-sort' ?
			(position.x - currentmenu.offsetWidth + target.offsetWidth) : position.x) + 'px';
		currentmenu.style.top = (position.y + target.offsetHeight) + 'px';

		currenttarget.className += ' pressed';
		currentmenu.style.visibility = 'visible';

		jQuery(currentmenu).find('a:first').focus();
		jQuery(currentmenu).find('a:contains('+jQuery(currenttarget).text()+')').focus();

		return false;
	};

	function getPosition(obj)
	{
		var position = {
			'x' : obj.offsetLeft,
			'y' : obj.offsetTop
			};
		while(obj.offsetParent)
		{
			obj = obj.offsetParent;
			position.x += obj.offsetLeft;
			position.y += obj.offsetTop;
		}
		return position;
	}

	// Enable tooltips
	jQuery('.tooltipify-trigger').tooltipify();

}());

/* Choose Industry Menu */
(function() {

	var button = jQuery('#choose-industries'),
		menu = jQuery('#options-industries');

	jQuery('#browse').append(menu);

	button.click(function(e) {
		e.preventDefault();
		button.toggleClass('pressed');
		menu.toggle();
	});

	jQuery('body').click(function(event) {

		if (menu.css('display') == 'none') return;

		var clickedOutside =
			jQuery(event.target).parents().andSelf().filter('#choose-industries, #options-industries').length === 0;

		if (clickedOutside) {
			menu.hide();
			button.removeClass('pressed');
		}
	});

})();

(function() {

	var iframe = document.createElement('iframe');
	jQuery(iframe)
		.attr('src', '/thmtrx/tags')
		.attr('height', '10px')
		.attr('width', '10px')
		.css({ 'position': 'absolute', 'top': '-100000px', 'left': '-100000px' })
		.appendTo('body')
		;

}());
/**
* @author Remy Sharp
* @url http://remysharp.com/2007/01/25/jquery-tutorial-text-box-hints/
*/

(function ($) {

$.fn.hint = function (blurClass) {
    if (!blurClass) blurClass = 'blur';

    return this.each(function () {
        // get jQuery instance of 'this'
        var $$ = $(this);

        // get it once since it won't change
        var title = $$.attr('title');

        // only apply logic if the element has the attribute
        if (title) {

            // Note this is a one liner

            // on blur, set value to title attr if text is blank
            $$.blur(function () {
                if ($$.val() == '') {
                    $$.val(title).addClass(blurClass);
                }
            })

            // on focus, set value to blank if current value matches title attr
            .focus(function () {
                if ($$.val() == title) {
                    $$.val('').removeClass(blurClass);
                }
            })

            // clear the pre-defined text when form is submitted
            .parents('form:first').submit(function () {
                if ($$.val() == title) {
                    $$.val('').removeClass(blurClass);
                }
            }).end()

            // now change all inputs to title
            .not(document.activeElement).blur();

            // counteracts the effect of Firefox's autocomplete stripping the blur effect
            if ($.browser.mozilla && !$$.attr('autocomplete')) {
                setTimeout(function () {
                    if ($$.val() == title) $$.val('');
                    $$.not(document.activeElement).blur();
                }, 10);
            }

			// remove the field text
			jQuery(window).bind('beforeunload', function() {
				if ($$.val() == title)
					$$.val('');
			});
        }
    });
};

})(jQuery);
