/**
 * @projectDescription CommentPress jQuery Plugin
 *
 * @version 3.0
 * @author Christian Wach/needle@haystack.co.uk
 *
 */
;



/** 
 * @description: a nifty JS array utility to remove a specified value
 *
 */
Array.prototype.remove_item = function( item ) {

	// loop through the array
	for (var i = 0; i < this.length; i++){
		
		// remove our item
		if (item === this[i]) { this.splice(i, 1); }
		
	}

}




/** 
 * @description: our jQuery plugin
 *
 */
;( function( $ ) {

	// plugin context (external or internal)
	var plugin_context = 'internal';

	/** 
	 * @description: set the context of this plugin
	 * @todo: remove
	 *
	 */	
	$.set_context = function( context ) {
	
		// store global
		plugin_context = context;
	
	};
	
	
	
	// define open accordion parts array
	var open_parts = new Array();
	
	/** 
	 * @description: reset the accordion
	 * @todo: remove
	 *
	 */	
	$.accordion_reset = function() {
	
		// reset open_parts
		open_parts = new Array();
	
	};
	
	
	
	/** 
	 * @description: open a section of the accordion
	 * @todo: remove
	 *
	 */	
	$.accordion_open = function( part ) {
	
		// add part to open array
		open_parts.push( part );
	
	};
	
	
	
	/** 
	 * @description: close a section of the accordion
	 * @todo: remove
	 *
	 */	
	$.accordion_close = function( part ) {
	
		// remove this part from the open array
		open_parts.remove_item( part );
	
	};
	
	
	
	/** 
	 * @description: query the accordion for the open/closed status of a part
	 * @todo: remove
	 *
	 */	
	$.accordion_query = function( part ) {

		// is our part in the open array?
		return $.in_array( part, open_parts )

	};
	
	
	
	// our currently highlighted paragraph
	var highlighted_para = '';
	
	// our widening constant (must match selected_para: top in CSS)
	var selected_para_widen = 7;

	/**
	 * @description: highlight the current paragraph
	 * @todo: 
	 *
	 */	
	$.highlight_para = function( element ) {
	
		// test that we have a proper element
		if ( typeof( element ) != 'object' ) {
		
			// --<
			return;
		
		}

		
		
		// unhighlight
		$.unhighlight_para();
		


		// only store highlight if in our Commentpress context
		if ( plugin_context == 'internal' ) {
	
			// is our item already highlighted?
			if ( $.accordion_query( element.attr('id') ) ) {
			
				// clear current element in global
				highlighted_para = '';
				
				// close this part of the accordion
				$.accordion_close( element.attr('id') );
			
				// --<
				return;
			
			} else {
			
				// open this part of the accordion
				$.accordion_open( element.attr('id') );
			
				// store current element in global
				highlighted_para = element;
				
			}
			
		}
		
		
		
		// widen
		//var width = parseInt( element.width() );
		//element.css( 'width', (width + selected_para_widen) + 'px' );

		// get padding
		var padding_top = parseInt( element.css( 'padding-top' ).split('px')[0] );
		var padding_right = parseInt( element.css( 'padding-right' ).split('px')[0] );
		var padding_bottom = parseInt( element.css( 'padding-bottom' ).split('px')[0] );
		var padding_left = parseInt( element.css( 'padding-left' ).split('px')[0] );

		element.css( 'padding-top', padding_top + selected_para_widen );
		element.css( 'padding-right', padding_right + selected_para_widen );
		element.css( 'padding-bottom', padding_bottom + selected_para_widen );
		element.css( 'padding-left', padding_left + selected_para_widen );
		
		// amend p tag css
		element.addClass( 'selected_para' );

	}
	
	

	/** 
	 * @description: unhighlight all text
	 * @todo: 
	 *
	 */	
	$.unhighlight_para = function() {
	
		// if we have a highlight
		if ( highlighted_para != '' ) {
			
			// remove class
			highlighted_para.removeClass( 'selected_para' );
		
			// get padding
			var padding_top = parseInt( highlighted_para.css( 'padding-top' ).split('px')[0] );
			var padding_right = parseInt( highlighted_para.css( 'padding-right' ).split('px')[0] );
			var padding_bottom = parseInt( highlighted_para.css( 'padding-bottom' ).split('px')[0] );
			var padding_left = parseInt( highlighted_para.css( 'padding-left' ).split('px')[0] );
			
			// remove visible highlight
			highlighted_para.css( 'padding-top', padding_top - selected_para_widen );
			highlighted_para.css( 'padding-right', padding_right - selected_para_widen );
			highlighted_para.css( 'padding-bottom', padding_bottom - selected_para_widen );
			highlighted_para.css( 'padding-left', padding_left - selected_para_widen );
			
			// narrow
			//var width = parseInt( highlighted_para.width() );
			//highlighted_para.css( 'width', (width - selected_para_widen) + 'px' );
	
		}

		// only clear highlight if in our Commentpress context
		if ( plugin_context == 'internal' ) {
	
			// clear global
			highlighted_para = '';
		
		}
		
	}

	

	/** 
	 * @description: get the element which is currently highlighted
	 * @todo: 
	 *
	 */	
	$.get_highlighted_para = function() {
	
		// --<
		return highlighted_para;
		
	}

	

	/** 
	 * @description: test if the element is currently highlighted
	 * @todo: 
	 *
	 */	
	$.is_highlighted_para = function( element ) {
	
		// only return highlight status if in our Commentpress context
		if ( plugin_context != 'internal' ) {
		
			// --<
			return false;
		
		}
	
		// test that we have a proper element
		if ( typeof( element ) != 'object' ) {
		
			// --<
			return false;
		
		}
	
		// is our item already highlighted?
		if ( $.accordion_query( element.attr('id') ) ) {
		
			// --<
			return true;
		
		} else {
		
			// --<
			return false;
		
		}
		
	}

	

	/**
	 * @description: highlight the current text
	 * @todo: 
	 *
	 */	
	$.highlight_text = function( element ) {
	
		// get padding
		var padding_top = parseInt( element.css( 'padding-top' ).split('px')[0] );
		var padding_right = parseInt( element.css( 'padding-right' ).split('px')[0] );
		var padding_bottom = parseInt( element.css( 'padding-bottom' ).split('px')[0] );
		var padding_left = parseInt( element.css( 'padding-left' ).split('px')[0] );

		/*
		alert( 'padding_bottom: ' + padding_bottom );
		alert( 'padding_top: ' + padding_top );
		alert( 'padding_right: ' + padding_right );
		alert( 'padding_left: ' + padding_left );
		*/
		
		// get margin
		var margin_top = parseInt( element.css( 'margin-top' ).split('px')[0] );
		var margin_right = parseInt( element.css( 'margin-right' ).split('px')[0] );
		var margin_bottom = parseInt( element.css( 'margin-bottom' ).split('px')[0] );
		var margin_left = parseInt( element.css( 'margin-left' ).split('px')[0] );
		
		/*
		alert( 'margin_top: ' + margin_top );
		alert( 'margin_bottom: ' + margin_bottom );
		alert( 'margin_right: ' + margin_right );
		alert( 'margin_left: ' + margin_left );
		*/
		
		// gap between paragraphs
		var gap = margin_top + margin_bottom + padding_top + padding_bottom;
		//alert( 'element gap: ' + gap );

		// so, halve it
		var half_gap = parseInt( gap / 2 );

		// get params
		var top = parseInt( element.position().top ) + margin_top + padding_top - selected_para_widen;
		var left = parseInt( element.position().left ) + margin_left + padding_left - selected_para_widen;
		var width = parseInt( element.width() ) + ( selected_para_widen * 2 );
		var height = parseInt( element.height() ) + ( selected_para_widen * 2 );

		/*
		alert( 'element top: ' + top );
		alert( 'element left: ' + left );
		alert( 'element width: ' + width );
		alert( 'element height: ' + height );
		
		// init adjustor value
		var adjust = 0;
		
		// if we have no padding and margin, adjust by 10px
		if ( margin_left + margin_right + padding_left + padding_right == 0 ) {
		
			// set adjust to our desired padding in px
			adjust = 10;
		
		}
		
		// set dimensions for highlighted element
		top = top + padding_top + margin_top - half_gap;
		height = height + gap - 40;
		left = left + padding_left + margin_left - adjust;
		width = width + padding_left + padding_right + adjust + adjust - 18; // + margin_left + margin_right;
		*/

		/*
		alert( 'final top: ' + top );
		alert( 'final left: ' + left );
		alert( 'final width: ' + width );
		alert( 'final height: ' + height );
		*/
		
		// unhighlight_text();		
	
		// create a highlighted element
		var highlite = $.create(
	
			'div', 
	
			{
			'id':'selected_text', 
			'class':'selected_text',
			'style':'top: ' + top + 'px; left: ' + left + 'px; width: ' + width + 'px; height: ' + height + 'px;'
			//'style':'top: ' + (top + 10) + 'px; left: ' + (left - 5) + 'px; width: ' + width + 'px; height: ' + (height - 20) + 'px;'
			}, ''
	
		);
		
		// show it
		$('#content').append(highlite);
	
	}
	
	

	/** 
	 * @description: unhighlight all text
	 * @todo: 
	 *
	 */	
	$.unhighlight_text = function() {
	
		// remove visible highlight
		$('.selected_text').remove();
		
	}

	

	/** 
	 * @description: scroll to page title
	 * @todo: implement
	 *
	 */	
	$.scroll_to_title = function() {
	
	};
	
	
	
	/** 
	 * @description: save comment box position
	 * @todo: 
	 *
	 */	
	$.save_position = function() {
	
		// get params
		var browser_scroll_top = $(window).scrollTop();
		var commentbox_top = $('#commentbox').position().top;
		var commentbox_left = $('#commentbox').position().left;
		var commentbox_relative_top = (commentbox_top - browser_scroll_top);
		
		// save in cookie
		$.cookie( 'left_postion_commentbox', commentbox_left.toString(), { expires: 28, path: '/' } );
		$.cookie( 'top_postion_commentbox', commentbox_relative_top.toString(), { expires: 28, path: '/' } );
		
	}
	
	
	
	/** 
	 * @description: save comment box position
	 * @todo: there's a mismatch between set position and actual position
	 *
	 */	
	$.load_position = function( top, left, user_can_move ) {
	
		// assume box position is sysadmin defined - we pass the default
		// values to this method and only override if all conditions are met

		// can user move it?
		if( user_can_move != 0 ) {
		
			// did they move it?
			if ( $.cookie('left_postion_commentbox') && $.cookie('top_postion_commentbox') ) {
		
				// cookie defined
				var top = $.cookie('top_postion_commentbox');
				var left = $.cookie('left_postion_commentbox');
		
			}
			
		} else {
			
			// do the cookies exist?
			if ( $.cookie('left_postion_commentbox') && $.cookie('top_postion_commentbox') ) {
		
				// delete cookies
				$.cookie('left_postion_commentbox', '', { expires: -1, path: '/' });
				$.cookie('top_postion_commentbox', '', { expires: -1, path: '/' });
				
			}
			
		}
		
		// there's a mismatch between set position and actual position...
		
		//alert( 'Load top: ' + top );
		//alert( 'Load left: ' + left );

		// set position
		$("#commentbox").css("left", left + 'px');
		$("#commentbox").css("top", top + 'px');
		
		//alert( 'Final top: ' + $('#commentbox').position().top );
		//alert( 'Final left: ' + $('#commentbox').position().left );
	
	}
	
	
	
	/** 
	 * @description: save comment box dimensions
	 * @todo: 
	 *
	 */	
	$.save_size = function() {
	
		// get params
		var commentbox_height = $("#commentbox").height();
		var commentbox_width = $("#commentbox").width();
		
		// save in cookie
		$.cookie( 'height_commentbox', commentbox_height.toString(), { expires: 28, path: '/' } );
		$.cookie( 'width_commentbox', commentbox_width.toString(), { expires: 28, path: '/' } );
		
	}
	
	
	
	/** 
	 * @description: load comment box dimensions
	 * @todo: 
	 *
	 */	
	$.load_size = function( height, width, user_can_resize ) {
	
		// can user move it?
		if( user_can_resize != 0 ) {
		
			// did they move it?
			if ( $.cookie('height_commentbox') && $.cookie('width_commentbox') ) {
		
				// save in cookie
				var height = $.cookie('height_commentbox');
				var width = $.cookie('width_commentbox');
				
			}
		
		} else {
		
			// do the cookies exist?
			if ( $.cookie('height_commentbox') && $.cookie('width_commentbox') ) {
		
				// delete cookies
				$.cookie('height_commentbox', '', { expires: -1, path: '/' });
				$.cookie('width_commentbox', '', { expires: -1, path: '/' });
				
			}
			
		}
		
		// set position
		$("#commentbox").css("height", height + 'px');
		$("#commentbox").css("width", width + 'px');
		
	}
	
	
	
	/** 
	 * @description: get width of page_wrapper
	 * @todo: 
	 *
	 */
	$.get_page_wrapper_width = function() {
	
		// get page_wrapper col data
		var page_wrapper = $('#page_wrapper');
		var page_wrapper_bl = $.css_to_num( $.px_to_num( page_wrapper.css( 'borderLeftWidth' ) ) );
		var page_wrapper_br = $.css_to_num( $.px_to_num( page_wrapper.css( 'borderRightWidth' ) ) );
		var page_wrapper_pl = $.css_to_num( $.px_to_num( page_wrapper.css( 'padding-left' ) ) );
		var page_wrapper_pr = $.css_to_num( $.px_to_num( page_wrapper.css( 'padding-right' ) ) );
		var page_wrapper_ml = $.css_to_num( $.px_to_num( page_wrapper.css( 'margin-left' ) ) );
		var page_wrapper_mr = $.css_to_num( $.px_to_num( page_wrapper.css( 'margin-right' ) ) );
		var page_wrapper_adjust = page_wrapper_bl + page_wrapper_br; // + page_wrapper_pl + page_wrapper_pr; // + page_wrapper_ml + page_wrapper_mr;
		var page_wrapper_w = page_wrapper.width(); // + page_wrapper_adjust;
		//alert( 'page_wrapper_w: ' + page_wrapper_w );
		
		// --<
		return page_wrapper_w;
		
	}
	
	
	
	/** 
	 * @description: get width of content
	 * @todo:
	 *
	 */
	$.get_content_width = function() {
	
		// get content col data
		var content = $('#content');
		var content_bl = $.css_to_num( $.px_to_num( content.css( 'borderLeftWidth' ) ) );
		var content_br = $.css_to_num( $.px_to_num( content.css( 'borderRightWidth' ) ) );
		var content_pl = $.css_to_num( $.px_to_num( content.css( 'padding-left' ) ) );
		var content_pr = $.css_to_num( $.px_to_num( content.css( 'padding-right' ) ) );
		var content_ml = $.css_to_num( $.px_to_num( content.css( 'margin-left' ) ) );
		var content_mr = $.css_to_num( $.px_to_num( content.css( 'margin-right' ) ) );
		var content_adjust = content_bl + content_br + content_pl + content_pr; // + content_ml + content_mr;
		var content_w = content.width() + content_adjust;
		//alert( 'content_w: ' + content_w );
		
		// --<
		return content_w;
		
	}
	
	
		
	/** 
	 * @description: get width of tools column
	 * @todo: 
	 *
	 */
	$.get_tools_width = function() {
	
		// get tools col data
		var tools = $('#tools');
		var tools_bl = $.css_to_num( $.px_to_num( tools.css( 'borderLeftWidth' ) ) );
		var tools_br = $.css_to_num( $.px_to_num( tools.css( 'borderRightWidth' ) ) );
		var tools_pl = $.css_to_num( $.px_to_num( tools.css( 'padding-left' ) ) );
		var tools_pr = $.css_to_num( $.px_to_num( tools.css( 'padding-right' ) ) );
		var tools_ml = $.css_to_num( $.px_to_num( tools.css( 'margin-left' ) ) );
		var tools_mr = $.css_to_num( $.px_to_num( tools.css( 'margin-right' ) ) );
		var tools_adjust = tools_bl + tools_br + tools_pl + tools_pr + tools_ml + tools_mr;
		var tools_w = tools.width() + tools_adjust;
		//alert( 'tools_w: ' + tools_w );
		
		// --<
		return tools_w;
		
	}
	
	
		
	/** 
	 * @description: get width of tools handle column
	 * @todo: 
	 *
	 */
	$.get_tools_handle_width = function() {
	
		// get tools handle data
		var tools_handle = $('#tools_handle');
		var tools_handle_bl = $.css_to_num( $.px_to_num( tools_handle.css( 'borderLeftWidth' ) ) );
		var tools_handle_br = $.css_to_num( $.px_to_num( tools_handle.css( 'borderRightWidth' ) ) );
		var tools_handle_pl = $.css_to_num( $.px_to_num( tools_handle.css( 'padding-left' ) ) );
		var tools_handle_pr = $.css_to_num( $.px_to_num( tools_handle.css( 'padding-right' ) ) );
		var tools_handle_ml = $.css_to_num( $.px_to_num( tools_handle.css( 'margin-left' ) ) );
		var tools_handle_mr = $.css_to_num( $.px_to_num( tools_handle.css( 'margin-right' ) ) );
		var tools_handle_adjust = tools_handle_bl + tools_handle_br + tools_handle_pl + tools_handle_pr + tools_handle_ml + tools_handle_mr;
		var tools_handle_w = tools_handle.width() + tools_handle_adjust;
		//alert( 'tools_handle_w: ' + tools_handle_w );
		
		// --<
		return tools_handle_w;
		
	}
	
	
		
	/** 
	 * @description: get width of content column when expanded
	 * @todo: 
	 *
	 */
	$.get_content_wide = function( page_wrapper_min_width, content_min_width ) {
	
		// find right space in page_wrapper
		var original_diff = page_wrapper_min_width - content_min_width - $.get_tools_width() - $.get_tools_handle_width();
		//alert( 'original_diff: ' + original_diff );
	
		// main column expanded width
		var content_wide = ( $.get_page_wrapper_width() - $.get_tools_handle_width() - original_diff ).toString();
		//alert( 'content_wide: ' + content_wide );
		
		// --<
		return content_wide;
		
	}
	
	
	
	/** 
	 * @description: get width of content column when contracted
	 * @todo: 
	 *
	 */
	$.get_content_narrow = function( page_wrapper_min_width, content_min_width ) {
	
		// main column standard width
		var content_narrow = ( $.get_content_wide( page_wrapper_min_width, content_min_width ) - $.get_tools_width() ).toString();
		//alert( 'content_narrow: ' + content_narrow );
		
		// --<
		return content_narrow;
		
	}
	
	
	
	
	
	
	/** 
	 * @description: get height of sidebar column so that it fills the viewport
	 * @todo: 
	 *
	 */
	$.get_sidebar_height = function( sidebar, header, wrapper ) {
	
		// get viewport data
		var viewport_height = $(window).height();
		var viewport_scrolltop = $(window).scrollTop();
		var viewport = viewport_height + viewport_scrolltop;
		
		// get data on column element
		var c_top = sidebar.position().top;
		var c_bt = $.css_to_num( $.px_to_num( sidebar.css( 'borderTopWidth' ) ) );
		var c_bb = $.css_to_num( $.px_to_num( sidebar.css( 'borderBottomWidth' ) ) );
		var c_pad_t = $.css_to_num( $.px_to_num( sidebar.css( 'padding-top' ) ) );
		var c_pad_b = $.css_to_num( $.px_to_num( sidebar.css( 'padding-bottom' ) ) );
		var column_adjust = c_top + c_bt + c_bb + c_pad_t + c_pad_b;
		//alert( 'column_adjust: ' + column_adjust );

		// get data on header element
		var h_bt = $.css_to_num( $.px_to_num( header.css( 'borderTopWidth' ) ) );
		var h_bb = $.css_to_num( $.px_to_num( header.css( 'borderBottomWidth' ) ) );
		var h_pad_t = $.css_to_num( $.px_to_num( header.css( 'padding-top' ) ) );
		var h_pad_b = $.css_to_num( $.px_to_num( header.css( 'padding-bottom' ) ) );
		var h_mar_t = $.css_to_num( $.px_to_num( header.css( 'margin-top' ) ) );
		var h_mar_b = $.css_to_num( $.px_to_num( header.css( 'margin-bottom' ) ) );
		var header_adjust = header.height() + h_bt + h_bb + h_pad_t + h_pad_b + h_mar_t + h_mar_b
		//alert( 'header_adjust: ' + header_adjust );

		// get data on wrapper element
		var w_bt = $.css_to_num( $.px_to_num( wrapper.css( 'borderTopWidth' ) ) );
		var w_bb = $.css_to_num( $.px_to_num( wrapper.css( 'borderBottomWidth' ) ) );
		var w_pad_t = $.css_to_num( $.px_to_num( wrapper.css( 'padding-top' ) ) );
		var w_pad_b = $.css_to_num( $.px_to_num( wrapper.css( 'padding-bottom' ) ) );
		var w_mar_t = $.css_to_num( $.px_to_num( wrapper.css( 'margin-top' ) ) );
		var w_mar_b = $.css_to_num( $.px_to_num( wrapper.css( 'margin-bottom' ) ) );
		var wrapper_adjust = w_bt + w_bb + w_pad_t + w_pad_b + w_mar_t + w_mar_b
		//alert( 'wrapper_adjust: ' + wrapper_adjust );
		
		// get bottom margin of main column so sidebar lines up
		// NOTE: this is NOT why they line up - it just so happens that the values match
		// needs more investigation... it seems the clearfix class adds the margin. Sigh.
		var bottom_margin = $.css_to_num( $.px_to_num( $('#main_wrapper').css( 'margin-bottom' ) ) );
		//alert( 'bottom_margin: ' + bottom_margin );
		
		// calculate the necessary height to reach the bottom of the viewport
		var to_bottom = viewport - column_adjust - header_adjust - wrapper_adjust - bottom_margin;
		//alert( 'to_bottom: ' + to_bottom );
		
		
		
		// --<
		return to_bottom;
		
	}
	
	
	
	
	
	
	/** 
	 * @description: compare strings and returns a measure of similarity (replicates PHP's similar_text)
	 * @todo: 
	 * 
	 *
	 */	
	$.similar_string = function( str1, str2 ) {
	
		// use levenshtein
		var distance = $.cp_levenshtein( str1, str2 );
		
		// get percent
		var percent = ( 1 - distance / Math.max( str1.length, str2.length ) ) * 100;
		
		// debug
		//alert( 'TESTING: ' + str1 + ' AND ' + str2 + ' PERCENT: ' + percent );



		// --<
		return percent;
		
	}
	
	
	
	/** 
	 * @description: Javascript implementation of PHP levenshtein
	 * @todo: 
	 * 
	 *
	 */	
	$.cp_levenshtein = function(a, b) {
	
		// Calculate Levenshtein distance between two strings
		// 
		// +    discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_levenshtein/
		// +       version: 903.421
		// +      original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
		// +      bugfixed by: Onno Marsman
		// +       revised by: Andrea Giammarchi (http://webreflection.blogspot.com)
		// + reimplemented by: Brett Zamir
		// *        example 1: levenshtein('Kevin van Zonneveld', 'Kevin van Sommeveld');
		// *        returns 1: 3
		
		var split=false, min=Math.min, len1=0, len2=0, I=0, i=0, d=[], c='', j=0, J=0;
		try{
			('0')[0];
		} catch(i){
			split=true;
		}
		if (a == b) {
			return 0;
		}
		if (!a.length || !b.length) {
			return b.length || a.length;
		}
		if (split){
			a = a.split('');b = b.split('');
		}
		len1 = a.length + 1;
		len2 = b.length + 1;
		d = [[0]];
		while (++i < len2) {
			d[0][i] = i;
		}
		i = 0;
		while (++i < len1) {
			J = j = 0;
			c = a[I];
			d[i] = [i];
			while (++j < len2) {
				d[i][j] = min(d[I][j] + 1, d[i][J] + 1, d[I][J] + (c != b[J]));
				++J;
			}
			++I;
		}
		
		// --<
		return d[len1 - 1][len2 - 1];
		
	}



	/** 
	 * @description: testing submission via AJAX - unsure if this is wanted
	 * @todo: remove, if not required
	 *
	 */	
	$.submit_via_ajax = function( scriptURL ) {
	


		// try posting via AJAX
		$.ajax({


		
			// set post method
			type: "POST",
			
			// URL - how should we get this?
			// eg, 'http://www.haystack.co.uk/commentpress/wp-content/plugins/commentpress/commentpress_submit.php',
			url: scriptURL, 
			
			// data requires jquery.form.js plugin
			data: $("#commentform").formSerialize(),


			
			// yay, we got something back
			success: function( data, textStatus ) {
				
				// debug
				alert( "Success response: " + data );

			},


			
			// boo, we got something back
			error: function( XMLHttpRequest, textStatus, errorThrown ) {

				// debug
				alert( "Error received: " + this.parseError( XMLHttpRequest, textStatus ) );
				
			},


			
			// parse error
			parseError: function( XMLHttpRequest, textStatus ) {
				
				// debug
				var error = '';

				if ( typeof( XMLHttpRequest.responseText ) == 'string' && XMLHttpRequest.responseText != '' ) {
					error = XMLHttpRequest.responseText;
				} else {
					if ( textStatus == 'timeout' ) {
						error = 'The server is taking too long to respond. Please try again later.';
					} else {
						error = 'Unknown error while submitting your comment. Try again?';
					}
				}
				
				// --<
				return error;

			}


			
		});
		
		
	}
	
	
	
	/** 
	 * @description: move comment area to an accordion section
	 * @todo: 
	 *
	 */	
	$.move_comment_form = function( text_signature ) {
	
		// move the respond div
		$('#respond').appendTo('#comment-group-' + text_signature);

		// make it visible
		$('#respond').css('display', 'block');

		// set the text signature value
		$('#text_signature').val( text_signature );

		// clear the reply to value
		$('#comment_parent').val( '' );
		
		// hide cancel reply link
		$('#cancel-comment-reply-link').css('display','none');
		
	}
	
	
	
	/** 
	 * @description: utility replacement for PHP's in_array
	 * @todo: 
	 *
	 */	
	$.in_array = function( needle, haystack, argStrict ) {
	
		// http://kevin.vanzonneveld.net
		// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);
		// *     returns 1: true
	
		var found = false, key, strict = !!argStrict;
		
		for( key in haystack ) {
			if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
				found = true;
				break;
			}
		}
		
		return found;
		
	}
	
	
	
	/** 
	 * @description: utility replacement for PHP's is_object
	 * @todo: 
	 *
	 */	
	$.is_object = function ( mixed_var ) {
	
		// distiguish between arrays and objects
		if( mixed_var instanceof Array ) {
		
			// is an array
			return false;
			
		} else {
		
			// not null and is object
			return ( mixed_var !== null ) && ( typeof( mixed_var ) == 'object' );
		}
		
	}



	/** 
	 * @description: utility to strip 'px' off css values
	 * @todo: 
	 *
	 */	
	$.px_to_num = function( pix ) {
	
		// --<
		return parseInt( pix.substring( 0, (pix.length - 2) ) );
	
	};
	
	
	
	/** 
	 * @description: utility to return zero when css values may be NaN in IE
	 * @todo: 
	 *
	 */	
	$.css_to_num = function( strNum ) {
	
		// http://mattstark.blogspot.com/2009/05/javascript-jquery-plugin-to-fade.html
		if (strNum && strNum != "") {
		
			var i = parseFloat(strNum);
			if (i.toString() == "NaN") {

				// --<
				return 0;

			} else {

				// --<
				return i;

			}
			
		}
		
		// --<
		return 0;
	
	};
	
	
	
	/** 
	 * @description: a test
	 * @todo: remove
	 *
	 */	
	$.frivolous = function( message ) {
	
		// do a simple alert
		alert( message );
	
	};
	
	
	
})( jQuery );