// namespace
com.jobrapido.form = {};

com.jobrapido.form.Form = function(form, options) {
 var clazz = "com.jobrapido.form.Form";
 var optionsDefaults = {
 "enableDefaultCss" : true,
 "enableUnsavedWarning" : false,
 "unsavedWarningMessage" : "Error"
 };
 var options = jQuery.extend({}, optionsDefaults, options);
 var _this = this;
 var _form = form;
 
 // ---------------
 // PUBLIC API
 // ---------------
 this.convertSelectToMultiSelect=this.convertSelectToDropdownMultiSelect = function(selector, options) {
 return new com.jobrapido.form.DropdownMultiSelect(jQuery(selector, _form), options, _this);
 }
 
 this.convertToToggleButton = function(selector, selectorToggleArea, options) {
 return new com.jobrapido.form.ToggleButton(jQuery(selector, _form), jQuery(selectorToggleArea, _form), options, _this);
 }
 
 this.convertInputFileToUpload = function(selector, options) {
 return new com.jobrapido.form.Upload(jQuery(selector, _form), options, _this);
 }
 
 this.disableUnsavedWarning = function() {
 options.enableUnsavedWarning = false;
 }
 
 this.enableUnsavedWarning = function() {
 options.enableUnsavedWarning = true;
 }
 
 this.getSelect = function(selector, options) {
 return new com.jobrapido.form.Select(jQuery(selector, _form), options, _this);
 }
 
 this.getDataString = function() {
 var data=""
 var formFields = jQuery(":input",_form);
 for (var index=0;index<formFields.length;index++) {
 var field = formFields[index];
 if (field.name!=undefined && field.name.length>0) {
 if (data!="") {
 data += "&"
 }
 data += field.name +"="+ field.value
 }
 }
 return data;
 }
 
 this.getForm = function() {
 return _form;
 }
 
 this.submit = function(action) {
 log.debug(clazz+"|SUBMIT");
 if (action != undefined) { _form.action = action; alert(_form.action);}
 this.disableUnsavedWarning();
 _form.submit();
 }
 
 this.thereIsAlmostOneFormFieldInQueryStringWithValueNotNull = function(context, ignoreValueArray, ignoreParamArray) {
 var queryString = location.search;
 var ignoreValueArray = (ignoreValueArray!=undefined && ignoreValueArray.length>0) ? jQuery.merge([""],ignoreValueArray) : [""];
 var formFields = (context!=undefined) ? jQuery(":input",context) : jQuery(":input",_form);
 log.debug(clazz+"|thereIsAlmostOneFormFieldInQueryStringWithValueNotNull|FIELDS",formFields);
 log.debug(clazz+"|thereIsAlmostOneFormFieldInQueryStringWithValueNotNull|NULL VALUES",ignoreValueArray);
 var parameters = [];
 if (formFields.length>0 && queryString!=undefined && queryString.length>0) {
 log.debug(clazz+"|thereIsAlmostOneFormFieldInQueryStringWithValueNotNull|QUERY STRING|"+queryString);
 try {
 parameters = queryString.split("?")[1].split("&");
 } catch(ex) {
 log.warn(clazz+"|thereIsAlmostOneFormFieldInQueryStringWithValueNotNull|QUERY STRING",ex);
 }
 for (paramIndex in parameters) {
 var param = parameters[paramIndex];
 var paramName = param.split("=")[0];
 var paramValue = param.split("=")[1];
 if ((ignoreParamArray==undefined || ignoreParamArray.length==0 || jQuery.inArray(paramName,ignoreParamArray)<0) && jQuery.inArray(paramValue,ignoreValueArray)<0) {
 for (var index=0;index<formFields.length;index++) {
 var field = formFields[index];
 if (field.name == paramName) {
 log.debug(clazz+"|thereIsAlmostOneFormFieldInQueryStringWithValueNotNull|PRAMETER FOUND|"+paramName+"="+paramValue+" "+jQuery.inArray(paramValue,ignoreValueArray));
 return true;
 }
 }
 } else {
 log.debug(clazz+"|thereIsAlmostOneFormFieldInQueryStringWithValueNotNull|IGNORED PARAM|"+paramName+"="+paramValue);
 }
 }
 }
 return false;
 }

 // ---------------
 // PRIVATE
 // ---------------
 var _isValidTargetElement = function() {
 if (_form!=null && _form!=undefined && _form.length>0 && _form[0].tagName == "FORM") {
 return true;
 } else {
 log.error(clazz+"|NEW|Not valid target element",_form);
 return false;
 }
 }
 
 var _applyDefaultCss = function() {
 log.debug(clazz+"|APPLY CSS|");
 if (!_form.hasClass("jrwt-form")) _form.addClass("jrwt-form");
 }
 
 var _onBeforeUnload = function() {
 if (options.enableUnsavedWarning) { 
 return options.unsavedWarningMessage;
 } else {
 return;
 }
 }
 
 // ---------------
 // CONSTRUCTOR
 // ---------------
 var _new = function() {
 if (_isValidTargetElement.call()) {
 log.debug(clazz+"|NEW|");
 if (options.enableDefaultCss) _applyDefaultCss.call();
 if (options.enableUnsavedWarning) window.onbeforeunload = _onBeforeUnload;
 }
 }
 _new.call();
}

com.jobrapido.form.DropdownMultiSelect = function(select, options, jrwtForm) {
 var clazz = "com.jobrapido.form.DropdownMultiSelect";
 var optionsDefaults = {
 "fadeSpeed":250,
 "height":100,
 "textNoneSelected":"",
 "enableAnimations":false,
 "enableSelectAll":true,
 "closeBeforeSelectAll":false,
 "enableUnselectAll":true,
 "closeBeforeUnselectAll":false,
 "value": undefined, /* default starting value */
 "onChange": function(){}, /* when the select value change */
 "onOpen": function(){}, /* when the select menu is opened */
 "onClose": function(){} /* when the select menu is closed */
 };
 var options = jQuery.extend({}, optionsDefaults, options);
 var _this = this;
 var _jrwtForm = jrwtForm;
 var _select = select;
 var multiSelect;
 var selectInput;
 var state = "closed";

 // ---------------
 // PUBLIC API
 // ---------------
 this.setValue = function(value) {
 if (typeof value == "string") {
 multiSelect.val(value.split(","));
 } else {
 multiSelect.val(value);
 }
 multiSelect.trigger("change");
 };
 
 this.getValue = function() {
 return multiSelect.val();
 };
 
 this.selectAll = function() {
 if (options.closeBeforeSelectAll) {multiSelect.trigger("close");}
 jQuery(jQuery('option',multiSelect).get().reverse()).each( function() {
 if (!jQuery(this).hasClass("jrwt-multiselect-selectall") && !jQuery(this).hasClass("jrwt-multiselect-unselectall")) {
 this.selected = true;
 } else {
 this.selected = false;
 }
 });
 multiSelect[0].options[0].selected = true;
 multiSelect[0].options[0].selected = false;
 multiSelect.blur();
 }
 
 this.unselectAll = function() {
 if (options.closeBeforeUnselectAll) {multiSelect.trigger("close");}
 jQuery(jQuery('option',multiSelect).get().reverse()).each( function() {
 this.selected = false;
 });
 multiSelect[0].options[0].selected = true;
 multiSelect[0].options[0].selected = false;
 }
 
 // ---------------
 // PRIVATE
 // ---------------
 var _isValidTargetElement = function() {
 if (_select!=null && _select!=undefined && _select.length>0 && _select[0].tagName == "SELECT") {
 return true;
 } else {
 log.error(clazz+"|NEW|Not valid target element",_select);
 return false;
 }
 }
 
 var _resize = function() {
 var offset = selectInput.position();
 var top = (offset.top+selectInput.outerHeight());
 var width = selectWrapper.width()-parseInt(multiSelect.css("padding-left"),10)-parseInt(multiSelect.css("padding-right"),10);
 var height = options.height;
 multiSelect.css({"position":"absolute","top":top+"px","left": offset.left+"px","height": height+"px","width": width+"px"});
 }
 // ---------------
 // CONSTRUCTOR
 // ---------------
 var _new = function() {
 if (_isValidTargetElement.call()) {
 log.debug(clazz+"|NEW|");
 var height = _select.height() + parseInt(_select.css("border-top-width"),10) + parseInt(_select.css("border-bottom-width"),10);
 var html = [];
 html.push("<div class=\"jrwt-multiselect\">");
 html.push("<div style=\"height:"+height+"px;overflow:hidden\">");
 html.push("<select class=\"jrwt-multiselect-fake\" tabindex=\"-1\" size=\"0\"><option>&nbsp;</option></select>");
 html.push("<input class=\"jrwt-multiselect-input\" type=\"text\" style=\"background:transparent;position:relative;top:-"+height+"px;z-index:2\" value=\""+options.textNoneSelectedText+"\">");
 html.push("</div>");
 html.push("<select class=\"jrwt-multiselect-options jrwt-hidden\" multiple=\"true\">");
 if (options.enableSelectAll) html.push("<option class=\"jrwt-multiselect-selectall jrwt-bluelink\">select all</option>");
 if (options.enableUnselectAll) html.push("<option class=\"jrwt-multiselect-unselectall jrwt-bluelink\">unselect all</option>");
 if (_select[0].options) {
 for (index=0;index<_select[0].options.length;index++) {
 var option = _select[0].options[index];
 html.push("<option value=\""+option.value+"\">"+option.text+"</option>");
 }
 }
 html.push("</select>");
 html.push("</div>");
 
 selectWrapper = _select.after( html.join("") ).next("div.jrwt-multiselect");
 selectFake = selectWrapper.find("select.jrwt-multiselect-fake");
 selectInput = selectWrapper.find("input.jrwt-multiselect-input");
 multiSelect = selectWrapper.find("select.jrwt-multiselect-options");
 
 var disabled = _select.attr("disabled");
 var name = _select.attr("name");
 var tabIndex = parseInt(_select.attr("tabindex"));
 var value = _select.val();
 
 _select.remove();
 
 if (disabled!=undefined) selectInput.attr("disabled",disabled);
 if (name!=undefined) selectInput.attr("name",name);
 if (tabIndex!=NaN) {
 selectInput.attr("tabindex",tabIndex);
 multiSelecTabIndex = tabIndex+1;
 multiSelect.attr("tabindex",multiSelecTabIndex);
 form = jrwtForm.getForm();
 for (index=0;index<form[0].elements.length;index++){
 var field = jQuery(form[0].elements[index]);
 var tabIndex = field[0].tabIndex;
 if ((tabIndex>0) && (field!=multiSelect) && (multiSelecTabIndex>tabIndex)) {
 tabIndex = tabIndex+1;
 }
 if (tabIndex>0) {
 log.debug(clazz+"|RE-TABINDEX|fieldName["+field[0].name+"],tabindex["+tabIndex+"]");
 field[0].tabIndex = tabIndex;
 }
 }
 }
 
 if (options.value!=undefined) {
 multiSelect.val(options.value);
 selectInput.val(options.value);
 }
 
 var closeTimeout;
 jQuery(document).bind({
 "click": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 if (e.currentTarget.activeElement == selectInput.get(0) || e.currentTarget.activeElement == selectFake.get(0)) {
 //multiSelect.trigger("toggle");
 } else if (e.currentTarget.activeElement != multiSelect.get(0)) {
 multiSelect.trigger("close");
 }
 }
 });
 
 jQuery("input.jrwt-multiselect-input").keypress(function(event) {
	  if ( event.which == 32 ) {
	     event.preventDefault();
	   }
	});

 
 selectFake.bind({
 "focus": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 multiSelect.trigger("open");
 },
 "select": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 multiSelect.trigger("open");
 }
 });
 
 var onKeyUp = function(e){
 log.debug(clazz+"|EVENT|"+e.type,e);
 var code = (e.keyCode ? e.keyCode : e.which);
 switch (code) { 
 case 27:
 multiSelect.trigger("close"); 
 break;
 case 40:
 if (e.currentTarget == selectInput.get(0)) multiSelect.trigger("open");
 break;
 }
 }
 selectInput.bind({
 "keyup": function(e){onKeyUp(e);}
 });
 jQuery(document.body).bind({
 "resize.rainbows": function(e){
 log.debug(clazz+"|EVENT|"+e.type,e);
 _resize();
 setTimeout(function(){_resize();},500);
 }
 });
 multiSelect.bind({
 "blur": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 closeTimeout = setTimeout(function() {
 multiSelect.trigger("close");
 },250);
 },
 "change": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 var value = "";
 var selectAll = (options.enableSelectAll) ? jQuery("option.jrwt-multiselect-selectall",multiSelect) : undefined;
 var unselectAll = (options.enableUnselectAll) ? jQuery("option.jrwt-multiselect-unselectall",multiSelect) : undefined;
 if (selectAll!=undefined && selectAll[0].selected) {
 _this.selectAll();
 } else if (unselectAll!=undefined && unselectAll[0].selected) {
 _this.unselectAll();
 } 

 var value = multiSelect.val();
 
 if (value!=null && value.length>0) {
 selectInput.val(value);
 } else {
 selectInput.val(options.textNoneSelected);
 }
 options.onChange.call(this, _this);
 },
 "close": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 if (state=="opened") {
 state = "closed";
 selectFake.blur();
 if (options.enableAnimations) {
 closeTimeout = setTimeout(function() {
 state = "closed";
 multiSelect.fadeOut(options.fadeSpeed);
 options.onClose.call(this,_this);
 },250);
 } else {
 multiSelect.hide();
 options.onClose.call(this,_this);
 } 
 }
 },
 "dblclick" : function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 multiSelect.trigger("close");
 },
 "keyup": function(e){onKeyUp(e);},
 "open": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 if (state=="closed") {
 state = "opened";
 
 _resize();
 
 if (options.enableAnimations) multiSelect.fadeIn(options.fadeSpeed);
 else multiSelect.show();
 multiSelect.focus();
 
 if (options.enableSelectAll || options.enableUnselectAll) {
 if (jQuery(":selected",multiSelect[0]).length == 0) {
 var index = (options.enableSelectAll && options.enableUnselectAll) ? 2 : 1;
 multiSelect[0].selectedIndex = index;
 multiSelect[0].options[index].selected = false;
 }
 }
 
 options.onOpen.call(this,_this);
 }
 },
 "toggle": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 clearTimeout(closeTimeout);
 multiSelect.trigger((state=="closed") ? "open" : "close");
 }
 });
 }
 }
 _new.call(this);
}

com.jobrapido.form.Select = function(select, options, jrwtForm) {
 var clazz = "com.jobrapido.form.Select";
 var optionsDefaults = {
 "onChange": function(){} /* when the selection change */
 };
 var options = jQuery.extend({}, optionsDefaults, options);
 
 var _this = this;
 var _jrwtForm = jrwtForm;
 var _select = select;
 
 // ---------------
 // PUBLIC API
 // ---------------
 
 this.addOption = function(optionValue, optionText) {
 if ((optionValue!=null) && (optionValue.length>0)) {
 log.debug(clazz+".addOption()|optionValue["+optionValue+"],optionText["+optionText+"]");
 var option = document.createElement("option")
 option.value = optionValue;
 option.text = (optionText!=undefined && optionText.length>0) ? optionText : optionValue;
 _select[0].options[_select[0].options.length] = option;
 }
 }
 
 this.removeOption = function(option) {
 _select.remove(option);
 }
 
 this.removeSelectedOptions = function() {
 _select.find(":selected").remove();
 }
 
 this.selectOption = function(optionValue) {
 log.debug(clazz+".selectOption()|optionValue["+optionValue+"]");
 _select.find(":selected").removeAttr("selected");
 _select.find("option[value="+optionValue+"]").attr("selected","selected");
 _select.trigger("change");
 }
 
 this.getValue = function() {
 return _select.val();
 }

 this.getOptionValues = function(separatorCharacter) {
 var value = ""; 
 var separator = ";"
 
 if (separatorCharacter != undefined) separator = separatorCharacter;
 
 for (index=0;index<_select[0].options.length;index++) {
 if (index>0) {
 value += separator
 }
 value += _select[0].options[index].value;
 }
 return value;
 }
 // ---------------
 // PRIVATE
 // ---------------
 var _isValidTargetElement = function() {
 if ((_select!=null) && (_select!=undefined) && (_select.length>0) && (_select[0].tagName == "SELECT")) {
 return true;
 } else {
 log.error(clazz+"|NEW|Not valid target element",_select);
 return false;
 }
 }
 
 // ---------------
 // CONSTRUCTOR
 // ---------------
 var _new = function() {
 if (_isValidTargetElement.call()) {
 log.debug(clazz+"|NEW|");
 _select.bind({
 "change": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 options.onChange.call(this,_this);
 }
 });
 }
 }
 _new.call(this);
}

com.jobrapido.form.ToggleButton = function(button, area, options, form) {
 var clazz = "com.jobrapido.form.ToggleButton";
 var optionsDefaults = {
 "fadeSpeed": 250,
 "enableAnimations": false,
 "enableQueryStringCheck": true,
 "queryStringCheckIgnoreValueArray" : [],
 "queryStringCheckIgnoreParamArray" : [],
 "toggleButtonHideText" : "Hide",
 "toggleButtonShowText" : "Show",
 "toggleButtonClosedClass" : "jrwt-toggleClosed",
 "toggleButtonOpenedClass" : "jrwt-toggleOpened",
 "onOpen": function(){}, /* when the toggle area is opened */
 "onClose": function(){} /* when the toggle area is closed */
 };
 var options = jQuery.extend({}, optionsDefaults, options);
 
 var _this = this;
 var _form = form;
 var _button = button;
 var _area = area;
 var state = "closed"
 
 // ---------------
 // PRIVATE
 // ---------------
 var _isValidTargetElement = function() {
 if (_button!=null && _button!=undefined && _area!=null && _area!=undefined) {
 return true;
 } else {
 log.error(clazz+"|NEW|Not valid target element",_button,_area);
 return false;
 }
 }
 
 // ---------------
 // CONSTRUCTOR
 // ---------------
 var _new = function() {
 if (_isValidTargetElement.call()) {
 log.debug(clazz+"|NEW|");
 
 _button.bind({
 "click": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 _area.trigger("toggle");
 }
 });
 
 _area.bind({
 "close": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 if (state=="opened") {
 state = "closed";
 _button.attr("value",options.toggleButtonShowText);
 _button.removeClass(options.toggleButtonOpenedClass);
 _button.addClass(options.toggleButtonClosedClass);
 if (options.enableAnimations) _area.fadeOut(options.fadeSpeed);
 else _area.hide();
 options.onClose.call(this,_this);
 }
 },
 "open": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 if (state=="closed") {
 state = "opened";
 _button.attr("value",options.toggleButtonHideText);
 _button.removeClass(options.toggleButtonClosedClass);
 _button.addClass(options.toggleButtonOpenedClass);
 if (options.enableAnimations) _area.fadeIn(options.fadeSpeed);
 else _area.show();
 options.onOpen.call(this,_this);
 }
 },
 "toggle": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 _area.trigger((state=="closed") ? "open" : "close");
 }
 });
 }
 
 // starting settings
 _button.addClass("jrwt-bluelink");
 if (options.enableQueryStringCheck && _form.thereIsAlmostOneFormFieldInQueryStringWithValueNotNull(_area, options.queryStringCheckIgnoreValueArray, options.queryStringCheckIgnoreParamArray)) {
 _area.trigger("open");
 } else {
 state = "opened";
 _area.trigger("close"); 
 }
 
 }
 _new.call(this);
}

com.jobrapido.form.Upload = function(input, options, jrwtForm) {
 var clazz = "com.jobrapido.form.Upload";
 var optionsDefaults = {
 "pxToSizeFactor":7.0,
 "styleBrowseButtonWidth":70,
 "textBrowseButton":"Browse...",
 "onChange":function(){}
 };
 var options = jQuery.extend({}, optionsDefaults, options);
 
 var _this = this;
 var _jrwtForm = jrwtForm;
 var _input = input;
 var _container = _input.parent();
 var _inputFileFake;
 var _inputButtonBrowse;

 // ---------------
 // PUBLIC API
 // ---------------
 this.getValue = function() {
 return _inputFileFake.val();
 }
 
 // ---------------
 // PRIVATE
 // ---------------
 var _isValidTargetElement = function() {
 if ((_input!=null) && (_input!=undefined) && (_input.length>0) && (_input[0].tagName == "INPUT") && (_input[0].type == "file")) {
 return true;
 } else {
 log.error(clazz+"|NEW|Not valid target element",_input);
 return false;
 }
 }
 
 var _resize = function() {
 var inputFileFakeHeight = _inputFileFake.height() + 2 + parseInt(_inputFileFake.css("border-top-width"),10) + parseInt(_inputFileFake.css("border-bottom-width"),10);
 var inputButtonBrowseHeight = _inputButtonBrowse.height() + parseInt(_inputButtonBrowse.css("border-top-width"),10) + parseInt(_inputButtonBrowse.css("border-bottom-width"),10)
 var height = Math.max(inputFileFakeHeight,inputButtonBrowseHeight) ;
 uploadWrapper.attr("style","height:"+height+"px;overflow:hidden");
 var _inputFileFakeWidth = uploadWrapper.width() - options.styleBrowseButtonWidth - 10;
 log.debug(clazz+"|RESIZE|height["+height+"] width["+_inputFileFakeWidth+"]");
 _inputFileFake.width(_inputFileFakeWidth);
 _input.attr("style","position:relative;top:-"+height+"px;width:auto;float:right;-moz-opacity:0;filter:alpha(opacity: 0);opacity: 0;z-index:2;");
 
 _resizeInput();
 }
 
 var _resizeInput = function() {
 if (!jQuery.browser.mozilla) {
 _input.width(uploadWrapper.width());
 } else {
 var inputSize = Math.ceil(uploadWrapper.width() / options.pxToSizeFactor);
 _input.attr("size", inputSize);
 while (inputSize>1 &&_input.width() > (uploadWrapper.width()-10)){
 inputSize = inputSize-1;
 _input.attr("size", inputSize);
 log.debug(clazz+"|RESIZE|size["+inputSize+"]width["+input.width()+"]");
 }
 }
 }
 
 // ---------------
 // CONSTRUCTOR
 // ---------------
 var _new = function() {
 if (_isValidTargetElement.call()) {
 log.debug(clazz+"|NEW|");
 _input.wrap("<div class=\"jrwt-upload\"/>");
 var html = [];
 html.push("<input type=\"text\" class=\"jrwt-upload-file\" readonly value=\"\" />");
 html.push("<input type=\"button\" class=\"jrwt-upload-browse\" style=\"width:"+options.styleBrowseButtonWidth+"px\" value=\""+options.textBrowseButton+"\" />");
 uploadWrapper = _input.before(html.join("")).parent();
 _inputFileFake = uploadWrapper.find("input.jrwt-upload-file");
 _inputButtonBrowse = uploadWrapper.find("input.jrwt-upload-browse");
 _input.bind({
 "change": function(e) {
 log.debug(clazz+"|EVENT|"+e.type,e);
 _inputFileFake.val(_input.val());
 options.onChange.call(this, _this);
 }
 });
 
 // Sizing
 _resize();
 
 _container.bind({
 "resize.rainbows": function(e){
 log.debug(clazz+"|EVENT|"+e.type,e);
 _resize();
 setTimeout(function(){_resize();},500);
 }
 });
 
 }
 }
 _new.call(this);
}
