/*
 * jQuery UI Effects 1.7.1
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/
 */
;jQuery.effects || (function($) {

$.effects = {
	version: "1.7.1",

	save: function(element, set) {
		for(var i=0; i < set.length; i++) {
			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
		}
	},

	restore: function(element, set) {
		for(var i=0; i < set.length; i++) {
			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
		}
	},

	setMode: function(el, mode) {
		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
		return mode;
	},

	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
		var y, x;
		switch (origin[0]) {
			case 'top': y = 0; break;
			case 'middle': y = 0.5; break;
			case 'bottom': y = 1; break;
			default: y = origin[0] / original.height;
		};
		switch (origin[1]) {
			case 'left': x = 0; break;
			case 'center': x = 0.5; break;
			case 'right': x = 1; break;
			default: x = origin[1] / original.width;
		};
		return {x: x, y: y};
	},

	createWrapper: function(element) {

		if (element.parent().is('.ui-effects-wrapper'))
			return element.parent();

		var props = { width: element.outerWidth(true), height: element.outerHeight(true), 'float': element.css('float') };
		element.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');
		var wrapper = element.parent();

		if (element.css('position') == 'static') {
			wrapper.css({ position: 'relative' });
			element.css({ position: 'relative'} );
		} else {
			var top = element.css('top'); if(isNaN(parseInt(top,10))) top = 'auto';
			var left = element.css('left'); if(isNaN(parseInt(left,10))) left = 'auto';
			wrapper.css({ position: element.css('position'), top: top, left: left, zIndex: element.css('z-index') }).show();
			element.css({position: 'relative', top: 0, left: 0 });
		}

		wrapper.css(props);
		return wrapper;
	},

	removeWrapper: function(element) {
		if (element.parent().is('.ui-effects-wrapper'))
			return element.parent().replaceWith(element);
		return element;
	},

	setTransition: function(element, list, factor, value) {
		value = value || {};
		$.each(list, function(i, x){
			unit = element.cssUnit(x);
			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
		});
		return value;
	},

	animateClass: function(value, duration, easing, callback) {

		var cb = (typeof easing == "function" ? easing : (callback ? callback : null));
		var ea = (typeof easing == "string" ? easing : null);

		return this.each(function() {

			var offset = {}; var that = $(this); var oldStyleAttr = that.attr("style") || '';
			if(typeof oldStyleAttr == 'object') oldStyleAttr = oldStyleAttr["cssText"]; /* Stupidly in IE, style is a object.. */
			if(value.toggle) { that.hasClass(value.toggle) ? value.remove = value.toggle : value.add = value.toggle; }

			var oldStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
			if(value.add) that.addClass(value.add); if(value.remove) that.removeClass(value.remove);
			var newStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
			if(value.add) that.removeClass(value.add); if(value.remove) that.addClass(value.remove);

			for(var n in newStyle) {
				if( typeof newStyle[n] != "function" && newStyle[n] /* No functions and null properties */
				&& n.indexOf("Moz") == -1 && n.indexOf("length") == -1 /* No mozilla spezific render properties. */
				&& newStyle[n] != oldStyle[n] /* Only values that have changed are used for the animation */
				&& (n.match(/color/i) || (!n.match(/color/i) && !isNaN(parseInt(newStyle[n],10)))) /* Only things that can be parsed to integers or colors */
				&& (oldStyle.position != "static" || (oldStyle.position == "static" && !n.match(/left|top|bottom|right/))) /* No need for positions when dealing with static positions */
				) offset[n] = newStyle[n];
			}

			that.animate(offset, duration, ea, function() { // Animate the newly constructed offset object
				if(typeof $(this).attr("style") == 'object') { $(this).attr("style")["cssText"] = ""; $(this).attr("style")["cssText"] = oldStyleAttr; } else $(this).attr("style", oldStyleAttr);
				if(value.add) $(this).addClass(value.add); if(value.remove) $(this).removeClass(value.remove);
				if(cb) cb.apply(this, arguments);
			});

		});
	}
};


function _normalizeArguments(a, m) {

	var o = a[1] && a[1].constructor == Object ? a[1] : {}; if(m) o.mode = m;
	var speed = a[1] && a[1].constructor != Object ? a[1] : (o.duration ? o.duration : a[2]); //either comes from options.duration or the secon/third argument
		speed = $.fx.off ? 0 : typeof speed === "number" ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
	var callback = o.callback || ( $.isFunction(a[1]) && a[1] ) || ( $.isFunction(a[2]) && a[2] ) || ( $.isFunction(a[3]) && a[3] );

	return [a[0], o, speed, callback];

}

$.fn.extend({

	_show: $.fn.show,
	_hide: $.fn.hide,
	__toggle: $.fn.toggle,
	_addClass: $.fn.addClass,
	_removeClass: $.fn.removeClass,
	_toggleClass: $.fn.toggleClass,

	effect: function(fx, options, speed, callback) {
		return $.effects[fx] ? $.effects[fx].call(this, {method: fx, options: options || {}, duration: speed, callback: callback }) : null;
	},

	show: function() {
		if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
			return this._show.apply(this, arguments);
		else {
			return this.effect.apply(this, _normalizeArguments(arguments, 'show'));
		}
	},

	hide: function() {
		if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
			return this._hide.apply(this, arguments);
		else {
			return this.effect.apply(this, _normalizeArguments(arguments, 'hide'));
		}
	},

	toggle: function(){
		if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])) || (arguments[0].constructor == Function))
			return this.__toggle.apply(this, arguments);
		else {
			return this.effect.apply(this, _normalizeArguments(arguments, 'toggle'));
		}
	},

	addClass: function(classNames, speed, easing, callback) {
		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
	},
	removeClass: function(classNames,speed,easing,callback) {
		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
	},
	toggleClass: function(classNames,speed,easing,callback) {
		return ( (typeof speed !== "boolean") && speed ) ? $.effects.animateClass.apply(this, [{ toggle: classNames },speed,easing,callback]) : this._toggleClass(classNames, speed);
	},
	morph: function(remove,add,speed,easing,callback) {
		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
	},
	switchClass: function() {
		return this.morph.apply(this, arguments);
	},

	cssUnit: function(key) {
		var style = this.css(key), val = [];
		$.each( ['em','px','%','pt'], function(i, unit){
			if(style.indexOf(unit) > 0)
				val = [parseFloat(style), unit];
		});
		return val;
	}
});

/*
 * jQuery Color Animations
 * Copyright 2007 John Resig
 * Released under the MIT and GPL licenses.
 */

$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
		$.fx.step[attr] = function(fx) {
				if ( fx.state == 0 ) {
						fx.start = getColor( fx.elem, attr );
						fx.end = getRGB( fx.end );
				}

				fx.elem.style[attr] = "rgb(" + [
						Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0],10), 255), 0),
						Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1],10), 255), 0),
						Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2],10), 255), 0)
				].join(",") + ")";
			};
});


function getRGB(color) {
		var result;

		if ( color && color.constructor == Array && color.length == 3 )
				return color;

		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];

		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];

		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];

		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];

		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
				return colors['transparent'];

		return colors[$.trim(color).toLowerCase()];
}

function getColor(elem, attr) {
		var color;

		do {
				color = $.curCSS(elem, attr);

				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
						break;

				attr = "backgroundColor";
		} while ( elem = elem.parentNode );

		return getRGB(color);
};


var colors = {
	aqua:[0,255,255],
	azure:[240,255,255],
	beige:[245,245,220],
	black:[0,0,0],
	blue:[0,0,255],
	brown:[165,42,42],
	cyan:[0,255,255],
	darkblue:[0,0,139],
	darkcyan:[0,139,139],
	darkgrey:[169,169,169],
	darkgreen:[0,100,0],
	darkkhaki:[189,183,107],
	darkmagenta:[139,0,139],
	darkolivegreen:[85,107,47],
	darkorange:[255,140,0],
	darkorchid:[153,50,204],
	darkred:[139,0,0],
	darksalmon:[233,150,122],
	darkviolet:[148,0,211],
	fuchsia:[255,0,255],
	gold:[255,215,0],
	green:[0,128,0],
	indigo:[75,0,130],
	khaki:[240,230,140],
	lightblue:[173,216,230],
	lightcyan:[224,255,255],
	lightgreen:[144,238,144],
	lightgrey:[211,211,211],
	lightpink:[255,182,193],
	lightyellow:[255,255,224],
	lime:[0,255,0],
	magenta:[255,0,255],
	maroon:[128,0,0],
	navy:[0,0,128],
	olive:[128,128,0],
	orange:[255,165,0],
	pink:[255,192,203],
	purple:[128,0,128],
	violet:[128,0,128],
	red:[255,0,0],
	silver:[192,192,192],
	white:[255,255,255],
	yellow:[255,255,0],
	transparent: [255,255,255]
};

/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 *
 * Open source under the BSD License.
 *
 * Copyright 2008 George McGinley Smith
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 *
 * Neither the name of the author nor the names of contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
*/

$.easing.jswing = $.easing.swing;

$.extend($.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		return $.easing[$.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 *
 * Open source under the BSD License.
 *
 * Copyright 2001 Robert Penner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 *
 * Neither the name of the author nor the names of contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

})(jQuery);
/*
 * jQuery UI Effects Highlight 1.7.1
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Highlight
 *
 * Depends:
 *	effects.core.js
 */
(function($) {

$.effects.highlight = function(o) {

	return this.queue(function() {

		var el = $(this), props = ['backgroundImage','backgroundColor','opacity'];

		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
		var color = o.options.color || "#ffff99"; // Default highlight color
		var oldColor = el.css("backgroundColor");

		$.effects.save(el, props); el.show(); // Save & Show
		el.css({backgroundImage: 'none', backgroundColor: color}); // Shift

		var animation = {backgroundColor: oldColor };
		if (mode == "hide") animation['opacity'] = 0;

		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
			if(mode == "hide") el.hide();
			$.effects.restore(el, props);
		if (mode == "show" && $.browser.msie) this.style.removeAttribute('filter');
			if(o.callback) o.callback.apply(this, arguments);
			el.dequeue();
		}});

	});

};

})(jQuery);
/*
 * Facebox (for jQuery)
 * version: 1.2 (05/05/2008)
 * @requires jQuery v1.2 or later
 *
 * Examples at http://famspam.com/facebox/
 *
 * Licensed under the MIT:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ]
 *
 * Usage:
 *
 *  jQuery(document).ready(function() {
 *    jQuery('a[rel*=facebox]').facebox()
 *  })
 *
 *  <a href="#terms" rel="facebox">Terms</a>
 *    Loads the #terms div in the box
 *
 *  <a href="terms.html" rel="facebox">Terms</a>
 *    Loads the terms.html page in the box
 *
 *  <a href="terms.png" rel="facebox">Terms</a>
 *    Loads the terms.png image in the box
 *
 *
 *  You can also use it programmatically:
 *
 *    jQuery.facebox('some html')
 *
 *  The above will open a facebox with "some html" as the content.
 *
 *    jQuery.facebox(function($) {
 *      $.get('blah.html', function(data) { $.facebox(data) })
 *    })
 *
 *  The above will show a loading screen before the passed function is called,
 *  allowing for a better ajaxy experience.
 *
 *  The facebox function can also display an ajax page or image:
 *
 *    jQuery.facebox({ ajax: 'remote.html' })
 *    jQuery.facebox({ image: 'dude.jpg' })
 *
 *  Want to close the facebox?  Trigger the 'close.facebox' document event:
 *
 *    jQuery(document).trigger('close.facebox')
 *
 *  Facebox also has a bunch of other hooks:
 *
 *    loading.facebox
 *    beforeReveal.facebox
 *    reveal.facebox (aliased as 'afterReveal.facebox')
 *    init.facebox
 *
 *  Simply bind a function to any of these hooks:
 *
 *   $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... })
 *
 */
(function($) {
  $.facebox = function(data, klass) {
    $.facebox.loading()

    if (data.ajax) fillFaceboxFromAjax(data.ajax)
    else if (data.image) fillFaceboxFromImage(data.image)
    else if (data.div) fillFaceboxFromHref(data.div)
    else if ($.isFunction(data)) data.call($)
    else $.facebox.reveal(data, klass)
  }

  /*
   * Public, $.facebox methods
   */

  $.extend($.facebox, {
    settings: {
      opacity      : 0.15,
      overlay      : true,
      loadingImage : 'http://dev-jsrails.timeinc.net/i/facebox/loading.gif',
      closeImage   : 'http://dev-jsrails.timeinc.net/i/facebox/closelabel.gif',
      imageTypes   : [ 'png', 'jpg', 'jpeg', 'gif' ],
      faceboxHtml  : '<div id="facebox"><div id="co_bkgd"><div class="content"></div></div><span id="co_nw" class="co_corner"></span><span id="co_ne" class="co_corner"></span><span id="co_se" class="co_corner"></span><span id="co_sw" class="co_corner"></span><span class="close"></span></div>'
    },

    loading: function() {
      init()
      if ($('#facebox .loading').length == 1) return true
      showOverlay()

      $('#facebox .content').empty()
      $('#facebox .body').children().hide().end().
        append('<div class="loading"><img src="'+$.facebox.settings.loadingImage+'"/></div>')

      $('#facebox').css({
        top:	getPageScroll()[1] + (getPageHeight() / 10),
        left:	385.5
      }).show()

      $(document).bind('keydown.facebox', function(e) {
        if (e.keyCode == 27) $.facebox.close()
        return true
      })
      $(document).trigger('loading.facebox')
    },

    reveal: function(data, klass) {
      $(document).trigger('beforeReveal.facebox')
      if (klass) $('#facebox .content').addClass(klass)
      $('#facebox .content').append(data)
      $('#facebox .loading').remove()
      $('#facebox .body').children().fadeIn('normal')
      $('#facebox').css('left', $(window).width() / 2 - ($('#facebox').width() / 2))
      $(document).trigger('reveal.facebox').trigger('afterReveal.facebox')
    },

    close: function() {
      $(document).trigger('close.facebox')
      return false
    }
  })

  /*
   * Public, $.fn methods
   */

  $.fn.facebox = function(settings) {
    init(settings)

    function clickHandler() {
      $.facebox.loading(true)

      var klass = this.rel.match(/facebox\[?\.(\w+)\]?/)
      if (klass) klass = klass[1]

      fillFaceboxFromHref(this.href, klass)
      return false
    }

    return this.click(clickHandler)
  }

  /*
   * Private methods
   */

  function init(settings) {
    if ($.facebox.settings.inited) return true
    else $.facebox.settings.inited = true

    $(document).trigger('init.facebox')
    makeCompatible()

    var imageTypes = $.facebox.settings.imageTypes.join('|')
    $.facebox.settings.imageTypesRegexp = new RegExp('\.' + imageTypes + '$', 'i')

    if (settings) $.extend($.facebox.settings, settings)
    $('body').append($.facebox.settings.faceboxHtml)

    var preload = [ new Image(), new Image() ]
    preload[0].src = $.facebox.settings.closeImage
    preload[1].src = $.facebox.settings.loadingImage

    $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() {
      preload.push(new Image())
      preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1')
    })

    $('#facebox .close').click($.facebox.close)
    $('#facebox .close_image').attr('src', $.facebox.settings.closeImage)
  }

  function getPageScroll() {
    var xScroll, yScroll;
    if (self.pageYOffset) {
      yScroll = self.pageYOffset;
      xScroll = self.pageXOffset;
    } else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict
      yScroll = document.documentElement.scrollTop;
      xScroll = document.documentElement.scrollLeft;
    } else if (document.body) {// all other Explorers
      yScroll = document.body.scrollTop;
      xScroll = document.body.scrollLeft;
    }
    return new Array(xScroll,yScroll)
  }

  function getPageHeight() {
    var windowHeight
    if (self.innerHeight) {	// all except Explorer
      windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
      windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
      windowHeight = document.body.clientHeight;
    }
    return windowHeight
  }

  function makeCompatible() {
    var $s = $.facebox.settings

    $s.loadingImage = $s.loading_image || $s.loadingImage
    $s.closeImage = $s.close_image || $s.closeImage
    $s.imageTypes = $s.image_types || $s.imageTypes
    $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml
  }

  function fillFaceboxFromHref(href, klass) {
    if (href.match(/#/)) {
      var url    = window.location.href.split('#')[0]
      var target = href.replace(url,'')
      $.facebox.reveal($(target).clone().show(), klass)

    } else if (href.match($.facebox.settings.imageTypesRegexp)) {
      fillFaceboxFromImage(href, klass)
    } else {
      fillFaceboxFromAjax(href, klass)
    }
  }

  function fillFaceboxFromImage(href, klass) {
    var image = new Image()
    image.onload = function() {
      $.facebox.reveal('<div class="image"><img src="' + image.src + '" /></div>', klass)
    }
    image.src = href
  }

  function fillFaceboxFromAjax(href, klass) {
    $.get(href, function(data) { $.facebox.reveal(data, klass) })
  }

  function skipOverlay() {
    return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null
  }

  function showOverlay() {
    if (skipOverlay()) return

    if ($('facebox_overlay').length == 0)
      $("body").append('<div id="facebox_overlay" class="facebox_hide"></div>')

    $('#facebox_overlay').hide().addClass("facebox_overlayBG")
      .css('opacity', $.facebox.settings.opacity)
      .click(function() { $(document).trigger('close.facebox') })
      .fadeIn(200)
    return false
  }

  function hideOverlay() {
    if (skipOverlay()) return

    $('#facebox_overlay').fadeOut(200, function(){
      $("#facebox_overlay").removeClass("facebox_overlayBG")
      $("#facebox_overlay").addClass("facebox_hide")
      $("#facebox_overlay").remove()
    })

    return false
  }

  /*
   * Bindings
   */

  $(document).bind('close.facebox', function() {
    $(document).unbind('keydown.facebox')
    $('#facebox').fadeOut(function() {
      $('#facebox .content').removeClass().addClass('content')
      hideOverlay()
      $('#facebox .loading').remove()
    })
  })

})(jQuery);
/**
 * Copyright (c) 2005 - 2009, James Auldridge
 * All rights reserved.
 *
 * Licensed under the BSD, MIT, and GPL (your choice!) Licenses:
 *  http://code.google.com/p/cookies/wiki/License
 *
 */
var jaaulde = window.jaaulde || {};
jaaulde.utils = jaaulde.utils || {};
jaaulde.utils.cookies = ( function()
{
	var cookies = [];

	var defaultOptions = {
		hoursToLive: null,
		path: '/',
		domain:  null,
		secure: false
	};
	/**
	 * resolveOptions - receive an options object and ensure all options are present and valid, replacing with defaults where necessary
	 *
	 * @access private
	 * @static
	 * @parameter Object options - optional options to start with
	 * @return Object complete and valid options object
	 */
	var resolveOptions = function( options )
	{
		var returnValue;

		if( typeof options !== 'object' || options === null )
		{
			returnValue = defaultOptions;
		}
		else
		{
			returnValue = {
				hoursToLive: ( typeof options.hoursToLive === 'number' && options.hoursToLive !== 0 ? options.hoursToLive : defaultOptions.hoursToLive ),
				path: ( typeof options.path === 'string' && options.path !== '' ? options.path : defaultOptions.path ),
				domain: ( typeof options.domain === 'string' && options.domain !== '' ? options.domain : defaultOptions.domain ),
				secure: ( typeof options.secure === 'boolean' && options.secure ? options.secure : defaultOptions.secure )
			};
		}

		return returnValue;
	};
	/**
	 * expiresGMTString - add given number of hours to current date/time and convert to GMT string
	 *
	 * @access private
	 * @static
	 * @parameter Integer hoursToLive - number of hours for which cookie should be valid
	 * @return String - GMT time representing current date/time plus number of hours given
	 */
	var expiresGMTString = function( hoursToLive )
	{
		var dateObject = new Date();
		dateObject.setTime( dateObject.getTime() + ( hoursToLive * 60 * 60 * 1000 ) );

		return dateObject.toGMTString();
	};
	/**
	 * assembleOptionsString - analyze options and assemble appropriate string for setting a cookie with those options
	 *
	 * @access private
	 * @static
	 * @parameter Object options - optional options to start with
	 * @return String - complete and valid cookie setting options
	 */
	var assembleOptionsString = function( options )
	{
		options = resolveOptions( options );

		return (
			( typeof options.hoursToLive === 'number' ? '; expires=' + expiresGMTString( options.hoursToLive ) : '' ) +
			'; path=' + options.path +
			( typeof options.domain === 'string' ? '; domain=' + options.domain : '' ) +
			( options.secure === true ? '; secure' : '' )
		);
	};
	/**
	 * splitCookies - retrieve document.cookie string and break it into a hash
	 *
	 * @access private
	 * @static
	 * @return Object - hash of cookies from document.cookie
	 */
	var splitCookies = function()
	{
		cookies = {};
		var pair, name, value, separated = document.cookie.split( ';' );
		for( var i = 0; i < separated.length; i = i + 1 )
		{
			pair = separated[i].split( '=' );
			name = pair[0].replace( /^\s*/, '' ).replace( /\s*$/, '' );
			value = decodeURIComponent( pair[1] );
			cookies[name] = value;
		}
		return cookies;
	};

	var constructor = function(){};

	/**
	 * get - get one, several, or all cookies
	 *
	 * @access public
	 * @paramater Mixed cookieName - String:name of single cookie; Array:list of multiple cookie names; Void (no param):if you want all cookies
	 * @return Mixed - String:if single cookie requested and found; Null:if single cookie requested and not found; Object:hash of multiple or all cookies
	 */
	constructor.prototype.get = function( cookieName )
	{
		var returnValue;

		splitCookies();

		if( typeof cookieName === 'string' )
		{
			returnValue = ( typeof cookies[cookieName] !== 'undefined' ) ? cookies[cookieName] : null;
		}
		else if( typeof cookieName === 'object' && cookieName !== null )
		{
			returnValue = {};
			for( var item in cookieName )
			{
				if( typeof cookies[cookieName[item]] !== 'undefined' )
				{
					returnValue[cookieName[item]] = cookies[cookieName[item]];
				}
				else
				{
					returnValue[cookieName[item]] = null;
				}
			}
		}
		else
		{
			returnValue = cookies;
		}

		return returnValue;
	};
	/**
	 * filter - get array of cookies whose names match the provided RegExp
	 *
	 * @access public
	 * @paramater Object RegExp - The regular expression to match against cookie names
	 * @return Mixed - Object:hash of cookies whose names match the RegExp
	 */
	constructor.prototype.filter = function( cookieNameRegExp )
	{
		var returnValue = {};

		splitCookies();

		if( typeof cookieNameRegExp === 'string' )
		{
			cookieNameRegExp = new RegExp( cookieNameRegExp );
		}

		for( var cookieName in cookies )
		{
			if( cookieName.match( cookieNameRegExp ) )
			{
				returnValue[cookieName] = cookies[cookieName];
			}
		}

		return returnValue;
	};
	/**
	 * set - set or delete a cookie with desired options
	 *
	 * @access public
	 * @paramater String cookieName - name of cookie to set
	 * @paramater Mixed value - Null:if deleting, String:value to assign cookie if setting
	 * @paramater Object options - optional list of cookie options to specify (hoursToLive, path, domain, secure)
	 * @return void
	 */
	constructor.prototype.set = function( cookieName, value, options )
	{
		if( typeof value === 'undefined' || value === null )
		{
			if( typeof options !== 'object' || options === null )
			{
				options = {};
			}
			value = '';
			options.hoursToLive = -8760;
		}

		var optionsString = assembleOptionsString( options );

		document.cookie = cookieName + '=' + encodeURIComponent( value ) + optionsString;
	};
	/**
	 * del - delete a cookie (domain and path options must match those with which the cookie was set; this is really an alias for set() with parameters simplified for this use)
	 *
	 * @access public
	 * @paramater MIxed cookieName - String name of cookie to delete, or Bool true to delete all
	 * @paramater Object options - optional list of cookie options to specify ( path, domain )
	 * @return void
	 */
	constructor.prototype.del = function( cookieName, options )
	{
		var allCookies = {};

		if( typeof options !== 'object' || options === null )
		{
			options = {};
		}

		if( typeof cookieName === 'boolean' && cookieName === true )
		{
			allCookies = this.get();
		}
		else if( typeof cookieName === 'string' )
		{
			allCookies[cookieName] = true;
		}

		for( var name in allCookies )
		{
			if( typeof name === 'string' && name !== '' )
			{
				this.set( name, null, options );
			}
		}
	};
	/**
	 * test - test whether the browser is accepting cookies
	 *
	 * @access public
	 * @return Boolean
	 */
	constructor.prototype.test = function()
	{
		var returnValue = false, testName = 'cT', testValue = 'data';

		this.set( testName, testValue );

		if( this.get( testName ) === testValue )
		{
			this.del( testName );
			returnValue = true;
		}

		return returnValue;
	};
	/**
	 * setOptions - set default options for calls to cookie methods
	 *
	 * @access public
	 * @param Object options - list of cookie options to specify (hoursToLive, path, domain, secure)
	 * @return void
	 */
	constructor.prototype.setOptions = function( options )
	{
		if( typeof options !== 'object' )
		{
			options = null;
		}

		defaultOptions = resolveOptions( options );
	};

	return new constructor();
} )();

( function()
{
	if( window.jQuery )
	{
		( function( $ )
		{
			$.cookies = jaaulde.utils.cookies;

			var extensions = {
				/**
				 * $( 'selector' ).cookify - set the value of an input field or the innerHTML of an element to a cookie by the name or id of the field or element
				 *                           (radio and checkbox not yet supported)
				 *                           (field or element MUST have name or id attribute)
				 *
				 * @access public
				 * @param Object options - list of cookie options to specify
				 * @return Object jQuery
				 */
				cookify: function( options )
				{
					return this.each( function()
					{
						var i, resolvedName = false, resolvedValue = false, name = '', value = '', nameAttrs = ['name', 'id'], nodeName, inputType;

						for( i in nameAttrs )
						{
							if( ! isNaN( i ) )
							{
								name = $( this ).attr( nameAttrs[ i ] );
								if( typeof name === 'string' && name !== '' )
								{
									resolvedName = true;
									break;
								}
							}
						}

						if( resolvedName )
						{
							nodeName = this.nodeName.toLowerCase();
							if( nodeName !== 'input' && nodeName !== 'textarea' && nodeName !== 'select' && nodeName !== 'img' )
							{
								value = $( this ).html();
								resolvedValue = true;
							}
							else
							{
								inputType = $( this ).attr( 'type' );
								if( typeof inputType === 'string' && inputType !== '' )
								{
									inputType = inputType.toLowerCase();
								}
								if( inputType !== 'radio' && inputType !== 'checkbox' )
								{
									value = $( this ).val();
									resolvedValue = true;
								}
							}

							if( resolvedValue )
							{
								if( typeof value !== 'string' || value === '' )
								{
									value = null;
								}
								$.cookies.set( name, value, options );
							}
						}
					} );
				},
				/**
				 * $( 'selector' ).cookieFill - set the value of an input field or the innerHTML of an element from a cookie by the name or id of the field or element
				 *
				 * @access public
				 * @return Object jQuery
				 */
				cookieFill: function()
				{
					return this.each( function()
					{
						var i, resolvedName = false, name = '', value, nameAttrs = ['name', 'id'], iteration = 0, nodeName;

						for( i in nameAttrs )
						{
							if( ! isNaN( i ) )
							{
								name = $( this ).attr( nameAttrs[ i ] );
								if( typeof name === 'string' && name !== '' )
								{
									resolvedName = true;
									break;
								}
							}
						}

						if( resolvedName )
						{
							value = $.cookies.get( name );
							if( value !== null )
							{
								nodeName = this.nodeName.toLowerCase();
								if( nodeName === 'input' || nodeName === 'textarea' || nodeName === 'select' )
								{
								    $( this ).val( value );
								}
								else
								{
									$( this ).html( value );
								}
							}
						}

						iteration = 0;
					} );
				},
				/**
				 * $( 'selector' ).cookieBind - call cookie fill on matching elements, and bind their change events to cookify()
				 *
				 * @access public
				 * @param Object options - list of cookie options to specify
				 * @return Object jQuery
				 */
				cookieBind: function( options )
				{
					return this.each( function()
					{
						$( this ).cookieFill().change( function()
						{
							$( this ).cookify( options );
						} );
					} );
				}
			};

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

		} )( window.jQuery );
	}
} )();
/*
 * comments.js
 *
 */
var Comment = (function($) {
  var c = {
    base_url: null,
    brand_name: null,
    section_name: null,
    board_name: null,
    board_url: null,
    board_resource_id: null,

    init: function(options) {
      options = options || {};

      c.base_url = options["base_url"];
      c.brand_name = options["brand_name"];
      c.section_name = options["section_name"];
      c.board_name = encodeURIComponent(options["board_name"]);
      c.board_url = encodeURIComponent(options["board_url"]);
      c.board_resource_id = escape(options["board_resource_id"]);

      c.init_form_behaviours();
    },

    init_expand_replies_links: function() {
      $("#comments a.get.expand_replies_link").live("click", function() {
        var comment_id = $(this).parents(".comment").attr("id").split('_').last();
        c.render_children(comment_id);
        $(this).removeClass("get").addClass("toggle expanded");
        return false;
      });

      $("#comments a.toggle.expand_replies_link").live("click", function() {
        var comment_id = $(this).parents(".comment").attr("id").split('_').last();
        var replies = $("#comment_"+comment_id+" .replies:first");
        if(replies.is(":visible")) {
          replies.hide();
          $(this).removeClass("expanded");
        } else {
          replies.show();
          $(this).addClass("expanded");
          c.scroll_to(replies);
        }
        return false;
      });
    },

    init_add_reply_links: function() {
      $("#comments a.get.add_reply_link").live("click", function() {
        var comment_id = $(this).parents(".comment").attr("id").split('_').last();
        if($(this).parents(".comment").length < 3) {
          var parent_id = comment_id;
        } else {
          var parent_id = $($(this).parents(".comment")[1]).attr("id").split('_').last();
        }
        reply_form = c.clone_form(parent_id);
        reply_form.appendTo("#comment_"+comment_id+" div.form:first");
        c.init_form_behaviours(comment_id);
        c.scroll_to(reply_form);
        $(this).removeClass("get").addClass("toggle");
        return false;
      });

      $("#comments a.toggle.add_reply_link").live("click", function() {
        var comment_id = $(this).parents(".comment").attr("id").split('_').last();
        var form_div = $("#comment_"+comment_id+" div.form:first");
        form_div.toggle();
        if(form_div.is(":visible")) c.scroll_to(form_div);
        return false;
      });
    },

    init_form_behaviours: function(id) {
      var iframe_name = id ? "postiframe_"+id : "postiframe";
      var form = id ? $("#comment_"+id+" form:first") : $("#new_comment_form");

      form.submit(function() {
        var iframe = '<iframe name="'+iframe_name+'" style="display:none;"></iframe>';
        $(document.body).append(iframe);
        iframe = $("iframe:last");

        form.attr("action", c.comments_url()).attr("target", iframe_name).attr("method", "post");

        iframe.load(function(){
          var response_string = iframe.contents().find("body").html();
          try {
            response = eval("(" + response_string + ")");
          } catch(e) { response = {}; }
          if(response.errors) {
            c.render_comment_errors(response.errors, form);
          } else if(response.comment) {
            c.insert_comment(response.comment);
            c.reset_form(form, {hide: true});
          } else if(response_string.length > 0) {
            c.render_message(response_string); // e.g.: Your comment will appear shortly
            c.reset_form(form, {hide: true});
          }
          setTimeout(function() { iframe.remove(); }, 200);
        });
      });
    },



    comments_url: function() {
      return c.build_url([c.board_resource_id, "comments"], ".json?page="+Url.get_param("page")+"&order="+Url.get_param("order")+"&expand_all="+Url.get_param("expand_all")+"&per_page="+Url.get_param("per_page")+"&board_name="+c.board_name+"&board_url="+c.board_url+"&callback=?");
    },

    children_url: function(parent) {
      return c.build_url([c.board_resource_id, "comments", parent, "children"], ".json?board_name=" + c.board_name + "&board_url=" + c.board_url + "&callback=?");
    },

    top_boards_url: function() {
      return c.build_url([], ".json?callback=?");
    },

    featured_comment_url: function(options) {
      var options = options || {};
      var url = c.base_url + "/featured_comments.json?callback=?";

      switch(options["scope"]) {
      case 'brand':
        url += "&brand_name="+c.brand_name;
        break;
      case 'section':
        url += "&brand_name="+c.brand_name+"&section_name="+c.section_name;
        break;
      case 'board':
        url += "&brand_name="+c.brand_name+"&section_name="+c.section_name+"&board_resource_id="+c.board_resource_id+"&board_name="+c.board_name+"&board_url="+c.board_url;
        break;
      }
      return url;
    },

    comments_count_url: function() {
      var board_resource_ids = $.map($("a.comments_count"), function(link) { return link.rel; });
      if (board_resource_ids.length == 0) return;
      var url = c.base_url + "/brands/" + c.brand_name + "/sections/" + c.section_name + "/boards/comments_count?board_resource_id[]=" + board_resource_ids.join("&board_resource_id[]=") + "&callback=?";
      return url;
    },

    build_url: function(url_atoms, qs) {
      return [c.base_url, 'brands', c.brand_name, 'sections', c.section_name, 'boards'].concat(url_atoms).join('/') + qs;
    },

    render_comments_with_pagination: function(options) {
      Url.defaults = options || {};

      $.getJSON(c.comments_url(), function(data) {
        var pagination = data.pagination;
        Pagination.init(pagination);
        pagination.info = Pagination.pagination_info();
        pagination.links = Pagination.paginate();
        pagination.expand_all_or_collapse_all = c.expand_all_or_collapse_all_link();
        pagination.oldest_first = c.oldest_first_link_or_span();
        pagination.newest_first = c.newest_first_link_or_span();

        $("#comments").empty();
        $("#comments").before(Template.evaluate(c.top_pagination_template(), pagination));
        c.render_comments(data.comments, "#comments");
        $("#comments").after(Template.evaluate(c.bottom_pagination_template(), pagination));
        c.init_expand_replies_links();
        c.init_add_reply_links();
      });
    },

    render_comments: function(comments, container) {
      $.each(comments, function(i, obj) {
        var comment = obj.comment ? obj.comment : obj;
        $(container).append(Template.evaluate(c.comment_template(), comment));
        if(comment.comments && comment.comments.length > 0) {
          $("#toggle_replies_"+comment.id).removeClass("get").addClass("toggle expanded");
          c.render_comments(comment.comments, "#comment_"+comment.id+" .replies:first");
          if(comment.viewable_children_count > comment.comments.length) {
            $("#comment_"+comment.id+" .replies:first").append(Template.evaluate(c.more_comments_template(), {comments: comment.viewable_children_count, remaining_comments: comment.viewable_children_count-comment.comments.length }));
          }
        }
      });
    },

    render_comment_errors: function(errors, form) {
      var object = {};
      object.count = errors.length;
      object.errors = '';
      $.each(errors, function(i, error) {
        object.errors += error[0].capitalize() + " " + error[1] + "<br />";
      });
      form.find("div.errors").empty().append(Template.evaluate(c.comment_errors_template(), object));
    },

    render_message: function(response) {
      message = $("<div/>").attr("class", "comment").append(response);
      $("#comments").append(message);
      c.scroll_to(message);
    },

    render_children: function(parent, options) {
      options = options || {};
      $.getJSON(c.children_url(parent), function(data) {
        var container = $("#comment_"+parent+" .replies:first");
        container.empty();
        c.render_comments(data, container);
        c.scroll_to(container);
        if(options.highlight) c.highlight("#comment_"+options.highlight);
      });
    },

    render_top_boards: function() {
      $.getJSON(c.top_boards_url(), function(data) {
  		if(data.length > 0) {
  		  var top_boards = '';
        $.each(data, function(i, obj) {
          top_boards += Template.evaluate(c.top_board_template(), obj.board);
        });
        $("#top_boards").append(Template.evaluate(c.top_boards_template(), {top_boards: top_boards}));
  		}
      });
    },

    render_featured_comment: function(options) {
      $.getJSON(c.featured_comment_url(options), function(data) {
        if(data) $("#featured_comment").append(Template.evaluate(c.featured_comment_template(), data.comment));
      });
    },

    render_comments_count: function() {
      $.getJSON(c.comments_count_url(), function(data) {
        $("a.comments_count").each(function() {
          board_resource_id = $(this).attr("rel");
          object = {count: data[board_resource_id]};
          if (object.count > 0) $(this).html(Template.evaluate(c.comments_count_template(), object));
        });
      });
    },

    insert_comment: function(comment) {
      order = Url.get_param("order") || 'ASC';

      if ($("#comments").size() == 0) {
        window.location = Url.new_url({order: "DESC"}, decodeURIComponent(c.board_url));
      } else if (comment["parent_id"] > 0) {
        if ($("#toggle_replies_"+comment.parent_id).hasClass("get.expand_replies_link.not_empty")) {
          c.render_children(comment.parent_id, {highlight: comment.id});
        } else {
          var replies = $("#comment_"+comment["parent_id"]+" .replies:first");
          replies.append(Template.evaluate(c.comment_template(), comment));
          if (replies.is(":hidden")) replies.show();
          c.scroll_to_and_highlight("#comment_"+comment["id"]);
        }
        $("#toggle_replies_"+comment.parent_id).removeClass("get").addClass("toggle expanded");
        c.update_replies_count(comment.parent_id);
      } else if (order == "ASC") {
        if (Pagination.current_page == Pagination.total_pages) {
          $("#comments").append(Template.evaluate(c.comment_template(), comment));
          c.scroll_to_and_highlight("#comment_"+comment["id"]);
        } else {
          window.location = Url.new_url({page: Pagination.total_pages});
        }
      } else if (order == "DESC") {
        if (Pagination.current_page == 1) {
          $("#comments").prepend(Template.evaluate(c.comment_template(), comment));
          c.scroll_to_and_highlight("#comment_"+comment["id"]);
        } else {
          window.location = Url.new_url({page: 1});
        }
      }
    },

    clone_form: function(comment_id) {
      var reply_form = $("#new_comment_form").clone();
      reply_form.removeAttr("id");
      reply_form.append('<input type="hidden" name="comment[parent_id]" value="'+comment_id+'" />');
      reply_form.find(".form_title").text("Reply");
      c.reset_form(reply_form);
      return reply_form;
    },

    scroll_to: function(element) {
      scroll_to_if_necessary(element);
    },

    highlight: function(comment) {
      $(comment).effect("highlight", {}, 3000);
    },

    scroll_to_and_highlight: function(comment) {
      c.scroll_to(comment);
      c.highlight(comment);
    },

    reset_form: function(form, options) {
      options = options || {};
      form = $(form);

      form.find("input#comment_user_name").val("");
      form.find("textarea").val("");
      form.find("div.errors").empty();
      if (form.attr("id") != "new_comment_form" && options.hide) form.parent().hide();
    },

    update_replies_count: function(id) {
      var tag = $("#toggle_replies_"+id);
      tag.text(tag.text().replace(/([\d]+)/, function(i) {return parseInt(i)+1;}));
      if(tag.hasClass("empty")) tag.removeClass("empty").addClass("not_empty");
      if(tag.hasClass("get_comment_replies")) tag.removeClass("get_comment_replies").addClass("toggle_replies");
    },

    expand_all_or_collapse_all_link: function() {
      if(Url.get_params().expand_all == 'true') {
        return '<a class="collapse" href="'+Url.new_url({expand_all: 'false'})+'">Collapse all replies</a>';
      } else {
        return '<a class="expand" href="'+Url.new_url({expand_all: 'true'})+'">Expand all replies</a>';
      }
    },

    oldest_first_link_or_span: function() {
      return c.link_or_span('Oldest first', Url.new_url({page: 1, order: 'ASC'}), Url.get_params().order == 'DESC')
    },

    newest_first_link_or_span: function() {
      return c.link_or_span('Newest first', Url.new_url({page: 1, order: 'DESC'}), Url.get_params().order != 'DESC')
    },

    link_or_span: function(text, link, needs_link) {
      if(needs_link) {
        return '<a href="'+link+'">'+text+'</a>';
      } else {
        return '<span>'+text+'</span>';
      }
    },

    comment_template: function() {
      return '<li class="comment" id="comment_#{id}"><span class="author">#{user_name}</span><span class="date">#{created_at:Format.iso_date}</span>#{body:Format.text}<div class="options"><a href="#" class="get expand_replies_link #{viewable_children_count:Format.quantity_class_name}" id="toggle_replies_#{id}">Read replies (#{viewable_children_count})</a> <a href="#" class="get add_reply_link" id="toggle_add_reply_#{id}">Add reply</a></div><div class="form"></div><ul class="replies"><li/></ul></li>';
    },

    top_pagination_template: function() {
      return '<div class="top_pagination"><div class="pagination_row1"><div class="left"><b>COMMENTS</b> (#{info})</div><div class="right">#{expand_all_or_collapse_all} <a href="#new_comment_form">Add comment</a></div></div><div class="pagination_row2"><div class="left"><span class="label">Sort by:</span> #{newest_first} | #{oldest_first}</div><div class="right"><span class="label">Page:</span><div class="pagination">#{links}</div></div></div></div>';
    },

    bottom_pagination_template: function() {
      return '<div class="bottom_pagination"><div class="right"><span class="label">Page:</span><div class="pagination">#{links}</div></div></div>';
    },

    top_boards_template: function() {
      return '<h1>Most talked about boards</h1>#{top_boards}';
    },

    top_board_template: function() {
      return '<div class="top_board"><a href="#{url}">#{name}</a> | <a href="#{url}">Comments (#{viewable_comments_count})</a></div>';
    },

    comments_count_template: function() {
      return 'Replies (#{count})';
    },

    more_comments_template: function() {
      return '<li>There are <a href="#" class="get expand_replies_link">#{remaining_comments}</a> more comments</li>';
    },

    featured_comment_template: function() {
      return '<h3>You Said It…</h3><h4>…about <a href="#{board_url}" class="link-to-article">#{board_name}</a></h4><a href="#{board_url}" class="link-to-comments">Comments (#{board_viewable_comments_count})</a><a href="#{board_url}#add-your-comment" class="link-to-comments">Add comment</a><div class="comment-body"><div class="ldquo">“</div><p>#{body}</p><div class="rdquo">”</div><span class="mdash">—</span><span class="author">#{user_name}</span></div>';
    },

    comment_errors_template: function() {
      return '#{count} errors:<br/>#{errors}';
    }
  };
  return(c);
})(jQuery);
/*
 * polls.js
 *
 */
var Poll = (function($) {
  var init_vote_form = function(id) {
    var iframe_name = "postiframe_"+id;
    var form = $("#poll_form_"+id);

    form.submit(function() {
      var voted_answers = $.map(form.find("input:checked"), function(x) { return(Poll.answer_by_id[x.value]); });
      var validation_message = Poll.validate_votes(voted_answers)
      if (validation_message) {
        Poll.render_error(id, validation_message);
        return false;
      }
      var poll = voted_answers[0].poll;
      var input_me = function(x) { return '<input name="poll[votes][]" value="' + x.id + '" />' };
      var fieldset = $("<fieldset>" + $.map(voted_answers, input_me).join('') + "</fieldset>").hide();
      fieldset.appendTo(form);
      $(document.body).append('<iframe name="'+iframe_name+'" style="display:none;"></iframe>');
      var iframe = $("iframe[name="+iframe_name+"]:last");
      form.attr("action", vote_url(id)).attr("target", iframe_name).attr("method", "post");
      iframe.load(function(){
        var response = iframe.contents().find("body").html();
        try { response = eval(response); }
        catch(e) { response = 'Something went wrong!  Please, try again!'; }
        if (response == ' ') {
          $.each(voted_answers, function(i, answer) {
            answer.vote_count += 1;
            answer.question.total_vote_count += 1;
          });
          if (poll.vote_again_in) {
            var payload = '[' + $.map(voted_answers, function(a) { a.id }) + ']';
            $.cookies.set('poll_'+poll.id, payload, {hoursToLive: (poll.vote_again_in / 3600)});
          }
          form.replaceWith(build_poll(poll, Poll.closed_poll_template(), Poll.closed_question_template(), Poll.closed_answer_template()));
        } else {
          Poll.render_error(id, response);
        }
        setTimeout(function() { iframe.remove(); fieldset.remove(); }, 200);
      });
    });
  };

  var polls_url = function() {
    return [create_article_url(), Poll.article, "polls?callback="].join('/') + Poll.callback;
  };

  var vote_url = function(poll_id) {
    return [create_article_url(), Poll.article, "polls", poll_id, "vote"].join('/');

  };

  var create_article_url =  function() {
    return [Poll.base_url, "brands", Poll.brand, "sections", Poll.section, "articles"].join('/');
  };

  var get_target = function(i) {
    return Poll.poll_targets[i] || "#polls";
  };

  var build_poll = function(poll, poll_template, question_template, answer_template) {
    poll.prebuilt_questions = build_questions(poll.questions, question_template, answer_template);
    return Template.evaluate(poll_template, poll);
  };

  var build_questions = function(questions, question_template, answer_template) {
    return $.map(questions, function(question) {
      question.prebuilt_answers = build_answers(question.answers, answer_template);
      return Template.evaluate(question_template, question);
    }).join('');
  };

  var build_answers = function(answers, answer_template) {
    return $.map(answers, function(answer) {
      var tvc = answer.question.total_vote_count;
      answer.prebuilt_image = (answer.image_source_url ? Template.evaluate(Poll.answer_image_template(), answer) : '');
      answer.prebuilt_enlarge = (answer.image_enlarge_url ? Template.evaluate(Poll.answer_image_enlarge_template(), answer) : '');;
      answer.percentage = ((tvc && tvc > 0) ? ((answer.vote_count / tvc) * 100) : 0).toFixed(2);
      return Template.evaluate(answer_template, answer);
    }).join('');
  };

  var build_creating_article = function(article) {
    article.prebuilt_creating_polls = build_creating_polls(article.polls)
    return Template.evaluate(creating_article_template(), article);
  };

  var build_creating_polls = function(polls) {
    return $.map(polls, function(poll, i) {
      poll.i = i;
      poll.prebuilt_creating_questions = build_creating_questions(poll.questions, i)
      return Template.evaluate(creating_poll_template(), poll);
    }).join('');
  };

  var build_creating_questions = function(questions, pi) {
    return $.map(questions, function(question, i) {
      question.pi = pi;
      question.i = i;
      question.prebuilt_creating_answers = build_creating_answers(question.answers, pi, i)
      return Template.evaluate(creating_question_template(), question);
    }).join('');
  };

  var build_creating_answers = function(answers, pi, qi) {
    return $.map(answers, function(answer, i) {
      answer.pi = pi;
      answer.qi = qi;
      answer.i = i;
      answer.prebuilt_image = (answer.image_source_url ? Template.evaluate(creating_answer_image_template(), answer) : '');
      answer.prebuilt_enlarge = (answer.image_enlarge_url ? Template.evaluate(creating_answer_image_enlarge_template(), answer) : '');;
      return Template.evaluate(creating_answer_template(), answer);
    }).join('');
  };

  var creating_article_template = function() {
    return '<input name="article[name]" value="#{name}" /><input name="article[url]" value="#{url}" /><input name="article[resource_id]" value="#{resource_id}" />#{prebuilt_creating_polls}';
  };

  var creating_poll_template = function() {
    return '<input name="article[polls_attributes][new_#{i}][name]" value="#{name}" /><input name="article[polls_attributes][new_#{i}][description]" value="#{description}" /><input name="article[polls_attributes][new_#{i}][vote_again_in]" value="#{vote_again_in}" /><input name="article[polls_attributes][new_#{i}][position]" value="#{position}" />#{prebuilt_creating_questions}';
  };

  var creating_question_template = function() {
    return '<input name="article[polls_attributes][new_#{pi}][questions_attributes][new_#{i}][text]" value="#{text}" /><input name="article[polls_attributes][new_#{pi}][questions_attributes][new_#{i}][position]" value="#{position}" />#{prebuilt_creating_answers}';
  };

  var creating_answer_template = function() {
    return '<input name="article[polls_attributes][new_#{pi}][questions_attributes][new_#{qi}][answers_attributes][new_#{i}][text]" value="#{text}" /><input name="article[polls_attributes][new_#{pi}][questions_attributes][new_#{qi}][answers_attributes][new_#{i}][vote_count]" value="#{vote_count}" /><input name="article[polls_attributes][new_#{pi}][questions_attributes][new_#{qi}][answers_attributes][new_#{i}][position]" value="#{position}" />#{prebuilt_image}#{prebuilt_enlarge}';
  };

  var creating_answer_image_template = function() {
    return '<input name="article[polls_attributes][new_#{pi}][questions_attributes][new_#{qi}][answers_attributes][new_#{i}][image_source_url]" value="#{image_source_url}" />';
  };

  var creating_answer_image_enlarge_template = function() {
    return '<input name="article[polls_attributes][new_#{pi}][questions_attributes][new_#{qi}][answers_attributes][new_#{i}][image_enlarge_url]" value="#{image_enlarge_url}" />';
  };

  var Poll = {
    base_url: null,
    brand: null,
    section: null,
    article: null,
    callback: null,
    answer_by_id: null,
    data_url: null,
    poll_targets: null,

    init: function(options) {
      options = options || {};
      Poll.base_url = options["base_url"];
      Poll.brand = options["brand"];
      Poll.section = options["section"];
      Poll.article = options["article"];
      Poll.callback = options["callback"] || '?';
      Poll.data_url = options["data_url"];
      Poll.answer_by_id = {};
      Poll.poll_targets = options["poll_targets"] || [];
    },

    validate_votes: function(voted_answers){
      if (!voted_answers || voted_answers.length == 0) {
        return 'You must answer every question before voting!';
      }
      var answered_questions = $.map(voted_answers, function(answer) { return answer.question });
      if (!answered_questions.compare($.unique(answered_questions))) {
        return 'You may not vote for more than one answer per question!';
      }
      if (!answered_questions.compare(voted_answers[0].poll.questions)) {
        return 'You must answer every question before voting!';
      }
      return false;
    },

    render_polls: function() {
      var nest_and_stash = function(poll) {
        $.each(poll.questions, function(i, question) {
          question.poll = poll;
          $.each(question.answers, function(i, answer) {
            answer.question = question;
            answer.poll = poll;
            Poll.answer_by_id[String(answer.id)] = answer;
          });
        });
      };
      var get_templates = function(poll) {
        if (poll.starts_at && (Date.from_iso(poll.starts_at) > new Date())) {
          return [Poll.unopened_poll_template(), Poll.unopened_question_template(), Poll.unopened_answer_template()];
        } else if ((poll.stops_at && (Date.from_iso(poll.stops_at) < new Date())) || $.cookies.get('poll_'+poll.id)) {
          return [Poll.closed_poll_template(), Poll.closed_question_template(), Poll.closed_answer_template()];
        } else {
          return [Poll.poll_template(), Poll.question_template(), Poll.answer_template()];
        }
      };
      var success = function(polls) {
        $.each(polls, function(i, poll) {
          nest_and_stash(poll);
	  poll.target = get_target(i);
          var templates = get_templates(poll);
          $(poll.target).append(build_poll(poll, templates[0], templates[1], templates[2]));
          init_vote_form(poll.id)
        });
      };
      var error = function() {
        $.getJSON(Poll.data_url, function(article) {
          var form = $('<form style="display:none;">' + build_creating_article(article) + "</form>");
          form.appendTo($(document.body));
          form.submit(function() {
            $(document.body).append('<iframe name="creating_article_iframe" style="display:none;"></iframe>');
            var iframe = $("iframe[name=creating_article_iframe]:last");
            form.attr("action", create_article_url()).attr("target", "creating_article_iframe").attr("method", "post");
            iframe.load(function() {
              var response = eval('('+iframe.contents().find("body").html()+')');
              if (response.polls) {
                success(response.polls);
              }
              setTimeout(function() { iframe.remove(); form.remove(); }, 200);
            });
          });
          form.submit();
        });
      };
      var decision_tree = function(response) {
        if (response && response.status != '404') {
          success(response);
        } else {
          error();
        }
      };

      $.getJSON(polls_url(), decision_tree);
    },

    render_error: function(id, message) {
      $('#poll_' + id + '_errors').html(message);
    },

    poll_template: function() {
      return '<h1>#{name}</h1><p class="description">#{description}</p><form method="post" action="#" id="poll_form_#{id}"><div class="poll_errors" id="poll_#{id}_errors" /><ol class="questions">#{prebuilt_questions}</ol><input type="submit" value="Vote" class="vote_button"></form>';
    },

    question_template: function() {
      return '<li id="question_#{id}"><p>#{text}</p><ul class="answers">#{prebuilt_answers}</ul></li>';
    },

    answer_template: function() {
      return '<li><input type="radio" name="question_#{question_id}" id="answer_#{id}" value="#{id}" /><label for="answer_#{id}">#{prebuilt_image}#{text}</label>#{prebuilt_enlarge}</li>';
    },

    answer_image_template: function() {
      return '<img src="#{image_source_url}" /> ';
    },

    answer_image_enlarge_template: function() {
      return ' <a href="#{image_enlarge_url}" class="small red">enlarge</a>';
    },

    unopened_poll_template: function() {
      return '<div id="poll_#{id}"><h1>#{name}</h1><p class="description">#{description}</p><ol class="questions">#{prebuilt_questions}</ol></div>';
    },

    unopened_question_template: function() {
      return '<li id="question_#{id}"><p>#{text}</p><ul class="answers">#{prebuilt_answers}</ul></li>';
    },

    unopened_answer_template: function() {
      return '<li>#{prebuilt_image}#{text}#{prebuilt_enlarge}</li>';
    },

    closed_poll_template: function() {
      return '<ol>#{prebuilt_questions}</ol>';
    },

    closed_question_template: function() {
      return '<li id="question_#{id}"><p>#{text}</p><ul class="answers">#{prebuilt_answers}</ul></li>';
    },

    closed_answer_template: function() {
      return '<li><div class="bar" style="width:#{percentage}%; background:#{percentage:Format.get_color};"></div>#{text} <span class="answer_percentage">(#{percentage}%)</span></li>';
    }
  };
  return(Poll);
})(jQuery);
/*
 * profiles.js
 *
 */
var Profile = (function($) {
  var p = {


    init: function(options) {
      for(var key in options) { Profile[key] = options[key]; }
      p.init_sign_up_behaviour();
      p.init_log_in_behaviour();
      p.init_log_out_behaviour();
      p.init_forgot_password_behaviour();
      p.init_edit_photo_behaviour();
      p.init_my_profile_behaviour();
    },

    init_log_in_behaviour: function(form) {
      $(".profile_log_in").live('click', function() {
        $.facebox(p.log_in_form_template());
        var form = $("#facebox form");
        Iframe.post(form, p.log_in_url(), {
          success: function() { p.render_profile_box(); $("#facebox").fadeOut(); },
          failure: function() { p.render_errors(response.errors, form); }
        });
        return false;
      });
    },

    init_sign_up_behaviour: function(form) {
      $(".profile_sign_up").live('click', function() {
        $.facebox(p.sign_up_form_template());
        var form = $("#facebox form");
        Iframe.post(form, p.sign_up_url(), {
          success: function() { $("#facebox .content").html(Template.evaluate(p.sign_up_success_template(), response.profile)); },
          failure: function() { p.render_errors_inline(response.errors, form); }
        });
        return false;
      });
    },

    init_forgot_password_behaviour: function() {
      $(".profile_forgot_password").live('click', function() {
        $.facebox(p.forgot_password_form_template());
        var form = $("#facebox form");
        Iframe.post(form, p.forgot_password_url(), {
          success: function() { $("#facebox .content").html(p.forgot_password_success_template()); },
          failure: function() { p.render_errors(response.errors, form); }
        });
        return false;
      });
    },

    init_log_out_behaviour: function() {
      $(".profile_log_out").live('click', function() {
        var form = $("<form/>").append('<input type="hidden" name="_method" value="delete" />').hide();
        Iframe.post(form, p.log_in_url(), { success: function() { p.render_profile_box(); } });
        form.submit();
        return false;
      });
    },

    init_edit_photo_behaviour: function() {
      $(".profile_edit_photo").live('click', function() {
        $("#profile_center_column").html(p.edit_photo_form_template());
        var form = $("#profile_center_column form");
        Iframe.post(form, p.profile_url(), {
          before:  function() { form.find("input[type=submit]").val('Uploading...').attr('disabled', 'true'); },
          success: function() { p.refresh_my_profile(); },
          failure: function() { p.render_errors(response.errors, form); }
        });
        return false;
      });
    },

    init_my_profile_behaviour: function() {
      $(".my_profile").live('click', function() {
        $(this).attr("href", p.my_profile_url());
        return true;
      });
    },


    log_in_url: function() {
      return p.base_url + '/session?callback=?';
    },

    profile_url: function() {
      return p.base_url + '/profile';
    },

    sign_up_url: function() {
      return p.base_url + '/profiles';
    },

    forgot_password_url: function() {
      return p.base_url + '/profiles/reset_password';
    },

    my_profile_url: function() {
      return p.base_url + '/profiles/' + p.profile.id;
    },



    logged_in: function(callbacks) {
      $.getJSON(p.log_in_url(), function(data) {
        if(profile = data.profile) {
          p.profile = profile;
          if(callbacks.success) callbacks.success();
        } else {
          if(callbacks.failure) callbacks.failure();
        }
      });
    },

    refresh_my_profile: function() {
      window.location = p.my_profile_url();
    },



    render_profile_box: function() {
      p.logged_in({
        success: function() { $("#profile_box").html(Template.evaluate(p.logged_in_profile_box_template(), profile)) },
        failure: function() { $("#profile_box").html(p.logged_out_profile_box_template()) }
      });
    },

    render_errors: function(errors, form) {
      var object = { count: errors.length, errors: ''};
      $.each(errors, function(i, error) {
        if(typeof error == 'string') {
          object.errors += error + "<br />";
        } else {
          object.errors += error[0].humanize() + " " + error[1] + "<br />";
        }
      });
      form.find("div.errors").empty().append(Template.evaluate(p.errors_template(), object));
    },

    render_errors_inline: function(errors, form) {
      form.find("span.error").empty();
      $.each(errors, function(i, error) {
        form.find("input[id$='"+error[0]+"'] + span.error").html(" &larr; " + error[1]);
      });
    },


    logged_in_profile_box_template: function() {
      return '<h3>Welcome back! #{name}</h3><img src="#{photos_small}" /><p>There are xx new messages in your profile.</p><p><a href="#" class="my_profile">My profile</a> | Not #{name}? <a href="#" class="profile_log_out">Sign out</a></p>';
    },

    logged_out_profile_box_template: function() {
      return '<h2><a href="#" class="profile_log_in">Log in</a> or <a href="#" class="profile_sign_up">Sign up</a></h2>';
    },

    sign_up_form_template: function() {
      return '<div id="profile_sign_up_form"><h1>Sign up</h1><form><p>email address<br /><input type="text" id="profile_email" name="profile[email]" /><span class="error"></span></p><p>password<br /><input type="password" id="profile_password" name="profile[password]" /><span class="error"></span></p><p>confirm password<br /><input type="password" id="profile_password_confirmation" name="profile[password_confirmation]" /><span class="error"></span></p><p>member name<br /><input type="text" id="profile_name" name="profile[name]" /><span class="error"></span></p><p><input type="hidden" value="0" name="profile[terms_of_service]" /><input type="checkbox" value="1" id="profile_terms_of_service" name="profile[terms_of_service]" /> I accept the terms.<span class="error"></span></p><input type="submit" value="Done" /></form></div>';
    },

    edit_photo_form_template: function() {
      return '<div id="profile_edit_photo_form"><h1>Edit photo</h1><form enctype="multipart/form-data"><div class="errors" /><p>upload your own photo<br /><input type="file" id="profile_photo" name="profile[photo]" /></p><input type="submit" value="Save" /><input type="hidden" name="_method" value="put" /></form></div>';
    },

    sign_up_success_template: function() {
      return '<h1>We\'ve just emailed you the activation link!</h1>';
    },

    log_in_form_template: function() {
      return '<div id="profile_log_in_form"><h1>Log in</h1><form><div class="errors" /><p>Email<br /><input type="text" name="email" /></p><p>Password<br /><input type="password" name="password" /></p><input type="submit" /></form><a href="#" class="profile_forgot_password">forgot password</a></div>';
    },

    forgot_password_form_template: function() {
      return '<div id="profile_forgot_password_form"><h1>Forgot password</h1><form><div class="errors" /><p>email address<br /><input type="text" name="email" /></p><input type="submit" value="Submit" /></form></div>';
    },

    forgot_password_success_template: function() {
      return '<h1>We\'ve just emailed you instructions on how to reset your password.</h1>';
    },

    errors_template: function() {
      return '#{errors}';
    }

  };
  return(p);
})(jQuery);
/*
 * extensions.js
 *
 */
Array.prototype.last = function() {
  return this[this.length-1];
}

Array.prototype.compare = function(testArr) {
  if (this.length != testArr.length) return false;
  for (var i = 0; i < testArr.length; i++) {
    if (this[i].compare) {
      if (!this[i].compare(testArr[i])) return false;
    }
    if (this[i] !== testArr[i]) return false;
  }
  return true;
}

String.prototype.capitalize = function() {
  return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
}

String.prototype.humanize = function() {
  return this.replace(/_/g, ' ').capitalize();
}

String.prototype.tableize = function() {
  return this.toLowerCase().replace(/[\s]+/g, "_");
}

String.prototype.inspect = function() {
  var special_chars = {
    '\b': '\\b',
    '\t': '\\t',
    '\n': '\\n',
    '\f': '\\f',
    '\r': '\\r',
    '\\': '\\\\'
  };

  var escape_text = function(match) {
    var character = special_chars[match];
    return character ? character : '\\u00' + match.charCodeAt().toPaddedString(2, 16);
  }

  return this.replace(/[\x00-\x1f\\]/g, escape_text);
}

Date.prototype.strftime = function(format) {
  var MONTHNAMES = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
  var DAYNAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
  var ABBR_MONTHNAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  var ABBR_DAYNAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
  var date = this;

  /*
  %a - The abbreviated weekday name (``Sun'')
  %A - The  full  weekday  name (``Sunday'')
  %b - The abbreviated month name (``Jan'')
  %B - The  full  month  name (``January'')
  TODO %c - The preferred local date and time representation
  %d - Day of the month (01..31)
  %H - Hour of the day, 24-hour clock (00..23)
  %I - Hour of the day, 12-hour clock (01..12)
  TODO %j - Day of the year (001..366)
  %m - Month of the year (01..12)
  %M - Minute of the hour (00..59)
  %p - Meridian indicator (``AM''  or  ``PM'')
  %S - Second of the minute (00..60)
  TODO %U - Week  number  of the current year, starting with the first Sunday as the first day of the first week (00..53)
  TODO %W - Week  number  of the current year, starting with the first Monday as the first day of the first week (00..53)
  %w - Day of the week (Sunday is 0, 0..6)
  TODO %x - Preferred representation for the date alone, no time
  TODO %X - Preferred representation for the time alone, no date
  %y - Year without a century (00..99)
  %Y - Year with century
  TODO %Z - Time zone name
  %% - Literal ``%'' character
  */

  var a = function() { return ABBR_DAYNAMES[date.getDay()]; };
  var A = function() { return DAYNAMES[date.getDay()]; };
  var b = function() { return ABBR_MONTHNAMES[date.getMonth()]; };
  var B = function() { return MONTHNAMES[date.getMonth()]; };
  var d = function() { return date.getDate(); };
  var H = function() { return add_zero_if_necessary(date.getHours()); };
  var I = function() { return add_zero_if_necessary(date.getHours() > 0 && date.getHours() < 13 ? date.getHours() : Math.abs(date.getHours()-12)); };
  var m = function() { return date.getMonth()+1; };
  var M = function() { return add_zero_if_necessary(date.getMinutes()); };
  var p = function() { return (date.getHours() > 11) ? "PM" : "AM"; };
  var S = function() { return add_zero_if_necessary(date.getSeconds()); };
  var w = function() { return date.getDay(); };
  var y = function() { return date.getYear().toString().substr(1); };
  var Y = function() { return date.getFullYear(); };

  var add_zero_if_necessary = function(number) { return number < 10 ? "0"+number : number; };

  var replace_value = function(str, match) {
    try { convertion = match == '%' ? match : eval(match+"()"); }
    catch(e) { convertion = null; }
    return convertion ? convertion : str;
  }

  return format.replace(/%([a-zA-Z%])/g, replace_value);
}

Date.from_iso = function(isoDate) {
  var matches = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})([+|-]?\d{2}:\d{2})$/.exec(isoDate);
  var date = new Date(matches[1], matches[2]-1, matches[3], matches[4], matches[5], matches[6]);
  return date;
}
var Format = {
  text: function(text) {
    text = text.replace(/\r\n?/g, "\n");                    // \r\n and \r -> \n
    text = text.replace(/\n\n+/g, "</p>\n\n<p>");           // 2+ newline  -> paragraph
    text = text.replace(/([^\n]\n)(?=[^\n])/g, '$1<br />'); // 1 newline   -> br
    return "<p>" + text + "</p>";
  },

  quantity_class_name: function(count) {
    return count > 0 ? "not_empty" : "empty";
  },

  iso_date: function(iso_date) {
    var date = new Date.from_iso(iso_date);
    return date.strftime('%a %m/%d/%y %I:%M %p'); // e.g.: Wed 04/22/09 8:53 AM
  },

  colors: [ [255,0,0] ],
  color_index: 0,
  get_color: function(percentage) {
    if(Format.colors.length > 1) {
      var color = Format.colors[Format.color_index];
      Format.color_index = (Format.color_index + 1 == Format.colors.length) ? 0 : Format.color_index + 1;
    } else {
      var base_color = Format.colors[0];
      var color = [];
      var inverse_percentage = 100 - percentage;
      var max_value = 225;
      for(var i in base_color) {
        color_diff = base_color[i] < max_value ? max_value - base_color[i] : 0;
        color[i] = base_color[i] + Math.floor(inverse_percentage * color_diff / 100);
      }
    }
    return "rgb(" + color.join(",") + ")";
  }
}
/*
 * iframe.js
 *
 */
var Iframe = {
  post: function(form, url, callbacks) {
    form.submit(function() {
      if(callbacks.before) callbacks.before();

      var id = new Date().getTime();
      var iframe = '<iframe name="'+id+'" id="'+id+'" style="display:none;"></iframe>';
      $(document.body).append(iframe);
      iframe = $("#"+id+"");

      form.attr("action", url).attr("target", id).attr("method", "post");

      iframe.load(function(){
        var response_string = iframe.contents().find("body").html();
        try { response = eval("(" + response_string + ")"); } catch(e) { response = {}; }
        if(response.errors) {
          if(callbacks.failure) callbacks.failure();
        } else if(typeof response == 'object') {
          if(callbacks.success) callbacks.success();
        }
        setTimeout(function() { iframe.remove(); }, 200);
      });
    });
  }
}
/*
 * pagination.js
 *
 */
var Pagination = {

  inner_window: 2, // links around the current page
  outer_window: 0, // links around beginning and end
  gap_marker: '<span class="gap">&hellip;</span>',
  separator: ' ',
  previous_label: '&laquo; Previous',
  next_label: 'Next &raquo;',
  total_pages: null,
  current_page: null,
  total_entries: null,
  entries: null,
  per_page: null,
  offset: null,

  init: function(pagination) {
    Pagination.total_entries = pagination["total_entries"];
    Pagination.entries = pagination["entries"];
    Pagination.per_page = pagination["per_page"];
    Pagination.offset = pagination["offset"];

    Pagination.total_pages = Math.ceil(Pagination.total_entries / Pagination.per_page);
    Pagination.current_page = (Pagination.offset / Pagination.per_page) + 1;
  },

  paginate: function() {
    links = Pagination.windowed_links();

    links.unshift(Pagination.page_link_or_span(Pagination.previous_page(), 'disabled prev_page', Pagination.previous_label));
    links.push(Pagination.page_link_or_span(Pagination.next_page(), 'disabled next_page', Pagination.next_label));

    html = links.join(Pagination.separator);

    return html;
  },

  pagination_info: function() {
    var from = Pagination.offset + 1;
    var to = Pagination.offset + Pagination.per_page;
    var total = Pagination.total_entries;
    if (to > total) to = total;

    return from + "-" + to + " of " + total;
  },

  visible_page_numbers: function() {
    window_from = Pagination.current_page - Pagination.inner_window;
    window_to = Pagination.current_page + Pagination.inner_window;

    if(window_to > Pagination.total_pages) {
      window_from -= window_to - Pagination.total_pages;
      window_to = Pagination.total_pages;
    }
    if(window_from < 1) {
      window_to += 1 - window_from;
      window_from = 1;
      if(window_to > Pagination.total_pages)
        window_to = Pagination.total_pages;
    }

    visible = [];
    left_gap = [];
    right_gap = [];
    for(i=1; i<=Pagination.total_pages; i++) visible.push(i);
    for(i=(2 + Pagination.outer_window); i<=(window_from - 1); i++) left_gap.push(i);
    for(i=(window_to + 1); i<=(Pagination.total_pages - Pagination.outer_window - 1); i++) right_gap.push(i);
    if(left_gap[left_gap.length - 1] + 1 - left_gap[0] > 1) {
     for(i=0; i<left_gap.length; i++) {
       index = jQuery.inArray(left_gap[i], visible);
       if(index >= 0) visible.splice(index,1);
     }
    }
    if(right_gap[right_gap.length - 1] + 1 - right_gap[0] > 1) {
      for(i=0; i<right_gap.length; i++) {
        index = jQuery.inArray(right_gap[i], visible);
        if(index >= 0) visible.splice(index,1);
      }
    }

    return visible;
  },

  windowed_links: function() {
    links = [];
    prev = null;

    $.each(Pagination.visible_page_numbers(), function(i, obj) {
      if(prev && obj > prev + 1) links.push(Pagination.gap_marker);
      links.push(Pagination.page_link_or_span(obj, 'current'));
      prev = obj;
    });

    return links;
  },

  previous_page: function() {
    return Pagination.current_page > 1 ? (Pagination.current_page - 1) : null;
  },

  next_page: function() {
    return Pagination.current_page < Pagination.total_pages ? (Pagination.current_page + 1) : null;
  },

  page_link_or_span: function(page, span_class, text) {
    text = text || page.toString();

    if(page && page != Pagination.current_page) {
      classnames = span_class && span_class.indexOf(' ') && span_class.split(' ')[span_class.split(' ').length-1];
      return '<a href="'+Url.new_url({page: page})+'" class="'+span_class+'">'+text+'</a>';
    } else {
      return '<span class="'+span_class+'">'+text+'</span>';
    }
  }

};
/*
 * scroll_to_if_necessary.js
 *
 */
function scroll_to_if_necessary(element) {
  element = $(element);

  element_height = element.height();
  element_top_position = element.offset().top;
  element_bottom_position = element_height + element_top_position;

  viewport_height = $(window).height();
  viewport_top_position = $(window).get(0).pageYOffset;
  viewport_bottom_position = viewport_height + viewport_top_position;

  if (element_bottom_position > viewport_bottom_position) {
    $('html,body').animate({scrollTop: element_bottom_position - viewport_height}, 250);
  } else if (element_top_position < viewport_top_position) {
    $('html,body').animate({scrollTop: element_top_position}, 250);
  }
}
/*
 * template.js
 *
 */
var Template = {
  evaluate: function(template, values) {
  	template = template || '';
  	values = values || {};

    var replace_value = function (str, match) {
      if ((arr = match.split(":")) && arr.length > 1) {
        return eval(arr[1]+'("'+values[arr[0]].toString().inspect().replace(/"/g, '\\"')+'")');
      } else if(typeof values[match] == 'string' || typeof values[match] == 'number') {
        return values[match];
      } else if( (arr = match.split("_")) && typeof values[arr[0]] == 'object' && (field = arr.slice(1).join("_")) && (typeof values[arr[0]][field] == 'string' || typeof values[arr[0]][field] == 'number')) {
        return values[arr[0]][field];
      } else {
        return str;
      }
  	};

  	return template.replace(/#\{([^{}]*)\}/g, replace_value);
  }
}
/*
 * url.js
 *
 */
var Url = {
  params: null,
  defaults: null,

  set_params: function(options) {
    options = options || {};
    Url.params = jQuery.extend({}, Url.defaults);
    var url = window.location.href;

    if ( (match = /^[^\?]*\?([^#]*).*$/.exec(url)) && (params = match[1].split("&")) ) {
      for (i = 0; i < params.length; i++) {
        key = params[i].split("=")[0];
        value = params[i].split("=")[1];
        Url.params[key] = value;
      }
    }

    for(var key in options) {
      Url.params[key] = options[key];
    }
  },

  get_params: function() {
    if(!Url.params) { Url.set_params(); }
    return Url.params;
  },

  get_param: function(param) {
    value = Url.get_params()[param];
    return value ? value : "";
  },

  new_url: function(object, url) {
    var base_url = (url ? url : window.location.href).split("?")[0];
    var merged_object = jQuery.extend({}, Url.get_params(), object);
    var params = [];
    for(var key in merged_object) {
      params.push(key+"="+merged_object[key]);
    }
    return base_url + "?" + params.join("&");
  }
}
