/* $Id: parship.js 137076 2009-04-22 10:11:32Z parship.weber $ */

var PS_properties = Class.create({
    initAt: new Date().getTime(),
    debug: false,
    debugWithTimeElapsed: true,
	internalSys : window.location.host.endsWith('parship.office') || window.location.host.indexOf('localhost') != -1 ? true : false,
 	queryDebug : window.location.search.indexOf('jsDebug=true') != "-1" ? true : false,

    popupDefaultWidth: 600,
    popupDefaultHeight: 500,

	geoInputState: null,

	editListenerCache: new Array()
});

/**
 * Ähnlich wie Element.descendants, nur schneller auf dem IE6
 * @param element Das Element
 * @return Eine Liste aller Abkommen dieses Elementes, inkl. des Elementes. Es wird jedoch noch nicht
 * durch $() gewrappt.
 */
var getDescendants = function(element) {
	var list = [element];
	var length = element.childNodes.length;
	for(var i=0; i<length; i++) {
		var child = element.childNodes[i];
		// Der IE gibt uns aus irgendwelchen Gründen hier manchmal ein null rein
		if (child && child.nodeType == 1) {
			 list = list.concat(getDescendants(child));
		}
	}
	return list;
};

/**
 * Hilfsfunktion. Durchläuft den gesamten Dokumentbaum und ruft für jedes
 * Element, das eine Klasse hat, die in der methodMap vorkommt, den entsprechenden Handler auf.
 * @param methodMap Eine Map von Klassename zu Handler. Der Handler bekommt das von Prototype gewrappte
 * Element zurück
 */
var applyClassHandlers = function(methodMap) {
	var allElements = getDescendants(document.body);
	var aLength = allElements.length;
	for (var i=0; i<aLength; i++) {
		var q = new Date().getTime();
		var element = allElements[i];
	    var classes = element.className.split(" ");
	    var length = classes.length;
	    for(var j = 0; j<length; j++) {
	        var method = methodMap[classes[j]];
	        if (method) {
	    	    method($(element));
	        }
	    }
	}
}

document.whenReady = (function() {
  var queue = [ ];
  document.observe('dom:loaded', function() {
    ps_js_timings.parshipJsFirstDomLoaded = new Date().getTime();
    queue.invoke('call', document);
    queue.clear();
    document.whenReady = function(callback) { callback.bind(document).defer() };
  });
  return function(callback) { queue.push(callback) };
})();


var PS_domInit = Class.create({
    initialize: function(){
    	PS.debug('performing PS_domInit.initialize()');
   		var listViewInput = null;
   		var elems;
		if(typeof pageVars  != "undefined") {
			pageVars.init(); //Backend-Variablen auf der HTML-Seite
		}


   		var productBoxFunction = function(ele) {
    		PS.debug("init PS_productBox: id=" + ele.id);
            new PS_productBox(ele);
            // profile("productBox", s);
        }

   		var methodMap = {
   	        ps_disabledButton: function(ele) {
                PS.debug("init PS_buttonDisable: id=" + ele.id);
	            new PS_buttonDisable(ele,[]);
            },

        	ps_inputDefault: function(ele) {
                    PS.debug("init PS_inputDefault: id=" + ele.id);
    	            new PS_inputDefault(ele);
    		},

        	ps_buttonIconMouseover: function(ele) {
                    PS.debug("init PS_buttonIconMouseover: id=" + ele.id);
    	            new PS_buttonIconMouseover(ele);
    		},

        	ps_uncheckAll: function(ele) {
                    PS.debug("init PS_checkUncheckInputs: id=" + ele.id);
    	            new PS_checkUncheckInputs(ele, false);
    		},

    		ps_checkAll: function(ele){
                    PS.debug("init PS_checkUncheckInputs: id=" + ele.id);
    	            new PS_checkUncheckInputs(ele, true);
    		},

    		ps_lightenMouseover: function(ele){
                    PS.debug("init PS_lightenMouseover: id=" + ele.id);
    	            new PS_lightenMouseover(ele);
        	},

			/*
        	ps_growingTextarea: function(ele){
                	PS.debug("init PS_growingTextarea");
    				new PS_growingTextarea(ele);
    		},
    		*/

    		ps_pop: function(ele){
                    PS.debug("init PS_popupHandler: href=" + ele.href);
                    new PS_popupHandler(ele);
            },
            ps_listViewRow: function(ele){
                    PS.debug("init PS_listViewRow: id=" + ele.id);
                    // listViewInput: name of the radio-input in the listViewRow
					// DIV, that
             		// highlights the DIV, when it is checked.
                    if (listViewInput)
                    	new PS_listViewRow(ele, listViewInput);
                    else
                    	new PS_listViewRow(ele, null);
            },

            ps_tailoredMessage: function(ele){
              PS.debug("init PS_tailoredMessage: id=" + ele.id);
              new PS_tailoredMessage(ele);
            },

            ps_genderChoiceImg: function(ele){
                    PS.debug("init PS_regSexImage: id=" + ele.id);
                    new PS_regSexImage(ele);
            },

            ps_mouseOverImage: function(ele){
                    PS.debug("init PS_mouseOverImage: id=" + ele.id);
                    new PS_mouseOverImage(ele);
            },

            ps_showEditMode: function(ele) {
            		PS.debug("init PS_showEditMode: id=" + ele.id);
                    new PS_showEditMode(ele, false);
            },

            ps_hideEditMode: function(ele) {
            		PS.debug("init PS_hideEditMode: id=" + ele.id);
                    new PS_hideEditMode(ele);
            },

            ps_openEditMode: function(ele) {
            		PS.debug("init PS_showEditBox: id=" + ele.id);
            		if (!ele.hasClassName('ps_editIconDisabled')) {
                    	new PS_showEditBox(ele);
                    }
            },

            ps_hideEditBox: function(ele) {
            		PS.debug("init PS_hideEditBox: id=" + ele.id);
                    new PS_hideEditBox(ele);
            },

            ps_productBox: productBoxFunction,

            ps_productBoxWithSeal: productBoxFunction,

            ps_productBoxWithLargeSeal: productBoxFunction,

			ps_selectedProduct: productBoxFunction,

            ps_productBoxHorizontal: productBoxFunction,

            ps_productBoxHorizontalWithSeal: productBoxFunction,

            ps_toggle: function(ele) {
    	            PS.debug("init PS_toggle for "+ele.id);
    	            new PS_toggle(ele);
    		},

    		ps_areaSwitch: function(ele) {
    	            PS.debug("init PS_areaSwitch for "+ele.id);
    	            new PS_areaSwitch(ele);
    		},


    		ps_charLimit: function(ele){
                    PS.debug("init PS_inputObserver: id=" + ele.id);
                    new PS_inputObserver(ele);
            },

            ps_tooltip: function(ele){
                    PS.debug("init PS_tooltip: id=" + ele.id);
                    new PS_tooltip(ele);
            },

            ps_payment_submit: function(ele){
            		PS.debug("init PS_disableOnSubmit: id="+ele.id);
            		new PS_disableOnSubmit(ele);
            },

            ps_invoke_noteeditor: function(ele){
              PS.debug("init ps_invoke_noteeditor");
              new PS_invokeNoteEditor(ele);
            },
            ps_resetNoteForm: function(ele){
              PS.debug("init ps_resetNoteForm");
              new PS_resetNoteForm(ele);
            },

            ps_makeWritableNote: function(ele){
              PS.debug("init ps_makeWritableNote");
              new PS_makeWritableNote(ele);
            },

            ps_genBut: function(elem){
              PS.debug("init ps_genButHover");
              new PS_genButHover(elem);
            },

            ps_genConv: function(elem){
              PS.debug("init ps_genConvHover");
              new PS_genConvHover(elem);
            },

            ps_oldMottoSave: function(ele){
                PS.debug("init ps_oldMottoSave");
                new PS_oldMottoSave(ele);
              },

			ps_mottoSave: function(ele){
              PS.debug("init ps_mottoSave");
              new PS_mottoSave(ele);
            },

			ps_ratingScale: function() {
              PS.debug("init ps_ratingScale");
			  PS.loadScript('slider', pageVars.libPath + "scriptaculous/");
			  setTimeout("PS.loadScript('parship_userrating')", 100);
			  //init called in external File
			},

			ps_searchFilters: function(ele) {
              PS.debug("init ps_searchFilters");
              new PS_searchFilters(ele);
			},

			ps_editUploadedImages: function(ele) {
	            PS.debug("init ps_editUploadedImages");
				new PS_editUploadedImages(ele);
			},

			ps_releaseForm: function(ele) {
	            PS.debug("init ps_releaseForm");
				new PS_releaseForm(ele);
			},

			ps_write_msg: function(ele) {
				new PS_beforeUnloadAction(ele);
			},

			ps_welcomeMail: function(ele) {
				new PS_welcomeMail(ele);
			},

			ps_sorting: function(ele) {
				new PS_sorting(ele);
			}

			/*ps_sortLinks: function(ele) {
				alert("a");
				new PS_omnTracking(ele);
			}*/

		};

   		applyClassHandlers(methodMap);
   		elems = $$('label');
   		if (elems) {
   			new PS_imgLabelClickable(elems);
   		}

   		elems = $$('.ps_navTabs li');
        if (elems) {
            elems.each(function(ele){
                PS.debug("init PS_navTabs: id=" + ele.id);
                new PS_navTabs(ele);
            });
        }

    	// only at the about one self edit page
		if ($('ps_cancelation_step3')) {
			new PS_buttonDisable($('ps_btnNext'),$$('input[name="ps_field_0"]'));
		}

    	if($('ps_testProfilePrefill')) {
			new PS_fakeInput(); //for Image-Upload
		}

		if ($$('.ps_aboutoneself_edit_page')[0]) {
	        new PS_fakeInput(); //for Image-Upload

    		// caution, this var is needed at listViewRow later, too!
    		listViewInput = "ps_field_profile_img";
			var rootElem = $$('.ps_aboutoneself_edit_page')[0];
    		var imgInputs = rootElem.select('input[name="'+listViewInput+'"]');
    		if (imgInputs) {
    			imgInputs.each(function(i){
					PS.debug("init PS_galleryImgInput: id=" + i.id);
			        new PS_galleryImgInput(i, imgInputs);
    			});
    		}
		}
    	// only at the search criteria page
		elems = $('ps_search_criteria');

		if (elems) {
    		var rootElem = elems;
           // extra behaviour for geo search elems
           var hideBoxs = rootElem.select('.ps_hideGeoBox');
           if (hideBoxs) {
           		hideBoxs.each(function(e) {
	               PS.debug("init PS_toggleGeoBox: id=" + e.id);
		            new PS_toggleGeoBox(e, true);
           		});
           }
           var showBoxs = rootElem.select('.ps_showGeoBox');
           if (showBoxs) {
           		showBoxs.each(function(e) {
	               PS.debug("init PS_toggleGeoBox: id=" + e.id);
		            new PS_toggleGeoBox(e, false);
           		});
           }
           var geoInputs = rootElem.select('input[name="ps_field_geosearch"].ps_triggerEditBox');
           if (geoInputs) {
           		geoInputs.each(function(e) {
	              	PS.debug("init PS_triggerEditBox: id=" + e.id);
		            new PS_triggerEditBox(e, geoInputs);
           		});
           }
           var geoInputs = rootElem.select('input[name="ps_field_geosearch"].ps_grayingEnabled');
           if (geoInputs) {
           		geoInputs.each(function(e) {
	              	PS.debug("init PS_grayGeoBox: id=" + e.id);
		            new PS_grayGeoBox(e, geoInputs);
           		});
           }
           var selectElem = $('ps_field_country_selection');
           if (selectElem) {
        	   var alloptions = selectElem.cloneNode(true).options;

	           var addCountryCtrl = $('ps_addCountryCtrl');
	           if (addCountryCtrl) {
	               PS.debug("init PS_handleCountryCtrls: id=" + addCountryCtrl.id);
		            new PS_handleCountryCtrls(addCountryCtrl, true, true, alloptions, selectElem);
	           }
	           var remCountryCtrls = rootElem.select('.ps_removeCountryCtrl');
	           if (remCountryCtrls) {
	           		remCountryCtrls.each(function(e) {
		               PS.debug("init PS_removeCountryCtrls: id=" + e.id);
			            new PS_handleCountryCtrls(e, false, false, alloptions, selectElem);
	           		});
	           }
           }
    	}
        elems = $('ps_field_password_dynamic');
        if (elems) {
            PS.debug("init PS_passwordDynamic");
            new PS_passwordDynamic(elems);
        }
        if ($('ps_regSex')) {
            PS.debug("init PS_regSex");
            new PS_regSex();
        }
        if ($$('.ps_guidedForm').any()) {
          PS.debug("init PS_guidedForm");
          new PS_guidedForm();
        }

		if($$('.ps_debugLayer').any()) {
			new PS_debugLayer();
		}

	}
});

/*
 * PS_onload = Class.create({ initialize: function(){ PS.debug('performing
 * PS_onload.initialize()');
 *
 *  } });
 */

var PS_whenReady = Class.create({
    initialize: function(){
		PS.debug('performing PS_whenReady.initialize()');

		if ($$('.ps_layerID_ps_layer_map').any()) {
			PS.debug('setting zipcode map');

			if ($('ps_zipMap')) {
				var mapImg = $('ps_zipMap');
				var zipCode, country;

				mapImg.className.split(" ").each(function(c) {
					if (c.match(/^ps_zipMap_zip_\d+$/)) {
					    zipCode = c.replace('ps_zipMap_zip_', '');
					}
					if (c.match(/^ps_zipMap_country_.+$/)) {
					    country = c.replace('ps_zipMap_country_', '');
					}
				});

			    if (country && zipCode) {
			        mapImg.src = '../img/maps/zipmap_' + country + '_' + zipCode + '.png';
			    }
            }
		}

		var methodMap = {
	    	ps_imageFlow: function (ele) {
	    		PS.debug("init PS_imageFlow: id=" + ele.id);
	    		new PS_imageFlow(ele);
	    	},

	    	ps_focusField: function(ele){
				ele.focus();
			},

			ps_focusTextarea: function(ele, st, end){
				setCursor(ele, 0, 0)
				ele.focus();
				function setCursor(ele, st, end){
					if (ele.setSelectionRange) {
						ele.setSelectionRange(st, end);
					}
					else {
						if (ele.createTextrange) {
							range = ele.createTextrange();
							range.collapse(true);
							range.moveEnd(' ', end);
							range.moveStart(' ', st);
							range.select();
						}
					}
				}
			}
	    };

	    applyClassHandlers(methodMap);


		// fix scriptaculous Autocompleter iframe positioning at the end of page
		// in IE...assuming there are no "real" iframes with absolute
		// positioning!
		var iframeElems = $$('iframe');
		if (iframeElems) iframeElems.each(function(iframeElem) {
			if (iframeElem.style.position == 'absolute')
				iframeElem.setStyle({top : '-1000px'});
		});

		PS.debug('completed PS_whenReady.initialize()');

    }

});


// enhances scriptaculous Effect.ScrollTo so that scrolling can stop at a chosen
// margin above the element
function PS_scrollTo(ele, margin, alignBottom) {
	if (ele == undefined) return false;
	// special case: scroll to align bottom border of element at viewport bottom
	if (alignBottom) margin = document.viewport.getHeight() - ele.getHeight() - margin;
	var oldPos = ele.getStyle('position');
	var oldTop = ele.getStyle('top');
	var oldPaddingTop = ele.getStyle('paddingTop');
	ele.setStyle({position: 'relative', top: -margin + 'px', paddingTop: margin + 'px'});
	new Effect.ScrollTo(ele);
	ele.setStyle({position: oldPos, top: oldTop, paddingTop: oldPaddingTop});
}



var PS_popup;


var PS_regSex = Class.create({
    initialize: function(){
        this.changer = new PS_regSexImageChange();
    	/* use click instead of change, IE does not know it for radio buttons */
        $('ps_regSex').observe('mouseup', this.changeMouse.bindAsEventListener(this));
        $('ps_regSex').observe('keyup', this.changeKey.bindAsEventListener(this));
    },

    changeMouse: function(evt){
    	var input = evt.element();
        this.changer.changeInput(input);
		$('email').focus();
    },
    changeKey: function(evt){
        this.changer.changeInput(evt.element());
    }

});

var PS_regSexImageChange = Class.create({
    initialize: function(){
    	this.imgAct = new PS_imageActivating();

    	// restore previous state if back-button or page reload was used
    	if ($('ps_mysex0').checked) this.imgAct.setActive($('ps_mysex0_img'));
    	if ($('ps_mysex1').checked) this.imgAct.setActive($('ps_mysex1_img'));
    	if ($('ps_essex0').checked) this.imgAct.setActive($('ps_essex0_img'));
    	if ($('ps_essex1').checked) this.imgAct.setActive($('ps_essex1_img'));
	},
    changeImages: function(name, sex, othersex) {
        // change the img for current
        if ($("ps_" + name + sex + "_img")) {
			this.imgAct.setActive($("ps_" + name+sex+"_img"));
        }
        // change the img for other sex
        if ($("ps_" + name + othersex + "_img")) {
			this.imgAct.setInactive($("ps_" + name+othersex+"_img"));
        }
    },
    changeInput: function(ele){
        var name = ele.name;
       	var othername = "essex";
        var sex = ele.value;
        var othersex = sex == "1" ? "0" : "1";
        // change the essex
        if (name == "mysex") {
            $("ps_" + othername + sex).removeAttribute('checked');
            $("ps_" + othername + othersex).click();
	        // this is only needed, if the click does not trigger the change
			// method of the inputs (e.g. in Firefox2)
    		this.changeImages(othername, othersex, sex);
	    }
		PS.debug("change" + name + " " + sex + " " + othersex)
        this.changeImages(name, sex, othersex);
    }
});

var PS_imageActivating = Class.create({
    initialize: function(){
    	this.postfix = "_active";
    },

    setActive: function(ele){
    	var extIndex = ele.src.lastIndexOf(".");
        if (!ele.src.substring(0, extIndex).endsWith(this.postfix)) {
        	ele.src = ele.src.substring(0, extIndex) + this.postfix + ele.src.substring(extIndex, ele.src.length);
        }
    },
    setInactive: function(ele){
        ele.src = ele.src.replace(this.postfix, "");
    }
});


var PS_buttonIconMouseover = Class.create({
    initialize: function(ele){
    	this.ele = $(ele);
    	this.icon = this.ele.next();
    	Event.observe(this.ele, 'mouseover', this.inside.bindAsEventListener(this));
    	Event.observe(this.ele, 'mouseout', this.outside.bindAsEventListener(this));

    	if (this.icon) this.icon.setStyle({visibility: 'hidden'});
    },

    inside: function() {
    	if (this.icon) this.icon.setStyle({visibility: 'visible'});
    },
    outside: function() {
    	if (this.icon) this.icon.setStyle({visibility: 'hidden'});
    }
});

/*
 * adds inline default values for input texts and password fields default values
 * are parsed from labels attached to input fields
 */
var PS_inputDefault = Class.create({
    initialize: function(ele){
    	this.ele          = $(ele);
    	this.fieldLabel   = $(this.ele.id + '_label');
    	this.fieldType    = this.ele.readAttribute('type');
    	this.defaultValue = '';

    	if (this.fieldType == 'password') {
      	  this.fakeField = $(this.ele.id + '_fakefield');
      	  this.fakeField.value = this.fakeField.value.gsub(/\s*:\s*$/,"");
		  // check for auto fill!!
		  if (this.ele.value) {
		  	this.fakeField.hide();
		    this.ele.setStyle('display:inline');
		    this.ele.focus();
		  }
		  Event.observe(this.fakeField, 'focus', this.focus.bindAsEventListener(this));
		  Event.observe(this.ele, 'blur', this.blur.bindAsEventListener(this));
    	} else {
    	  if (this.fieldLabel) {
      	      this.defaultValue = this.fieldLabel.innerHTML.gsub(/\s*:\s*$/,"");
  	      }
		  // check for auto fill!!
		  if (!this.ele.value) {
		  	this.ele.value = this.defaultValue;
		  }
      	  Event.observe(this.ele, 'focus', this.focus.bindAsEventListener(this));
      	  Event.observe(this.ele, 'blur', this.blur.bindAsEventListener(this));
    	}
    },

    focus: function() {
		PS.debug("FOCUS: " + this.ele.value +"-"+  this.defaultValue)
		  if (this.fieldType == 'password') {
		    this.fakeField.hide();
		    this.ele.setStyle('display:inline');
		    this.ele.focus();
		    Event.stopObserving(this.fakeField, 'focus', this.focus.bindAsEventListener(this));
		  } else {
		    if (this.ele.value == this.defaultValue)
  		    this.ele.value = '';
			this.ele.removeClassName("ps_defaultValueClass");
		  }
    },
    blur: function() {
		PS.debug("BLUR: " + this.ele.value +"-"+  this.defaultValue)
	     if (this.ele.value == '') {
		 	if (this.fieldType == 'password') {
		 		this.fakeField.show();
		 		this.ele.setStyle('display:none');
		 	}
		 	else {
				this.ele.addClassName("ps_defaultValueClass");
		 		this.ele.value = this.defaultValue;
		 	}
		 }
    }
});

var PS_layerCloseButton = Class.create({
    initialize: function(ele){
    	Event.observe(ele, 'mouseover', this.inside.bindAsEventListener(this));
    	Event.observe(ele, 'mouseout', this.outside.bindAsEventListener(this));
    },

    inside: function(evt) {
    	evt.element().setStyle({backgroundImage : 'url(../img/btn_closeX_over.gif)' });
    },
    outside: function(evt) {
    	evt.element().setStyle({backgroundImage : 'url(../img/btn_closeX.gif)' });
    }
});

var PS_navTabs = Class.create({
    initialize: function(ele){
    	this.ele = $(ele);
    	this.overClass = "ps_hover";

    	Event.observe(this.ele, "mouseover", this.inside.bindAsEventListener(this));
    	Event.observe(this.ele, "mouseout", this.outside.bindAsEventListener(this));
    },

    inside: function(){
    	if (!this.ele.hasClassName('ps_tabActive') && !this.ele.hasClassName('ps_tabDisabled'))
    		this.ele.addClassName(this.overClass);
    },
    outside: function(){
		this.ele.removeClassName(this.overClass);
	}
});


var PS_regSexImage = Class.create({
    initialize: function(ele){
        this.ele = $(ele);
        this.changer = new PS_imageActivating();
        Event.observe(this.ele, "click", this.click.bindAsEventListener(this));
        Event.observe(this.ele, "mouseout", this.outside.bindAsEventListener(this));
        Event.observe(this.ele, "mouseover", this.inside.bindAsEventListener(this));
    },
    inside: function(){
    	this.changer.setActive(this.ele);
    },
    outside: function(){
    	var inp = this.getInputElem();
    	if (!inp.checked) {
   			this.changer.setInactive(this.ele);
   		}
    },
    click: function() {
    	var inp = this.getInputElem();
    	inp.click();

        // this is only needed, if the click does not trigger the change method
		// of the inputs (e.g. in Firefox2)
        var changer = new PS_regSexImageChange();
        changer.changeInput(inp);
        if (inp.name=='ps_mysex') {
        	$('ps_field_email').focus();
        }
    },
    getInputElem: function() {
    	return $(this.ele.id.replace(/_img/, ""));
    }
});

// allows outside access to the imageflow-gallery as used on the "about me" area
// in profile
var globalGalleryInstance;

var PS_imageFlow = Class.create({
    initialize: function(ele){
		this.ele = ele;
        this.imgMargin = 11;

        this.imgWidth = 72 + this.imgMargin;
        this.frmWidth = ele.down('.ps_imageFlowImagesWrapper').getWidth();
        this.isLayerGallery = !this.frmWidth;

		if (this.isLayerGallery) {
			this.imgWidth = 360 + this.imgMargin;
			this.frmWidth = 360;
		}

		// make gallery instance public
		if (this.isLayerGallery) globalGalleryInstance = this;

        this.imgNum   = ele.down('.ps_imageFlowImages').childElements().length;

        ele.down('.ps_imageFlowImagesWrapper').makePositioned();

        // IE6 for some reason loses overflow:hidden
        ele.down('.ps_imageFlowImagesWrapper').setStyle({overflow:'hidden'});
        this.leftLimit = (-this.imgNum * this.imgWidth) + this.frmWidth;
        this.rightLimit = -11;

		this.leftBtn  = ele.down('.ps_imageFlowLeftNavi');
		this.rightBtn = ele.down('.ps_imageFlowRightNavi');

        Event.observe(this.leftBtn, 'click', this.leftClick.bindAsEventListener(this));
        Event.observe(this.leftBtn, 'mouseover', this.inside.bindAsEventListener(this));
        Event.observe(this.leftBtn, 'mouseout', this.outside.bindAsEventListener(this));
        Event.observe(this.rightBtn, 'click', this.rightClick.bindAsEventListener(this));
        Event.observe(this.rightBtn, 'mouseover', this.inside.bindAsEventListener(this));
        Event.observe(this.rightBtn, 'mouseout', this.outside.bindAsEventListener(this));
        this.disableButtons(this.getPosition());
    },

    inside: function(evt){
    	if (!evt.element().hasClassName('ps_flowBtnDisabled')) {
	        new Effect.Opacity(evt.element(), {
				from: 1.0,
	            to: 0.75,
				duration: 0.1
	        })
        } else {
			evt.element().writeAttribute('style', '');
        }
    },
    outside: function(evt){
    	if (!evt.element().hasClassName('ps_flowBtnDisabled')) {
	        new Effect.Opacity(evt.element(), {
				from: 0.75,
	            to: 1.0,
				duration: 0.1
	        })
        } else {
			evt.element().writeAttribute('style', '');
        }
    },

    showGalleryImage: function(galleryImgNum) {
    	var pos = galleryImgNum * -this.imgWidth;
    	this.ele.down('.ps_imageFlowImages').setStyle({position: 'relative', left: pos + 'px'});
    	this.disableButtons(pos);
    },
    getPosition: function() {
    	return this.ele.down('.ps_imageFlowImages').positionedOffset().first();
    },
    disableButtons: function(pos) {
        var moveLen = this.getMoveLen(pos, true);
    	if (pos <= this.leftLimit || moveLen == 0) {
    		this.disableBtn(this.rightBtn);
    	}  else {
    		this.enableBtn(this.rightBtn);
    	}
        moveLen = this.getMoveLen(pos, false);
    	if (pos > this.rightLimit || moveLen == 0) {
    		this.disableBtn(this.leftBtn);
    	}  else {
    		this.enableBtn(this.leftBtn);
    	}
    },
    disableBtn: function(btn) {
    	btn.addClassName('ps_flowBtnDisabled');
		btn.writeAttribute('style', '');
    },
    enableBtn: function(btn) {
    	btn.removeClassName('ps_flowBtnDisabled');
    },
    getMoveLen: function(pos, right) {
    	if (right)
    		return Math.max(-this.imgWidth, this.leftLimit - pos + this.imgMargin);
    	else
    		return Math.min(this.imgWidth, this.rightLimit - pos + this.imgMargin);
    },
    rightClick: function(evt){
		evt.stop();
        pos = this.getPosition();
        moveLen = this.getMoveLen(pos, true);

        if (pos <= this.leftLimit || moveLen == 0) {
            /*
			 * new Effect.Opacity(this.rightBtn, { from: 0.75, to: 0.25,
			 * duration:0.1 }); new Effect.Opacity(this.rightBtn, { from: 0.25,
			 * to: 0.75, duration:0.1, queue: 'end' });
			 */
        }
        else {
            new Effect.Move(this.ele.down('.ps_imageFlowImages'), {
                x: moveLen,
                y: 0,
                duration: -moveLen / this.imgWidth,
                queue: {
                    scope: 'imageflow',
                    limit: 1
                }
            });
            var nextPos = pos + moveLen;
	        this.disableButtons(nextPos);
        }
    },

    leftClick: function(evt){
		evt.stop();
        pos = this.getPosition();
        moveLen = this.getMoveLen(pos, false);

        if (pos > this.rightLimit || moveLen == 0) {
            /*
			 * new Effect.Opacity(this.leftBtn, { from: 0.75, to: 0.25,
			 * duration:0.1 }); new Effect.Opacity(this.leftBtn, { from: 0.25,
			 * to: 0.75, duration:0.1, queue: 'end' });
			 */
        }
        else {
            new Effect.Move(this.ele.down('.ps_imageFlowImages'), {
                x: moveLen,
                y: 0,
                duration: moveLen / this.imgWidth,
                queue: {
                    scope: 'imageflow',
                    limit: 1
                }
            });
            var nextPos = pos + moveLen;
	        this.disableButtons(nextPos);
        }
    }
});


var PS_popupHandler = Class.create({
    initialize: function(ele){
        this.prop = new PS_properties();
        this.ele = ele;
        this.width = this.getPopWidth();
        this.height = this.getPopHeight();
        this.ele.observe('click', this.open.bindAsEventListener(this));

        if (this.ele.hasClassName('ps_pop_auto')) {
            this.ele.observe('ps:pop_auto', this.open.bindAsEventListener(this));
            this.ele.fire("ps:pop_auto");
        }
    },


    getPopWidth: function(){
        value = this.prop.popupDefaultWidth;
        if (this.ele.className) {
            this.ele.className.split(" ").each(function(v){
                if (v.match(/^ps_pop_\d+_\d+$/)) {
                    value = v.gsub(/^ps_pop_(\d+)_\d+/, '#{1}');
                }
            })
        }
        return value;
    },

    getPopHeight: function(){
        value = this.prop.popupDefaultHeight;
        if (this.ele.className) {
            this.ele.className.split(" ").each(function(v){
                if (v.match(/^ps_pop_\d+_\d+$/)) {
                    value = v.gsub(/^ps_pop_\d+_(\d+)/, '#{1}');
                }
            })
        }
        return value;
    },

    open: function(evt){
        params = "width=" + this.width + ",height=" + this.height + ",resizable=1,scrollbars=1";
        if (PS_popup)
            PS_popup.close();
        PS_popup = window.open(evt.element().href, "ps_popup", params);
        if (PS_popup)
            PS_popup.focus();
        evt.stop();
    }
});


var PS_inputObserver = Class.create({
    initialize: function(ele){
        this.ele = ele;
        this.id = ele.id;
        this.max = this.getMax();
        this.observe();
    },

    observe: function(){
        this.ele.observe('click', this.updateCount.bindAsEventListener(this));
        this.ele.observe('keydown', this.updateCount.bindAsEventListener(this));
        this.ele.observe('keyup', this.updateCount.bindAsEventListener(this));
        this.ele.observe('change', this.updateCount.bindAsEventListener(this));
        this.ele.observe('focus', this.updateCount.bindAsEventListener(this));
        this.ele.observe('blur', this.updateCount.bindAsEventListener(this));
        this.ele.observe('ps:inputobserver_init', this.updateCount.bindAsEventListener(this));
        this.ele.fire("ps:inputobserver_init");
    },

    getMax: function(){
        count = "10000";
        if (this.ele.className) {
            this.ele.className.split(" ").each(function(c){
                if (c.match(/^ps_max_\d+$/)) {
                    count = c.replace('ps_max_', '');
                }
            })
        }
        return count;
    },

    updateCount: function(){
    	if ($(this.id)) {
	    	var counterElem = $(this.id + "_counter");
	        var word = $F(this.id);
	        var count = 0;
	        if (word) count = word.length;
	        if (count >= this.max) {
	        	if (count > this.max) {
		        	var truncValue = word.truncate(this.max, '');
		            this.ele.value = truncValue;
			        count = truncValue.length;
			    }
		        if (counterElem) {
		        	counterElem.up().addClassName('ps_inputLimitReached');
		        }
	        } else {
	        	if (counterElem) counterElem.up().removeClassName('ps_inputLimitReached');
	        }

	        if (counterElem) counterElem.update(count);

	        if (this.ele.hasClassName("ps_expand")) {
	            if (this.scrollHeight > this.getHeight())
	                this.rows += 1;
	        }

	        // Show message for length limit
	        var messageElem = $(this.id + "_message");
	        if (messageElem) {
	        	if (count >= this.max) {
	        		messageElem.show();
	        	}
	        	else {
	        		$(this.id + "_message").hide();
	        	}
	        }
        }
    }
});

var PS_tooltip = Class.create({
    initialize: function(ele){
		if (!ele.id) {
			ele.identify();
			if (!ele.next())
				ele.up().next().addClassName(ele.id)
			else
				ele.next().addClassName(ele.id)

		}

    	// get tooltip to treat
        this.ele = $(ele);
        this.tooltip = $$("." + this.ele.id)[0];

		if (!this.tooltip) return;

        // simple styled dropdown uses tooltip function in a special way
		this.isDropdown = this.ele.hasClassName('ps_tooltipDropdown');

		this.w = this.getWidth(this.tooltip);

        if (!this.tooltip) return;
		this.tooltip.show();

    	// create tooltip area layer if it's not already present
    	if (!$('ps_tooltipAreaWrapper')) {
    		var tooltipArea = new Element('div', {'id' : 'ps_tooltipAreaWrapper', 'class' : 'parship'});
    		Element.insert($('parship'), {'after' : tooltipArea});
			Element.insert($('ps_tooltipAreaWrapper'), new Element('div', { 'id' : 'ps_tooltip_arrow' }));
    	}

        // wrap in necessary elements
        var tempElem = this.tooltip.wrap('div', {'class' : 'ps_tooltip_body'});
        var dialogElem = tempElem.wrap('div', {'class' : 'ps_tooltip_dialog ' + this.tooltip.className});
        dialogElem.removeClassName(this.ele.id);
        this.tooltip.className = 'ps_tooltip_c';

        var topDiv = new Element('div', {'class' : 'ps_tooltip_c'});
        topDiv = topDiv.wrap('div', {'class' : 'ps_tooltip_head'});
        Element.insert(tempElem, {'before' : topDiv});

        var bottomDiv = new Element('div', {'class' : 'ps_tooltip_c'});
        bottomDiv = bottomDiv.wrap('div', {'class' : 'ps_tooltip_foot'});
        Element.insert(tempElem, {'after' : bottomDiv});

        var wrapperStyle = 'display: none; ' + (this.w ? ' width: ' + this.w + 'px;' : ' white-space: nowrap;');
        dialogElem.wrap('div', {'class' : this.ele.id + ' ps_tooltipWrapper', 'style' : wrapperStyle});

        // unhide tooltip content area (previously hidden to prevent flickering)
        this.tooltip.show();

        // get newly wrapped tooltip and move it to tooltip area layer
        this.tooltip = $$("." + this.ele.id)[0];
		Element.insert($('ps_tooltipAreaWrapper'), Element.remove(this.tooltip));

		/*if (Prototype.Browser.IE && (typeof window.XMLHttpRequest == "undefined") && ! this.ele.hasClassName('ps_tooltipBelow')){
			iframe = new Element('iframe', { src: "/static/lib/prototype-ui/blank.html"});
			Element.insert(this.tooltip, iframe);
			iframe.setStyle( {
				width : this.tooltip.getWidth()+"px",
				height : (this.tooltip.getHeight()+26)+"px"
			});
		}*/
		this.orange = this.tooltip.down().hasClassName("ps_orangeTooltip");

        // register events
        if (this.isDropdown) {
        	this.h = this.ele.getHeight();
        	this.dropDownClickListener = this.dropdownClick.bindAsEventListener(this)
        	Event.observe(this.ele, "click", this.dropDownClickListener);
        	this.additionalOpener = this.ele.up().up().down('.ps_additionalDropdownOpener');
        	if (this.additionalOpener) {
        		Event.observe(this.additionalOpener, "click", this.dropdownClick.bindAsEventListener(this));
        		this.additionalOpener.setStyle({cursor: 'pointer'});
        	}

        	var t = this;
        	var dropdownOptions = this.tooltip.select('a');
        	if (dropdownOptions) dropdownOptions.each(function(opt){
        		Event.observe(opt, 'click', t.dropdownOptionChoose.bindAsEventListener(t, opt));
        		if (t.ele.innerHTML == opt.innerHTML) {
        			opt.addClassName('ps_simpleDropdown_selectedValue');
        			t.selectedValue = opt;
        		}
        	});
			//new PS_omnTracking(this.ele);

        	// close btn inside dropdown (arrow-icon)
        	/*
			 * var closerElems =
			 * this.tooltip.select('.ps_simpleDropdown_close'); if (closerElems)
			 * closerElems.each(function(closerElem) { Event.observe(closerElem,
			 * 'click', t.dropdownOptionChoose.bindAsEventListener(t)); });
			 */

        	// global click to close this dropdown when clicked outside
        	Event.observe(document, 'click', this.documentClick.bindAsEventListener(this));

        } else {
	        Event.observe(this.ele, "mouseover", this.inside.bindAsEventListener(this));
	        Event.observe(this.ele, "mousemove", this.inside.bindAsEventListener(this));
	        Event.observe(this.ele, "mouseout", this.outside.bindAsEventListener(this));
	    }

    },
    dropDownOpen: function(ele, listener, tooltip) {
    	tooltip.show();
    	ele.removeClassName("ps_dropdownClosed");
    	ele.addClassName("ps_dropdownOpened");
    },
    dropDownClose: function(ele, listener, tooltip) {
    	tooltip.hide();
		ele.removeClassName("ps_dropdownOpened");
		ele.addClassName("ps_dropdownClosed");
    },
    dropdownOptionChoose: function(evt, opt){
    	// evt.stop();
    	if (opt && this.selectedValue) {
    		this.ele.innerHTML = opt.innerHTML;
    		this.selectedValue.removeClassName('ps_simpleDropdown_selectedValue');
    		this.selectedValue = opt;
    		this.selectedValue.addClassName('ps_simpleDropdown_selectedValue');
    	}
    	this.dropDownClose(this.ele, this.dropDownClickListener, this.tooltip);
    },
    dropdownClick: function(evt){
    	if (this.tooltip.style.display=='none') {
		    // recalc width if it was set previously, to prevent errors due to
			// false widths on some browsers on page load
	    	if (this.w) {
	    		this.w = this.getWidth(this.tooltip);
	    		this.tooltip.setStyle({width: this.w + 'px'});
	    	}
	    	this.dropDownOpen(this.ele, this.dropDownClickListener, this.tooltip);

	        x = this.ele.cumulativeOffset().left;
			y = this.ele.cumulativeOffset().top + this.h;

			Element.setStyle(this.tooltip, {
	            top: y + "px",
	            left: x + "px"
	        });
	    } else {
	    	this.dropDownClose(this.ele, this.dropDownClickListener, this.tooltip);
	    }
    },
    documentClick: function(evt){
    	var mouseX = Event.pointerX(evt);
    	var mouseY = Event.pointerY(evt);
    	var dropdownOptions = this.tooltip.down('.ps_simpleDropdown_options');
    	var x = dropdownOptions.cumulativeOffset().left;
    	var y = dropdownOptions.cumulativeOffset().top-this.h;
    	var width = dropdownOptions.getDimensions().width;
    	var height = dropdownOptions.getDimensions().height;

    	if (this.additionalOpener) y -= 10;

    	var stillInside = mouseX > x && mouseX < x+width && mouseY > y && mouseY < y+height;
    	if (!stillInside) {
    		if (this.isDropdown) {
	    		this.dropDownClose(this.ele, this.dropDownClickListener, this.tooltip);
	    	} else {
       			this.tooltip.hide();
       		}
       	}
    },

    inside: function(evt){
		this.tooltip.show();

		$('ps_tooltip_arrow').show();
        x = Event.pointerX(evt);
        y = Event.pointerY(evt) - Element.getDimensions(this.tooltip).height - 6 ;
		scrollX =  document.viewport.getScrollOffsets()[0];
		scrollY =  document.viewport.getScrollOffsets()[1];
		viewportX = document.viewport.getWidth();
		url = "url(/static/redesign09/img/bg_roundTooltipArrow_n.gif)"

		if (this.ele.hasClassName('ps_tooltipBelow')) {
			arrow="s";
			x = this.ele.cumulativeOffset()[0] + 34;
			y = this.ele.cumulativeOffset()[1] + 98;

			arrowX = this.ele.cumulativeOffset()[0] + 28;
			arrowY = this.ele.cumulativeOffset()[1] + 90;
			url = "url(/static/redesign09/img/bg_roundTooltipArrow_s.gif)"
		} else if (this.ele.hasClassName('ps_myStatusHeadPhoto')) {
			arrow="s";
			x = this.ele.cumulativeOffset()[0] + 19;
			y = this.ele.cumulativeOffset()[1] + 54;

			arrowX = this.ele.cumulativeOffset()[0] + 13;
			arrowY = this.ele.cumulativeOffset()[1] + 46;
			url = "url(/static/redesign09/img/bg_roundTooltipArrow_s.gif)"
		} else if (this.ele.hasClassName('ps_tooltipBelowPartnerProfile')) {
			arrow="s";
			x = this.ele.cumulativeOffset()[0] + 64;
			y = this.ele.cumulativeOffset()[1] + 162;

			arrowX = this.ele.cumulativeOffset()[0] + 58;
			arrowY = this.ele.cumulativeOffset()[1] + 154;
			url = "url(/static/redesign09/img/bg_roundTooltipArrow_s.gif)"
		} else if (this.ele.hasClassName('ps_iconFavouriteYes') || this.ele.hasClassName('ps_iconFavouriteNo') ||
					this.ele.hasClassName('ps_iconProfileCompleteYes') || this.ele.hasClassName('ps_iconProfileCompleteNo')) {
			arrow="n";
			x = this.ele.cumulativeOffset()[0] + 25;
			y = this.ele.cumulativeOffset()[1] - 34;

			arrowX = this.ele.cumulativeOffset()[0] + 10;
			arrowY = this.ele.cumulativeOffset()[1] - 5;
		} else if (this.ele.hasClassName('ps_iconProfileChecked')) {
			arrow="n";
			x = this.ele.cumulativeOffset()[0] + 30;
			y = this.ele.cumulativeOffset()[1] - 11;

			arrowX = this.ele.cumulativeOffset()[0] + 19;
			arrowY = this.ele.cumulativeOffset()[1] + 18;
		} else if (this.ele.hasClassName('ps_iconProfileCheckedAndNew')) {
			arrow="n";
			x = this.ele.cumulativeOffset()[0] + 25;
			y = this.ele.cumulativeOffset()[1] - 34;

			arrowX = this.ele.cumulativeOffset()[0] + 20;
			arrowY = this.ele.cumulativeOffset()[1] - 5;
		} else if (this.ele.hasClassName('ps_iconProfileCheckedNarrow')) {
			arrow="n";
			x = this.ele.cumulativeOffset()[0] + 40;
			y = this.ele.cumulativeOffset()[1] - 11;

			arrowX = this.ele.cumulativeOffset()[0] + 29;
			arrowY = this.ele.cumulativeOffset()[1] + 18;
		} else if (this.ele.hasClassName('ps_iconProfileCheckedAndNewNarrow')) {
			arrow="n";
			x = this.ele.cumulativeOffset()[0] + 35;
			y = this.ele.cumulativeOffset()[1] - 34;

			arrowX = this.ele.cumulativeOffset()[0] + 29;
			arrowY = this.ele.cumulativeOffset()[1] - 5;
		} else if (this.ele.hasClassName('ps_ratingTooltipTrigger1')) {
			arrow="n";
			x = this.ele.cumulativeOffset()[0] + 8;
			y = this.ele.cumulativeOffset()[1] - 40;

			arrowX = this.ele.cumulativeOffset()[0] - 3;
			arrowY = this.ele.cumulativeOffset()[1] - 11;
		} else if (this.ele.hasClassName('ps_ratingTooltipTrigger')) {
			arrow="n";
			x = this.ele.cumulativeOffset()[0] + 14;
			y = this.ele.cumulativeOffset()[1] - 40;

			arrowX = this.ele.cumulativeOffset()[0] + 4;
			arrowY = this.ele.cumulativeOffset()[1] - 11;

		/*} else if (this.ele.hasClassName('ps_commentTooltip')) { //doesnt work properly
			arrow="n";
			x = this.ele.cumulativeOffset()[0] + 30;
			y = this.ele.cumulativeOffset()[1] - 63;

			arrowX = this.ele.cumulativeOffset()[0] + 29;
			arrowY = this.ele.cumulativeOffset()[1] - 0;*/
		} else {
			arrow = "n";
			if (y - scrollY - 10 < 0) {
				arrow = "s";
				y = Event.pointerY(evt) + 20;
			}
			if (x + Element.getDimensions(this.tooltip).width > viewportX) {
				x = viewportX - Element.getDimensions(this.tooltip).width + 20;
			}

			if (arrow == "n") {
				arrowX = Event.pointerX(evt) - 5;
				arrowY = Event.pointerY(evt) - 21;
				url = "url(/static/redesign09/img/bg_roundTooltipArrow_n.gif)"
			} else {
				arrowX = Event.pointerX(evt) - 8;
				arrowY = Event.pointerY(evt) + 12;
				url = "url(/static/redesign09/img/bg_roundTooltipArrow_s.gif)"
			}

		}
		if (url != $('ps_tooltip_arrow').style.backgroundImage) {
			$('ps_tooltip_arrow').setStyle( {
				backgroundImage: url
			});
		};

		$('ps_tooltip_arrow').setStyle( {
			top: arrowY+"px",
			left: arrowX+"px"
		});

		widthValue = this.w ? this.w : this.tooltip.getWidth();
        Element.setStyle(this.tooltip, {
			width: widthValue,
            top: (y - 5) + "px",
            left: x + "px"
        });

    },

    outside: function(evt){
        this.tooltip.hide();
		$('ps_tooltip_arrow').hide();
    },

	getWidth: function(elem){
		if (this.isDropdown) return this.ele.getDimensions().width + 20;

		var width;
        if (elem.className) {
            elem.className.split(" ").each(function(v){
                if (v.match(/^ps_w\d+$/)) {
                    width =  v.gsub(/^ps_w(\d+)/, '#{1}');
                }
            })
        }
	    return width;
	}
});

var PS_galleryImgInput = Class.create({
    initialize: function(ele, allInputs){
    	this.allInputs = allInputs;
    	Event.observe(ele, "click", this.click.bindAsEventListener(this));
    },
    click: function(evt) {
    	this.allInputs.each(function(i){
    		var listRowDiv = i.up('div.ps_listViewRow');
    		if (listRowDiv) {
	    		if (evt.element().id == i.id) {
	    			listRowDiv.addClassName("ps_over");
	    		} else {
	    			listRowDiv.removeClassName("ps_over");
	    		}
    		}
    	});
    }
});

var PS_listViewRow = Class.create({
  initialize: function(ele, listViewInput){
    this.ele = $(ele);
    this.rowLinkHref = false;
	this.disabled = false;
    var t = this;

    // read params
    if (this.ele.className) {
      this.ele.className.split(" ").each(function(v){
        if (v.match(/^ps_overOnClass_.+$/)) {
          t.overOnClass = v.replace('ps_overOnClass_', '');
        }
		    if (v === "ps_disabled") {
			    t.disabled=true
		    }
      });
    }
    var thisRow = this;

	  if (! this.disabled) {
	  	var globalLinkElem = this.ele.select('.ps_listViewRowGlobalLink').first();
	  	if (globalLinkElem)
	  			thisRow.rowLinkHref = globalLinkElem.getAttribute('href');

		// FIXME indentation does not match parenthesis
		  if (listViewInput) {
			this.listInput = this.ele.down('input[name="' + listViewInput + '"]');
			if (this.listInput && this.listInput.checked) {
				this.move();
			}
		  }

		  if (this.overOnClass) {
		  	// special case: mouesover for row is only triggered by subelements
			// with a certain class
		  	var overSubElems = this.ele.select('.' + this.overOnClass);
		  	if (overSubElems)
		  		overSubElems.each(function(subElem){
		  			Event.observe(subElem, "PS:mousemover", t.move.bindAsEventListener(t));
		  			Event.observe(subElem, "mousemove", t.move.bindAsEventListener(t));
		  			Event.observe(subElem, "PS:mouseoutr", t.outside.bindAsEventListener(t));
		  			Event.observe(subElem, "mouseout", t.outside.bindAsEventListener(t));
					subElem.fire("PS:mousemover");
					subElem.fire("PS:mouseoutr");
		  		});
		  } else {
		  	Event.observe(this.ele, "PS:mousemover", this.move.bindAsEventListener(this));
		  	Event.observe(this.ele, "mousemove", this.move.bindAsEventListener(this));
		  	Event.observe(this.ele, "PS:mouseoutr", this.outside.bindAsEventListener(this));
		  	Event.observe(this.ele, "mouseout", this.outside.bindAsEventListener(this));
			this.ele.fire("PS:mousemover");
			this.ele.fire("PS:mouseoutr");
		  }

		  if (this.rowLinkHref) {
		  	Event.observe(this.ele, "click", this.click.bindAsEventListener(this));
		  	this.ele.style.cursor = 'pointer';
		  }

		  this.ele.select('.ps_listViewCol').each(function(col){
		    col.className.split(" ").each(function(c){
		      if (c == 'ps_listViewCol_clickable') {
			  	if (col.getElementsBySelector('a').length > 0) {
					col.style.cursor = 'pointer';
					href = col.getElementsBySelector('a').first().href;
					Event.observe(col, "click", thisRow.columnClick.bindAsEventListener(thisRow, href));
				}
		      }
		    });
		  });


		  this.ele.select('.ps_listViewCol_noClick').each(function(col){
			  Event.observe(col, "click", thisRow.stopEventBubbeling.bindAsEventListener(this));
		  });


	  }
  },

  stopEventBubbeling: function(event) {
	  Event.stop(event); //so when clicking on a noClick Row that no other events will be executed
  },

  move: function(){
    this.ele.addClassName("ps_over");
  },

  outside: function(event){
  	if (!this.listInput || !this.listInput.checked) {
	  	var mouseX = Event.pointerX(event);
	  	var mouseY = Event.pointerY(event);
	  	var x = this.ele.cumulativeOffset().left+2;
	  	var y = this.ele.cumulativeOffset().top+2;
	  	var width = this.ele.getDimensions().width-4;
	  	var height = this.ele.getDimensions().height-4;

	  	var stillInside = mouseX > x && mouseX < x+width && mouseY > y && mouseY < y+height;
	  	if (this.overOnClass || !stillInside)
	      this.ele.removeClassName("ps_over");
    }
  },

  click: function(event) {
  	// first check, if the mouse has clicked on a div with noClick='true'
  	var mouseX = Event.pointerX(event);
  	var mouseY = Event.pointerY(event);
  	var noLinkElems = this.ele.select(".ps_listViewCol_noClick");

  	var canClick = true;
  	if (noLinkElems) {
  		var i = 0;
  		while (canClick && i < noLinkElems.length) {
  			var curr = noLinkElems[i];
  			var x = curr.cumulativeOffset().left;
  			var y = curr.cumulativeOffset().top;
  			var width = curr.getDimensions().width;
  			var height = curr.getDimensions().height;
  			canClick = ((mouseX < x) || (mouseX > (x+width))) || ((mouseY < y) || (mouseY > (y+height)));
  			i++;
  		}
  	}
  	// go to global link, if configured and mouse not on a noClick element
  	if (this.rowLinkHref && canClick && !this.disabled)
  		window.location.href = this.rowLinkHref;
  },

  columnClick: function(event, href) {
    window.location.href = href;
  }

});

var PS_invokeNoteEditor = Class.create({
    initialize: function(ele){
    	this.ele            = $(ele);
    	this.loggedInUserId = '';
    	this.matchUserId    = '';
    	this.hasText        = false;
    	this.skin           = '1';
    	var t = this;

    	// read params
      if (this.ele.className) {
        this.ele.className.split(" ").each(function(v){
          if (v.match(/^ps_invoke_noteeditor_from_.+$/)) {
            t.loggedInUserId = v.replace('ps_invoke_noteeditor_from_', '');
          }
          if (v.match(/^ps_invoke_noteeditor_for_.+$/)) {
            t.matchUserId = v.replace('ps_invoke_noteeditor_for_', '');
          }
          if (v.match(/^ps_invoke_noteeditor_skin_.+$/)) {
            t.skin = v.replace('ps_invoke_noteeditor_skin_', '');
          }
        });

        if (this.ele.hasClassName('ps_invoke_noteeditor_with_text')) this.hasText = true;
      }

    	if (this.loggedInUserId !== '' && this.matchUserId !== '') {
      	Event.observe(this.ele, 'click', this.click.bindAsEventListener(this));
    	} else {
    	  PS.debug('warning: could not initialize click handler to invoke note editor, since parameters are missing');
    	}
    },

    click: function(event) {
      if(event) Event.stop(event);
      PS.debug('preparing note editor for user ' + this.matchUserId);
      PS.debug('preparing note editor skin ' + this.skin);
      $('ps_noteEditor_loggedInUserId').value = this.loggedInUserId;
      $('ps_noteEditor_matchUserId').value = this.matchUserId;
      if (this.hasText) {
        PS.debug('copying content: ' + $('ps_note_text_for_' + this.matchUserId).innerHTML);
        $('ps_field_note').value = ($('ps_note_text_for_' + this.matchUserId).innerHTML).unescapeHTML().stripTags();
      } else {
        $('ps_field_note').value = '';
      }
      Modalbox.show($('ps_modal_noteEditor'), {skin : this.skin, width: 450, overlayDuration: 0, slideDownDuration: 0, slideUpDuration: 0, resizeDuration: 0});
    }
});

var PS_makeWritableNote = Class.create({
	initialize: function(elem){
		this.elem = elem;
		this.elem.observe('click', this.write.bind(this));
		if($('ps_field_note').value == $('ps_field_note_label').innerHTML) {
			$('ps_field_note').setStyle({
				  color: '#999'
			});
		}
	},

	write: function() {
		$$('.ps_openNotebox')[0].addClassName('ps_inv');
		$('ps_field_note').readOnly=false;
		$('ps_field_note').removeClassName('ps_isReadonly');
		if($('ps_field_note').value == $('ps_field_note_label').innerHTML) {
			$('ps_field_note').value = "";
		}
		$('ps_field_note').focus();
		$('ps_field_note').setStyle({
			  color: '#000'
		});
	}
});

/* if unsaved message on page give a warning */

var PS_beforeUnloadAction = Class.create({
	initialize: function(elem) {
		that = this;
		this.unloadCheck = false;
		$('ps_writeMessage').observe('change', function() {
			that.unloadCheck = true; //something changed in textarea
		});
		$('ps_writeMessage').observe('keyup', function() {
			that.unloadCheck = true; //something changed in textarea
		});

		$('subject').observe('change', function() {
			that.unloadCheck = true; //something changed in subject text input
		});
		$('subject').observe('keyup', function() {
			that.unloadCheck = true; //something changed in subject text input
		});

		$$('.ps_write_msg .ps_tabContent form')[0].observe('submit', function() {
			that.unloadCheck = false;
		});
		// Doesn't works in all Browser (eg. Chrome) Event.observe(window, "beforeunload", function(event) {..}
		if(Prototype.Browser.IE) {
			window.onbeforeunload = this.checkBeforeUnload;
		}
		else {
			onbeforeunload = this.checkBeforeUnload;
		}

	},

	checkBeforeUnload: function() {
		if (that.unloadCheck && (($('ps_writeMessage').value.length > 0) || ($('subject').value.length > 0))) {
			return writemessageVars.beforeUnloadMessage;
		}
	}
});


var PS_resetNoteForm = Class.create({
	initialize: function(elem){
		this.elem = elem;
		this.elem.observe('click', this.cancel.bind(this));
	},

	cancel: function() {
		$$('.ps_openNotebox')[0].removeClassName('ps_inv');
		$('ps_field_note').readOnly = true;
		$('ps_field_note').addClassName('ps_isReadonly');
		$('ps_field_note').value = $('ps_noteTextKeeper').value;
		if($('ps_field_note').value == $('ps_field_note_label').innerHTML) {
			$('ps_field_note').setStyle({
				  color: '#999'
			});
		}
	}
});

var PS_sorting = Class.create({
	initialize: function(elem){
		elem.observe('change', this.doSorting.bind(this, elem));
	},

	doSorting: function(elem, ev) {
		formUrl = elem.up('form').action;
		if(elem.options[elem.selectedIndex].value != "") {
			submitUrl = formUrl + elem.options[elem.selectedIndex].value;
		} else {
			submitUrl = $('baseMemberUrl').value;
		}
		document.location.href = submitUrl;
	}


});

var PS_genButHover = Class.create({
	initialize: function(elem){
		this.elem = elem;
		hoverClass = "";
		elem.className.split(" ").each(function(v){
            if (v.match(/^ps_genButSkin.+$/)) {
               hoverClass = v;
            }
        });
		this.elem.observe('mouseover', this.over.bind(this, hoverClass));
		this.elem.observe('mouseout', this.out.bind(this, hoverClass));
	},

	over: function(ev, hoverClass) {
		this.elem.addClassName(ev + '_over')
	},

	out: function(ev, hoverClass) {
		this.elem.removeClassName(ev + '_over')
	}

});

var PS_genConvHover = Class.create({
	initialize: function(elem){
		this.elem = elem;
		hoverClass = "";
		elem.className.split(" ").each(function(v){
            if (v.match(/^ps_genConvSkin.+$/)) {
               hoverClass = v;
            }
        });
		this.elem.observe('mouseover', this.over.bind(this, hoverClass));
		this.elem.observe('mouseout', this.out.bind(this, hoverClass));

		if (this.elem.down('a') != null) {
			href = this.elem.down('a').href;
			if (href) {
				this.elem.observe('click', this.click.bind(this, href));
			}
		}

	},

	over: function(hoverClass) {
		this.elem.addClassName(hoverClass + '_over')
	},

	out: function(hoverClass) {
		this.elem.removeClassName(hoverClass + '_over')
	},

	click: function(href) {
	  document.location.href = href;
	}

});

var PS_oldMottoSave = Class.create({
	initialize: function(ele){
		checkStatusValue = this.checkStatusValue;
		blurField = this.blurField;

		$('ps_mottoId').observe('focus', this.focusField.bind());
		$('ps_mottoId').observe('blur', this.blurField.bind());

		Event.observe(ele, "click", function() {
			if($('ps_mottoId_label').innerHTML.gsub(/\s*:\s*$/,"") == $('ps_mottoId').value) {
				$('ps_mottoId').value = '';
			}
			url = ele.up("form").action;
			parameters = ele.up( "form" ).serialize( true );
			var tmp = '';
			if (url.indexOf('?') != -1){
				tmp = 	url + '&rand=' + new Date().getTime();
			}else{
				tmp = 	url + '?rand=' + new Date().getTime();
			}

			new Ajax.Request( tmp, {//FIXME mixing post and get request parameters (used for overriding browser caching?)
					method : 'post',
					onSuccess : function( transport ) {
						checkStatusValue(transport.responseText.evalJSON().userMottoStatus);
					},
					parameters : parameters } );
		});
	},

	checkStatusValue: function(userMottoStatus) {
		$$('.ps_mottoTexts').each(function(ele) {
			ele.setStyle({
			  display: 'none'
			})
		});

		if(userMottoStatus == "2") {
			$('ps_motto_empty').setStyle({
			  display: 'block'
			})
			blurField();
 		}
		if(userMottoStatus == "0") {
			$('ps_motto_waitApprove').setStyle({
			  display: 'block'
			})
 		}
		if(userMottoStatus == "1") {
			$('ps_motto_approved').setStyle({
			  display: 'block'
			})
 		}
		if(userMottoStatus == "-1") {
			$('ps_motto_rejected').setStyle({
			  display: 'block'
			})
 		}
		new PS_updateProfileCompletion();
	},

	focusField: function() {
		if($('ps_mottoId_label').innerHTML.gsub(/\s*:\s*$/,"") == $('ps_mottoId').value) {
			$('ps_mottoId').value = '';
			$('ps_mottoId').removeClassName('ps_defaultValueClass');
		}
	},

	blurField: function() {
		if($('ps_mottoId').value == "") {
			$('ps_mottoId').value = $('ps_mottoId_label').innerHTML.gsub(/\s*:\s*$/,"");
			$('ps_mottoId').addClassName('ps_defaultValueClass');
		}
	}

});

/* New Motto Function remove old one as soon as all apperances of fullwidth Mottobox are removed */
var PS_mottoSave = Class.create({
	initialize: function(ele){
		checkStatusValue = this.checkStatusValue;
		myHideEditField = this.hideEditField;

		$$('.ps_mottoChange')[0].observe('click', this.showEditField.bind());
		$$('.ps_mottoChangeClickArea')[0].observe('click', this.showEditField.bind());
		$$('.ps_resetMottoForm')[0].observe('click', this.resetMottoForm.bind());

		Event.observe(ele, "click", function() {
			url = ele.up("form").action;
			parameters = ele.up( "form" ).serialize( true );
			var tmp = '';
			if (url.indexOf('?') != -1){
				tmp = 	url + '&rand=' + new Date().getTime();
			}else{
				tmp = 	url + '?rand=' + new Date().getTime();
			}

			new Ajax.Request( tmp, {//FIXME mixing post and get request parameters (used for overriding browser caching?)
					method : 'post',
					onSuccess : function( transport ) {
						checkStatusValue(transport.responseText.evalJSON().userMottoStatus);
					},
					parameters : parameters } );
		});
	},

	checkStatusValue: function(userMottoStatus) {
		$$('.ps_mottoTexts').each(function(ele) {
			ele.setStyle({
			  display: 'none'
			});
		});

		if(userMottoStatus == "0") {
			$('ps_motto_waitApprove').setStyle({
			  display: 'block'
			});
			$('ps_displayMottoText').innerHTML = $('ps_mottoTextarea').value;
 		}
		if(userMottoStatus == "-1") {
			$('ps_motto_rejected').setStyle({
			  display: 'block'
			});
 		}
		if(userMottoStatus == "2") {
			$('ps_displayMottoText').innerHTML = $('ps_defaultTextKeeper').innerHTML;
 		}
		myHideEditField();
		new PS_updateProfileCompletion();
	},

	showEditField: function() {
		$('ps_displayMotto').addClassName('ps_inv');
		$('ps_editMotto').removeClassName('ps_inv');
	},
	hideEditField: function() {
		$('ps_displayMotto').removeClassName('ps_inv');
		$('ps_editMotto').addClassName('ps_inv');
	},

	resetMottoForm: function() {
		$('ps_editMottoForm').reset();
		myHideEditField();
	}

});


/**
 * Function for ImageRelease Box
 */
var PS_releaseForm = Class.create({
	initialize: function(ele){
		if($('imageReleaseFragment_default') != null) { //true if image uploaded
			myShowFreetextbox = this.showFreetextbox;
			$$('#imageReleaseFragment_unwrapped input').each(function(elem) {
				elem.observe('click', myShowFreetextbox.bind(this));
			})
			if($$('#imageReleaseFragment_default .ps_toggleHandle')[0] != null) {
				$$('#imageReleaseFragment_default .ps_toggleHandle')[0].observe('click', this.showFreetextbox.bind(this));
				$('ps_image_release_close_button').observe('click', this.resetForm.bindAsEventListener());
			}
			$('ps_image_release_close_button').observe('click', this.resetForm.bindAsEventListener());
		}
	},

	showFreetextbox: function() {
		if($('ps_field_state_img_release0').checked == true) {
			if($('ps_additionalText')) $('ps_additionalText').removeClassName("ps_inv");
		} else {
			if($('ps_additionalText')) $('ps_additionalText').addClassName("ps_inv");
		}
	},

	resetForm: function() {
		$$('.ps_releaseForm')[0].reset();
	}
})


var PS_searchFilters = Class.create({
	initialize: function(ele){
		that = this;
		$$('.ps_searchFilters select').each(function(elem) {
			elem.observe('change', that.selectFilter.bind(this, elem));
		})
		$('ps_deactivateFilter').observe('click', that.resetFilter.bind(this, 2));
		$('ps_startFiltering').observe('click', that.startFilter.bind(this, 2));

	},

	selectFilter: function(elem) {
		var atLeastOneFilterSelected = false;
		var url = $('filterHitsCountUrl').value;
		var parameters = $('ps_searchFilterForm').serialize();
		$$('.ps_searchFilters select').each(function(elem) {
			if(elem.options.selectedIndex > 0) {
				atLeastOneFilterSelected = true;
			}

		})
		if(atLeastOneFilterSelected == false) {
			that.resetFilter(elem);
		} else {
			new Ajax.Request( url, {
				method : 'post',
				onSuccess : function( transport ) {
					myJson = transport.responseText.evalJSON();
					if (Object.isUndefined(myJson.errorOn) || Object.keys(myJson.errorOn).length == 0) { //noError
						that.fillFilteredNumber(myJson.hitsForAll);
						$$('.ps_resetFilter')[0].removeClassName('ps_inv');
						$('ps_startFiltering').removeClassName('ps_buttonDisabled');
					} else {
						$$('.ps_resetFilter')[0].addClassName('ps_inv');
						$('ps_startFiltering').addClassName('ps_buttonDisabled');
						$('ps_filterError').removeClassName('ps_inv');
					}

				},
				parameters : parameters } );
		}

	},

	fillFilteredNumber: function(filteredNumber) {
		$('ps_filteredNumber').innerHTML = filteredNumber;
	},

	startFilter: function(elem) {
		if($('noFilterRightUrl') != null) {
			url = $('noFilterRightUrl').value;
		} else {
			url = $('ps_searchFilterForm').action + "?action=applyAndFilter";
		}

		window.location.href = url;
		return false;
	},
	resetFilter: function(elem) {
		/*$$('.ps_searchFilters select').each(function(elem) {
			elem.options[0].selected = true;
		})*/
		//$$('.ps_resetFilter')[0].addClassName('ps_inv');
		//$('ps_startFiltering').addClassName('ps_buttonDisabled');
		url = $('ps_searchFilterForm').action + "?action=removeFilter";
		window.location.href = url;
		return false;
	}
})



/*
 * Switching BlurredImagePreview on ProfilePage when clicked
 */
var PS_editUploadedImages = Class.create({
	initialize: function(ele){
		changeBlurredImage = this.changeBlurredImage;
		$$('#aboutme_pics_self input[type=radio]').each(function(elem) {
			elem.observe('click', changeBlurredImage.bind(this, elem));
		})
	},

	changeBlurredImage: function(elem) {
		clickedImage = elem.up('.ps_listViewCol').down('.ps_photo_profile').getStyle('background-image');
		var re = new RegExp("forceBlurred=false");
		newUrl = clickedImage.replace(re, "forceBlurred=true");
		$('ps_blurredPhoto').setStyle({backgroundImage: newUrl});

		/*clickedImgId = elem.id.substr(20, elem.id.length);
		curBlurredImage = $('ps_blurredPhoto').style.backgroundImage;
		curBlurredImageNo = curBlurredImage.toQueryParams().imageNumber;
		var re = new RegExp("imageNumber=" + curBlurredImageNo);
		newUrl = curBlurredImage.replace(re, "imageNumber=" + clickedImgId);
		$('ps_blurredPhoto').setStyle({backgroundImage: newUrl});
		*/
	}

});

var PS_updateProfileCompletion = Class.create({
	initialize: function(url){
		if ($$('.ps_profile_edit_page')[0] && $$('.ps_statusBar')[0]) {
			if ($F('profileUpdateUrl')) {
				url = $F('profileUpdateUrl');
				new Ajax.Request(url, {
					method: 'get',
					onSuccess: function(response){
						var myJson = response.responseText.evalJSON();
						if (Object.isUndefined(myJson.$errors) || Object.keys(myJson.$errors).length == 0) {
							if (myJson.profileCompletionValue) {
								if ($('ps_completionValueText')) {
									$('ps_completionValueText').update(myJson.profileCompletionValue + "%")
								}
								if ($('ps_completionValueBar')) {
									$('ps_completionValueBar').className = "ps_percentRemover upTo" + myJson.profileCompletionValue;
								}
							}
						}

					}
				})
			}
		}
	}
});

var PS_tailoredMessage = Class.create({
  initialize: function(ele){
    this.ele = $(ele);
    if (this.ele.getElementsBySelector('a').length > 0) {
		  this.ele.style.cursor = 'pointer';
		  this.linkTarget = this.ele.getElementsBySelector('a').first().href;
		  Event.observe(this.ele, "click", this.messageClick.bindAsEventListener(this));
    }
    PS.debug("target of tailored message: " + this.linkTarget);
  },

  messageClick: function(event) {
    window.location.href = this.linkTarget;
  }
});

var PS_mouseOverImage = Class.create({
    initialize: function(ele){
        this.ele = $(ele);
        this.changer = new PS_imageActivating();
        Event.observe(this.ele, "mouseover", this.inside.bindAsEventListener(this));
        Event.observe(this.ele, "mouseout", this.outside.bindAsEventListener(this));
    },

    inside: function(){
    	this.changer.setActive(this.ele);
    },
    outside: function(){
    	this.changer.setInactive(this.ele);
    }
});

var PS_passwordDynamic = Class.create({
    initialize: function(ele){
    	this.ele = $(ele);
    	this.percStep = 25;
    	Event.observe(this.ele, "focus", this.keyUp.bindAsEventListener(this));
        Event.observe(this.ele, "keyup", this.keyUp.bindAsEventListener(this));
    },

    keyUp: function(){
    	// show all
    	$$('.ps_formPasswordDynamicShow').each(function(ele){
                ele.show();
                // if (!ele.visible()) new Effect.BlindDown(ele);
            });
        var perc = this.getPasswordStrength();
        for (var i = 0; i <= 100; i += this.percStep) {
        	if (i == perc) {
    			$('ps_passwordStrength'+i).show();
    		} else {
    			$('ps_passwordStrength'+i).hide();
    		}
    	}
    	var newPerc = 100 - perc;
        $('ps_passWordGradient').style.width = newPerc+'%';
    },
    getPasswordStrength: function() {
    	var pass = this.ele.value;
    	if (!pass || pass.length < 4) {
    		return this.percStep;
    	} else {
    		var numCharGroups = this.calcNumOfCharGroups(pass);
	    	if (pass.length < 7 || numCharGroups == 1 ) {
	    		return this.percStep*2;
	    	} else if (pass.length >= 7 && numCharGroups == 2) {
	    		return this.percStep*3;
	    	} else if (pass.length >= 7 && numCharGroups > 2) {
	    		return this.percStep*4;
	    	}
    	}
    	return 0;
    },
    calcNumOfCharGroups: function(word) {
    	var res = 0;
    	if (word) {
    		var gNumbers = false;
    		var gCapitals = false;
    		var gLowerCase = false;
    		var gOther = false;

    		if (word) {
	    		for (var i = 0; i < word.length; i++) {
	    		 	var code = word.charCodeAt(i);
	    		 	/* numbers */
	    			if (code >= 48 && code <= 57) {
	    				gNumbers = true;
	    		 	/* capital letters */
	    			} else if (code >= 65 && code <= 90) {
	    				gCapitals = true;
	    		 	/* lower case letters */
	    			} else if (code >= 97 && code <= 122) {
	    				gLowerCase = true;
	    		 	/* all other characters */
	    			} else {
	    				gOther = true;
	    			}
	    		}
    		}

    		if (gNumbers) res++;
    		if (gCapitals) res++;
    		if (gLowerCase) res++;
    		if (gOther) res++;
    	}
    	return res;
    }

});

var PS_areaSwitch = Class.create({
    initialize: function(ele){
        this.ele = $(ele);

        // read params
        if (this.ele.className) {
        	// c will be this inside function
        	var c = this;
            this.ele.className.split(" ").each(function(v){
                if (v.match(/^ps_areaSwitchGroup_.+$/)) {
                    c.switchGroup = v.replace('ps_areaSwitchGroup_', '');
                }
                if (v.match(/^ps_areaSwitchTarget_.+$/)) {
                    c.switchTarget = v.replace('ps_areaSwitchTarget_', '');
                }
            });
        }

        // mandatory param for the area switch to work! (missing target is
		// acceptable, cause that switch will then disable all in group)
        if (!this.switchGroup) return;

		Event.observe(this.ele, "click", this.click.bindAsEventListener(this));
    },
    click: function() {
    	var els = $$('.'+this.switchGroup);
    	var showEle = false;
    	for (var i = 0; i < els.length; i++) {
    		if (els[i].id == this.switchTarget)
    			showEle = els[i];
    		else
    			els[i].hide();
    	}
    	// show new area after all others are hidden, to prevent flickering
    	if (showEle) {
    		showEle.show();
    		var focusEls = showEle.select('.ps_focusElementOnSwitch');
    		if (focusEls) {
    		    focusEls.each(function(focusEl){
    		        try {
    		            focusEl.focus();
    		        } catch (err) {
    		            // do nothing
    		        }
    		    });
    		}
    	}
    }
});

var PS_hideEditMode = Class.create({
    initialize: function(ele){
        this.ele = $(ele);
		Event.observe(this.ele, "click", this.click.bindAsEventListener(this));
    },
    click: function(evt) {
    	evt.stop();
    	var elem = $$('.ps_editIcon');
        if (elem) {
       		elem.each(function(ele) {
       			ele.toggle();
       		});
 		}
        elem = $$('.ps_showEditMode');
        if (elem) {
       		elem.each(function(ele) {
       			ele.show();
       		});
 		}
        elem = $$('.ps_hideEditMode');
        if (elem) {
       		elem.each(function(ele) {
       			ele.hide();
       		});
 		}
        elem = $$('.ps_toggleWithModeToggle');
        if (elem) {
       		elem.each(function(ele) {
       			ele.hide();
       		});
 		}
 		var editBoxs = $$('.ps_profileEditInputBox');
 		if (editBoxs) {
 			editBoxs.each(function(e) {
 				if (e.getStyle('display') == 'block') {
 					e.hide();
 					var inactiveBoxId = e.id.replace(/_active/, '_inactive');
 					if ($(inactiveBoxId)) { $(inactiveBoxId).show(); }
 					var editIconId = e.id.replace(/_active/, '');
 					if ($(editIconId)) $(editIconId).hide();
 				}
 			});
 		}
 		elem = $$('.ps_openEditMode');
        if (elem) {
       		elem.each(function(ele) {
       			var listenerFunc = PS.prop.editListenerCache[ele.id];
       			if (listenerFunc) {
       				Event.stopObserving(ele, 'click', listenerFunc);
       				ele.setStyle({ cursor: 'default'});
       			}
       		});
 		}
    }
});


var PS_showEditMode = Class.create({
    initialize: function(ele, onload){
    	this.ele = $(ele);
    	this.onLoad = onload;
    	if (!onload) {
			Event.observe(this.ele, "click", this.click.bindAsEventListener(this));
		} else {
			Event.observe(ele, 'ps:showEditMode', this.click.bindAsEventListener(this));
			ele.fire('ps:showEditMode');
		}
    },
    click: function(evt) {
    	evt.stop();
    	// if (!this.onLoad) PS_scrollTo(this.ele, 50);

    	var methodMap = {
    	    ps_editIcon: function(ele) {
       			ele.toggle();
       		},

       		ps_showEditMode: function(ele) {
       			ele.hide();
       		},

       		ps_hideEditMode: function(ele) {
       			ele.show();
       		},

       		ps_toggleWithModeToggle: function(ele) {
       			ele.show();
       		},

       		ps_openEditMode: function(ele) {
       			var listenerFunc = PS.prop.editListenerCache[ele.id];
       			if (listenerFunc) {
       				Event.observe(ele, 'click', listenerFunc);
       				ele.setStyle({ cursor: 'pointer'});
       			}
       		}
 		};

    	applyClassHandlers(methodMap);
    }
});

var PS_showEditBoxHandler = Class.create({
    initialize: function() { },
    handle: function(e, scroll) {
    	var className = null;
    	var cn = e.className.split(' ');
    	var i = 0;
    	var prefix = 'ps_openEditModeTarget_';
    	while (className == null && i < cn.length) {
    		if (cn[i].startsWith(prefix)) {
    			className = cn[i].substring(prefix.length, cn[i].length);
    		}
    		i++;
    	}

    	if (className != null) {
    		className = className.strip();

    		// hide icon
	       	if($(className)) $(className).hide();
	       	var elems = $$('.'+className);
	        if (elems) {
	       		elems.each(function(ele) {
	       			if (ele.id.endsWith('_active')) {
	       				ele.show();
	       				// scroll to element, if it lies out of viewport
	       				// if (scroll &&
						// ((ele.viewportOffset().top+ele.getHeight()) >
						// document.viewport.getHeight()))
	       				// PS_scrollTo(ele, 10, true); // scroll so that it's
						// aligned at the lower border
	       				/*
						 * new Effect.BlindDown(ele, {afterFinish: function() {
						 * if (scroll &&
						 * ((ele.viewportOffset().top+ele.getHeight()) >
						 * document.viewport.getHeight())) { PS_scrollTo(ele,
						 * 10, true); } }});
						 */
	       			} else {
	       				ele.hide();
	       				// new Effect.BlindUp(ele);
	       			}
	       		});
	 		}
       	}
    }
});

var PS_showEditBox = Class.create({
    initialize: function(ele){
    	this.ele = ele;
    	this.boxHandler = new PS_showEditBoxHandler();
    	if (ele.id) {
	    	PS.prop.editListenerCache[ele.id] = this.click.bindAsEventListener(this);
			Event.observe(ele, "click", PS.prop.editListenerCache[ele.id]);
			Event.observe(ele, "ps:click", PS.prop.editListenerCache[ele.id]);
		}
    },
    click: function(evt) {
    	this.boxHandler.handle(this.ele, true);
    }
});

var PS_hideEditBox = Class.create({
    initialize: function(ele){
        this.ele = $(ele);
		this.idPrefix = null;
    	var cn = this.ele.className.split(' ');
    	var i = 0;
    	var prefix = 'ps_hideEditBoxTarget_';
    	while (this.idPrefix == null && i < cn.length) {
    		if (cn[i].startsWith(prefix)) {
    			this.idPrefix = cn[i].substring(prefix.length, cn[i].length);
    		}
    		i++;
    	}
    	if (this.idPrefix != null) {
			Event.observe(this.ele, "click", this.click.bindAsEventListener(this));
			Event.observe(this.ele, "ps:click", this.click.bindAsEventListener(this));
			Event.observe(this.ele, "ps:hide", this.click.bindAsEventListener(this, true)); //Just close everything, BUT do not reset Form (Mantis#63424)
		}
    },
    click: function(evt, justHide) {
    	evt.stop();
    	var className = this.idPrefix;
    	var elems = $$('.'+className);
        if (elems) {
       		elems.each(function(ele) {
       			if (ele.id.endsWith('_active')) {
       				ele.hide();
       				// new Effect.BlindUp(ele);
       			} else {
       				ele.show();
       				// new Effect.BlindDown(ele);
       			}
       		});
 		}
 		// show icon
       	$(className).show();
		if (!justHide) {
			if ($(className).up('form')) $(className).up('form').reset();
		}
    }
});

var PS_productBox = Class.create({
    initialize: function(ele){
      this.ele = $(ele);
      this.boxClasses = ['ps_productBox', 'ps_selectedProduct', 'ps_productBoxHorizontal', 'ps_productBoxHorizontalWithSeal'];
      this.boxClasses.each(function(c) {
        if (this.ele.hasClassName(c))
          this.boxType = c;
      }, this);
		  Event.observe(this.ele, "click", this.click.bindAsEventListener(this));
		  Event.observe(this.ele, "mouseover", this.inside.bindAsEventListener(this));
		  Event.observe(this.ele, "mouseout", this.outside.bindAsEventListener(this));
		  if (this.ele.down('input')) {
		  	new Field.Observer(this.ele.down('input'), 0.05, this.checkradios.bind(this))
		  }
		  this.checkForMonthly();
    },
    click: function() {
		var id = this.ele.id;
		if ($(id+'_input')) {
			$(id+'_input').click();
		}

    },
	inside: function(evt) {
		try {
			e = evt.element().up("." + this.boxType) || evt.element();
			e.addClassName(e.id + "_on");
			e.addClassName(this.boxType + "_on");
		} catch(e) {}
	},
	outside: function(evt) {
		try {
			e = evt.element().up("." + this.boxType) || evt.element();
			if (!$F(e.down('input'))) {
				e.removeClassName(e.id + "_on");
				e.removeClassName(this.boxType + "_on");
			}
		} catch(e) {}
	},
	checkradios: function(el,v) {
		e = el.up("." + this.boxType);
		if (! $F(e.down('input'))) {
			e.removeClassName(e.id + "_on");
			e.removeClassName(this.boxType + "_on");
		}
		this.checkForMonthly();
	},

	checkForMonthly: function() {
		if($('ps_productBox4') != null && $('ps_monthly_Payment') != null) {
			theCheckbox = $$('#ps_productBox4 input[type=radio]')[0];
			if(theCheckbox.checked) {
				$('ps_monthly_Payment').addClassName("ps_inv");
				$('ps_field_mon_payment').disabled = true;
				$('ps_toggleArea_ps_monthly_Payment').hide();
			} else {
				$('ps_monthly_Payment').removeClassName("ps_inv");
				$('ps_field_mon_payment').disabled = false;
			}
		}
	}
});

var PS_toggle = Class.create({
    initialize: function(ele){
		  me = this;
      this.ele = $(ele);
		  if (!this.ele.id) this.ele.identify();
		  this.smooth = this.ele.hasClassName('ps_toggleSmooth');
		  var c = this;

		  var elem = $$('#' + this.ele.id + ' .ps_toggleHandle');
		  if (elem) {
        elem.each(function(ele) {
		  		Event.observe(ele, "click", me.toggle.bindAsEventListener(c));
		  	});
		  }

		  elem = $$('#' + this.ele.id + ' .ps_toggleHandle_alt');
		  if (elem) {
        elem.each(function(ele) {
		  		Event.observe(ele, "click", me.toggle.bindAsEventListener(c));
		  	});
		  }

		  elem = $$('#' + this.ele.id + ' .ps_toggleHandleIcon');
		  if (elem) {
        elem.each(function(ele) {
        	var visible = c.getToggleAreaVisibility(ele);
        	PS.debug(ele);
		  		ele.setStyle({
		  			backgroundImage: "url(/static/redesign09/img/bg_toggleHandle_"+visible+ ".gif)"
		  		});
		  		Event.observe(ele, "click", me.toggle.bindAsEventListener(c));
		  	});
		  }
    },

    toggle: function(evt) {
		  evt.stop();
		  var t = this;
		  var toggleParentElem = evt.element().up('.ps_toggle');

		  toggleAreas = toggleParentElem.select('.ps_toggleArea');
		  if (toggleAreas.length == 0) {
		  	toggleAreas = new Array();
		  	toggleAreas.push($('ps_toggleArea_'+toggleParentElem.id));
		  }
		  if (toggleAreas && toggleAreas.length > 0) toggleAreas.each(function(ele){
		  	// if (t.smooth) {
		  	if (false) {
		  		if (ele.visible()) new Effect.BlindUp(ele);
		  		else new Effect.BlindDown(ele);
		  	} else {
		  		ele.toggle();
		  	}
		  });

		  var toggleHandles = toggleParentElem.select('.ps_toggleHandle');
		  var toggleHandlesAlt = toggleParentElem.select('.ps_toggleHandle_alt');
		  if (toggleHandles.length > 0 && toggleHandlesAlt.length > 0) {
		  	toggleHandles.each(function(ele){ ele.toggle(); });
		  	toggleHandlesAlt.each(function(ele){ ele.toggle(); });
		  }
		  var toggleHandleIcons = toggleParentElem.select('.ps_toggleHandleIcon');
		  if (toggleHandleIcons.length > 0) {
		  	var c = this;
		  	toggleHandleIcons.each(function(ele){
		  		var visible = c.getToggleAreaVisibility(ele);
		  		ele.setStyle({backgroundImage: "url(/static/redesign09/img/bg_toggleHandle_"+visible+ ".gif)"});
		  	});
		  }
    },

    getToggleAreaVisibility: function(ele) {
		var toggleArea = null;
		var toggleAreaIn = ele.up('.ps_toggle').down('.ps_toggleArea');
		var visible = "off";
		if (toggleAreaIn) {
			toggleArea = toggleAreaIn;
		} else {
			var toggleAreaOut = $('ps_toggleArea_'+ele.up('.ps_toggle').id);
			if (toggleAreaOut) {
				toggleArea = toggleAreaOut;
			}
		}
		if (toggleArea) {
			visible = toggleArea.visible()?"off":"on";
		}
		return visible;
    }
});




// -------- extension to the UI.window object to add constraints to dragging
// ---------
Position.getWindowSize = function(w) {
	var width, height;
	w = w ? w : window;
	width = w.innerWidth || (w.document.documentElement.clientWidth || w.document.body.clientWidth);
	height = w.innerHeight || (w.document.documentElement.clientHeight || w.document.body.clientHeight);

	return { width: width, height: height };
}

var PS_imgLabelClickable = Class.create({
    initialize: function(labels){
    	if (navigator.appName == 'Microsoft Internet Explorer') {
	    	var c = this;
	        labels.each(function(l){
	        	var imgElem = l.select('img');
	        	if (imgElem) {
	        		imgElem.each(function(i){
	        			Event.observe(i, "click", c.click.bindAsEventListener(i));
	        		});
	        	}
	        });
        }
    },
    click: function() {
    	var ancestors = this.ancestors();
    	var found = false;
    	var i = 0;
    	while (!found && i < ancestors.length) {
    		if (ancestors[i].nodeName == 'LABEL') {
    			var id = ancestors[i].getAttributeNode("for").value;
    			if ($(id)) {
    				$(id).click();
    			}
    			found = true;
    		}
    		i++;
    	}
    }
});

var PS_growingTextarea = Class.create({
 	initialize: function(ele){
 		this.ele = ele;
 		this.rowHeight = 18;
 		this.minHeight = 110;  // default

 		var t = this;
 		if (this.ele.className) {
            this.ele.className.split(" ").each(function(v){
                if (v.match(/^ps_growingMinHeight_.+$/)) {
                    t.minHeight = v.replace('ps_growingMinHeight_', '');
                }
            });
        }

 		Event.observe(this.ele, "keyup", this.keyup.bindAsEventListener(this));
       	Event.observe(this.ele, "ps:PS_growingTextarea_init", this.keyup.bindAsEventListener(this));
        this.ele.fire("ps:PS_growingTextarea_init");
 	},
 	keyup: function() {
	 	var word = this.ele.value;
 		if (word) {
 			var rows = word.split("\n");
 			if (rows) {
 				var numRows = rows.length;
 				var height = numRows * this.rowHeight;
 				height = height < this.minHeight ? this.minHeight : height;
				this.ele.style.height = height + "px";
 			}
 		}
 	}
});

var PS_lightenMouseover = Class.create({
 	initialize: function(ele){
 		this.perc = 0.75;
 		var c = this;
 		var prefix = 'ps_lightenMouseover';
 		ele.classNames().each(function(cn) {
 			if (cn.startsWith(prefix)) {
 				var num = cn.substring(prefix.length, cn.length);
 				if (num) {
 					var n = parseInt(num);
 					if (!isNaN(n)) {
 						c.perc = n/100;
 					}
 				}
 			}
 		});
 		Event.observe(ele, "mouseover", this.inside.bindAsEventListener(this));
 		Event.observe(ele, "mouseout", this.outside.bindAsEventListener(this));
 	},
    inside: function(evt){
        new Effect.Opacity(evt.element(), {
			from: 1.0,
            to: this.perc,
			duration: 0.1
        })
    },
    outside: function(evt){
        new Effect.Opacity(evt.element(), {
			from: this.perc,
            to: 1.0,
			duration: 0.1
        })
    }
});

var PS_toggleGeoBox = Class.create({
 	initialize: function(ele, hide){
 		var prefix = 'ps_geoBoxId';
 		var c = this;
 		ele.classNames().each(function(cn) {
 			if (cn.startsWith(prefix)) {
 				c.boxId = cn.substring(prefix.length, cn.length);
 			}
 		});
 		if (this.boxId) {
 			if (hide) {
 				Element.observe(ele, 'click', this.hide.bindAsEventListener(this));
 			} else {
 				Element.observe(ele, 'click', this.show.bindAsEventListener(this));
 			}
 		}
 	},
 	hide: function(ev) {
 		if ($('ps_showEditBox'+this.boxId)) {
 			$('ps_showEditBox'+this.boxId).hide();
 		}
 		if ($('ps_showEditBox'+this.boxId+'_inactive')) {
 			$('ps_showEditBox'+this.boxId+'_inactive').hide();
 		}
 	},
 	show: function(ev) {
 		if ($('ps_showEditBox'+this.boxId)) {
 			$('ps_showEditBox'+this.boxId).show();
 		}
 		if ($('ps_showEditBox'+this.boxId+'_inactive')) {
 			$('ps_showEditBox'+this.boxId+'_inactive').show();
 		}
 	}
});

var PS_triggerEditBox= Class.create({
 	initialize: function(ele, allInputs){
 		this.grayHandler = new PS_grayGeoBoxHandler();
 		if (ele.checked) {
 			PS.prop.geoInputState = ele.id;
 		}
 		this.inputs = allInputs;
 		var prefix = 'ps_triggerTarget_';
 		var c = this;
 		ele.classNames().each(function(cn) {
 			if (cn.startsWith(prefix)) {
 				c.iconId = cn.substring(prefix.length, cn.length);
 			}
 		});
 		if (this.iconId) {
	 		Element.observe(ele, 'click', this.click.bindAsEventListener(this));
	 	}
 	},
 	click: function(ev) {
 		this.boxHandler = new PS_showEditBoxHandler();
    	this.boxHandler.handle($(this.iconId), false);
    	if ($(PS.prop.geoInputState)) {
    		$(PS.prop.geoInputState).checked = true;
    		// this.grayHandler.handle(this.inputs, $(PS.prop.geoInputState));
    		ev.stop();
    	}
 	}
});

PS_grayGeoBoxHandler = Class.create({
 	initialize: function(){},
 	handle: function(inputs, geoInput) {
 		inputs.each(function(i) {
 			var prefix = 'ps_targetID_';
	 		var grayBox = null;
	 		i.classNames().each(function(cn) {
	 			if (cn.startsWith(prefix)) {
	 				var boxId = cn.substring(prefix.length, cn.length);
	 				grayBox = $(boxId);
	 			}
	 		});
 			if (grayBox) {
 				if (geoInput.id == i.id) {
 					grayBox.addClassName('ps_tabRowDisabled');
 				} else {
 					grayBox.removeClassName('ps_tabRowDisabled');
 				}
 			}
 		});
 	}
});

var PS_grayGeoBox = Class.create({
 	initialize: function(ele, allInputs){
 		this.inputs = allInputs;
 		this.grayHandler = new PS_grayGeoBoxHandler();
 		Element.observe(ele, 'click', this.click.bindAsEventListener(this));
 		if (ele.checked) {
	 		Element.observe(ele, 'ps:init_grayBox', this.click.bindAsEventListener(this));
 			ele.fire('ps:init_grayBox');
 		}
 	},
 	click: function(ev) {
 		// always check, as the PS_triggerEditBox on click could have taken the
		// check away by now
 		if (ev.element().checked) {	this.grayHandler.handle(this.inputs, ev.element()); }
 	}
});

var PS_checkUncheckInputs = Class.create({
 	initialize: function(ele, check){
 		this.check = check;
 		var prefix = 'ps_checkTarget_';
 		var c = this;
 		ele.classNames().each(function(cn) {
 			if (cn.startsWith(prefix)) {
 				var inputGroupClass = cn.substring(prefix.length, cn.length);
 				c.inputs = $$('input[class="'+inputGroupClass+'"]');
 			}
 		});
 		if (this.inputs) {
 			Element.observe(ele, 'click', this.click.bindAsEventListener(this));
 		}
 	},
 	click: function(evt) {
 		evt.stop();
 		var checking = this.check;
 		this.inputs.each(function(i){
			i.checked = checking;
 		});
 	}
});

var PS_fakeInput = Class.create({
 	initialize: function(){
    	var ele = $$('input[type="file"]')[0];
    	if (ele) {
			PS.debug("init PS_fakeInput: id=" + ele.id);

			this.uploadBtn = $('ps_uploadBtn');
			if(this.uploadBtn) this.disableUploadBtn();
			// this.isClicked = true;
			var prefix = 'ps_fakeInputTarget_';
			var c = this;
			ele.classNames().each(function(cn){
				if (cn.startsWith(prefix)) {
					c.fakeInputId = cn.substring(prefix.length, cn.length);
				}
			});
			if (this.fakeInputId) {
				// Event.observe(ele, 'click',
				// this.click.bindAsEventListener(this));
				Event.observe(ele, 'mouseout', this.outside.bindAsEventListener(this));
				Event.observe(ele, 'mouseover', this.inside.bindAsEventListener(this));
				Event.observe(ele, 'change', this.outside.bindAsEventListener(this));
			}

		}
 	},
 	click: function() {
 		// this.isClicked = true;
 	},
 	inside: function() {
		//$('ps_field_fakeUploadCtrl').src='/static/img/_locales/' + $('ps_field_fakeUploadCtrl').lang + '/btn_uploadimg_hover.gif';
 	},
 	outside: function(ev) {
	 	 // if (this.isClicked) {
	 	 	$(this.fakeInputId).value = ev.element().value;
			if ($(this.fakeInputId).value == '') {
				if(this.uploadBtn) this.disableUploadBtn();
			} else {
				if(this.uploadBtn) this.enableUploadBtn();
			}
	 	 	// this.isClicked = false;
		  // }
 	},
 	disableUploadBtn: function() {
		this.uploadBtn.addClassName('ps_uploadDisabled')
		this.uploadBtn.onclick = function(){return false;};
 	},
 	enableUploadBtn: function() {
		this.uploadBtn.removeClassName('ps_uploadDisabled');
		this.uploadBtn.onclick = null;
 	}
});

/*
 * Dependant Dropdowns - if you choose something on min-box the max-box will be affected
 * */
var PS_dropdownDependency = Class.create({
    initialize: function(min, max, minVals, minTexts, maxVals, maxTexts){
		this.minDropdown = $(min);
		this.maxDropdown = $(max);

		this.minVals = $A(minVals);
		this.maxVals = $A(maxVals);

		this.minTexts = $A(minTexts);
		this.maxTexts = $A(maxTexts);

		this.minSelected = this.minDropdown.options[this.minDropdown.selectedIndex];
		this.maxSelected = this.maxDropdown.options[this.maxDropdown.selectedIndex];

		// somewhat of a hack, but _should_ contain the value that has attr selected=selected
		// on initialisation. saving this allows us to preserve the selected attr when calling refillMax,
		// so that form resets work correctly
		this.maxDefaultValue = this.maxSelected.value;

		this.dontCareOptionText = "x";

       Event.observe(this.minDropdown, "change", this.minChanged.bindAsEventListener(this, this.minDropdown));
       Event.observe(this.maxDropdown, "change", this.maxChanged.bindAsEventListener(this, this.maxDropdown));
    },

	setDontCareOptionText: function(text){
		this.dontCareOptionText = text;
	},

    minChanged: function(ev, ele){
		this.minSelected = ele.options[ele.selectedIndex];
		allNumbers = !isNaN(this.minSelected.value) && !isNaN(this.maxSelected.value);
		for(i=0; i<this.minDropdown.options.length; i++) {
			if(this.minDropdown.options[i].value == "0") {
				this.minDropdown.options[i].text = this.dontCareOptionText;
			}
		}
		if(allNumbers && this.minSelected.value >= this.maxSelected.value) {
			this.refillMax();
			//get actual maxsize - search in array for next higher value
			actSelectedValIndex = this.maxVals.indexOf(parseInt(this.maxSelected.value));
			newMaxValToSelect = this.maxVals[actSelectedValIndex-1];
			//alert(this.maxDropdown.options[this.maxDropdown.selectedIndex].value);
			if(this.maxSelected.value == "0" || this.maxDropdown.options[this.maxDropdown.selectedIndex].value == "0") {
				newMaxValToSelect = "0";
			}
			for(i=0; i<this.maxDropdown.options.length; i++) {
				if(this.maxDropdown.options[i].value == newMaxValToSelect) {
					//alert("select");
					this.maxDropdown.options[i].selected = true;
					return;
				}
			}
		} else if(allNumbers && this.minSelected.value < this.maxSelected.value) {
			//refill maxfield
			var oldMaxVal = this.maxSelected.value;
			this.refillMax();
			this.maxSelected.value = oldMaxVal;
			for(i=0; i<this.maxDropdown.options.length; i++) {
				if(this.maxDropdown.options[i].value == this.maxSelected.value) {
					this.maxDropdown.options[i].selected = true;
					return;
				}
			}
		//} else if(allNumbers && this.maxSelected.value == "0") {

		} else if(!allNumbers) {
			//alert("nan: " + this.minSelected.value +" - "+ this.maxSelected.value);
		}
    },
    maxChanged: function(ev, ele){
		this.maxSelected.value = ele.options[ele.selectedIndex].value;
    },

	refillMax: function() {
		this.removeAllOption(this.maxDropdown);
		for(i=0; i<this.maxVals.length; i++) {
			if(this.maxVals[i] > this.minSelected.value) {
				// was this option originally selected=selected?
				if (this.maxVals[i] == this.maxDefaultValue) {
					var makeDefaultSelected = true;
				} else {
					var makeDefaultSelected = false;
				}
				this.addOption(this.maxDropdown, this.maxTexts[i], this.maxVals[i], false, makeDefaultSelected);
			}

			if(this.maxVals[i] == this.minSelected.value) {
				if (this.maxSelected.value != "0") {
					this.maxSelected.value = this.minSelected.value;
				}
			}
		}

		for(i=0; i<this.maxDropdown.options.length; i++) {
			if(this.maxDropdown.options[i].value == "300") {
				this.maxDropdown.options[i].text = "70+";
			}
		}

		if (this.dontCareOptionText != "") { //append "egal" Option as last Value
			this.addOption(this.maxDropdown, this.dontCareOptionText, '0', false, false);
		}
	},

	addOption: function(selectObj, text, value, isSelected, defaultSelected) {
	    if (selectObj != null && selectObj.options != null) {
	    	selectObj.options[selectObj.options.length] = new Option(text, value, defaultSelected, isSelected);
	    }
	},
	removeAllOption: function(selectObj) {
	    if (selectObj != null && selectObj.options != null) {
	        selectObj.options.length = 0;
	    }
	}


});

var PS_handleCountryCtrls = Class.create({
 	initialize: function(ele, add, init, allOptions, selectElem){
 		this.selectElem = selectElem;
 		// the reference list: all options
 		this.allOptions = allOptions;
 		// init: by css class marked options will be removed (e.g. if they are
		// open on load)
 		if (init) this.initSelect();
 		if (add) {
	 		Event.observe(ele, 'click', this.addCountry.bindAsEventListener(this));
	 	} else {
	 		Event.observe(ele, 'click', this.removeCountry.bindAsEventListener(this));
	 	}
 	},
 	initSelect: function() {
 		var pre = 'ps_initRemove_';
 		var c = this;
 		var classes = this.selectElem.className.split(' ');
 		classes.each(function(cn) {
 			if (cn.startsWith(pre)) {
 				var indeces = cn.substring(pre.length, cn.length);
 				indeces.split('_').each(function(i) {
 					for(var j = 0; j < c.selectElem.options.length; j++) {
 						if (c.selectElem.options[j].value == i) {
 							c.selectElem.remove(j);
 							break;
 						}
 					};
 				});
 			}
 		});
 	},
 	addCountry: function(ev) {
 		ev.stop();
 		var sInput = this.selectElem.options[this.selectElem.selectedIndex];
 		var prefix = 'ps_target_';
 		var c = this;
 		var target = null;
 		// IE Bug: classNames() does not work
		var classes = sInput.className.split(' ');
 		classes.each(function(cn) {
 			if (cn.startsWith(prefix)) {
 				target = cn.substring(prefix.length, cn.length);
 			}
 		});
 		if (target && $(target)) {
 			var cBox = $(target);
 			// show target box
 			var inBefore = $('ps_insertNewCountryBeforeBefore');
 			if (inBefore) {
 				cBox.parentNode.removeChild(cBox);
 				inBefore.parentNode.insertBefore(cBox, inBefore);
 			}
 			cBox.show();
 			// remove selected option from selectbox
 			this.selectElem.remove(this.selectElem.selectedIndex);
	 		this.selectElem.selectedIndex = 0;
 		}
 	},
 	removeCountry: function(ev) {
 		ev.stop();
 		var prefix = 'ps_target_';
 		var c = this;
 		var target = null;
 		ev.element().classNames().each(function(cn) {
 			if (cn.startsWith(prefix)) {
 				target = cn.substring(prefix.length, cn.length);
 			}
 		});
 		if (target && $(target)) {
 			// hide target box
 			$(target).hide();
 			// add corresponding option back to selectbox
 			var i = 0;
 			var found = false;
 			// find saved option in allOptions
 			while(!found && i < this.allOptions.length ) {
	 			var classes = this.allOptions[i].className.split(' ');
	 			classes.each(function(cn){
 					if (cn == prefix+target) found = true;
 				});
 				if (!found) i++;
 			}
 			if (found) {
 				// find index, where to put the option (lexical order)
	 			var j = 1;
	 			var found1 = false;
	 			while(!found1 && j < this.selectElem.options.length ) {
	 				if (this.selectElem.options[j].text > this.allOptions[i].text) found1 = true;
	 				if (!found1) j++;
	 			}
	 			var b = j;
	 			if (!found1) {
	 				b = this.selectElem.options.length;
	 			}
	 			// create new option and copy text, value and class (IE needs
				// new option()....)
	 			var option = new Option(this.allOptions[i].text, this.allOptions[i].value);
	 			option.className = this.allOptions[i].className;
	 			this.selectElem.options.add(option, b);
 			}
	 		this.selectElem.selectedIndex = 0;
 		}
 	}
});
var PS_buttonDisable = Class.create({
 	initialize: function(btnEle, clickEles){
 		this.btnEle = btnEle;
 		var c = this;
		if (clickEles) {
			clickEles.each(function(e){
				Event.observe(e, 'click', c.click.bindAsEventListener(c));
			});
		}
 		this.disableBtn();
 	},
 	click: function() {
 		this.enableBtn();
 	},
 	disableBtn: function() {
		this.btnEle.setOpacity(0.3);
		this.btnEle.setStyle({
		  cursor: 'default'
		});
		this.btnEle.onclick = function(){return false;};
 	},
 	enableBtn: function() {
		this.btnEle.setOpacity(1);
		this.btnEle.setStyle({
		  cursor: 'pointer'
		});
		this.btnEle.onclick = null;
 	}
});

var PS_disableOnSubmit = Class.create({
 	initialize: function(btnEle){
 		this.btnEle = btnEle;
 		Event.observe(btnEle, 'click', this.disableBtn.bindAsEventListener(this));
 	},

 	disableBtn: function() {
 		this.btnEle.disabled=true;
 		this.btnEle.setOpacity(0.3);
		this.btnEle.setStyle({
		  cursor: 'default'
		});
		this.btnEle.onclick = function(){ return false; };
 	}
});

var PS_omnTracking = Class.create({
	initialize: function(ele) {
		//alert(ele.innerHTML);
		if(ele) {

		}
	}
});

var PS_welcomeMail = Class.create({
	initialize: function(ele) {
		if($('ps_messagesHeadline') != null) {
			msgCount = $$('#ps_messagesHeadline b')[0].innerHTML;
			PS.debug("msgCount=" + msgCount);

			oldMsgCount = msgCount.match(/\d+/);
			PS.debug("oldMsgCount=" + oldMsgCount);
			newMsgCount = parseInt(oldMsgCount) + 1;
			$('ps_messagesHeadline').innerHTML = $('ps_messagesHeadline').innerHTML.replace(/\d+/, newMsgCount);
		}
		if($$('.ps_noEntriesText')[0] != null) {
			$$('.ps_noEntriesText')[0].addClassName('ps_inv');
		}

	}
});


var PS_guidedForm = Class.create({
  initialize: function(){
    this.currentStep  = 1;
    this.hasFinished  = false;
    this.guidedFields = new Array();
    var t = this;

    $$('.ps_guidedField').each(function(field){
      var step = t.getStep(field);

      if (t.guidedFields[step] == null)
        t.guidedFields[step] = new Array();
      t.guidedFields[step].push(field);

      if (field.type == 'radio' || field.type == 'checkbox') {
  		  new Field.Observer(field, 0.05, t.watchChanges.bind(t));

      } else {
        field.observe('keyup', t.watchChanges.bindAsEventListener(t));
      }
    });

    this.currentField = this.guidedFields[this.currentStep];

    this.activateCurrentGuideIndicator();
  },

  watchChanges: function(ev){
    el = Object.isElement(ev) ? ev : ev.element();

    // do nothing if the user is editing a field ahead of time
    if (this.getStep(el) != this.currentStep) return;

    if(! this.conditionsSatisfied(el)) return;

    this.disableCurrentGuideIndicator();

    do {
      this.advanceStep();
      if (this.hasFinished) break;
    } while(this.currentFieldWasEdited() && this.conditionsSatisfied(this.currentField));

    this.activateCurrentGuideIndicator();
  },

  conditionsSatisfied: function(el) {
    returnVal = true;
    el.className.split(" ").each(function(c){
      if (c.match(/^ps_guidedField_condition_minlength_\d+$/))
        if (c.replace('ps_guidedField_condition_minlength_', '') > el.value.length) returnVal = false;
      if (c.match(/^ps_guidedField_condition_equals_.+$/))
        if ($(c.replace('ps_guidedField_condition_equals_', '')).value != el.value) returnVal = false;
    });

    return returnVal;
  },

  currentFieldWasEdited: function() {
    var f = this.guidedFields[this.currentStep].first();

    if(f.type == 'text' || f.type == 'password')
      if (f.value != '') return true;

    return false;
  },

  getStep: function(el){
    var step = false;
    el.className.split(" ").each(function(c){
      if (c.match(/^ps_guidedField_step_\d+$/))
        step = c.replace('ps_guidedField_step_', '');
    });
    return step;
  },

  advanceStep: function() {
    this.currentStep++;
    if (this.guidedFields[this.currentStep]) {
      this.currentField = this.guidedFields[this.currentStep].first();
    } else {
      this.hasFinished = true;
    }
  },

  currentGuideIndicator: function() {
    if (this.hasFinished) {
      return $$('.ps_guideIndicator_last').first();
    } else {
      return $$('.ps_guideIndicator_step_' + this.currentStep).first();
    }
  },

  activateCurrentGuideIndicator: function() {
    if (this.currentGuideIndicator())
      // this.currentGuideIndicator().setStyle({color: '#F58022'});
      this.currentGuideIndicator().show();
  },

  disableCurrentGuideIndicator: function() {
    if (this.currentGuideIndicator())
      // this.currentGuideIndicator().setStyle({color: 'black'});
      this.currentGuideIndicator().hide();
  }

});



/*
 * Initialize Properties and Dom stuff Some Utilities
 */
if(typeof log4javascript=='undefined'){var log={debug:function(){},info:function(){},warn:function(){},error:function(){}};}else{var log=log4javascript.getDefaultLogger()}
var PS_core = Class.create({
  initialize: function(){
      this.prop = new PS_properties();
      this.debug("dom:loaded and properties initialized");
  },

  /*
	 * Log to console in Firebug
	 */
  debug: function(str){
  	if ((this.prop.internalSys || this.prop.queryDebug) && typeof console != "undefined" && typeof console.debug != "undefined") { //this.prop.debug
  		timeElapsed = "";
  		if (this.prop.debugWithTimeElapsed)
  			timeElapsed = (new Date().getTime() - this.prop.initAt) / 1000 + ": ";
  		console.debug(timeElapsed + Object.inspect(str));
  	}
  },

  jsTest: function() {
	 	if (this.prop.queryDebug) {
	 		this.loadScript('jstest/unittest');
	 		this.loadCss('unittest');
	 		//this.loadScript('jstest/qunit');
	 		//this.loadCss('qunit');
	 		this.loadScript('jstest/mockme-0.9beta2');
	 		return true;
	 	} else {
	 		return false;
	 	}
  },

	/**
	* @classDescription Laedt dynamisch die benoetigten Js-Dateien nach
	* @param {Array} scripts Die Scripte, die eingebunden werden sollen
	*/
	loadScript : function(script, path) {
		if(!path) path = pageVars.jsPath;
		obj = document.createElement('script');
		obj.setAttribute('type','text/javascript');
		obj.setAttribute('src',path + script+'.js');
		document.getElementsByTagName('head')[0].appendChild(obj);
	},


	/**
	* @classDescription Laedt dynamisch die benoetigten CSS-Dateien nach
	* @author	Florian Weber (florian.weber@pixelpark.com)
	* @param {Array} styles Array mit den CSS-Dateinamen (ohne Suffix)
	*/
	loadCss : function(style) {
		obj = document.createElement('link');
		obj.setAttribute('rel','stylesheet');
		obj.setAttribute('type','text/css');
		obj.setAttribute('media','screen, projection');
		obj.setAttribute('href',pageVars.cssPath + style +'.css');
		document.getElementsByTagName('head')[0].appendChild(obj);
	},

  /*
	 * Writes the given object in the consle if these exists
	 */
  consoleDebug: function ( object ) {
  	if ( this.prop.debug && typeof console != "undefined" && typeof console.debug != "undefined" ) {
  		console.debug( object );
  	}
  }
});

var PS_debugLayer = Class.create({
	initialize: function(){
		PS.loadScript('debug');
		PS.loadCss('debug');
	}
});


/**
 * NEW Profile-Form-Validation Handling
 * @author: Florian Weber
 */
PS_ajaxForm = Class.create({
	initialize: function(submittedForm, ajaxPageLink, withApprovalBox, additionalParams, handleTransport){
		mySubmittedForm = submittedForm; //an ID of that specific form that should be submitted
		myWithApprovalBox = withApprovalBox;
		myAjaxCompletedSuccess = this.ajaxCompletedSuccess;
		myHandleServerError = this.handleServerError;
		myHandleTransport = handleTransport;
		this.ajaxPageLink = ajaxPageLink + "?rand=" + new Date().getTime(); //where to Submit - always set the timeStamp

		this.formParams = $(mySubmittedForm).serialize();
		if (!additionalParams) this.additionalParams = ""; //parameters that should be added to the request in the form ?param1=abc&param2=walla
		this.params = this.formParams + this.additionalParams;
		if (typeof this.params != "object") {
			this.params = this.params.toQueryParams();
		};

		this.submitMethod = "post";
		this.errorDiv = $('ajaxError'); //where to display errormessage
		//this.indicatorDiv = $('indicator'); //if we get an indicator for saving
		myDisplayValueReady = false;
		this.hasSuccess = false;
	},


	/**
	 * @classDescription The Ajax-Request itself.
	 * @author	Florian Weber
	 * @param {String} method If not set standard is post. You can give a "get" here.
	 */
	submitForm: function(){
		this.hasSuccess = false; //be pessimistic
		//params = removeDefaultValues(params); //Values prefilled in Textfields for example
		//ppAjax.showIndicator(replaceContainer);
		new Ajax.Request(this.ajaxPageLink, {
			method: this.submitMethod,
			parameters: this.params,
			onSuccess: function(){ //Invoked when a request completes and its status code is undefined or belongs in the 2xy family.
				this.hasSuccess = true;
			},
			onComplete: function(transport){ //Triggered at the very end of a request's life-cycle, once the request completed
				if (this.hasSuccess == true) {
					eval(myHandleTransport)(mySubmittedForm, transport);
					//myAjaxCompletedSuccess(transport);
				}
			},
			onFailure: myHandleServerError
		});
		//ppAjax.conf.indicatorDiv.removeClassName('inv');
	},

	/**
	 * @classDescription Indicator-Layer anzeigen
	 */
	showIndicator: function(which){
		//this.indicatorDiv.removeClassName('inv');
		//if ($$(which)[0] && $$(which)[0].select('.infoboxIndicator') && $$(which)[0].select('.infoboxIndicator')[0]) {
		//	$$(which)[0].select('.infoboxIndicator')[0].removeClassName('inv');
		//}
	},

	/**
	 * @classDescription Versteckt den Indicator-Layer
	 */
	hideIndicator: function(which){
		//this.indicatorDiv.addClassName('inv');
		///if ($$(which)[0] && $$(which)[0].select('.infoboxIndicator')) {
		//	$$(which)[0].select('.infoboxIndicator')[0].addClassName('inv');
		//}
	},

	/**
	 * @classDescription In case of 404/500 we could do something special here.
	 */
	handleServerError: function(){
		//nothing now
	}
});



/*
 * Handle Forms in Profile-Section
 * */
PS_profileForms = Class.create({
	initialize: function(submittedForm, theTransport) {
		transport = theTransport;
		myHideError = this.hideError;
		mySubmittedForm = submittedForm; //an ID of that specific form that should be submitted
		myCollectFormValues = this.collectFormValues;
		myToggleFormDisplay = this.toggleFormDisplay;
		myShowError = this.showError;
		myDisplayValueReady = this.displayValueReady;
		myHasError = false;
	},

	/**
	 * @classDescription Aufruf, nachdem die angeforderte Seite erfolgreich geladen wurde.
	 */
	ajaxCompletedSuccess: function(){
		model = transport.responseText.evalJSON();
		if (Object.isUndefined(model.errorMessages) || Object.keys(model.errorMessages).length == 0 ) { //noError

			myHasError = false;
			//When no error occured check if we have a profileCompletion Box on page. If so do a Ajax-refresh on that Box
   			if ($$('.ps_profile_edit_page')[0] && $$('.ps_statusBar')[0]) {
   				new PS_updateProfileCompletion()
			}

   			//show Modalbox when changes affect Matchingpoints
   			if (!Object.isUndefined(model.matchingPointsWillChange) && model.matchingPointsWillChange == true ){
   				Modalbox.show($('ps_modal_matchingPointsWillChange'), {width: 540,  skin: '1', hideCloseLink: false});
   			}

   			//Hide ErrorMessage if there is one
   			myHideError();
   			//take all form-elements and put selected/filled values to concatedString-Array
   			concatedString = myCollectFormValues();
   			//open / close Form
   			myToggleFormDisplay();
   			//write saved vales to DOM
   			saveFormToDOM($(mySubmittedForm));
   			//Close open Form
   			$(mySubmittedForm).select('.ps_hideEditBox')[0].fire('ps:hide');
		} else {
			myHasError = true;
			myShowError(model.errorMessages);
		}
		//this.hideIndicator(replaceContainer);
	},

	collectFormValues: function() {
		//Collect all checked CHECKBOX and put Text into Array
		var newValueArray = new Array();
		if($(mySubmittedForm).select('input[type=checkbox]')[0]) {
			$(mySubmittedForm).select('input[type=checkbox]').each(function(elem) {
				if($(elem.id).checked) {
					newValueArray.push( $(elem.id + "_label").innerHTML.strip() );
				}
			})
			value = newValueArray.join( ", " );
		}
		//Collect all checked RADIO and put Text into Array
		if($(mySubmittedForm).select('input[type=radio]')[0]) {
			$(mySubmittedForm).select('input[type=radio]').each(function(elem) {
				if($(elem.id).checked) {
					newValueArray.push( $(elem.id + "_label").innerHTML.strip() );
				}
			})
			value = newValueArray.join( ", " );
		}
		//Collect all INPUT-TEXT and put Text into Array
		if($(mySubmittedForm).select('input[type=text]')[0]) {
			$(mySubmittedForm).select('input[type=text]').each(function(elem) {
				if($(elem).value.strip() != "")  {
					newValueArray.push( $(elem).value.strip() );
				}
			})
			value = newValueArray.join( ", " );
		}
		//Collect all TEXTAREA and put Text into Array
		if($(mySubmittedForm).select('textarea')[0]) {
			$(mySubmittedForm).select('textarea').each(function(elem) {
				if ($(elem).value.strip() != "") {
					newValueArray.push(elem.value.strip());
				}
			})
			value = newValueArray.join( ", " );
		}

		concatedString = "";
		$A(value).each(function(displayText) {
			concatedString = concatedString + displayText
		})

		if(concatedString.search(/\./) > 0) { //factfile/overview has whole sentences. If sentence we have no "," between them
			concatedString = concatedString.gsub(',','')
		}
		return concatedString;
	},

	toggleFormDisplay: function() {
		notActiveDiv = null;
		displayTextDiv = $(mySubmittedForm).select('.ps_form_element_display')[0];
		emptyDiv = $(mySubmittedForm).select('.ps_emptyInput')[0];
		//alert(concatedString +" ##### "+ displayTextDiv.innerHTML);
		if (concatedString != displayTextDiv.innerHTML) {
			if(myWithApprovalBox != null && myWithApprovalBox){
				notActiveDiv = $(mySubmittedForm).select('div.ps_notActivatedBox')[0];
			}
			if (concatedString == "") { //no value selected or Text entered
				if(notActiveDiv != null){ notActiveDiv.hide(); }
				if ( emptyDiv != null ) { emptyDiv.show(); }
				displayTextDiv.hide();
			} else {
				if(notActiveDiv != null){ notActiveDiv.show(); }
				if ( emptyDiv != null ) { emptyDiv.hide(); }
				displayTextDiv.show();
			}

		} else {
			//PS.debug("nothing changed");
		}
		displayTextDiv.innerHTML = concatedString;
		myDisplayValueReady = true;
	},

	showError: function(errorMessages){
		//get all errorMessages (probably more than one)
		errorText = "";
		poststring = "";
		if ( ! Object.isArray( errorMessages ) ) {
			for ( var sub in errorMessages ) {
				PS.debug( errorMessages[ sub ] );
				if(errorText != "") poststring = "<br />";
				errorText = errorText + errorMessages[ sub ] + poststring;
			}
		}
		$(mySubmittedForm).select('.ps_profileEditInputBox .ps_errorBox .ps_errorText')[0].innerHTML = errorText;
		$(mySubmittedForm).select('.ps_profileEditInputBox .ps_errorBox')[0].show();
	},

	hideError: function(){
		$(mySubmittedForm).select('.ps_profileEditInputBox .ps_errorBox')[0].hide();
	},

	isErrorOccured: function() { //give back if an error occured
		if(myHasError) {
			return true;
		} else {
			return false;
		}
	},

	isDisplayValueReady: function() { //give back if displayValue String is ready and displayed
		PS.debug('myDisplayValueReady: ' + myDisplayValueReady);
		if(myDisplayValueReady) {
			return true;
		} else {
			return false;
		}
	},

	getSubmittedForm: function() {
		return mySubmittedForm;
	}

});



/**
 * BEGIN former fdc_parship.js
 * It has moved here in order to reduce http requests
 */


// AJAX

function submitFormPart ( element, url, errorCallback, noErrorCallback ) {
	// make sure DOM is updated and cleaned from tags,scripts and whitespaces before posting!
	saveFormToDOM(element.up( "form" ));

	//parameters = element.form.serialize( true );
	parameters = element.up( "form" ).serialize( true );
	var tmp = '';
	if (url.indexOf('?') != -1){
		tmp = 	url + '&rand=' + new Date().getTime();
	}else{
		tmp = 	url + '?rand=' + new Date().getTime();
	}

	new Ajax.Request( tmp, {//FIXME mixing post and get request parameters (used for overriding browser caching?)
			method : 'post',
			onSuccess : handleErrors( errorCallback, noErrorCallback ),
			parameters : parameters } );
}

function submitFormWithParameters( element, url, additionalParameters, errorCallback, noErrorCallback ) {
	// make sure DOM is updated and cleaned from tags,scripts and whitespaces before posting!
	saveFormToDOM(element.up( "form" ));

	parameters = element.up( "form" ).serialize( true );

	if ( ! Object.isUndefined( additionalParameters ) ) {
		var keys = Object.keys(additionalParameters);

		for(var i = 0;i< keys.length; i++){
			var value = additionalParameters[keys[i]];
		    parameters[keys[i]] = value;
		}
	}

	//console.debug(' --> submit form with params ' + noErrorCallback );

	new Ajax.Request( url + '?rand=' + new Date().getTime(), {
			method : 'post',
			onSuccess : handleErrors( errorCallback, noErrorCallback ),
			parameters : parameters } );
}

function submitFormAndFillResult( element, url, formNames, errorCallback, noErrorCallback ) {

	var additionalParameters = new Object();

	if ( Object.isArray( formNames ) ) {
		for ( var i = 0; i < formNames.length; i++ ) {
			additionalParameters[ "supportedForms" ] = formNames[ i ];
		}
	}

	submitFormWithParameters( element, url, additionalParameters, errorCallback,
			fillFieldsInFormPart( noErrorCallback, formNames, element ) );
}

/**
 * With this function you can submit a form and set an amount of fields you want to be validated, stored and updated.<br/>
 * <br/>
 * After submitting the response will be analysed and errors will be shown. If no error occured the submitted fields will be
 * filled with the new values (in the display mode only).<br/>
 * <br/>
 * The request handler has to analyse the <code>submittedFields</code> parameter which is a set. The validate and store steps
 * mentioned above are steps which are performed by the handler. The update step is a step perfomed by this function.
 *
 * @param element the element which triggers the submit or any other element which is a descend of the form
 * @param url the post url on wich the request handler should listen ;-)
 * @param formName the name of the submitted form in the response object. This name is the name used in the <code>ModelMap</code>
 * 		  in the handler
 * @param fields an array of field names which you want to be validated, stored and updated.
 * @param errorCallback a callback used if an error occured. The function has to look like <code>function(response, model)</code>
 * @param noErrorCallback a callback used if no error occured. The function has to look like the errorCallback
 *
 * @author Max Scheffler
 */
function submitFormPartsAndFillResult( element, url, formName, fields, errorCallback, noErrorCallback ) {

	var additionalParameters = new Object();

	if ( Object.isArray( fields ) ) {
		additionalParameters[ "submittedFields" ] = fields;
		//console.debug('added additional parameters')
	}
	submitFormWithParameters( element, url, additionalParameters, errorCallback,
			fillFieldsInWholeForm( noErrorCallback, formName, element, fields ) );
}

//--- helper methods -------------------------------------------------------------------------------------------------------------

function fillFieldsInWholeForm( finalNoErrorCallback, formName, element, fields ) {
	return function( response, model ) {

		var modelFormPart = model[ formName ];
		if ( Object.isUndefined( modelFormPart ) ) {
			return;
		}

		var form = element.form;

		for ( var sub in modelFormPart ) {
			if ( ! Object.isUndefined( modelFormPart[sub] ) && modelFormPart[sub] != null ) {
				for ( var i = 0; i < fields.length; ++i ) {
					if ( fields[i] == sub ) {
						fillField( form, sub, modelFormPart[sub] );
						break;
					}
				}
			}
		}
		finalNoErrorCallback( response, model );
	}
}

function fillFieldsInFormPart( finalNoErrorCallback, formNames, element ) {
	return function( response, model ) {

		for ( var i = 0; i < formNames.length; i++ ) {
			fillFieldsInForm( formNames[i], model, element );
		}

		finalNoErrorCallback( response, model );
	}
}

function fillFieldsInForm( formName, model, element ) {

	var modelFormPart = model[ formName ];

	if ( Object.isUndefined( modelFormPart ) ) {
		//console.debug( 'no formpart with name \'' + formName + '\' exists' );
		return;
	}

	var form = element.form;

	for ( var sub in modelFormPart ) {
		if ( ! Object.isUndefined( modelFormPart[sub] ) && modelFormPart[sub] != null ) {
			fillField( form, sub, modelFormPart[sub] );
		}
	}
}

function setFormPartDisplay(key, value) {

	if ( Object.isUndefined( value ) ) {
		//console.debug( 'empty value for key \'' + key + '\'' );
		return;
	}

	//console.debug( 'ps_form_element_display_' + key,  $( 'ps_form_element_display_' + key ) );
	var element = $( 'ps_form_element_display_' + key );
	if ( element == null || Object.isUndefined( element ) ) {
		return;
	}

	var emptyDiv = null;
	var parentDiv = element.parentNode;
	if ( parentDiv != null ) {
		var emptyDivs = Element.adjacent( parentDiv, 'div.ps_emptyInput' );
		if ( Object.isArray( emptyDivs ) && emptyDivs.length > 0 ) {
			emptyDiv = emptyDivs[ 0 ];
		}
	}

	if ( value == null || value == '' ) {
		if ( emptyDiv != null ) {
			emptyDiv.show();
		}
		element.hide();
	} else {
		if ( emptyDiv != null ) {
			emptyDiv.hide();
		}
		element.show();
		element.innerHTML = value;
	}

}

/**
 * Fills a display field in the display view with the value of the corresponding input field in the edit view.<br/>
 * <br/>
 * If the inputfield is of type select the option list will be searched for an option with the correct value and the displayed
 * value will be the text of this option.<br/>
 * <br/>
 * In case of checkbox or radio buttons the list of all inputfields will be searched for the right element and the value to
 * display will be the label of the inputefield. In case of checkbox the labels of multiple selected checkboxes will be joined
 * with an '<code>, </code>'.
 *
 * @param form the form containing the inputfields
 * @param key the <code>name</code> of the inputfield
 * @param value the value which comes from the response for this field
 *
 * @author Max Scheffler
 */
function fillField( form, key, value ) {
	var formElement = form[ key ];
	if (! formElement) {
		return;
	}
	// The only way to tell apart a NodeList from a Node which works in ie and ff is to ducktype the formElement
	if ( isNodeList( formElement ) ) {
		var newValueArray = new Array();
		//p.e. elements of a radiobutton-group
		for(var i = 0; i < formElement.length; i++) {
			var item = formElement[i];
			if ( Object.isArray( value ) ) {
				for ( var j = 0; j < value.length; j++ ) {
					if ( item.value == value[ j ] ) {
						newValueArray.push( $(item.id + "_label").innerHTML.strip() );
					}
				}

			} else if (item.value==value) {
				newValueArray.push($(item.id + "_label").innerHTML);
			}
			//HACK HACK HACK HACK to save posted value(s) and true checked in the DOM
			if (item.checked) {
				item.setAttribute("checked", "checked")
			} else if (item.hasAttribute("checked"))  {
				item.removeAttribute("checked")
			}
			// End HACK
		}

		value = newValueArray.join( ", " );
	} else {
		if (! formElement.nodeName) {
			return;
		}

		if ( formElement.nodeName.toLowerCase() == 'input' && formElement.type.toLowerCase() != 'text' ) {
			return;
		}
		//HACK HACK HACK HACK to save posted value(s) and true checked in the DOM
		else if (formElement.nodeName.toLowerCase() == 'input' && formElement.type.toLowerCase() == 'text') {
			formElement.setAttribute("value",value);
		}
		// End HACK

		if ( formElement.nodeName.toLowerCase() == 'select' ) {
			var options = formElement.options;

			for ( var i = 0; i < options.length; i++ ) {
				if ( value == options[i].value && options[i].value != '' ) {
					value = options[i].text;
				//HACK HACK HACK HACK to save posted value(s) and true checked in the DOM
					options[i].setAttribute("selected", "selected")
				} else {
					options[i].removeAttribute("selected")
				}
				// End HACK
			}
		}
	}


	setFormPartDisplay(key, value.toString().escapeHTML());
}

/**
 * The ie is unable to test whether or not the object is a NodeList. This test can determine whether an object is a NodeList or a
 * NodeElement.<br />
 * <br />
 * ATTANTION: it can check for NodeList or NodeElement only!
 *
 * @param object the object to test this object needs to be a NodeList or a NodeElement
 * @return true if the given object is an NodeList and false if it's a NodeElement
 *
 * @author Max Scheffler
 */
function isNodeList ( object ) {
	return (typeof object.length == 'number' && Object.isUndefined( object.nodeName ) );
}

function fillErrors( object, path ) {
	//PS.debug("1: " + object + " - " + $( path ));
	if ( ! Object.isArray( object ) ) {
		for ( var sub in object ) {
			if ( path == '' ) {
				fillErrors( object[ sub ], sub );
			} else {
				fillErrors( object[ sub ], path + '_' + sub );
			}
		}
	} else {
		//PS.debug(object + " - " + $( path ));
		var errorBox = $( path );
		if ( errorBox == null) {
			//console.debug( '$ ( "'+path+'" ) is null: no errorBox for errorDisplay found' );
			//alert( '$ ( "'+path+'" ) is null: no errorBox for errorDisplay found' );
		}

		var errorText = '';

		for ( var i = 0; i < object.length; i++ ) {
			errorText = errorText + '<p>' + object[ i ] + '</p>';
			if ( i != object.length - 1 ) {
				errorText = errorText + "<br/>";
			}
		}

		if ( errorText.length > 0 ) {
			errorBox.down('div.ps_errorText').update(errorText);
			errorBox.show();
		}
	}
}

/**
 * Analyses the errors in the response filed in by the JSONView and tries to find errorboxes in which the errors could be
 * written.<br/>
 * <br/>
 * If any error occured the errorCallback will be invoced otherwise the noErrorCallback will be invoced.</br>
 * <br/>
 * If you want to use this mechanism you have to use the [@ajaxAwareErrorBox] as the error box.
 *
 * @param errorCallback this function will be invoced if an error occured. The function must look like
 * 		  <code>function( response, model ){ ... }</code>
 * @param noErrorCallback this function will be invoced if no error occured. The function must look like
 * 		  <code>function( response, model ){ ... }</code>
 *
 * @author Max Scheffler
 */
function handleErrors( errorCallback, noErrorCallback ) {
	//alert("vv" + errorCallback + "noerror: " + noErrorCallback);
	return function ( response ) {

		var model = response.responseText.evalJSON();
		var errorBoxes = $$( '.ps_errorbox' );
		/* We have 2 differnet errorBox Types (spelling)
		 * "ps_errobox" are the old errortypes (no genBox stuff)
		 * "ps_errorBox" new errortypes with genBox stuff - do not delete all this with .innerHTML
		 * When all errorBoxes are the same (errorBox!) we can delete this workaround.
		 */
		errorBoxes.each( function( errorBox ) {
			errorBox.innerHTML = '';
			errorBox.hide();
		} );
		var errorBoxes = $$( '.ps_errorBox' );
		errorBoxes.each( function( errorBox ) {
			errorBox.hide();
		} );
		if ( Object.isUndefined( model.$errors ) || Object.keys( model.$errors ).length == 0 ) {
			noErrorCallback( response, model );

		  	//When no error occured check if we have a profileCompletion Box on page. If so do a Ajax-refresh on that Box
   			if ($$('.ps_profile_edit_page')[0] && $$('.ps_statusBar')[0]) {
				new PS_updateProfileCompletion()
			}
			 //console.debug( 'return - we have called the no error handler' );
			return;
		}
		errorCallback( response, model );
		fillErrors( model.$errors, 'ps_error_box' );
	}
}

/**
 * Failure handler for debugging
 */
function failure(request) {
	/*Could not handle the request.*/
	alert('Something went wrong while sending an ajax request.');
	refresh();
}

function refresh()
{
    //  This version of the refresh function will cause a new
    //  entry in the visitor's history.  It is provided for
    //  those browsers that only support JavaScript 1.0.
    //
    window.location.href = sURL;
}

// posting a whole form and indicate the field to save (think about using the standard way before using this)
// FIXME this is only used for saving factfile, with a hard coded form id. When refactoring, that page should
// use the standard way above as well.
function ajaxPostFieldInCompleteForm(updateField, formPartIndex, targetUrl, withApprovalBox) {
	//save form to DOM
	saveFormToDOM($('overViewEditForm'),updateField);

	var params = $('overViewEditForm').serialize( true );
	params[ "updateField" ] = updateField;
	var myAjax = new Ajax.Request(
	    targetUrl,
	    {
	        method: 'post',
	        parameters: params,
	        onSuccess: handleErrors( function(response, model) { var model = response.responseText.evalJSON(); fillErrors(model.$errors, 'ps_error_box') }, getNoErrorCallBackFor(formPartIndex, updateField, withApprovalBox) ),
		    onFailure: null
    	}
   	);

}

function getNoErrorCallBackFor(formPartIndex, updateField, withApprovalBox) {
	var result = function ( request, model ) {
		var formPartId = 'ps_showEditBox'+formPartIndex;
		var updatePlaceId = 'ps_form_element_display_'+updateField;
		var element = $( updatePlaceId );
		var emptyDiv = null;
		var parentDiv = element.parentNode;
		var notActiveDiv = null;

		//show Modalbox when changes affect Matchingpoints
		if (model.matchingPointsWillChange == true ){
		Modalbox.show($('ps_modal_matchingPointsWillChange'), {width: 540,  skin: '1', hideCloseLink: false});
		}

		//show not approved yet box (if new value)
		if (model.displayValue.toString().escapeHTML()!=element.innerHTML) {

			if ( parentDiv != null ) {
				var emptyDivs = Element.adjacent( parentDiv, 'div.ps_emptyInput' );
				if ( Object.isArray( emptyDivs ) && emptyDivs.length > 0 ) {
					emptyDiv = emptyDivs[ 0 ];
				}
			}
			if(withApprovalBox!=null && withApprovalBox){
				notActiveDiv = element.parentNode.adjacent( 'div.ps_notActivatedBox' )[0];
			}

			if ( model.displayValue == null || model.displayValue == '' ) {
				if(notActiveDiv !=null){
				    	notActiveDiv.hide();
				}
				if ( emptyDiv != null ) {
					emptyDiv.show();
				}
				element.hide();
			} else {
				if(notActiveDiv !=null){
				    	notActiveDiv.show();
				}
				if ( emptyDiv != null ) {
					emptyDiv.hide();
				}
				element.show();
				element.innerHTML = model.displayValue.toString().escapeHTML();
			}

		} else {
			element.innerHTML = model.displayValue.toString().escapeHTML();
		}
		$(formPartId + '_hide').fire('ps:hide');
	};
	return result;
}
// end posting whole form


/**
 * Helper function for saving form element values, select and checked states to the DOM
 *
 * @param form the form containing the input fields (form can be string integer or object)
 * @param elm a/the specific element to update if null whole form updates to the DOM
 *
 * @author Magnus Pettersson
 */

function saveFormToDOM(form, elm) {
	// check for valid input else return null
	if (typeof(form) === 'undefined' && document.forms[form] == 'undefined') {
		return;
	} else {
		if (typeof(form) == 'number') {
			form = document.forms[form.toString];
		} else if (typeof(form) == 'string') {
			form = document.forms[form];
		}
	   //else treat form as an object
	}

	// declare functions only available in this local scope
	var setA = function(o,a,v) { o.setAttribute(a,v); }
	var remA = function(o,a) { o.removeAttribute(a); }
	var remW = function(s) { return s.replace(new RegExp("^[//s]+$", "g"), ""); }


	// loop trough the form elements
	for (var i = 0; i < form.elements.length; i++) {
		var obj = form.elements[i];

		//om def och string och pa = pa
		if (typeof(elm) !== 'undefined' && typeof(elm) == 'string' && obj.getAttribute('name') != elm) {
			continue;
		}

		var strT = obj.type.toLowerCase();

		// if checkbox or radio
		if (strT == 'checkbox' || strT == 'radio') {
			if (obj.checked == true) {
				setA(obj,'checked','checked');
			} else {
				remA(obj,'checked');
			}
		}

		// if text (hidden can be added here at a later time if needed)
		if (strT == 'text') { obj.value = remW(obj.value.stripScripts().stripTags()); setA(obj,'value',obj.value); }

		// if textarea (cleaning whitespaces and updating both textarea innerHTML and value attribute in the DOM)
		if (strT == 'textarea') {
			obj.value = remW(obj.value.stripScripts().stripTags());
			setA(obj,'value',obj.value);
			obj.innerHTML = obj.value;
		}

		// if select box (works with single and multiple selections)
		if (strT == 'select-one' || strT == 'select-multiple') {
			for (var j = 0;j < obj.options.length; j++) {
				var objC = obj.options[j];
				if (objC.selected == true) {
					setA(objC,'selected','selected');
				} else {
					remA(objC,'selected');
				}
			}
		}
	}
}


//--- functions used as callbacks for special fields. Only touch them if you know what you do! -----------------------------------

function fillAnimalField (response, model) {

   	var animals = model.leisureForm.animals;

   	if ( ! Object.isArray( animals ) ) {
   		return;
   	}

   	var checkboxes = $( 'data_and_settings_form' )[ 'animals' ];
   	if ( ! isNodeList( checkboxes ) ) {
   		return;
   	}

   	var displayText = new Array();

   	for( var i = 0; i < checkboxes.length; i++ ) {
     		var item = checkboxes[i];
     		for ( var j = 0; j < animals.length; ++j ) {
       			if ( item.value  == animals[ j ] ) {
         				var checkboxLabel = $( item.id + '_label' );
         				if ( checkboxLabel != null ) {
         					displayText.push( checkboxLabel.innerHTML.strip() );
         				}
       			}
				//HACK HACK HACK HACK to save posted value(s) and true checked in the DOM
				if (item.checked) {
					item.setAttribute("checked", "checked")
				} else if (item.hasAttribute("checked"))  {
					item.removeAttribute("checked")
				}
				// End HACK
     		}
   	}

   	var freeText = $( 'data_and_settings_form' )[ 'animalFreeText' ];

	if (freeText != null) { freeText.value = freeText.value.stripScripts().stripTags(); }

   	if ( freeText != null && freeText.value != '' ) {
   		displayText.push( freeText.value );
   	}

	//HACK HACK HACK HACK to save posted value(s) in the DOM
	freeText.setAttribute("value", freeText.value);
	// End HACK

   	setFormPartDisplay( 'animals', displayText.join( ', ' ) )
   	$('ps_showEditBox6_hide').fire('ps:hide');
}


function fillHolidayExperienceField ( response, model ) {


	var element = $( 'ps_form_element_display_holidayExperience.answer' );
	if ( element == null || Object.isUndefined( element ) ) {
		return;
	}

	var value = model[ 'leisureForm' ][ 'holidayExperience' ][ 'answer' ]; //gespeicherter Wert

	var notActiveDiv = element.parentNode.adjacent( 'div.ps_notActivatedBox' )[0]; //nicht freigegeben
	var emptyDiv = element.parentNode.adjacent( 'div.ps_emptyInput' )[0]; //noch kein eintrag

	value = value.stripScripts().stripTags();

	if ( value == null || value == '' ) {
		emptyDiv.show();
		notActiveDiv.hide();
		element.hide();
	} else {
		emptyDiv.hide();
		notActiveDiv.show();
		element.innerHTML = value.escapeHTML();
		element.show();
	}
	//HACK HACK HACK HACK to save posted value(s) in the DOM
		$('ps_field_holiday_experience').setAttribute("value", value.escapeHTML());
		$('ps_field_holiday_experience').innerHTML = value.escapeHTML();
	// End HACK
	$('ps_showEditBox9_hide').fire('ps:hide');
}


// Checkboxes function
function toggleCheckBoxes(bool,name) {
    $$('input[name="'+name+'"]').each(function(ele){
        ele.checked = bool;
    });
}

// This function is called after the updating of a note that is attached to a profile
function updateNote(submittedForm, model){
	model = model.responseText.evalJSON();
	if (Object.isUndefined(model.$errors) || Object.keys(model.$errors).length == 0) {
		updateNoteFor = model.notesform.partnerId.value;
		userStr = "";
		if(updateNoteFor == null){
		}else{
			userStr = updateNoteFor;
		}
		if(model.notesform.note == null || model.notesform.note == ''){
			$('profileNoteNotEmpty' + userStr).hide();
			$('profileNoteEmpty' + userStr).show();
			if($('ps_note_text_for_' + userStr)) {
				$('ps_note_text_for_' + userStr).innerHTML = '';
			}
		} else {
			$('ps_show_note' + userStr).innerHTML = model.notesform.shortNote
			$('profileNoteNotEmpty' + userStr).show();
			$('profileNoteEmpty' + userStr).hide();

			//the new note editor with Modalbox needs a place to copy the full text from
			if($('ps_note_text_for_' + userStr)) {
				$('ps_note_text_for_' + userStr).innerHTML = model.notesform.note;
			}
		}
		//$('ps_layer_note' + userStr).down('.ps_layerInstance').fire('ps:close');
		Modalbox.hide();
	} else {
		//alert("error---");
	}
}

/*function shorten(value, shortenAfter, suffix) {
   return value != null && value.length > shortenAfter ? value.substring(0, shortenAfter) + suffix : value;
}*/

/**
 * END former fdc_parship.js
 */

 // TODO: refactor - only used once when initializing Modalbox

 // script.aculo.us builder.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007

 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
 //
 // script.aculo.us is freely distributable under the terms of an MIT-style license.
 // For details, see the script.aculo.us web site: http://script.aculo.us/

 var Builder = {
   NODEMAP: {
     AREA: 'map',
     CAPTION: 'table',
     COL: 'table',
     COLGROUP: 'table',
     LEGEND: 'fieldset',
     OPTGROUP: 'select',
     OPTION: 'select',
     PARAM: 'object',
     TBODY: 'table',
     TD: 'table',
     TFOOT: 'table',
     TH: 'table',
     THEAD: 'table',
     TR: 'table'
   },
   // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
   //       due to a Firefox bug
   node: function(elementName) {
     elementName = elementName.toUpperCase();

     // try innerHTML approach
     var parentTag = this.NODEMAP[elementName] || 'div';
     var parentElement = document.createElement(parentTag);
     try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
       parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
     } catch(e) {}
     var element = parentElement.firstChild || null;

     // see if browser added wrapping tags
     if(element && (element.tagName.toUpperCase() != elementName))
       element = element.getElementsByTagName(elementName)[0];

     // fallback to createElement approach
     if(!element) element = document.createElement(elementName);

     // abort if nothing could be created
     if(!element) return;

     // attributes (or text)
     if(arguments[1])
       if(this._isStringOrNumber(arguments[1]) ||
         (arguments[1] instanceof Array) ||
         arguments[1].tagName) {
           this._children(element, arguments[1]);
         } else {
           var attrs = this._attributes(arguments[1]);
           if(attrs.length) {
             try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
               parentElement.innerHTML = "<" +elementName + " " +
                 attrs + "></" + elementName + ">";
             } catch(e) {}
             element = parentElement.firstChild || null;
             // workaround firefox 1.0.X bug
             if(!element) {
               element = document.createElement(elementName);
               for(attr in arguments[1])
                 element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
             }
             if(element.tagName.toUpperCase() != elementName)
               element = parentElement.getElementsByTagName(elementName)[0];
           }
         }

     // text, or array of children
     if(arguments[2])
       this._children(element, arguments[2]);

      return element;
   },
   _text: function(text) {
      return document.createTextNode(text);
   },

   ATTR_MAP: {
     'className': 'class',
     'htmlFor': 'for'
   },

   _attributes: function(attributes) {
     var attrs = [];
     for(attribute in attributes)
       attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
           '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
     return attrs.join(" ");
   },
   _children: function(element, children) {
     if(children.tagName) {
       element.appendChild(children);
       return;
     }
     if(typeof children=='object') { // array can hold nodes and text
       children.flatten().each( function(e) {
         if(typeof e=='object')
           element.appendChild(e)
         else
           if(Builder._isStringOrNumber(e))
             element.appendChild(Builder._text(e));
       });
     } else
       if(Builder._isStringOrNumber(children))
         element.appendChild(Builder._text(children));
   },
   _isStringOrNumber: function(param) {
     return(typeof param=='string' || typeof param=='number');
   },
   build: function(html) {
     var element = this.node('div');
     $(element).update(html.strip());
     return element.down();
   },
   dump: function(scope) {
     if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope

     var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
       "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
       "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
       "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
       "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
       "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);

     tags.each( function(tag){
       scope[tag] = function() {
         return Builder.node.apply(Builder, [tag].concat($A(arguments)));
       }
     });
   }
 }


 /*
 ModalBox - The pop-up window thingie with AJAX, based on prototype and script.aculo.us.
Doku & Wiki: http://code.google.com/p/modalbox/w/list
 Copyright Andrey Okonetchnikov (andrej.okonetschnikow@gmail.com), 2006-2007
 All rights reserved.

 VERSION 1.5.4
 Last Modified: 07/16/2007
 */

 if (!window.Modalbox)
 	var Modalbox = new Object();

 Modalbox.Methods = {
 	focusableElements: new Array,
 	options: {
 		title: "", // Title of the ModalBox window
 		overlayClose: false, // Close modal box by clicking on overlay
 		width: 500, // Default width in px
 		height: 200, // Default height in px
 		overlayOpacity: .3, // Default overlay opacity
 		overlayDuration: 0, // Default overlay fade in/out duration in seconds
 		slideDownDuration: 0, // Default Modalbox appear slide down effect in seconds
 		slideUpDuration: 0, // Default Modalbox hiding slide up effect in seconds
 		resizeDuration: .35, // Default resize duration seconds
 		inactiveFade: true, // Fades MB window on inactive state
 		loadingString: "Please wait. Loading...", // Default loading string message
 		hideCloseLink: false,
 		closeString: "Close window", // Default title attribute for close window link
 		params: {},
 		method: 'get', // Default Ajax request method
 		galleryPic: null,
 		skin: '1'
 	},
 	_options: new Object,

 	setOptions: function(options) {
 		Object.extend(this.options, options || {});
 	},

 	_init: function(options) {
 		// Setting up original options with default options
 		Object.extend(this._options, this.options);
 		this.setOptions(options);
 		//Create the overlay
 		this.MBoverlay = Builder.node("div", { id: "MB_overlay" });
 		//Create the window
 		this.MBwindow = Builder.node("div", {id: "MB_window", style: "display: none", className: "parship ps_modalWindowSkin" + this.options.skin }, [
 			this.MBframe = Builder.node("div", {id: "MB_frame"}, [
 				this.MBheader = Builder.node("div", {id: "MB_header"}, [
 					this.MBcaption = Builder.node("h2", {id: "MB_caption"}),
 					this.MBclose = Builder.node("a", {id: "MB_close", title: this.options.closeString, href: "#", style: "display:none"}, [
 						Builder.build("<span>&times;</span>"),
 					]),
 				]),
 				this.MBcontent = Builder.node("div", {id: "MB_content"}, [
 					this.MBloading = Builder.node("div", {id: "MB_loading"}, this.options.loadingString),
 				]),
 			]),
 		]);

 		// Inserting into DOM
 		document.body.insertBefore(this.MBwindow, document.body.childNodes[0]);
 		document.body.insertBefore(this.MBoverlay, document.body.childNodes[0]);

    // IE doesn't allow setOpacity on the Builder element before placement
    $('MB_overlay').setOpacity(this.options.overlayOpacity);

 		// Initial scrolling position of the window. To be used for remove scrolling effect during ModalBox appearing
 		this.initScrollX = window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft;
 		this.initScrollY = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;

 		//Adding event observers
 		this.hide = this.hide.bindAsEventListener(this);
 		this.close = this._hide.bindAsEventListener(this);
 		this.kbdHandler = this.kbdHandler.bindAsEventListener(this);
 		this._initObservers();

 		this.initialized = true; // Mark as initialized
 		this.active = true; // Mark as active
 		this.contentAnchor = "";
 		this.usesDomNode = false;

 		if (this.options.galleryPic) {
 		  if (this.options.galleryPic >= 0 && globalGalleryInstance)
        globalGalleryInstance.showGalleryImage(this.options.galleryPic);
 		}
 	},

 	show: function(content, options) {
 	  PS.debug('preparing to show modal window, initialization status: ' + this.initialized);
 	  	$$('body')[0].scrollTo();
 	  	if(!this.initialized) this._init(options); // Check for is already initialized

 		this.content = content;
 		this.setOptions(options);

 		Element.update(this.MBcaption, this.options.title); // Updating title of the MB
 		//PS.debug(this.options.hideCloseLink)
 		if (this.options.hideCloseLink) {
 		    PS.debug("hcl hide")
 		    $('MB_close').hide();
 		} else {
 		    PS.debug("hcl show")
 		    $('MB_close').show();
 		    $('MB_close').blur();
 		}
 		if(this.MBwindow.style.display == "none") { // First modal box appearing
 			this._appear();
 			this.event("onShow"); // Passing onShow callback
 		}
 		else { // If MB already on the screen, update it
 			this._update();
 			this.event("onUpdate"); // Passing onUpdate callback
 		}
 	},

 	hide: function(options) { // External hide method to use from external HTML and JS
 		if(this.initialized) {
 			if(options) Object.extend(this.options, options); // Passing callbacks
 			// Effect.SlideUp(this.MBwindow, { duration: this.options.slideUpDuration, afterFinish: this._deinit.bind(this) } );
 			$(this.MBwindow).hide();
 			this._deinit();
 		} else throw("Modalbox isn't initialized");
 	},

 	_hide: function(event) { // Internal hide method to use inside MB class
 		if(event) Event.stop(event);
 		this.hide();
 	},

 	_appear: function() { // First appearing of MB
 		this._toggleSelects();
 		this._setOverlay();
 		this._setWidth();
 		this._setPosition();
 		this.MBwindow.setStyle({display:'block', visibility:'hidden'});

		this.loadContent();

 		this._setWidthAndPosition = this._setWidthAndPosition.bindAsEventListener(this);
 		Event.observe(window, "resize", this._setWidthAndPosition);

 		this.MBwindow.setStyle({visibility:'visible'});
 		//alert("----" + this.MBcontent);


 		setTimeout(this.fitModalWidthToElement.bind(this), 400); //need this due to IE Runtime-Error
 		setTimeout(this.unhideContent.bind(this), 500);
 	},

	fitModalWidthToElement: function() {
		if(this.MBcontent.down('.ps_fitModalWidthToThis')) {
		  PS.debug('found element to orient modal width at');
		  var currentWindowWidth    = this.MBwindow.getWidth();
		  var relevantElementWidth  = this.MBcontent.down('.ps_fitModalWidthToThis').getWidth();

		  if(currentWindowWidth < (relevantElementWidth + 30)) {
		    this.MBwindow.setStyle({width: (relevantElementWidth + 30) + 'px'});
		  }
		}
	},


 	unhideContent: function() {
 	  this.MBcontent.down().setStyle({visibility:'visible'})
 	},

 	resize: function(byWidth, byHeight, options) { // Change size of MB without loading content
 	  if(byWidth < 5 && byWidth > -5) byWidth = 0;
 	  if(byHeight < 5 && byHeight > -5) byHeight = 0;

    var oWidth = $(this.MBoverlay).getWidth();
    var wHeight = $(this.MBwindow).getHeight();
    var wWidth = $(this.MBwindow).getWidth();
    var hHeight = $(this.MBheader).getHeight();
    var cHeight = $(this.MBcontent).getHeight();
    var newHeight = ((wHeight - hHeight + byHeight) <= cHeight) ? (cHeight + hHeight) : (wHeight + byHeight);
    PS.debug("window height:" + wHeight + " header height:" + hHeight + " content height:" + cHeight + " by height:" + byHeight);
    PS.debug("w" + wHeight + " - h" + hHeight + " + b" + byHeight + " = " + (wHeight - hHeight + byHeight) + " <= c" + cHeight + "? " + ((wHeight - hHeight + byHeight) <= cHeight));
    PS.debug("resizing to " + newHeight);
    var newWidth = wWidth + byWidth;
        this.options.width = newWidth;
    if(options) this.setOptions(options); // Passing callbacks
 		new Effect.ScaleBy(this.MBwindow, byWidth, byHeight, {
 				duration: this.options.resizeDuration,
 			  	afterFinish: function() { this.event("afterResize") }.bind(this) // Passing callback
 			});
 	},

 	_update: function() { // Updating MB in case of wizards
 		this.currentDims = [this.MBwindow.offsetWidth, this.MBwindow.offsetHeight];
 		if((this.options.width + 10 != this.currentDims[0]) || (this.options.height + 5 != this.currentDims[1])) {
 		  PS.debug("resizing on update: " + this.options.width + " - " + this.currentDims[0] + "(" + (this.options.width - this.currentDims[0]) + ") and " + this.options.height + " - " + this.currentDims[1] + "(" +  + (this.options.height - this.currentDims[1]) + ")");
 			new Effect.ScaleBy(this.MBwindow,
 				(this.options.width - this.currentDims[0]), //New width calculation
 				(this.options.height - this.currentDims[1]), //New height calculation
 			{
 				duration: this.options.resizeDuration,
 				afterFinish: this._loadAfterResize.bind(this),
 				beforeStart: function(effect) {
 				  this._moveContentBack();
 					Element.update(this.MBcontent, "");
 					this.MBcontent.appendChild(this.MBloading);
 					Element.update(this.MBloading, this.options.loadingString);
 				}.bind(this)
 			});
 		} else {
 		  this._moveContentBack();
 			Element.update(this.MBcontent, "");
 			this.MBcontent.appendChild(this.MBloading);
 			Element.update(this.MBloading, this.options.loadingString);
 			this._loadAfterResize();
 		}
 	},

 	loadContent: function () {
 		if(this.event("beforeLoad") != false) { // If callback passed false, skip loading of the content
 			if(typeof this.content == 'string') {
 				var htmlRegExp = new RegExp(/<\/?[^>]+>/gi);
 				if(htmlRegExp.test(this.content)) // Plain HTML given as a parameter
 					this._insertContent(this.content);

 				else new Ajax.Request( this.content, { method: this.options.method.toLowerCase(), parameters: this.options.params,
 						onComplete: function(transport) {
 							var response = new String(transport.responseText);
 							response.extractScripts().map(function(script) {
 								return eval(script.replace("<!--", "").replace("// -->", ""));
 							}.bind(window));
 							this._insertContent(transport.responseText.stripScripts());
 						}.bind(this)
 					});

 			} else if (typeof this.content == 'object') {// HTML Object is given
 				this._insertContent(this.content);
 			} else {
 				Modalbox.hide();
 				throw('Please specify correct URL or HTML element (plain HTML or object)');
 			}
 		}
 	},

 	_insertContent: function(content){
 	  this.usesDomNode = false;
 		Element.extend(this.MBcontent);
 		this.MBcontent.update("");
 		if(typeof content == 'string') {
 			this.MBcontent.hide().update(content);
			if (this.MBcontent.down('.modal_title')) {
				PS.debug('modal window: using alternative title element labelled with class modal_title');
				Element.update(this.MBcaption, this.MBcontent.down('.modal_title').innerHTML);
				this.MBcontent.down('.modal_title').hide();
			}

 		} else if (typeof this.content == 'object') { // HTML Object is given
			this.usesDomNode = true;

			// save the frame element of the content block so we
			// can write the block back to its original position
			// later when closing the modal
			this.contentAnchor = this.content;

			// try to get the window title from an element defined
			// within the content block - this way we can define it
			// once instead of again and again in each trigger link / button
			if (this.content != null && this.content.id != null) {
				PS.debug('modal window: looking for element labelled ' + this.content.id + "_title");
				if ($(this.content.id + "_title")) {
					PS.debug('modal window: found. using content as title - ' + $(this.content.id + "_title").innerHTML);
					Element.update(this.MBcaption, $(this.content.id + "_title").innerHTML);
					$(this.content.id + "_title").hide();
				}
				else
					if (this.content.down('.modal_title')) {
						PS.debug('modal window: using alternative title element labelled with class modal_title');
						Element.update(this.MBcaption, this.content.down('.modal_title').innerHTML);
						this.content.down('.modal_title').hide();
					}
			}

			// move the content block out of its frame element into the modal
			this.MBcontent.update(this.content.firstDescendant());
			this.MBcontent.down().show();
			this.MBcontent.down().setStyle({
				visibility: 'hidden'
			});
		}

 		// Prepare and resize modal box for content

 		if(this.options.height == this._options.height) {
 		  PS.debug("content height: " + this.MBcontent.getHeight() + " window height: " + Element.getHeight(this.MBwindow) + " header height: " + Element.getHeight(this.MBheader));
 		  PS.debug("requesting resize by " + (this.MBcontent.getHeight() - Element.getHeight(this.MBwindow) + Element.getHeight(this.MBheader)));
 			Modalbox.resize(0, this.MBcontent.getHeight() - Element.getHeight(this.MBwindow) + Element.getHeight(this.MBheader), {
 				afterResize: function(){
 					this.MBcontent.show();
 					this.focusableElements = this._findFocusableElements();
 					this._moveFocus(); // Setting focus on first 'focusable' element in content (input, select, textarea, link or button)
 					this.event("afterLoad"); // Passing callback
 				}.bind(this)
 			});
 		} else { // Height is defined. Creating a scrollable window
 		  // WARNING: this path is broken, at least on IE7 - produces negative window heights
 		  // and throws an argument error in the process
 		  // don't set fixed heights as a workaround
 			this._setWidth();
 			//var newHeight = this.options.height + 'px';
 			var newHeight = (Element.getHeight(this.MBwindow) - Element.getHeight(this.MBheader)) + 'px';
 			this.MBcontent.setStyle({overflow: 'auto', height: newHeight});
 			this.MBcontent.show();
 			this.focusableElements = this._findFocusableElements();
 			this._moveFocus(); // Setting focus on first 'focusable' element in content (input, select, textarea, link or button)
 			this.event("afterLoad"); // Passing callback
 		}

 	},

 	activate: function(options){
 		this.setOptions(options);
 		this.active = true;
 		Event.observe(this.MBclose, "click", this.close);
 		if(this.options.overlayClose) Event.observe(this.MBoverlay, "click", this.hide);
 		Element.show(this.MBclose);
 		if(this.options.inactiveFade) new Effect.Appear(this.MBwindow, {duration: this.options.slideUpDuration});
 	},

 	deactivate: function(options) {
 		this.setOptions(options);
 		this.active = false;
 		Event.stopObserving(this.MBclose, "click", this.close);
 		if(this.options.overlayClose) Event.stopObserving(this.MBoverlay, "click", this.hide);
 		Element.hide(this.MBclose);
 		if(this.options.inactiveFade) new Effect.Fade(this.MBwindow, {duration: this.options.slideUpDuration, to: .75});
 	},

 	_initObservers: function(){
 		Event.observe(this.MBclose, "click", this.close);
 		if(this.options.overlayClose) Event.observe(this.MBoverlay, "click", this.hide);
 		Event.observe(document, "keypress", Modalbox.kbdHandler );
 	},

 	_removeObservers: function(){
 		Event.stopObserving(this.MBclose, "click", this.close);
 		if(this.options.overlayClose) Event.stopObserving(this.MBoverlay, "click", this.hide);
 		Event.stopObserving(document, "keypress", Modalbox.kbdHandler );
 	},

 	_loadAfterResize: function() {
 		this._setWidth();
 		this._setPosition();
 		this.loadContent();
 		setTimeout(this.unhideContent.bind(this), 500);
 	},

 	_moveFocus: function() { // Setting focus to be looped inside current MB
 		if(this.focusableElements.length > 0)
 		  try {
 		    this.focusableElements.first().focus(); // Focus on first focusable element except close button
 		  } catch(e) {
 		   // IE might for some reason complain about trying to give focus
 		   // to an invisible element
 		  }
 		else
 			if($("MB_close") && $("MB_close").visible()) $("MB_close").focus(); // If no focusable elements exist focus on close button
 	},

 	_findFocusableElements: function(){ // Collect form elements or links from MB content
 		return $A($("MB_content").descendants()).findAll(function(node){
 			return (["INPUT", "TEXTAREA", "SELECT", "A", "BUTTON"].include(node.tagName));
 		});
 	},

 	kbdHandler: function(e) {
 		var node = Event.element(e);
 		switch(e.keyCode) {
 			case Event.KEY_TAB:
 				if(Event.element(e) == this.focusableElements.last()) {
 					Event.stop(e);
 					this._moveFocus();  // Find last element in MB to handle event on it. If no elements found, uses close ModalBox button
 				}
 			break;
 			case Event.KEY_ESC:
 				if(this.active) this._hide(e);
 			break;
 			case 32:
 				this._preventScroll(e);
 			break;
 			case 0: // For Gecko browsers compatibility
 				if(e.which == 32) this._preventScroll(e);
 			break;
 			case Event.KEY_UP:
 			case Event.KEY_DOWN:
 			case Event.KEY_PAGEDOWN:
 			case Event.KEY_PAGEUP:
 			case Event.KEY_HOME:
 			case Event.KEY_END:
 				// Safari operates in slightly different way. This realization is still buggy in Safari.
 				if(/Safari|KHTML/.test(navigator.userAgent) && !["textarea", "select"].include(node.tagName.toLowerCase()))
 					Event.stop(e);
 				else if( (node.tagName.toLowerCase() == "input" && ["submit", "button"].include(node.type)) || (node.tagName.toLowerCase() == "a") )
 					Event.stop(e);
 			break;
 		}
 	},

 	_preventScroll: function(event) { // Disabling scrolling by "space" key
 		if(!["input", "textarea", "select", "button"].include(Event.element(event).tagName.toLowerCase()))
 			Event.stop(event);
 	},

 	_deinit: function()
 	{
 		this._toggleSelects(); // Toggle back 'select' elements in IE
 		this._removeObservers();
 		Event.stopObserving(window, "resize", this._setWidthAndPosition );
 		// Effect.toggle(this.MBoverlay, 'appear', {duration: this.options.overlayDuration, afterFinish: this._removeElements.bind(this) });
 		$(this.MBoverlay).hide();
 		this._removeElements();
 		// Element.setStyle(this.MBcontent, {overflow: '', height: ''});
 	},

 	_removeElements: function () {
 		if (navigator.appVersion.match(/\bMSIE\b/)) {
 			this._prepareIE("", ""); // If set to auto MSIE will show horizontal scrolling
 			window.scrollTo(this.initScrollX, this.initScrollY);
 		}
 		Element.remove(this.MBoverlay);
    this._moveContentBack();
 		Element.remove(this.MBwindow);
 		this.initialized = false;
 		this.event("afterHide"); // Passing afterHide callback
 		this.setOptions(this._options); //Settings options object into intial state
 		PS.debug('modal window elements removed, deinitialized');
 	},

 	_moveContentBack: function() {
 	  // write the modal content block back to its original frame in the page
 		// (provided we didn't pull the content in elsewhere)
 		if (this.usesDomNode) {
      $(this.contentAnchor).update(this.MBcontent.firstDescendant());
      this.contentAnchor.down().hide();
 		}
 	},

 	_setOverlay: function () {
 		if (navigator.appVersion.match(/\bMSIE\b/)) {
 			this._prepareIE("100%", "hidden");
 			if (!navigator.appVersion.match(/\b7.0\b/)) window.scrollTo(0,0); // Disable scrolling on top for IE7
 		}
 	},

 	_setWidth: function () { //Set size
 	  PS.debug('Modalwindow: _setWidth');
 		Element.setStyle(this.MBwindow, {width: this.options.width + "px"});
 	},

 	_setPosition: function () {
 	  PS.debug('Modalwindow: _setPosition');
 		this.MBwindow.style.left = Math.round((Element.getWidth(document.body) - Element.getWidth(this.MBwindow)) / 2 ) + "px";
 	},

 	_setWidthAndPosition: function () {
 	  PS.debug('Modalwindow: _setWidthAndPosition');
 		this._setWidth();
 		this._setPosition();
 	},

 	_getScrollTop: function () { //From: http://www.quirksmode.org/js/doctypes.html
 		var theTop;
 		if (document.documentElement && document.documentElement.scrollTop)
 			theTop = document.documentElement.scrollTop;
 		else if (document.body)
 			theTop = document.body.scrollTop;
 		return theTop;
 	},
 	// For IE browsers -- IE requires height to 100% and overflow hidden (taken from lightbox)
 	_prepareIE: function(height, overflow){
 		var body = document.getElementsByTagName('body')[0];
 		body.style.height = height;
 		//body.style.overflow = overflow; //if no scroller for page

 		var html = document.getElementsByTagName('html')[0];
 		html.style.height = height;
 		//html.style.overflow = overflow; //if no scroller for page
 	},
 	// For IE browsers -- hiding all SELECT elements
 	_toggleSelects: function() {
 		if (navigator.appVersion.match(/\bMSIE\b/))
 			$$("select").each( function(select) {
 				select.style.visibility = (select.style.visibility == "") ? "hidden" : "";
 			});
 	},
 	event: function(eventName) {
 		if(this.options[eventName]) {
 			var returnValue = this.options[eventName](); // Executing callback
 			this.options[eventName] = null; // Removing callback after execution
 			if(returnValue != undefined)
 				return returnValue;
 			else
 				return true;
 		}
 		return true;
 	}
 }

 Object.extend(Modalbox, Modalbox.Methods);

 Effect.ScaleBy = Class.create();
 Object.extend(Object.extend(Effect.ScaleBy.prototype, Effect.Base.prototype), {
   initialize: function(element, byWidth, byHeight, options) {
     this.element = $(element)
     var options = Object.extend({
 	  scaleFromTop: true,
       scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
       scaleByWidth: byWidth,
 	  scaleByHeight: byHeight
     }, arguments[3] || {});
     this.start(options);
   },
   setup: function() {
     this.elementPositioning = this.element.getStyle('position');

     this.originalTop  = this.element.offsetTop;
     this.originalLeft = this.element.offsetLeft;

     this.dims = null;
     if(this.options.scaleMode=='box')
       this.dims = [this.element.offsetHeight, this.element.offsetWidth];
 	 if(/^content/.test(this.options.scaleMode))
       this.dims = [this.element.scrollHeight, this.element.scrollWidth];
     if(!this.dims)
       this.dims = [this.options.scaleMode.originalHeight,
                    this.options.scaleMode.originalWidth];

 	this.deltaY = this.options.scaleByHeight;
 	this.deltaX = this.options.scaleByWidth;
   },
   update: function(position) {
     var currentHeight = this.dims[0] + (this.deltaY * position);
 	var currentWidth = this.dims[1] + (this.deltaX * position);

     this.setDimensions(currentHeight, currentWidth);
   },

   setDimensions: function(height, width) {
     var d = {};
     d.width = width + 'px';
     d.height = height + 'px';

  	var topd  = Math.round((height - this.dims[0])/2);
  	var leftd = Math.round((width  - this.dims[1])/2);
  	if(this.elementPositioning == 'absolute' || this.elementPositioning == 'fixed') {
  		if(!this.options.scaleFromTop) d.top = this.originalTop-topd + 'px';
  		d.left = this.originalLeft-leftd + 'px';
  	} else {
  		if(!this.options.scaleFromTop) d.top = -topd + 'px';
  		d.left = -leftd + 'px';
  	}
      this.element.setStyle(d);
    }
  });

if (typeof loadFirebugConsole=="function") {loadFirebugConsole()};
document.observe("dom:loaded", function(){
    PS = new PS_core();
    new PS_domInit();
    PS.debug("dom:loaded init complete");
	//alert(document.documentMode); what documentMode does IE8 have
    // window.onload = new PS_onload();
    document.whenReady(function(){new PS_whenReady(); ps_js_timings.parshipJsFinished = new Date().getTime();});
});


function getCookie(cookieName) {
	if (!document.cookie) {
		return null;
	}
	var cookieStr = document.cookie;
	var cookies = cookieStr.split(";");
	for (i=0; i<cookies.length; i++) {
		var cookie = cookies[i];
		var cookieKeyVal = cookie.split("=",2);
		if (cookieKeyVal[0].trim() == cookieName) {
			return cookieKeyVal[1];
		}
	}
	return null;
}

function setCookie(cookieName, cookieVal) {
	var lifetime = null; // optionaler 3. Parameter, cookie lifetime in sec
	var domain = null; // optionaler 4. Parameter
	var parameters;
	var arglength = 2;
	if (typeof setCookie.arguments === "undefined") {
		parameters = arguments
	} else {
		parameters = setCookie.arguments;
	}
	if (parameters.length > 2) {
		lifetime = parameters[2];
	}
	if (parameters.length > 3) {
		domain = parameters[3];
	}

	var cookieStr = cookieName+"="+cookieVal+"; path=/";
	if (lifetime != null) {
		var expires = lifetime;
		if (lifetime != -1){
			var ablauf = new Date();
			ablauf.setTime(ablauf.getTime() + lifetime*1000);
			expires = ablauf.toGMTString();
		}
		cookieStr += "; expires=" + expires;
	}
	if (domain != null) {
		cookieStr += "; domain=" + domain;
	}
	document.cookie = cookieStr;
}

function getMainDomain(fullDomain) {
	var pattern = /^.*?((\.?[^.]+?)(\.([^.]+?)\.[^.]+?))$/;
	var result = pattern.exec(fullDomain);
	if (result) {
		var secondleveldomainPart = result[4];
		var secondleveldomain = result[3];
		if (secondleveldomainPart == "co" || secondleveldomainPart == "com") {
			secondleveldomain = result[1];
		}
		return secondleveldomain;
	}
	return fullDomain;
}

String.prototype.trim = function() {
	return (this.replace(/^\s\s*/, '').replace(/\s\s*$/, ''));
}

//On welcomepage - in newAtParship-Box
function sendAGreeting(partner, url){
	new Ajax.Request(url, {
		parameters: { partner: partner},
		onSuccess: function showMe(response){
			var myJson = response.responseText.evalJSON();
			if(myJson.messageId.id) {
				Modalbox.show($('ps_modal_greetings'), {width: 340,  skin: '1', hideCloseLink: false});
				if($('ps_greeting_' + partner) != null) {
					$('ps_greeting_' + partner).hide();
					//Show link to send greetings message
					if ($('ps_greeted_' + partner) != null) {
						elem = $('ps_greeted_' + partner);
						elem.show();
						//elem.observe("click", gotoGreeted()"+ elem.href + myJson.messageId.id+ "'");
						Event.observe(elem, "click", gotoGreeted.bindAsEventListener(this, elem.href + myJson.messageId.id));
						Event.stop();
					}
				}
			}

		}
	});
}
function gotoGreeted(elem, url) {
	document.location.href = url;
}

function onFunctionAvailable(sMethod, oCallback, oObject, bScope){
	if (typeof(eval(sMethod)) === 'function') {
		alert("onFunctionAvailable ready");
	    bScope ? oCallback.call(oObject) : oCallback(oObject);
	}
	else {
	    setTimeout(function(){
	        onFunctionAvailable(sMethod, oCallback, oObject, bScope);
	    }), 50
	}
}
