/** cs libray, last update: January 26th, 2010 */
jQuery.fn.center = function (absolute) {
    return this.each(function () {
        var t = jQuery(this);
	if (jQuery.browser.msie)
		if (jQuery.browser.version < 7)
			var absolute = true;
        t.css({
            position:    absolute ? 'absolute' : 'fixed', 
            left:        '50%', 
            top:        '50%'
        }).css({
            marginLeft:    '-' + (t.outerWidth() / 2) + 'px', 
            marginTop:    '-' + (t.outerHeight() / 2) + 'px'
        });

        if (absolute) {
            t.css({
                marginTop:    parseInt(t.css('marginTop'), 10) + jQuery(window).scrollTop(), 
                marginLeft:    parseInt(t.css('marginLeft'), 10) + jQuery(window).scrollLeft()
            });
        }
	
	if(t.height() > jQuery(window).height())
		t.css({
					marginTop: '0px',
					top: '10px',
					position: 'absolute'
				  });
	
    });
};

jQuery.fn.centerDown = function (absolute) {
    return this.each(function () {
        var t = jQuery(this);
	if (jQuery.browser.msie)
		if (jQuery.browser.version < 7)
			var absolute = true;
        t.css({
            position:    absolute ? 'absolute' : 'fixed', 
            left:        '50%', 
            top:        '340px'
        }).css({
            marginLeft:    '-' + (t.outerWidth() / 2) + 'px', 
            marginTop:    '-10px'
        });

        if (absolute) {
            t.css({
                marginTop:    '350px', 
                marginLeft:    parseInt(t.css('marginLeft'), 10) + jQuery(window).scrollLeft()
            });
        }
	
	if(t.height() > jQuery(window).height())
		t.css({
					marginTop: '0px',
					top: '10px',
					position: 'absolute'
				  });
	
    });
};

jQuery.fn.centerDownHigh = function (px) {
    return this.each(function () {
        var t = jQuery(this);

        t.css({
            position:    'absolute', 
            left:        '50%', 
            top:        px + 'px'
        }).css({
            marginLeft:    '-' + (t.outerWidth() / 2) + 'px', 
            marginTop:    '-10px'
        });

            t.css({
                marginTop:    px + 'px', 
                marginLeft:    parseInt(t.css('marginLeft'), 10) + jQuery(window).scrollLeft()
            });
	
	if(t.height() > jQuery(window).height())
		t.css({
					marginTop: '0px',
					top: '10px',
					position: 'absolute'
				  });
	
    });
};

/**
* Submits a form via AJAX
* @param {Object} params 
	@param {jQuery Object} jqSection the wrapper of the form and it's related items(notices etc)
	@param {jQuery Object} jqForm the form that is submitted via AJAX(information read from the form attributes/elements: action, method(default: get), data(all form elements in serialized form))
	@param {Function(jqSection, frm, AJAXresponse)} fSuccess the function called on successful AJAX request
	@param {Function(jqSection, frm)} fPending the function called while AJAX request is pending
	@param {Function(jqSection, frm, AJAXerror)} fError the function called on unsuccessful AJAX request
*/
function AJAXFormSubmit(params)
{
	var settings = jQuery.extend({
									jqSection: null, 
									jqForm: null, 
									fSuccess: function(){return false}, 
									fPending: function(){return false}, 
									fError: function(){return false},
									fBeforeSubmit: function(){return false}
								 }, 
								 params);
	
	var jqForm = settings.jqForm;
	var jqSection = settings.jqSection;
	
	if ((jqForm.size() < 0) || (jqSection.size() < 0))
		return false;
		
	var formAJAXInfo = {};
	
	formAJAXInfo.url = jQuery.trim(jqForm.attr('action'));
	if(formAJAXInfo.url == '')
		return false;
		
	formAJAXInfo.method = jqForm.attr('method')||'get';
	
	jqForm
		.submit(function()
				{
					var frm  = jQuery(this);
					settings.fBeforeSubmit(frm);
					
					settings.fPending(jqSection, frm);
					
					formAJAXInfo.formData = frm.serialize();
					
					jQuery
						.ajax({
								url: formAJAXInfo.url,
								type: formAJAXInfo.method,
								data: formAJAXInfo.formData,
								success: function(AJAXresponse)
											{
												settings.fSuccess(jqSection, frm, AJAXresponse);
											},
											
								error: function(AJAXerror)
										{
											settings.fError(jqSection, frm, AJAXerror)
										}
								
							 })
					
					return false;
				})
}

/**
* On trigger click gets a form page via AJAX, filters all form related content, and displays the form inside a popup layer positioned relatively to the trigger link
* The form is submitted via AJAX. If the AJAX request response contains no form, it is considered a successful submit, and the page refreshes(other successful submit function can be passed as param). Otherwise the form and its related elements is displayed
* @param {Object} settings 
	@param {jQuery Object} popupFormTrigger: the link that trigger the popup
	@param {jQuery Object} dynamicWrapperId: the dyanmically created wrapper around all form related content.
	@param {} dynamicWrapperCssClass: the css class given to the dynamic wrapper 
	@param {} AJAXpageElementsFilter: the jQuery elements identifiers of the elements to be displayed inside the popup
	@param {} popupCloseButtonClass: the css class for the popup closing button
	@param {function} formLoadCallBack: the function called after the form is loaded via AJAX (usefull for re-setting events on certain form elements like date pickers, color pickers, submit link buttons etc)
	@param {function} successCallBack: the function called on successful AJAX request(default it reloads the page)
	@param {} closeOnSuccessfulSubmit: flag for closign the popup after a successful submit
*/
function AJAXForm(settings)
{
	this.settings = jQuery.extend({
									popupFormTrigger: null,
									dynamicWrapperId: null,
									dynamicWrapperCssClass: 'AJAXPopupForm',
									AJAXpageElementsFilter: '.notice_error, .notice_success, .notice_warning, form',
									popupCloseButtonClass: 'AJAXFormPopupCloseButton',
									formLoadCallBack: function(){},
									successCallBack: function(){location.reload();},
									closeOnSuccessfulSubmit: true,
									fBeforeSubmit: function(){return false},
									center: true,
									centerDown: false,
									centerDownHigh: false,
									open: false,
									offsetX: 0,
									offsetY: 0
								  }, settings);
	this.AJAXFormPopupTrigger = this.settings.popupFormTrigger;
	this.AJAXFormWrapper = jQuery('#' + this.settings.dynamicWrapperId);
	this.AJAXForm = null;
	this.AJAXProgressIndicator = null;
	
	this.init = function()
				{
					this.createDynamicElements();
					this.getAJAXForm();
					if (this.settings.open == true)
						this.openPopup()
					else
						this.setPopupTriggerEvents();
				}
				
	this.createDynamicElements = function()
					{
						if(this.AJAXFormWrapper.size() == 0)
						{
							this.createFormWrapper();
							this.createPopupCloseButton();
						}
							this.createProgressIndicator();
					}
									
	this.createFormWrapper = function()
				{
						this.AJAXFormWrapper = jQuery('<div></div>');
						this.AJAXFormWrapper
								.attr({
										'class': this.settings.dynamicWrapperCssClass,
										'id': this.settings.dynamicWrapperId
									  })
								.appendTo('body');
				}
								
	this.createPopupCloseButton = function()
					{
						// create close button
						var closeBtn = jQuery('<a href="#">[X]</a>');
						closeBtn
							.attr({
									'class': this.settings.popupCloseButtonClass,
									'rel': this.settings.dynamicWrapperId,
									'title': 'Close'
								  })
							.click(function()
										{
											ajaxFrm.closePopup();
											return false;
										})
							.appendTo(this.AJAXFormWrapper);
					}
									
	this.createProgressIndicator = function()
					{
						if(this.AJAXProgressIndicator == null)
						{
							this.AJAXProgressIndicator = jQuery('<div></div>');
							this.AJAXProgressIndicator
									.attr('class', 'AJAXProgressIndicator')
									.css('display', 'none')
									.text('processing request...')
									.appendTo(this.AJAXFormWrapper);
						}
					}
									
	this.setPopupTriggerEvents = function()
					{
						if (this.AJAXFormPopupTrigger != null) {
						this.AJAXFormPopupTrigger
							.click(function()
									{
										ajaxFrm.openPopup();
										return false;
									})
						}
					}
										
	this.getAJAXForm = function()
			{
				if (this.AJAXForm == null)
				{
					this.clearPopupContent();
					this.openPopup();
					this.displayProgressIndicator();
					jQuery.ajax({
							type: 'get',
							url: this.settings.AJAXpageUrl,
							dataType: 'html',
							success: function(htmlResp)
									{
										ajaxFrm.hideProgressIndicator(); // display progress indicator
										// build dynamic wrapper to be able to filter the HTML result
										ajaxFrm.filterHTMLresponse(htmlResp);
										ajaxFrm.processAJAXResults();
										
									},
							error: function(err)
								{
									//console.log(err);
								}
						})
				}
			}
						
	this.clearPopupContent = function()
				{
					this.AJAXFormWrapper.find(ajaxFrm.settings.AJAXpageElementsFilter).remove(); // remove current form
				}
						
	this.filterHTMLresponse = function(htmlResp)
					{
						// stripping everything outside the body tags
						var htmlStr = new String(htmlResp);
						var regExFilter = new RegExp("(^<[^\^]*<\/head>$)|(<body>)|(<\/body>[^\^]*<\/html>)", "mig");
						htmlStr = htmlStr.replace(regExFilter, "");
						var tmpWrapper = jQuery('<div style="display:none"></div>');
							tmpWrapper
								.html(htmlStr)
								.appendTo('body')
								.find(ajaxFrm.settings.AJAXpageElementsFilter)
								.appendTo(ajaxFrm.AJAXFormWrapper);
							tmpWrapper.remove();
					}
								
	this.processAJAXResults = function()
				{
					this.AJAXForm = this.AJAXFormWrapper.find(this.settings.AJAXpageElementsFilter).find('form');
															
					if (this.AJAXForm.size() > 0) // form displayed, unsuccessful submit
					{
						ajaxFrm.setAJAXFormEvents();
						ajaxFrm.openPopup();
						if (ajaxFrm.settings.formLoadCallBack != null)
							ajaxFrm.settings.formLoadCallBack(ajaxFrm.AJAXFormWrapper, ajaxFrm.AJAXFormPopupTrigger, ajaxFrm);
					}
					else
					{
						if(ajaxFrm.settings.successCallBack != null)
							ajaxFrm.settings.successCallBack(ajaxFrm.AJAXFormWrapper, ajaxFrm.AJAXFormPopupTrigger, ajaxFrm);
						
						if (ajaxFrm.settings.closeOnSuccessfulSubmit == true)
						{
							ajaxFrm.closePopup();
						}
					}
				}
								
	this.setAJAXFormEvents = function()
				{
					// prepare form submit
					if (this.AJAXForm != null)
					{
						this.AJAXForm
								.submit(function()
										{
											var frm = jQuery(this);
											ajaxFrm.settings.fBeforeSubmit(frm);
											ajaxFrm.clearPopupContent();
											ajaxFrm.displayProgressIndicator();
											
											jQuery.ajax({
															type: frm.attr('method'),
															url: frm.attr('action'),
															data: frm.serialize(),
															cache: false,
															dataType: 'html',
															success: function(htmlResp)
																		{
																			ajaxFrm.hideProgressIndicator(); // display progress indicator
																			// build dynamic wrapper to be able to filter the HTML result
																			ajaxFrm.filterHTMLresponse(htmlResp);
																			ajaxFrm.processAJAXResults();																										
																		}
														})
											return false;
										})	
					}
				}

	this.closePopup = function()
						{
							this.AJAXFormWrapper.css('display', 'none');
						}
						
	this.openPopup = function()
						{
							this.AJAXFormWrapper
									.css({
										position: 'absolute',
										zIndex: 3000
									 });
							if (this.settings.center == true)
								this.AJAXFormWrapper.center();
							else if (this.settings.centerDown == true)
								this.AJAXFormWrapper.centerDown();
							else if (this.settings.centerDownHigh == true)
								this.AJAXFormWrapper.centerDownHigh(125);
							else
								this.AJAXFormWrapper
										.css({
											left: this.AJAXFormPopupTrigger.offset().left + this.settings.offsetX + 'px',
											top: this.AJAXFormPopupTrigger.offset().top + this.settings.offsetY + 'px'
										 });
							
							this.AJAXFormWrapper.css('display', 'block')
						}
						
	this.displayProgressIndicator = function()
									{
										this.AJAXProgressIndicator.css('display', 'block');
									}
									
	this.hideProgressIndicator = function()
									{
										this.AJAXProgressIndicator.css('display', 'none');
									}
									
	var ajaxFrm = this;
	
	this.init();
}


// field character counter
jQuery.fn.extend({
			 count: function()
					{						
						$(this).each(function()
						{
							var target = jQuery(this);
							var counterWrapper = jQuery('<div class="counterWrapper"></div>');
							target.after(counterWrapper);
							
							target.extend({
									update: function()
											{
												var counter = {
														chars: 0
														};
												var targetContent = new String(target.val());
												
												var maxChars = parseInt(target.attr('max'));
												
												if (targetContent != '')
												{
													counter['chars'] = targetContent.length;
												}
												
												if(isNaN(maxChars))
													counterWrapper.html('[chars: ' + counter.chars + ']')
												else
												{
													var diff = maxChars - counter.chars;
													if(diff >= 0)
														var html = '<small>[characters remaining: ' + diff + ']</small>'
													else
													{
														var html = '<small style="color: red">[exceeded with: ' + Math.abs(diff) + ' characters]</small>'
													}
													counterWrapper.html(html)
												}
													
											}
									  })
							
							target.keyup(target.update);
							target.change(target.update);
							target.click(target.update);
							target.update();
						})
					}
})