FMUtils = {
	addNotice : function () {
	   	// create a bubble to notify user that the channel was added 
	    var chan = $('#my-channels-pan ul li:last');
	    var notice = { top : chan.offset().top, left : chan.offset().left-28 };
	    var name = $('div.icon-img img', chan).attr('title');		 		 
	    $('<div class="addNotice"></div>')
		 			.css({ top : notice.top+'px', left : notice.left+'px', opacity : '0' })
		 			.html('<strong>' + name + '</strong>' + TRANSLATIONS.Notifications.channelAddedWithoutName)
		 			.appendTo('body')
		 			.show().animate({opacity : '0.9', top : (notice.top-40)+'px'}, DELAY.addNotice_In);
	    var newNotice = $('div.addNotice:last');	
	    setTimeout(function () {
			newNotice.fadeOut( DELAY.addNotice_Out, function () {
	            newNotice.remove();
	        });
	    }, DELAY.addNotice_Stay );
	},
    addRuleCallout : function () {
    	// when user remove the last rule, display the rule callout bubble
		$('#my-channels-pan li[channel-id=' + this.getChannelId() + ']').attr('rule-completed', '');    
    },
    ajaxPOST : function (opts) {
    	var THIS = this;
    	var options = $.extend({
    		type : 'POST',
			url : '/', 
			data : {},
			dataType: 'json',
			success : null,
			error : THIS.throwAjaxError
    	}, opts);
    	$.ajax(options);
    },
	ajaxGraphic_Loader : function (state, mods) {
		/**
		 * Show/hide ajax graphics of type bar or circle
		 * @param state String 'on' or 'off'
		 * @param mods Object {loader: 'circle' or 'bar', covering: jQuery object reference to DOM object to be covered, attaching: jQuery object to attach the ajax loader }
		 * @return void
		 * 
		 * CSS required:
		 * div.ajax-loader-bar { display: none; position: absolute; background: #FFF url(/img/ajax-loader-bar.gif) no-repeat center center; opacity: 0.6; filter:alpha(opacity=60); -moz-border-radius: 6px; -webkit-border-radius: 6px; }
		 * div.ajax-loader-circle { display: none; position: absolute; background : #FFF url(/img/ajax-loader-circle.gif) no-repeat center center; opacity: 0.6; filter:alpha(opacity=60); -moz-border-radius: 6px; -webkit-border-radius: 6px; }
		 */
		var options = $.extend({
			loader : 'bar',
			covering : $('#search-result-container'),
			attaching : $('#content')
		}, mods);
		if (state==='on') {
			if (!options.attaching.find('div.ajax-loader-'+options.loader).length) {
				var $cI = options.covering;
				var styles = {
		    		width: $cI.width() + 'px',
		    		height: $cI.height() + 'px',
		    		top: $cI.offset().top + 'px',
		    		left: $cI.offset().left + 'px',
		    		opacity: '0.6'
		    	};
				if (!FMUtils.isEmpty(options.css)) {
					styles = $.extend(styles, options.css);
				}
			    $('<div class="ajax-loader-' + options.loader + '" />').css(styles).appendTo(options.attaching).fadeIn(); //brings up ajax loading graphic
			}
		} else {
			options.attaching.find('div.ajax-loader-'+options.loader).fadeOut(function () { $(this).remove(); });
		}
	},
	animateMyChannelsPan : function (viewBefore) {
		var THIS = this;
        if (!(!viewBefore && ($('#my-channels-pan ul li').length%9)===0)) {
            // scroll to the current page view containing the recently added item
            $('#my-channels-pan').animate(
                { marginLeft: -($('#my-channels-pan').width()-DIMENSIONS.myChannelsViewWidth) + 'px'},
                DELAY.myChannelsMove, function () {
                    THIS.addNotice();
                    THIS.resetCarouselArrowIMG();
            });
        }
	},
	bindCarousel : function (options) {
		var THIS = this;
		var options = $.extend({
			after : null,
			before : null,
			buttons : '.mc-arrow',
			container : '#my-channels-pan',
			callout : true,
			delay : 800,
			leftID : 'mc-arrow-left',
			rightID : 'mc-arrow-right',
			width : 855
		}, options);
		
		THIS.resetCarouselArrowIMG(options); //reset the arrow images for my channels pan
		$(options.buttons).click(function (e) {
			var $container = $(options.container); var $buttons = $(this);
			if ($container.is(':animated')) { return false; }
			var newMarginLeft;
		    var marginLeft = parseInt($container.css('margin-left'), 10);
		    var isLeft = ($buttons.attr('id')===options.leftID) && marginLeft<0;
		    var isRight = ($buttons.attr('id')===options.rightID) && !(Math.abs(marginLeft) >= ($container.width()-(options.width)));
		    
		    if (isLeft || isRight) {
			    newMarginLeft = isLeft ? marginLeft + options.width + 'px' : marginLeft - options.width +'px';
			    if ($.isFunction(options.before)) {	options.before(); }
			    THIS.removeAllRuleCalloutNotice();
			    $container.animate({marginLeft: newMarginLeft}, options.delay, function () {
			        if (options.callout) {
			        	THIS.ruleCalloutNotice();
			        }
			        THIS.resetCarouselArrowIMG(options);
			        if ($.isFunction(options.after)) {	options.after();}
			    });
		    }
		});
	},
	bindHoverEvent : function () {
		// bind all hover event
	    $.each(menuHover, function (i, menu) {
	        $(menu[0])
	        	.live('mouseover', function () {
	        		if (!$(this).hasClass('disabled')) {
	        			$(this).addClass(menu[1]);
	        		}
	    		}).live('mouseout', function () { $(this).removeClass(menu[1]); });
	    });
	    
	  // hover event for channel description
	    $('div.result-container.hover-e').live('mouseover', function () {
	            $('div.hover-description:visible').css('display', 'none');
	            if (!$(this).hasClass('already-added')) { $(this).addClass('result-channel-hover'); }
	            $(this).mousemove(function (e) {
	                $(this).find('div.hover-description').css({
	                        top : (e.pageY + 20) + 'px',
	                        left : ($(this).hasClass('margin-right-0px') ? e.pageX-150 : e.pageX-20)+ 'px',
	                        display: 'block'
	                });
	            });
	        }).live('mouseout', function () {
	            $(this).removeClass('result-channel-hover');
	            $('div.hover-description:visible').css('display', 'none').unbind('mousemove');
	        });
	        
	        //hover event for my channels arrow
	        $('div.mc-scroll-arrow').hover(
		        function () {
		        	if (!$(this).hasClass('arrow-disabled') && $(this).hasClass('arrow-normal')) {
		        		$(this).removeClass('arrow-normal').addClass('arrow-hover');
		        	}
		        },
		        function () {
		        	if ($(this).hasClass('arrow-hover')) {
		        		$(this).removeClass('arrow-hover').addClass('arrow-normal');
		        	}
		        });
	        //hover event for channel-name-edit in photoapi config
	        $('input.channel-name-edit').live('mouseover', function () {
	        	$(this).addClass('hover-edit');
	        }).live('mouseout', function () {
	        	$(this).removeClass('hover-edit');
	        });
	},
	checkbox_mod_handler : function (options) {
		var defaults = $.extend({elem : null, ajax : false, ajaxURL : '', ajaxData : {}, callback : false}, options);
		var $checkbox = defaults.elem;
		var toggle_state = function () {
			if ($checkbox.hasClass('selected')) {
				$checkbox.removeClass('selected').addClass('deselected');
			} else if ($checkbox.hasClass('deselected')) {
				$checkbox.removeClass('deselected canadd').addClass('selected');
			}
		};
		
		if (defaults.ajax) {
			$checkbox.closest('div.mod_checkbox').addClass('saving');
			$.post(defaults.ajaxURL, defaults.ajaxData, function (data) {
				$checkbox.closest('div.mod_checkbox').removeClass('saving');
				toggle_state()
				if ($.isFunction(defaults.callback)) {
					defaults.callback();
				}
			});
		} else {
			toggle_state()
			if ($.isFunction(defaults.callback)) {
				defaults.callback();
			}
		}
	},
	checkbox_mod_over : function () {
		if (!$(this).hasClass('selected')) {
			$(this).addClass('canadd');
		}
	},
	checkbox_mod_out : function () {
		$(this).removeClass('canadd');
	},
	checkConfigLevel : function () {
		   return this.typeCast($('#dialogbox').attr('config-level'));
	},
	disableNextPrevButton : function (page, total) {
		//Calculate whether the prev/next button should be disabled
		$('div.pagination-button.disabled').removeClass('disabled');
		if (page===total) {
			$('div.pagination-button.next').addClass('disabled');
		} else if (page===1) {
			$('div.pagination-button.prev').addClass('disabled');
		}	
	},
	displayMoreResults : function () {
		// display the have more content area when language is not English
	    if (this.session.read('languageId')===1) {
	       $('#have-more-content').slideUp('slow');
	    } else {
	        $('#have-more-content').slideDown('slow');
	    }
	},
	inputsDisable : function ($container) {
		$container.find('select, input, button').attr('disabled', 'disabled');
	},
	inputEnable : function ($container) {
		$container.find('select, input, button').removeAttr('disabled').filter('input').blur();
	},
	getAttrId : function (attr, $elem) {
		try {
			var result = $elem && $elem.length ? this.typeCast($elem.closest('[' + attr + ']').attr(attr)) : this.typeCast($('#dialogbox').attr(attr));
			return isNaN(result) ? '' : result;
		} catch (e) {
			return '';
		}
	},
	getBucketId : function ($elem) {
		// find the current side navigation (bucket) that has the class current-bucket and parse out the bucketId
		// there may or may not be a bucketId depends on whether it is user's first time browsing in this category
		var THIS = this;
		var bucketId = $elem && $elem.length ? parseInt($elem.closest('[bucket-id]').attr('bucket-id'), 10) : '';
		if (this.isEmpty(bucketId)) {
			var cB = $('#category-nav div.current-bucket');
			if (cB.length) {
				if ($_Session.read('currentPage')==='OnDemand' && cB.hasClass('child')) {
					bucketId = THIS.typeCast(cB.closest('ul.all-bucket-children').siblings('div.hasChildren').attr('bucket-id'));
				} else {
					bucketId = THIS.typeCast(cB.attr('bucket-id'));
				}
			}
		}
		return isNaN(bucketId) ? '' : bucketId;
	},
	getBucketName : function ($elem) {
		//Returns the current Bucket Id number
	    // find the current side navigation (bucket) that has the class current-bucket and return the bucket name
	    // which is in the title attribute
	    return $elem && $elem.length ? $elem.attr('title') : $('#category-nav div.current-bucket').attr('title');
	},
	getCategoryId : function ($elem) {
		// find the current side navigation (bucket) that has the class current-bucket and parse out the categoryId
		// there should always be a categoryId
		var categoryId = $elem && $elem.length ? parseInt($elem.closest('[category-id]').attr('category-id'), 10) : '';
		if (this.isEmpty(categoryId)) {
			if ($('#category-nav div.current-bucket').length) {
				categoryId = parseInt($('#category-nav div.current-bucket').attr('category-id'), 10);
			}
		}
		return isNaN(categoryId) ? '' : categoryId;
	},
	getChannelId : function ($elem) {
		// get channel-id attribute in the info div of #dialogbox
		// if a selector/jquery object is passed then find the closest parent with a channel-d attribute to get the id
		return this.getAttrId('channel-id', $elem);
	},
	getChannelName : function ($elem) {
		// return channel name
		return $('#my-channels-pan li.my-channel-container[channel-id=' + this.getChannelId() + ']').find("div.my-channel-name").text();
	},
	getCurrentMyChannelsItem : function () {
		return $('#my-channels-pan li.my-channel-container[channel-id=' + this.getChannelId() + ']'); 
	},
	getCurrentSearchResultsItem : function () {
		return $('#search-results-pan div.result-container[channel-id=' + this.getChannelId() + ']');
	},
	getFeedTypeId : function ($elem) {
		//return feed type id of a channel or current channel
		return this.getAttrId('feed-type-id', $elem);
	},
	getOwnerId : function ($elem) {
		return this.getAttrId('owner-id', $elem);
	},
	getPaginatePages : function (total, limit) {
	    var pages = parseInt(total/limit, 10);
	    if (pages===0) { pages = 1; }
	    if ((total%limit) && (pages*limit)<total ) { pages += 1; }
	    return pages;
	},
	getRuleId : function ($elem) {
		// get rule-id attribute in the info div of #dialogbox
		return this.getAttrId('rule-id', $elem);
	},
	getUsersAndContainersId : function ($elem) {
		// Returns the current UsersAndContainersId number
		return this.getAttrId('usersandcontainers-id', $elem);
	},
	isEmpty : function (item) {
		var type = typeof(item);
		switch(type) {
			case 'boolean':
				return !item;
			case 'number':
				return item ? false : true;
			case 'object':
				return item!==null ? !$.param(item).length : true;
			case 'string':
				return item.length ? false : true;
			case 'undefined':
				return true;
		}
	},
	log : function (data) {
		if (console) {
			console.log(data);
		} else {
			alert(data);
		}
	},
	makeTimeFromMinutes : function (time, clean_format) {
		var hour = parseInt(time/60, 10);
		var minutes = time%60;
		var am_pm = time<=720 && hour!=12 ? 'AM' : 'PM';
		var real_time = {hour: hour, minute: minutes, am_pm: am_pm};
		if (clean_format) {
			real_time.am_pm = real_time.hour===24 ? 'AM' : real_time.am_pm; //converts 24:00 into AM
			real_time.hour = real_time.hour===0 || real_time.hour===24 ? 12 : real_time.hour; //converts 0:00 and 24:00 into 12:00
			real_time.hour = real_time.hour<10 ? '0' + real_time.hour : real_time.hour; //add a leading 0 for hour if it has 1 digit
			real_time.minute = real_time.minute<10 ? '0' + real_time.minute : real_time.minute; //add a leading 0 for minutes if it has 1 digit
		}
		return real_time;
	},
	makeTimeFromHours : function (time) {
		var am_pm = time<12 || time===24 ? 'AM' : 'PM';
		var hour = time>12 ? time-12 : time; hour = hour===0 ? 12 : hour;
		return {hour: hour, am_pm : am_pm};
	},
	now : function () {
        return new Date().getTime();
    },
	parseImgAttr : function (str) {
		// parsing an image's class string and return an object
		// ex: class="width-300 height-400 duration-10"
	    var data = str || "";
	    var tmpArr = $.map(data.split(' '), function (n, i) {
	        return parseInt(n.split('-')[1], 10);
	    }); 
	    return {width : tmpArr[0], height : tmpArr[1], duration : tmpArr[2]};  
	},
	parseSearchResults : function (data) {
		this.typeCast(data.total, true) ? $('#search-result-container h1.clickadd-msg:hidden').css('display', 'block') : $('#search-result-container h1.clickadd-msg:visible').css('display', 'none');
		$('#search-results-pan').css({ 'width' : data.width, 'marginLeft' : '0px'}).html(data.channels);
		$('div.pagination-current-num').html(data.nav_num);
		this.updateSearchResultsHeight(1);
    	if ($('#search-result-container').hasClass('ugen-category-lock')) { 
    		$('#search-result-container').removeClass('ugen-category-lock').find('#user_generated_msg').fadeOut(); 
    	}
		calledPages = [1, 2];
	},
	getItemValue : function ($item, typeCast) {
		return typeCast ? this.typeCast($item.attr('item-value')) : $item.attr('item-value');
	},
	setItemValue : function ($item, value) {
		return $item.attr('item-value', value);
	},
	radio_mod_handler : function (options) {
		var defaults = $.extend({elem : null, ajax : false, ajaxURL : '', ajaxData : {}, callback : false}, options);
		var $radio = defaults.elem;
		var $radio_group = $radio.closest('.radio-group');
		var toggle_state = function () {
			$radio_group.find('.radio-mod.selected').removeClass('selected');
			$radio.addClass('selected');
		};
		
		if (defaults.ajax) {
			$radio_group.addClass('saving');
			$.post(defaults.ajaxURL, defaults.ajaxData, function (data) {
				toggle_state();
				$radio_group.removeClass('saving');
				if ($.isFunction(defaults.callback)) {
					defaults.callback();
				}
			});
		} else {
			toggle_state();
			if ($.isFunction(defaults.callback)) {
				defaults.callback();
			}
		}
	},
	radio_mod_val : function ($radio_group) {
		return this.getItemValue($radio_group.find('.radio-mod.selected:first'));
	},
	removeAllRuleCalloutNotice : function () {
		// remove all call outs notices
	    $('div.ruleCalloutNotice').each(function () {
	        var $this = $(this);
	        $this.fadeOut(100, function () {
	            $this.remove();
	        });
	    });
	},
    removeRuleCallout : function () {
    	// when users successfully configure a channel, remove the rules callout bubble
		$('#my-channels-pan li[channel-id=' + this.getChannelId() + ']').attr('rule-completed', 1);    
    },
    resetCarouselArrowIMG : function (options) {
		var options = $.extend({
			container : '#my-channels-pan',
			callout : true,
			leftID : 'mc-arrow-left',
			rightID : 'mc-arrow-right',
			width : 855
		}, options);
		// Reset the arrow image states
		var $left = $('#' + options.leftID + ' div:first');
		var $right = $('#' + options.rightID + ' div:first');
		var $container = $(options.container);
	    var marginLeft = parseInt($container.css('margin-left'), 10);
	    
	    // left
	    if (marginLeft===0) {
	    	// disable arrow when you cannot scroll to the left anymore
	    	$left.removeClass('arrow-normal arrow-hover').addClass('arrow-disabled');
	    } else if ($container.width()+marginLeft>0) {
	    	$left.removeClass('arrow-hover arrow-disabled').addClass('arrow-normal');
	    }
	    
	    // right
	    if ($container.width()+marginLeft===options.width) {
	    	// disable arrow when you cannot scroll to the right anymore
	    	$right.removeClass('arrow-normal arrow-hover').addClass('arrow-disabled');
	    } else if ($container.width()+marginLeft>options.width) {
	    	$right.removeClass('arrow-hover arrow-disabled').addClass('arrow-normal');
	    }
	},
	resetMyChannelsWidth : function () {
	    //reset the width of the My Channels item
	    $('#my-channels-pan').css('width', (FMUtils.getPaginatePages($('#my-channels-pan ul li').length, 9)*DIMENSIONS.myChannelsViewWidth)+'px');
	},
	ruleCalloutNotice : function () {
		var THIS = this;
		// function to create and display callouts if the required user rules for a channel is not complete
	    // first remove all existing callouts
	    this.removeAllRuleCalloutNotice();
	    // then go through each My Channels items searching for callout requirement and display where appropriate    
	    $('#my-channels-pan li.my-channel-container').each(function () {
	        // boolean check to see if the channel is currently being shown
	        var isInView = ($(this).offset().left < ($('#my-channels-viewport').offset().left + $(this).width()*7)) &&
	                       ($(this).offset().left > $('#my-channels-viewport').offset().left);
	        if (THIS.typeCast($(this).attr('rule-id')) && !THIS.typeCast($(this).attr('rule-completed')) && !$(this).is(':hidden') && isInView) {
	            var notice = { top : $(this).offset().top, left : $(this).offset().left-28 };
	            var name = $('div.icon-img img', $(this)).attr('title');
	            var id = $(this).attr('id');
	            $('<div class="ruleCalloutNotice ' + id + '"></div>')
	                .css({top : notice.top+'px', left : notice.left+'px', opacity : '0', display: 'block'})
	                .html('<strong>' + name + '</strong>' + TRANSLATIONS.Notifications.ruleCalloutNotice)
	                .appendTo('body')
	                .animate({ opacity : '0.9', top : (notice.top-40)+'px'}, DELAY.addNotice_In);
	        }
	    });               
	},
	setUsersAndContainersId : function (id) {
		// Set the UsersAndContainersId number
		$('#dialogbox').attr('usersandcontainers-id', id);       
	},
	setChannelId : function (id) {
		// Set the Channel Id for item
		$('#dialogbox').attr('channel-id', id);
	},
	setConfigLevel : function (id) {
		//Set the Config Level for item
		$('#dialogbox').attr('config-level', id);
	},
	setChannelName : function (channelName) {
		$('#my-channels-pan li[channel-id=' + this.getChannelId() + ']').find("div.my-channel-name").text(channelName);
	},
	setRuleCompleted : function () {
		$('#my-channels-pan li[channel-id=' + this.getChannelId() + ']').attr('rule-completed', 1); 
		$('#my-channels-pan li[channel-id=' + this.getChannelId() + ']').attr('config-level', 3); 
	},	
	setRuleId : function (id) {
		$('#dialogbox').attr('rule-id', id);
	},
	session : {
		cache : $('#variables-cache'),
		init : function () {
			var THIS = this;
			var constants = {};
			var sessions = {};
			var vars = {};
			if (!this.cache.length) { this.cache = $('#variables-cache'); }
			this.cache.data('FMUtils.session',{ constants: constants, sessions : sessions, vars: vars});
			this.cache.find('div.cache').each(function () {
				
				if ($(this).hasClass('CONSTANT')) {
					constants[$(this).attr('title')] = FMUtils.typeCast($(this).text());
				} else if ($(this).hasClass('VAR')) {
					vars[$(this).attr('title')] = FMUtils.typeCast($(this).text());
				} else {
					sessions[$(this).attr('title')] = $(this).attr('title')==='sessionId' ? $(this).text() : FMUtils.typeCast($(this).text());
				}
			});
			THIS.merge_session(constants, sessions, vars);
			THIS.cache.empty();
		},
		check : function (item) {
			return typeof(item)==='string' && !FMUtils.isEmpty(this.read(item)) ? true : false; 
		},
		del : function (item, type) {
			var THIS = this;
			var curr_session = this.read();
			var constants = {}; var sessions = {}; var vars = {};
			$.each($_Session.read(), function (sess, data) {
				if (sess==='constants') {
					constants = type===sess || FMUtils.isEmpty(type) ? THIS.reassign(data, item) : data;
				} else if (sess==='sessions') {
					sessions = type===sess || FMUtils.isEmpty(type)  ? THIS.reassign(data, item) : data;
				} else if (sess==='vars') {
					vars = type===sess || FMUtils.isEmpty(type)  ? THIS.reassign(data, item) : data;
				}
			});
			THIS.cache.removeData('FMUtils.session');
			THIS.merge_session(constants, sessions, vars);
		},
		merge_session : function (constants, sessions, vars) {
			if (!FMUtils.isEmpty(constants)) {
				this.cache.data('FMUtils.session', $.extend(this.cache.data('FMUtils.session'), {constants : constants}));
			}
			if (!FMUtils.isEmpty(sessions)) {
				this.cache.data('FMUtils.session', $.extend(this.cache.data('FMUtils.session'), {sessions : sessions}));
			}
			if (!FMUtils.isEmpty(vars)) {
				this.cache.data('FMUtils.session', $.extend(this.cache.data('FMUtils.session'), {vars : vars}));
			}
		},
		read : function (item) {
			var curr_session = this.cache.data('FMUtils.session');
			if (FMUtils.isEmpty(item) || item==='*') {
				return curr_session;
			} else if (!FMUtils.isEmpty(curr_session) && typeof(item)==='string' && item.indexOf('.')===-1) {
				if (!FMUtils.isEmpty(curr_session.constants) && !FMUtils.isEmpty(curr_session.constants[item])) {
					return curr_session.constants[item];
				} else if (!FMUtils.isEmpty(curr_session.sessions) && !FMUtils.isEmpty(curr_session.sessions[item])) {
					return curr_session.sessions[item];
				} else if (!FMUtils.isEmpty(curr_session.vars) && !FMUtils.isEmpty(curr_session.vars[item])) {
					return curr_session.vars[item];
				} else {
					return null;
				}
				
			} else if (typeof(item)==='string' && item.length && item.indexOf('.')!==-1) {
				var _type = item.split('.')[0];
				var _item = item.split('.')[1];
				curr_session = this.read();
				if (this.check(_item) && !FMUtils.isEmpty('constantssessionsvars'.match(_type))) {
					var value = curr_session[_type][_item];
					return !FMUtils.isEmpty(value) ? value : null;
				} else {
					return null;
				}
			} else {
				return null;
			}
		},
		reassign : function (data, item) {
			var session = {};
			$.each(data, function (key, value) { 
				if (key!==item) {
					session[key] = value;
				}
			});
			return session;
		},
		write : function (key, value, type) {
			var _type = !FMUtils.isEmpty(type) ? type : 'sessions';
			var curr_session = this.read();
			curr_session[_type][key] = value;
			this.cache.data('FMUtils.session', curr_session);
			return this.check(key);
		}
	},
	showHidePaginationGroup : function ($new_page_button, direction) {
		// handle the show/hide of pagination groups
	    $new_page_button.addClass('pagination-current-on');
		if ($new_page_button.parent().is(':hidden')) {
		    if (direction==='next') {
		    	$new_page_button.parent().prev().addClass('hidden');
		    } else {
		    	$new_page_button.parent().next().addClass('hidden');
		    }
		    $new_page_button.parent().removeClass('hidden');
		}
	},
	throwAjaxError : function (request, status, options) {
		$('#dialog-ajax-error-alert').dialog({
			modal: true, resizable: false,
			buttons: {
				'Refresh' : function () {
					window.location.href = '/';
				},
				'Cancel' : function () {
					$(this).dialog('close');
				}
			},
			close: function (event, ui) {
				$(this).dialog('destroy');
				$('#dialogbox').find('select, input, button').removeAttr('disabled').filter('input').blur();
			}
		});
	},
	throwGlobalError : function (opts) {
		var THIS = this;
		var options = $.extend({
			modal: true, resizable: false,
			errorTitle : 'An error has occurred!',
			errorContent : 'We are sorry, but FrameChannel has encountered a problem while performing your request. Please click <strong>Close</strong> and try your request again.',
			buttons : {
				'Close' : function () {
					$(this).dialog('close');
					$(this).dialog('destroy');
				}
			},
			close: function (event, ui) {
				$(this).dialog('destroy');
			}
		}, opts);
		!$('#dialog-global-alert').length &&
			$('<div id="dialog-global-alert" title="' + options.errorTitle + '"><div class="error">' + options.errorContent + '</div></div>').appendTo('body');
		$('#dialog-global-alert').dialog(options);
	},
    throwFormError : function (opts) {
        // throw an error on form submission
        var Err = {
            error: false,
            element: false,
            errorContainer : '#dialogbox div.rules-dialog-form-error',
            callback : false
        };
        $.extend(Err, opts);
        // resets form alert div
        $(Err.errorContainer).empty();
        if (Err.element) {
        	Err.element.addClass('error-background');
        }
        $('<div style="display:none">' + Err.error + '</div>').appendTo(Err.errorContainer).fadeIn('fast');
        if ($.isFunction(Err.callback)) {
            Err.callback();
        }          
    },
    throwFormSuccess: function (opts) {
        // display a success message on form submission
        var Mess = {
            message: false,
            messageContainer : '#dialogbox div.rules-dialog-form-error',
            callback : false
        };
        $.extend(Mess, opts);
        // resets form alert div
        $(Mess.messageContainer).empty();
        $('<div style="color: black; display:none">' + Mess.message + '</div>').appendTo(Mess.messageContainer).fadeIn('fast');
        if ($.isFunction(Err.callback)) {
            Mess.callback();
        }          
    },
    toolTipInit : function () {
    	$('.tool-tip-trigger').unbind('mouseover mouseout').live('mouseover', function () {
    		var tooltip_content = $(this).find('.tool-tip-content').html();
    		$('#fc-tt-' + $('body').data('fc_tool_tip')).remove();
    		$('body').data('fc_tool_tip', FMUtils.now());
    		$('<div id="fc-tt-' + $('body').data('fc_tool_tip') + '" class="tool-tip-bubble" style="z-index:9999;">' + tooltip_content + '</div>').appendTo('body');
            $(this).mousemove(function (e) {
            	$('#fc-tt-' + $('body').data('fc_tool_tip')).css({
                        top : (e.pageY+20) + 'px',
                        left : (e.pageX-100)+ 'px',
                        display: 'block'
                });
            });
    	}).live('mouseout', function () {
    		$('#fc-tt-' + $('body').data('fc_tool_tip')).fadeOut('fast', function () {
    			$(this).remove();
    		});
    	});
    },
	typeCast : function (item, force_integer) {
		if (typeof(item)==='string') {
			var num = parseInt(item, 10);
			return (typeof(num)==='number' && !isNaN(num)) && (item.length==String(num).length || !this.isEmpty(force_integer)) ? num : item;
		} else {
			return item;
		}
	},
	updateSearchResultsHeight : function (page) {
		// updates the height of the search results div
	    var totalPromo = $('#search-results-pan div.results-pan:eq(' + (page-1) + ')').find('div.result-container:not(".rssfeed-channel")').length; //total search results that are Promoted Channel
	    var totalRSS = $('#search-results-pan div.results-pan:eq(' + (page-1) + ')').find('div.result-container.rssfeed-channel').length; //total results that are Suggested RSS feeds    
	    if (totalPromo || totalRSS) {
	        var promoRows = parseInt((totalPromo/5), 10);
	        var rssRows = parseInt((totalRSS/5), 10);
	        
	        // add 1 extra row if the total number of results has remainder
	        if (totalPromo && (5*promoRows)<totalPromo) { promoRows += 1; }
	        if (totalRSS && (5*rssRows)<totalRSS) { rssRows += 1; }
	        
	        // the rough height should be calculated using rows x item height
	        // NOTE: +5 is to handle the margin-top of 5px per result-container item
	        var newHeight = (promoRows + rssRows) * ($('div.result-container:first').height() + 5);
	        
	        // if the page has the "Suggested Feeds" insert, take that height into consideration
	        // the height of the "Suggested Feeds" insert is 75px
	        if (!!$('#search-results-pan div.results-pan:eq(' + (page-1) + '):has(' + "#suggested-feeds-begin" + ')').length) { newHeight += 75; }
	        
	        // animating to the new height
	        // NOTE: also animating opacity of the whole div while it's moving for a fake motion blur fx
	        newHeight = (newHeight>537) ? newHeight : 537;
	        $('#search-results').animate({ height: newHeight + 'px'}, DELAY.searchResultsHeight, function () {
	        	$('##get-search-results-ajax-load').css('height', $('#search-result-container').height() + 'px');
	        });
	    } else {
	        $('#search-results').animate({height : '300px'}, DELAY.searchResultsHeight, function () {
	        	$('##get-search-results-ajax-load').css('height', $('#search-result-container').height() + 'px');
	        }); 
	    }
	},
	validateRSS : function (opts) {
		var options = $.extend({data : {url:'',feedTypeId:FMUtils.getFeedTypeId()}, callback : false}, opts);
		var feed = options.data.url.replace('feed://', '');
		options.data.url = feed.match('http://') ? feed : 'http://' + feed;
        FMUtils.ajaxPOST({
        	url : '/channels/validateAddExternalFeed/',
        	data :  options.data,
        	success : function (response){        		
    			if ($.isFunction(options.callback)) {
    				options.callback(response);
    			}
    		}
        });
        
	},
	validateURL : function (value) {
		value = value.replace('feed://', '');
		value = value.match('http://') ? value : 'http://' + value;
		return /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
	},
	validateZip : function (value) {
		return /^\d{5}([\-]\d{4})?$/i.test(value);
	},
	validateEmail : function (value) {
		// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
		return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
	},
	visibleDOMObj : function ($objArray, return_first_item) {
		//take an array of DOM Objects and return an array containing only visible DOM Object(s)
		//if return_first_item flag is set to true and there is one or more visible item, return the first visible item
		var results = $.map($objArray, function ($jqObj) {
			return $jqObj.is(':visible') ? $jqObj : null;
		});
		
		return return_first_item && results.length ? results[0] : results;  
	}
};

$(document).ready(function () {
	FMUtils.session.init();
	if (FMUtils.isEmpty(window.$_Session)) {
		window.$_Session = FMUtils.session;
	}
});