/**
 * TextMarks Common JavaScript Support Library.
 * ---------------------------------------------------------------------------
 *
 * Requires jQuery.
 *
 * ---------------------------------------------------------------------------
 * Author: Dan Kamins [d k a m i n s A T t e x t m a r k s D O T c o m]
 * ---------------------------------------------------------------------------
 * Copyright (c) 2010, TextMarks Inc.
 * ---------------------------------------------------------------------------
 */
/** */


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

/**
 * Set up .alt_mouseover such that first <div> child is shown, but alts to second <div> on mouseover.
 */
function tm_setup_alt_mouseover(je_parent) {
	je_parent.find('.alt_mouseover > div:last-child').hide();
	function _show() { $(this).children(':first').hide().next().show(); }
	function _hide() { $(this).children(':first').show().next().hide(); }
	if (typeof($.fn.hoverIntent) != 'undefined') {
		je_parent.find('.alt_mouseover').hoverIntent(_show, _hide);
	} else {
		je_parent.find('.alt_mouseover').hover(_show, _hide);
	}
}

/**
 * Setup .disable_on_click such that clicking disables the element.
 */
function tm_setup_disable_on_click(je_parent) {
	je_parent.find('.disable_on_click').click(function() { $(this).attr('disabled', 'disabled'); })
}

/**
 * Setup .disable_on_click such that clicking disables the element.
 */
function tm_setup_tooltip(je_parent) {
	je_parent.find('.tooltip > a').each(function(idx, je_tooltip) {
		$(je_tooltip).hover(
			function() { var box = $(je_tooltip).parent().find('> span'); box.fadeIn(100); },
			function() { $('.tooltip > span').fadeOut(200); }
		);
		$('.tooltip > span').click(function() { $(this).fadeOut(200); }); // (for touch interfaces)
	});
}

/**
 * Initialize Grumble messaging subsystem.
 */
function tm_setup_Grumble_defaults() {
	if(typeof(Grumble) == "undefined") { return; }
	Grumble.defaults.top = 110;
	Grumble.defaults.duration = 10000;
}

// Run our setup routines as soon as the page is ready:
$(function() { 
	tm_setup_alt_mouseover($('body'));
	tm_setup_disable_on_click($('body'));
	tm_setup_Grumble_defaults();
	tm_setup_tooltip($('body'));
})


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


/**
 * Improved slideUp / slideDown to fix jQuery buggy "wontfix" implementation that causes jumpy flashes of content.
 * Code inspired by http://blog.pengoworks.com/index.cfm/2009/4/21/Fixing-jQuerys-slideDown-effect-ie-Jumpy-Animation
 */
function slideToggle(je_elem, bShow){
	var $el = je_elem, height = $el.data("originalHeight"), visible = $el.is(":visible");
	if (arguments.length < 2) {
		bShow = !visible;
	}
	if (bShow == visible) {
		return false;
	}
	if( !height ) {  // Show temporarily to get/save orig height:
		height = $el.show().height();
		$el.data("originalHeight", height);
		if (!visible) { $el.hide().css({height: 0}); }
	}
	if (bShow) {
		$el.show().animate({height: height}, {duration: 250});
	} else {
		$el.animate({ height: 0 }, { duration: 250, complete:function (){ $el.hide(); } });
	}
}


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


/**
 * Count text characters, enforce max, and update count field.
 *
 * Use optional warnspec param dict to show warning at some point:
 *   - length : Length at which to show warning. e.g. 140.
 *   - warning : selector string of elements to show. e.g. '.warn_140'.
 */
function TextCharCounter(je_text, je_count, max_len, warnspec)
{
	this.text_change_handler = function() {
		len = this.value.length;
		if (len > max_len) { this.value = this.value.substring(0, max_len); len = this.value.length; }
		je_count.text(len);
		if (warnspec) {
			if (len > warnspec.length) {
				$(warnspec['warning']).show();
			} else {
				$(warnspec['warning']).hide();
			}
		}
	}
	this.init = function() {
		je_count.text(je_text.val().length);
		je_text.keyup(this.text_change_handler);
		je_text.change(this.text_change_handler);
	}
}


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


/**
 * Run A/B/N test on elements of the current page, choosing one and hiding others.
 * Currently backed by KissMetrics so choice persists for user.
 * Multiple elements on the page can be shown/hidden based on the choice.
 * Elements should be CSS classed as "ab_alts {{TEST_ID}}_{{CHOICE}}".
 * Include optional empty classed "ab_init {{TEST_ID}}" as placeholder.
 * Once choice made, "ab_run" attr is applied.
 * Reload page with #ab_CHOICE to force various choices for testing.
 * See tm-common.css for CSS defs ("ab_alts" is hidden by default, etc.)
 *
 * Example usage:
 * <h1 class="ab_init ab_signup_keyword_ChooseKW"></h1>
 * <h1 class="ab_alts ab_signup_keyword_ChooseKW_keyword">Choose a Keyword</h1>
 * <h1 class="ab_alts ab_signup_keyword_ChooseKW_group">Name your group</h1>
 * <script>abtest('ab_signup_keyword_ChooseKW', ['keyword', 'group']);</script>
 */
function abtest_km(test_id, choices) {
	_kmq.push(function(){
		var which = undefined;
		if (window.location.hash) {
			if (window.location.hash.substring(0, 4) == '#ab_') {
				which = window.location.hash.substring(4);
			}
		} 
		if (!which) {
			which = KM.ab(test_id, choices);
		}
		for (var i=0; i<choices.length; i++) {
			var jel = $('.ab_alts.'+test_id+'_'+choices[i]);
			if (jel.attr('ab_run')) { return; }
			jel.attr('ab_run', 'km');
			if (choices[i] == which)	{ jel.show(); }
			else						{ jel.hide(); }
		}
		$('.ab_init.'+test_id).hide();
	});
	function fallback() { // (eg if KM fails)
		var jel = $('.ab_alts.'+test_id+'_'+choices[0]);
		if (jel.attr('ab_run')) { return; }
		jel.attr('ab_run', 'timeout');
		jel.show();
		$('.ab_init.'+test_id).hide();
	}
	setTimeout(fallback, 1500);
}
/**
 * Temp abtest to bypass KM and make dumb selection.
 */
function abtest(test_id, choices) {
	var jel = $('.ab_alts.'+test_id+'_'+choices[0]);
	jel.show();
	$('.ab_init.'+test_id).hide();
}


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


/**
 * Return HTML-encoded (gt, lt, amp, etc.) version of string provided.
 */
function tm_htmlencode(txt) {
	var html = $('<div/>').text(txt).html();
	return html;
}


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


/** Dismiss single page notification. */
function tm_notif_dismiss(je_notif) {
	var url_root = $('#link_root').attr('href');
	$.ajax({
		type: 'POST',
		url: url_root + 'front/helper/ajax_dismiss_notification/',
		data: 'notif_id=' + escape(je_notif.attr('id')),
		dataType: 'json'
	});
	je_notif.animate({ opacity: 0.0 }, 500).slideUp(300);
}

/** Add/animate reveal of a new notification. */
function tm_notif_add(notif_class, notif_id, main_html, details_html) {
	var notif_html = '\
	<div class="notification ' + notif_class + '" id="' + notif_id + '">	\
		<table class="notification"><tr>	\
			<td class="left"></td>	\
			<td class="content">	\
				<div class="main"></div>	\
				<div class="details"></div>	\
			</td>	\
			<td class="dismiss">	\
				<span class="widget"><a href="javascript:void(0);" title="Dismiss notification">X</a></span>	\
				<div class="explain"><a href="javascript:void(0);" title="Dismiss notification">(hide)</a></div>	\
			</td>	\
		</tr></table>	\
	</div>	\
	';
	var je_notif = $(notif_html);
	je_notif.find('.content .main').html(main_html);
	je_notif.find('.content .details').html(details_html);
	je_notif.find('.dismiss a').each(function() {
		$(this).click(function() { tm_notif_dismiss(je_notif); });
	});
	$('#page_notifications').prepend(je_notif);
	je_notif.slideDown(250).animate({ opacity: 1.0 }, 750);
}

/* Shorthand for adding new notification by dict/object with params named from tm_notif_add. */
function tm_notif_add_dict(notif_dict) {
	if (notif_dict) {
		return tm_notif_add(notif_dict['notif_class'], notif_dict['notif_id'], notif_dict['main_html'], notif_dict['details_html']);
	}
}

