/* -*- mode: c; tab-width: 2; c-tab-always-indent: t; c-basic-offset: 2; comment-column: 0 -*- */
/* global platform js */

/* Add "ka-hover" class to elements on with class name "ka-hvr" in IE6 */
/*@cc_on
@if (@_jscript_version < 5.7)
(function(){
  var rx = /^hvr(?:\s|$)|\ska-hvr(?:\s|$)/;
	function onMouseHover() {
		var e = event;
		for (var el = e.srcElement; el; el = el.parentNode){
			if (!rx.test(el.className))
				continue;
			if (e.type == 'mouseover')
				el.className += ' ka-hover';
			else
				el.className = el.className.replace(/^ka-hover(?:\s|$)|\ska-hover(?:\s|$)/, ' ');
		}
	}

	document.attachEvent('onmouseout', onMouseHover);
	document.attachEvent('onmouseover', onMouseHover);
})();
@end @*/


/*@cc_on try { document.execCommand('BackgroundImageCache', false, true); } catch(e) {} @*/

if (!Function.prototype.bind){
	Function.prototype.bind = function(context){
		var oArgs, fnMethod = this, slice = Array.prototype.slice;
		if (arguments.length > 1)
			oArgs = slice.call(arguments, 1);
		return function(){
			return oArgs ?
				fnMethod.apply(context, slice.call(arguments, 0).concat(oArgs)) :
				fnMethod.apply(context, arguments);
		};
	};
}

if (!Array.prototype.some)
{
  Array.prototype.some = function(fun /*, thisp*/)
  {
    var i = 0,
        len = this.length >> 0;

    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (; i < len; i++)
    {
      if (i in this &&
          fun.call(thisp, this[i], i, this))
        return true;
    }

    return false;
  };
}

if (!Array.prototype.map)
{
  Array.prototype.map = function(fun /*, thisp*/)
  {
    var len = this.length >>> 0;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array(len);
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        res[i] = fun.call(thisp, this[i], i, this);
    }

    return res;
  };
}

if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisp*/)
  {
    var len = this.length >>> 0;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        fun.call(thisp, this[i], i, this);
    }
  };
}

if (!Array.prototype.filter) {
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length >>> 0;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array();
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
      {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
}

if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length >>> 0;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this && this[from] === elt)
        return from;
    }
    return -1;
  };
}

(function() {
	/* Extending the jQuery event with a basic predicate for leting us
		 know what key was pressed.  */
	var keymap = {
		Backspace: 8,
		Tab: 9,
		Delete: 46,
		Enter: 13,
		Escape: 27,
		Left: 37,
		Up: 38,
		Right: 39,
		Down: 40,
		Comma: 44,
		Space: 32
	};

	jQuery.Event.prototype.isKeyPressed = function(key) {
		if (key == 'Down')
			return this.keyCode == keymap[key];
		var k = +(this.keyCode || this.charCode);
		return k == keymap[key] || String.fromCharCode(k) == key;
	};

	jQuery.Event.prototype.isAnyKeyPressed = function() {
		return Array.prototype.some.call(arguments, this.isKeyPressed, this);
	};

	jQuery.Event.prototype.isAlphaKey = function() {
		var k = +(this.keyCode || this.charCode);
		return (k > 64 && k < 91) || (k > 96 &&  k < 123);
	};

	jQuery.Event.prototype.isNumericKey = function() {
		var k = +(this.keyCode || this.charCode);
		/* a number 0-9 was pressed */
		return (k > 47 && k < 58);
	};

	jQuery.Event.prototype.isNumericHexKey = function() {
		var k = (this.keyCode || this.charCode);
		/* an `#' or a to f or A to F was pressed */
		return this.isNumericKey() || k == 35 || (k > 96 && k < 103) || (k > 64 && k < 71);
	};

	jQuery.Event.prototype.isAlphaNumericKey = function() {
		return this.isNumericKey() || this.isAlphaKey();
	};

	jQuery.Event.prototype.isDelOrArrowKey = function() {
		var k = +(this.keyCode || this.charCode);
		return this.isAnyKeyPressed('Up', 'Down', 'Left', 'Right', 'Delete', 'Backspace');
	};

})();

(function(){
	function handle(e, $t, actions, test, context) {
	for (var action in actions)
		if (test($t, action)){
			actions[action](context, e, $t);
			return true;
		}
		return false;
	}

	jQuery.Event.prototype.handleTargetWithActionsByTest = function(actions, test, context) {
		return handle(this, $j(this.target), actions, test, context);
	};
})();

jQuery.Event.prototype.handleTargetWithActionClasses = function(actions, context) {
	return this.handleTargetWithActionsByTest(actions, function($t, cls) {
		return $t.hasClass(cls) || $t.parents('.'+cls+':first').length > 0;
	}, context);
};

/* punny jQuery */
jQuery.event.props.push('layerX', 'layerY', 'offsetX', 'offsetY');

/* Overwriting the default jquery serializeArray, coz it ignores named
	 submit buttons. As our server side guys expect a lot of forms to
	 work with named submits we can't just ignore this. When jQuery guys
	 fix this then we should remove this patch. On a side not jquery's
	 form serialization gets expotentionally slower as the form size
	 grows. Where yukus old form serialization grew leniary.
 */
jQuery.fn.serializeArray = function(){
	return this.map(function(){
		return this.elements ? jQuery.makeArray(this.elements) : this;
	})
	.filter(function(){
		return this.name && !this.disabled &&
			(this.checked || /select|textarea/i.test(this.nodeName) ||
			 /text|hidden|submit|password/i.test(this.type));
	})
	.map(function(i, elem){
		var val = jQuery(this).val();
		return val == null ? null :
			jQuery.isArray(val) ?
			jQuery.map(val, function(val, i){
				return {name: elem.name, value: val};
			}) :
			{name: elem.name, value: val};
		}).get();
};

/* crappy scroll into view */
(function($){
$.fn.extend({
	scrollIntoView: function(speed, easing) {
		var $el;
		if (document.documentElement.scrollHeight)
			$el = $(document.documentElement);
		else
			$el = $(document.body);
		$el.animate({'scrollTop': this.offset().top }, speed || 500, easing);
	}
});
})(jQuery);
// move jQuery object to $j namespace, and defaut $ to usual
var $j = jQuery.noConflict(), $ = function(x){return document.getElementById(x);};

(function(){
	var cls = ' ka-js ka-loading-page';
	var bwr = jQuery.browser;
	var n = navigator.userAgent;
	for (var key in bwr) {
		if (bwr[key] === true)
				cls += ' ka-'+key+' ka-'+key+'-'+bwr.version.replace(/\./g, '-');
				break;
	}
	if (n.indexOf('Mobile') !== -1) {
		var types = ['iPhone', 'iPad'];
		var n = navigator.userAgent;
		for (var i = 0, type; type = types[i]; i++)
			if (n.indexOf(type) !== -1) {
				cls += ' ka-'+type;
				break;
			}
	}

	document.documentElement.className += cls;
})();

$j.fn.get$J = function(){
	/* Return the jquery object from any element. Needed when for when
		 passing $elements across frames and you want to create $elements
		 in the frame from wich the $element came. Not sure if jquery
		 provides such thing already. */
	return $j;
};

Yuku = {
	Paths: {
		SKINS: '/skins/pro/',
		UPLOADIFY: window.gs.staticServer + '/common/bypass/images/uploadify.swf'
	},

	Info: {
		 Skin: {
		/*
			this stuff is printed from the header.tpl
			 default_skin_id: id
		*/
		 },
		 User: {
		/*
		 These are printed by server-side in the <head> after the inclusion of base.js
			NAME: 'Mauvis'
			PHOTO: "static.something/loaction/to/image",
			DEFAULT_PHOTO: "static.something/loaction/to/image"
			FRIENDS_LISTS: [{title: string, id: 1}, ...]
		*/
		}

	},

	Preferences: {
		UI: {
			roundedCorners: false
		},
		Notice: { /* used by Yuku.Util.showNotice */
			displayDuration: 1 /* in seconds */
		}
	},

	Util: {
		String: {
			TPLS: {},
			replaceFromDict: function(str, dict) {
				return str.replace(/#{([^}]+)}/g, function(m, k) { return k in dict ? dict[k] : m; });
			},
			deserialize: function(str) {
				var ret = {};
				var search = str.slice(str.indexOf('?')+1);
				if (search){
					for (var pairs = search.split('&'), i = 0, l = pairs.length, pair; i < l; i++) {
						pair = pairs[i].split('=');
						key = decodeURIComponent(pair[0]);
						val = decodeURIComponent(pair[1]);
						if (key in ret){
							if (!(ret[key] instanceof Array)){
								ret[key] = [ret[key]];
							}
							ret[key].push(val);
						} else {
							ret[key] = val;
						}
					}
				}
				return ret;
			},

			camelize: function(str) {
				return str.replace(/[-_]\w/g, function(x){return x.charAt(1).toUpperCase();});
			},

			capitalize: function(str) {
				return str.replace(/\b\w/g, function(x){return x.charAt(0).toUpperCase();});
			},

			strToHTMLSafeClassName: function(str){
				return str.replace(/(?:\[[0-9]+\])+|-?[^-\s_A-Za-z0-9]+|^-+|-+$/g, '').replace(/\s+/g, '-').toLowerCase();
			},

			entify: function(str){
				var d = document.createElement('div');
				d.appendChild(document.createTextNode(str));
				return d.innerHTML;
		  }
		},

		Math: {
			limit: function(n, nMin, nMax) {
				return n < nMin ? nMin : (n > nMax ? nMax : n);
			}
		},

		Dom: {},

		pageScroll: function(){
			var win = document.documentElement, body = document.body;
			return {top: Math.max(win.scrollTop, body.scrollTop),
							left:Math.max(win.scrollLeft, body.scrollLeft)};
		},

		normalize_color: function(v){
			if (v === null || v === undefined)
				return null;
			if (v.constructor == Number)
				return ("000000" + v).toString(16).slice(-6);
			else if (v.charAt(0) == '#')
				return v.slice(1);
			else if (v.constructor == String){
				if (v.indexOf('rgb(') != -1){
					v = v.match(/\d+/g);
					if (v)
						return ("000000"+ (v[0] << 16 | v[1] << 8 | v[2] << 0).toString(16)).slice(-6);
				}
				else if (v == 'transparent')
					return '';
				return v;
			}
			return null;
		},

		changeTheme: function(filename, title){
			title = title || 'skin: ' + filename;

			// if active style is current style return
			if ( title == $('ka-currentSkin').title ){
				return;
			}

			/* shold probably be replaced with api call to yuku.skins.apply */
			$j.get('/skins/change/skin/' + filename);

			$j('#ka-currentSkin')
			.attr('title', title)
			.attr('disabled',true)
			.attr('href', Yuku.Paths.SKINS + filename +'/skin.css')
		  .attr('disabled', false);
			$j('a.ka-edit-current-skin:first').attr('href', '/skins/edit/name/'+filename);
		},

		Cookie: {
			get: function(sName){
				for (var aCookies = document.cookie.split('; '), i = aCookies.length, aPair; i--;){
					aPair = aCookies[i].split('=');
					if (aPair[0] == sName){
						return decodeURIComponent(aPair[1]);
					}
				}
				return null;
			},

			set: function(sName, sValue, iHours){
				if (!iHours){
					iHours = 1000000; // 100+ years
				}
				var oDate = new Date();
				oDate.setTime( +oDate + (iHours * 3600 * 1000));
				document.cookie = sName + '=' + encodeURIComponent(sValue)
					+ '; expires=' + oDate.toGMTString() + '; path=/;';
			},

			del: function(sName) {
				yut.Cookie.set(sName, '', -1);
			}
		},

		getWrappingModuleTitle: function($el){
			var $module;
			if ($el.hasClass('ka-module'))
				$module = $el;
			else
				$module = $el.parents('div.ka-module:first');
			if (!$module.length)
				return '';
			return $module.find('h4.ka-tab:first').text();
		},

		getWrappingSectionTitle: function($el){
			var $section = $el.parents('div.ka-section:first');
			if (!$section.length)
				return '';
			return $section.find('h2:first, h3:first').text();
		},

	  removeListItem: function($li, def_title, on_remove){
			if (!$li.length){
				return;
			}
			if (!def_title)
				def_title = 'items';
			$li.fadeOut('slow', function() {
/* wierd IE6 bug with resizing of with section action position messing up,
	 this is an ugly hack, but I don't have another way of doing it right now.
*/
/*@cc_on
	@if (@_jscript_version < 5.8)
				var $col = $li.parents('.ka-section:first').find('.ka-section-actions').hide();
				setTimeout(function() {
					$col.show();
				}, 1);
@end @*/

				var $ul = $li.parent();
				if ($li.siblings().length){
					$li.remove();
					$ul.find('li:last').addClass('ka-last-list-item');
				} else {
					var $p = $j('<p class="ka-no-items"></p>');
					var title = $ul[0].ka_default_title;
					if (!title)
						title = 'No '+ (yut.getWrappingModuleTitle($li).toLowerCase() || yut.getWrappingSectionTitle($li).toLowerCase() || def_title) + 'yet.';
					$p.text(title);
					$ul.replaceWith($p);
				}
				if (on_remove)
					on_remove();
			});
		},

	  getItemLists: function($where, dont_create) {
			var $ul = $where.find('ul.ka-item-list:first');
			if (!$ul.length && !dont_create) {
				$ul = $j('<ul class="ka-item-list"></ul>');
				var $ps = $where.find('p.ka-no-items');
				if ($ps.length) {
					$ps.replaceWith($ul);
					$ul[0].ka_default_title = $ps.text();
				}
				if (!$ps.length)
					$where.append($ul);
			}
			return $ul;
		},

	  addListItem: function($list, itemcontent, maxItems) {
			var $item;

			$list.find('> li:last').removeClass('ka-last-list-item');
			if (itemcontent.constructor == String)
				$item = $j('<li style="display: none">'+itemcontent+'</li>').appendTo($list);
			else
				$item = $j('<li style="display: none"></li>').append(itemcontent).appendTo($list);

			if (maxItems !== undefined) {
				var $lis = $list.children();
				if ($lis.length > maxItems)
					$j($lis[0]).remove();
			}

			$item.fadeIn().addClass('ka-last-list-item');
			return $item;
		}
	},

	Platform: {
		globalMethodNames: ['checkUserSettings', 'clearSearch'],

		checkUserSettings: function(){
			var y = Yuku, ypr = y.Preferences;

			// first check if rounded corners are enabled
			if (ypr.UI.roundedCorners){

				//add a inner wrapper around all div elements with class .rounded
				//console.profile('rounded');
				$j('div.ka-rounded').each(function(i,o){
					//console.log('rounding', i);
					var $e = $j(o),
					id = $e.attr('id'),
					label = id !== ''
						? ' id="' + id + '-inner" class="ka-inner"'
						: '';
					$e.wrapInner('<div' + label + '></div>');
				});
				//console.profileEnd();
			}
		},

		clearSearch: function(){
			$j('input.ka-search-query').one('focus', function() {
				this.value = '';
			});
		}
	},

	Plugins: {
		Carousel: function(vContainer, oArgs){
			// ensure this function is instantiated (needed for supporting old cached pages)
			if (!this.template){
				return new arguments.callee(vContainer, oArgs);
			}

			var c = this;
			this.$elContainer = $j(vContainer);
			this.$holder = this.$elContainer.find('div.ka-carousel-container:first');
			this.$elList = this.$elContainer.find('ul:first');

			// return if no images
			/* removing this since it doesn't support dynamic adding
			if (!this.$elList.find('img:first').length){
				this.$elContainer.find('button').hide();
				return;
			}
			*/

			this.scroll_size = null;
			this.scroll_container_width = null;
			this.scroll_width = null;

			this.setScrollVars();

			this.page = 1;
			this.perPageLimit = Math.ceil(this.scroll_container_width / 50); //this.$elList.find('img:first')[0].width);
			this.loadedAll = $('ka-profile-page') ? false : true;
			this.$btns = this.$elContainer.find('button');
			this.oArgs = $j.extend(oArgs, {
				leftButton: this.$btns[0],
				rightButton: this.$btns[1]
			});

			this.elLButton = this.oArgs.leftButton;
			this.elRButton = this.oArgs.rightButton;
			this.buttonsActive = 1;

			$j(this.elLButton).click(c.handleScrollButton.bind(this));
			$j(this.elRButton).click(c.handleScrollButton.bind(this));
			this.setScrollState();

			return {reshape: this.setScrollVars};
		}
	},

	Page: {}
};

Yuku.Plugins.Carousel.prototype = {
	template: '<li><a href="#{href}" title="#{username}"><img width="50" height="50" src="#{image}" alt="#{username}"></a></li>',

	//set width on UL
	setScrollVars: function(){
		if (!this.$elList) return;

		var $oItemList = this.$elList.find('li');
		if ($oItemList.length){
			this.$elList.width($oItemList[0].offsetWidth * $oItemList.length);
		}else{
			this.$elList.width(50);
		}
		this.scroll_size = this.$holder[0].scrollWidth;
		this.scroll_container_width = parseInt(this.$holder.css('width'));
		this.scroll_width = this.$holder[0].offsetWidth;
	},

	// set and hide scroll buttons
	setScrollState: function(){
		var scroll_left = this.$holder[0].scrollLeft;
		var hasMoreResults = scroll_left + this.scroll_width >= this.scroll_size;
		if (!this.loadedAll){this.loadedAll = hasMoreResults;}
		$j(this.elLButton).toggleClass('ka-inactive', scroll_left == 0);
		$j(this.elRButton).toggleClass('ka-inactive', hasMoreResults);

	},

	shownFriendsCount: function(){
		return this.$elList[0].getElementsByTagName('li').length;
	},

	// animate scroll
	scroll: function (by){
		var c = this;
		var callback = function(){
			c.page = c.page + by;
			c.buttonsActive = 1;

			c.$holder.animate({
				scrollLeft: Math.min(c.$holder.scrollLeft() + ( by * c.scroll_container_width), c.scroll_size)
			},	c.setScrollState.bind(c));
		};
		var startIndex = this.perPageLimit * this.page;
		var maxResults = this.perPageLimit;
		// fetch more friends if loadedAll is not true and moving foward

		this.buttonsActive = 0;

		if (by == 1 && !this.loadedAll && this.shownFriendsCount() < (startIndex + 1)){

			$j.post('/friends/more/start-index/' + startIndex + '/max-results/' + maxResults, function(r){
			    r = eval('('+r+')');
			    if (r.result.length){
			    	if (r.result.length < c.perPageLimit){
			    		c.loadedAll = true;
			    	}

			    	var newItmes = '';

					$j.each(r.result, function(){
						var t = yut.String.replaceFromDict(c.template,{
							href: this.url,
							image: this.pic,
							username: this.name
						});
						newItmes += t;
					});
					c.$elList.append(newItmes);
					c.setScrollVars();

					// prevent future calls if we've exactly reached total friends
					if (r.total_friends == c.shownFriendsCount()){
						this.loadedAll = true;
					}

				}
			    callback();
			});
		}else{
			callback();
		}

	},

	handleScrollButton: function(e){
		if (this.buttonsActive){
			var bLeft = (e.target == this.elLButton);
			this.scroll(bLeft ? -1 : 1);
			e.target.blur();
		}
		return false;
	}
}

// backwards support for old way of calling
Yuku.Plugins.Carousel.create = function(vContainer, oArgs){
    return new Yuku.Plugins.Carousel(vContainer, oArgs);
}

var y = Yuku, ypr = y.Preferences, ypl = y.Platform, yut = y.Util, yusr = Yuku.Info.User;

yut.withDelegateOp = function(opName, fn) {
	return function() {
		var del = this.delegate;
		var	op = 'can'+opName;

		if (del && (op in del) && !del[op](this))
			return false;

		var success = fn.apply(this, arguments);

		if (del) {
			if (success !== false) {
				op = 'did'+opName;
				if (op in del)
					del[op](this);
			}
			else {
				op = opName+'DidFail';
				if (op in del)
					del[op](this);
			}
		}
		return success;
	};
};

yut.make_clearable = function($el, defaultValue, className, onclear) {
	if (!defaultValue)
		defaultValue = '';
	if (!className)
		className = '';

	var $span = $j('<span class="ka-clearable ka-clearable-'+$el.attr('tagName').toLowerCase()+' '+className+'"></span>');
	if ($el.parent().length)
		$span.insertBefore($el);
	$el.appendTo($span);

	$el.attr('value', defaultValue);

	function change(){
		$span.toggleClass('ka-has-value', $el.attr('value') != '');
	}
	change();

	$el.bind('keyup', change).bind('change', change);
	yut.make_$button('clear', 'clear').appendTo($span).click(function(){
/* 		$el.attr('value', defaultValue).trigger('change'); */
			$el.attr('value', '').trigger('change');
		if (onclear)
			onclear($span);
		}).bind('mousedown', function(e){e.preventDefault(); return false;}).attr('UNSELECTABLE', true);
	return $span;
};

yut.make_clearable$Input = function(defaultValue, className, onclear) {
	return yut.make_clearable($j('<input>'), defaultValue, className, onclear);
};

yut.make_clearable$Textarea = function(defaultValue, className, onclear) {
	return yut.make_clearable($j('<textarea>'), defaultValue, className, onclear);
};

yut.make_$button = function(title, className) {
	if (!title) title = '';
	return $j('<button UNSELECTABLE type="button" title="'+title+'" class="'+(className || '')+'"><span>'+title+'<span></button>');
};

(function(){
	function rangeLengthWithEndPoint(el, endpoint){
		if (document.selection && document.selection.createRange){
			var rng = document.selection.createRange().duplicate();
      var rng2 = document.body.createTextRange();
      rng2.moveToElementText(el);
			rng2.setEndPoint(endpoint, rng);
			return rng2.text.length;
		}
		return -1;
	};

	yut.getSelectionStart = function(el){
		if (typeof el.selectionStart != 'undefined')
			return el.selectionStart;
		return rangeLengthWithEndPoint(el, 'EndToStart');
	};

	yut.getSelectionEnd = function(el){
		if (typeof el.selectionEnd != 'undefined')
			return el.selectionEnd;
		return rangeLengthWithEndPoint(el, 'StartToEnd');
	};

	yut.setSelectionStart = function(el, offset){
		if (typeof el.selectionStart != 'undefined')
			el.selectionStart = offset;
		else if (document.selection && document.selection.createRange){
			var rng = document.selection.createRange();
      var rng2 = document.body.createTextRange();
      rng2.moveToElementText(el);
			rng2.setEndPoint('EndToStart', rng);
			rng2.moveStart('character', offset);
			rng2.select();
		}
	};

	yut.setSelectionEnd = function(el, offset){
		if (typeof el.selectionEnd != 'undefined')
			el.selectionEnd = offset;
		else if (document.selection && document.selection.createRange) {
			var rng = document.selection.createRange();
      var rng2 = document.body.createTextRange();
      rng2.moveToElementText(el);
			rng2.moveStart('character', offset);
			rng.setEndPoint('EndToStart', rng2);
			rng.select();
		}
	};
})();

(function(counter){
	/* yut.String.unique generates a strig guarantied not to be the same to
		 a string has been or will be generated by String.unique */
	var a = 'a'.charCodeAt(0), z = 'z'.charCodeAt(0);
	yut.String.unique = function(prefix){
		return (prefix || '') + String.fromCharCode(a + (++counter % (z-a)) ) +''+counter;
	};
})(0);

(function() {
	/* yut.Dom.getId returns element ID, if element does not have an ID
		 it generatse an unique ID for that element, assigns it to the
		 element and returs that new ID.  */
	var unique = yut.String.unique;
	yut.Dom.getId = function(el){
		if (el.constructor === String)
			return arguments.callee($(el));
		else if (!el.id) {
			var id = unique();
			if ($(id)) /* There is already an element with such id, so try again. */
				return arguments.callee(el);
			el.id = 'ka-'+id;
		}
		return el.id;
	};
})();


//dimScreen addon by Brandon Goldman (Modified)
(function($j){

	var isFF2 = navigator.userAgent.indexOf('Firefox/2.0') !==-1,
		isIE6 = navigator.appVersion.indexOf('MSIE 6.0') != -1,
		// If Firefox 2, use transparent png instead of transparent background to fix flash popup browser bug
		background = isFF2 ? 'transparent url(http://media.kickstatic.com/kickapps/images/lightbox.png) repeat' : '#000';

	$j.extend({
		dimScreen:function(speed,opacity,callback){
	    	var placeholder;

			if($j('#ka-__dimScreen').size()>0){return;}

			document.documentElement.className += ' ka-dimmed';
			if(typeof speed=='function'){
	        	callback=speed;
	            speed=null;
	        }

			if(typeof opacity=='function'){
	        	callback=opacity;
	            opacity=null;
	        }

			if(speed<1){
	        	placeholder=opacity;
	            opacity=speed;
	            speed=placeholder;
	        }

			if(opacity>=1){
				placeholder=speed;
				speed=opacity;
				opacity=placeholder;
			}

			speed=(speed>0)?speed:500;
			opacity=(opacity>0)?opacity:0.5;

  			$j('<div></div>')
	            .attr({id:'ka-__dimScreen',fade_opacity:opacity,speed:speed})
	            .css({
	                background: background,
	                height:( ($j(document).height() >= $j(window).height())? $j(document).height():$j(window).height())+'px',
	                left:'0px',
	                opacity:0,
	                position:'absolute',
	                top:'0px',
	                width: '100%',
	                zIndex:999
	            })
	            .click(function(e){e.stopPropagation()})
	            .appendTo(document.body)
	            .fadeTo(speed,opacity,callback);


	           $j(window).bind("resize",function(){
				$j('#ka-__dimScreen').css('height',( ($j(document).height() >= $j(window).height())? $j(document).height():$j(window).height())+'px');
			});

			return $j('#ka-__dimScreen');
	    },

	    dimScreenStop:function(callback){
	            var x=$j('#ka-__dimScreen');
	            var opacity=x.attr('fade_opacity');
	            var speed=x.attr('speed');

	            if(navigator.userAgent.indexOf('Firefox/2.0') !==-1){
	            	x.remove();

	        		$j(window).unbind("resize",function(){
						$j('#ka-__dimScreen').css('height',( ($j(document).height() >= $j(window).height())? $j(document).height():$j(window).height())+'px');
					});

		            if(typeof callback=='function'){
		            	callback();
		            }
	            }else{
		            x.fadeOut(speed,function(){
		                x.remove();

		                if (isIE6){
							$j('select').each(function(){$j(this).css('visibility','visible');});
						}

		        		$j(window).unbind("resize",function(){
							$j('#ka-__dimScreen').css('height',( ($j(document).height() >= $j(window).height())? $j(document).height():$j(window).height())+'px');
						});

		                if(typeof callback=='function'){
		                	callback();
		                }
		            });
	            }
							$j(document.documentElement).removeClass('ka-dimmed');
	    }
	});

})(jQuery);


(function(){
	var $modal = $j(['<div class="ka-modal">',
										'<button type="button" class="ka-main-close ka-close">close</button>',
										'<div class="ka-modal-content"></div>',
									'</div>'].join(''));
	var $modalContent = $j($modal[0].lastChild);

	function event_handlers(e){
		e.stopPropagation();
		var $t = $j(e.target);
		if (!$t.hasClass('ka-close')
				&& $t.parents('.ka-close:first').length == 0)
			return;

		m.close();
		return false;
	}


	var m = yut.Modal = {
		open: function(){
			$j.dimScreen();
			$modal.css({
				'z-index':  1000,
				'top': $j(window).scrollTop() + 100
			});
			$modal.appendTo($j(document.body));
			$modal.click(event_handlers);
			return m;
		},

		setHTMLContent: function(html){
			m.setContent($j(html));
			return m;
		},

		setContent: function(els){
			$modalContent.empty()
				.append(els);
			return m;
		},

		close: function(){
			if (m.onclose){
				m.onclose();
				m.onclose = null;
			}
			$modal.remove();
			$j.dimScreenStop();
			$modal.unbind('click', event_handlers);
		}
	};

	var cache = {};
	m.openWithXhr = function(sUrl, sParams){
		yut.Modal.open();
		var key = sUrl+sParams;
		if (key in cache){
			m.setHTMLContent(cache[key]);
		}	else {
			m.setHTMLContent('<span class="ka-loading">Loading...</span>');
			$j.post(sUrl, sParams,function (response){
				m.setHTMLContent(cache[key] = response);
			});
		}
	};
})();


(function() {
	var m = yut.Modal;

	yut.Alert = function(message){
		message += '<div class="ka-form-actions"><button type="button" class="ka-submit ka-close"><span>OK</span></button></div>';
		var $content = $j(yut.String.replaceFromDict(yut.String.TPLS.sectionTpl, {title: 'Notice', message: message}));
		m.open();
		m.setContent($content);
	};

	var c = yut.Confirm = function(title, message, onsuccess, oncancel){
		var $content = $j(yut.String.replaceFromDict(yut.String.TPLS.confirm, {title: title, message: message}));
		$content.click(function(e) {
			var $t = $j(e.target);
			if ($t.hasClass('ka-cancel')){
				if (oncancel)
					oncancel();
				m.close();
			}else if (($t.hasClass('ka-submit') || $t.parent().hasClass('ka-submit')) && onsuccess) {
			  if (onsuccess()){
			    m.close();
			  }
			}
		});
		m.open();
		m.setContent($content);
		var cls = 'ka-'+yut.String.strToHTMLSafeClassName(title)+'-modal';
    var $modal = $content.parents('div.ka-modal:first').addClass(cls);
    yut.Modal.onclose = function(){
      $modal.removeClass(cls);
      $modal = $content = cls = null;
    }
	};

	yut.ConfirmDelete = function(message, onsuccess, oncancel){
		return c('Confirm Delete', message, onsuccess, oncancel);
	};

	yut.ConfirmRemove = function(message, onsuccess, oncancel){
		return c('Confirm Remove', message, onsuccess, oncancel);
	};
})();

(function(){
	$holder = $j(['<div id="ka-notice">',
									'<div class="ka-nw"></div><div class="ka-n"></div><div class="ka-ne"></div>',
									'<div class="ka-notice-content"></div>',
									'<div class="ka-sw"></div><div class="ka-s"></div><div class="ka-se"></div>',
								'</div>'].join(''));

	$holder.hide();

	$content = $holder.find('div.ka-notice-content:first');

	$j(function(){
		$holder.appendTo($j(document.body));
	});

	yut.showNotice = function(msg){
		$holder.show();
		$content.html(msg);
		$holder.css({
			top: yut.pageScroll().top + 150 + 'px',
			'margin-left': '-' + $holder[0].offsetWidth/2 + 'px'
		});

		setTimeout(function(){
			$holder.fadeOut();
		}, ypr.Notice.displayDuration * 1000);
	};
})();


// all functionality that gets called on DOM ready();
$j(function(){
	$j(ypl.globalMethodNames).each(function() {
		ypl[this]();
	});

	if ('init' in y.Page){
		y.Page.init();
	}
	Yuku.page_loaded = true;
	$j(document.documentElement).removeClass('ka-loading-page');
});

/* dropdowns */
$j('.ka-dropmenu > a').live('click',function(e){
	var $parent = $j(this).parent();
	e.preventDefault();
	if ($parent.hasClass('ka-opened'))
		return;
	$parent.addClass('ka-opened');
	$j(document.body).one('click', function(){
		$parent.removeClass('ka-opened');
	});
});

$j('a[href*=/login/logout]').live('click', function(e){
	e.preventDefault();
	var href = this.href;
	var cname = yut.String.capitalize(Yuku.Info.COMPANY_NAME);
	yut.Confirm('Logout of '+cname+'?', 'Click the OK button to be logged out of '+cname+'.',	function(){
		$j('<form method="post" action="'+href+'"><input type="hidden" name="logout" value="1"></form>').appendTo(document.body).submit();
	});
});

// autogrow for textareas with .autogrow class
(function($) {
	$.fn.simpleautogrow = function() {
		return this.each(function(){
			$(this).data('ag', new $.simpleautogrow(this));
		});
	};

	$.simpleautogrow = function(e) {
		var self = this;
		var $e = this.textarea = $(e)
			.css({overflow: 'hidden', display: 'block'})
			.bind('focus', function() {
				this.timer = window.setInterval(function(){
					self.checkExpand();
				}, 200);
			})
			.bind('blur', function(){
				clearInterval(this.timer);
			});

		this.border = $e.outerHeight() - $e.innerHeight();
		this.clone = $e.clone().css({
			position: 'absolute',
			visibility: 'hidden'
		})
			.attr('name', '');

	$e.height(e.scrollHeight + this.border)
		.after(this.clone);
		this.checkExpand();
	};

	$.simpleautogrow.prototype.checkExpand = function() {
		var target_height = this.clone[0].scrollHeight + this.border;
		if (this.textarea.outerHeight() != target_height)
			this.textarea.height(target_height + 'px');
		this.clone.attr('value', this.textarea.attr('value')).height(0);
	};
})(jQuery);

$j(function(){
	$j('textarea.ka-autogrow').each(function(){
		var $t = $j(this);
			$t.simpleautogrow();
			$t.parents('form:first').submit(function(){
				$t.data('ag').checkExpand();
			});
	})
	.live('keypress', function(e){
		if (e.originalEvent.shiftKey && (e.which == 13 || e.keyCode == 13)){
			e.preventDefault();
			e.stopPropagation();
			$j(this).parents('form:first').submit();
		}
	});
});

// maxlength support for textareas
(function($){
	// use keypress instead of keydown as that's the only place keystrokes could be canceled in Opera
	$('textarea[maxlength]')
		.live('keypress', function(event) {
				var maxlength = +this.getAttribute('maxlength');
				code = $.data(this, 'keycode');

			if (maxlength && maxlength > 0){
				return ( this.value.length < maxlength || event.isDelOrArrowKey() );
			}
		})
		.live('keydown', function(event){
			$.data(this, 'keycode', event.keyCode || event.which);
		});
})(jQuery);

Yuku.Util.serialize = function(o){
	var to = [];
	for (var k in o) {
		if (!o.hasOwnProperty(k) )
			continue;
		if (o[k] == undefined)
			continue;
		if (o[k].constructor !== Array)
			to.push(encodeURIComponent(k) + '=' + encodeURIComponent(o[k]));
		else
			to.push.apply(to, o[k].map(function(v){return encodeURIComponent(k+'[]') +"="+ encodeURIComponent(v)}));
	}
	return to.join('&');
};


(function(){
	var counter = 0;
	Yuku.Util.String.rand = function(){
		return String.fromCharCode('a'.charCodeAt(0) + ('z'.charCodeAt(0) - 'a'.charCodeAt(0))*Math.random()) + (++counter);
	}
})();
