/*  
    3OS JAVASCRIPT FUNCTIONS 
    $.fn.triax  : replaces html() content with result, coming as json "result.html", datatype plain
    $.triax     : makes a general ajax call with specifying of the success handler, handling post, datatype json    
*/

// SCROLLTO PLUGIN

/**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 5/25/2009
 * @author Ariel Flesler
 * @version 1.4.2
 *
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 */
;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);

// SOME COMMON FUNCTIONS
(function($){
    $.fn.getElementPos = function(translatex, translatey) {
        if(typeof translatex == 'undefined') translatex = 0;
        if(typeof translatey == 'undefined') translatey = 0;
        if(isNaN(translatex)) translatex=0;
        if(isNaN(translatey)) translatey=0;
        return [$(this).offset().left + translatex - $(document).scrollLeft(), $(this).offset().top + translatey - $(document).scrollTop()];
    }

    $.createServiceAlert = function(title, text) {        
        if($('#serviceDialog').length == 0) {
            $('body').append('<div id="serviceDialog" style="display:none"></div>');                         
        }        
        $('#serviceDialog').html(text).dialog(
                { buttons: 
                    { "Ok": function() { $(this).dialog("close"); } },
                  title: title  
        });
    }
    
    $.strReplace = function(search, replace, subject, count) {
        f = [].concat(search),
        r = [].concat(replace),
        s = subject,
        ra = r instanceof Array, sa = s instanceof Array;    s = [].concat(s);
        if (count) {
            this.window[count] = 0;
        }
         for (i=0, sl=s.length; i < sl; i++) {
            if (s[i] === '') {
                continue;
            }
            for (j=0, fl=f.length; j < fl; j++) {            temp = s[i]+'';
                repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
                s[i] = (temp).split(f[j]).join(repl);
                if (count && s[i] !== temp) {
                    this.window[count] += (temp.length-s[i].length)/f[j].length;
                }
            }
        }
        return sa ? s : s[0];
    }
    
    // accepts birth date in format: YYYY-MM-DD
    $.getAge = function(string) {
        var parts = String(string).split(/[- :]/);
        var byear = parseInt(parts[0]);
        var bmonth = parseInt(parts[1]);
        var bday = parseInt(parts[2]);
        var currDay = new Date();
        var day = currDay.getDate()
        var month = currDay.getMonth() + 1;
        var year = currDay.getFullYear();
        // diff
        var diff = year-byear;
        // is it already past the date in this year?
        if(bmonth < month) {
            return diff;
        } else if(bmonth == month) {
            if(bday <= day) {
                return diff;
            } else {
                return diff-1;
            }
        } else {
            return diff-1;
        }         
    };
    
}(jQuery)); 

jQuery.extend(jQuery.expr[':'], {
    focus: function(element) { 
        return element == document.activeElement; 
    }
});

// AJAX HANDLING: THE TRIAX
(function($){
    // !PUBLIC
    $.ajaxSetup({
        async: true,
        cache: false,
        dataType: 'json',
        error: function(XMLHttpRequest, textStatus) {
            $.createServiceAlert('Connection error', "Server connection failed or timeout:<br />" + textStatus);                
        },
        global: true,
        timeout: 5000,
        type: "POST"
    });
   
    // !PUBLIC
    var createAjaxPath = function(module, script) {
        return (PATH + "?ajax=" + module + "-" + script); 
    }   
    
    // !PUBLIC
    var getAjaxParams = function(data, module, script, successHandler, errorHandler) { 
        var params = {
                url: createAjaxPath(module, script),
                success: successHandler,
                data: data
            };
        if(typeof errorHandler == 'function') {
            $.extend(params, {error: errorHandler});
        }
        return params;
    }    
    
    
    // PUBLIC: triax to replace element innerHtml by new content
    $.fn.triax = function(data, module, script, successHandler) {                         
        $.ajaxSetup({dataType: 'text'});
        $(this).load(createAjaxPath(module, script), data, successHandler);        
        $.ajaxSetup({dataType: 'json'});
        return this;                                    
    }
    
    // PUBLIC: JSON ajax handler
    $.triax = function(data, module, script, successHandler, errorHandler) {        
        var commonSuccess = function(data) {
            // check for JSON compatibility
            if(!$.isPlainObject(data)) {
                $.createServiceAlert('Wrong data', 'obtained data type is not JSON:<br /><br />' + data + '<br />module: ' + module + ', script: ' + script);
                if(typeof errorHandler == 'function') errorHandler(data);
                return;                             
            }
            // check for error handling
            if(typeof data.error == 'string') {
                $.createServiceAlert('Service error', data.error + '<br />module: ' + module + ', script: ' + script);                
                if(typeof errorHandler == 'function') errorHandler(data);
                return;    
            }
            successHandler(data);
        };
        $.ajax(getAjaxParams(data, module, script, commonSuccess, errorHandler));
    }
    
}(jQuery));

// AJAXFORM: EASY WAY TO EDIT / CREATE INFORMATION FROM THE PAGE
(function($){

    // PUBLIC: data converter form->item
    var convertFormToData = function(name, settings) {
      var hodnota = '';
      // detect all inputs, labels, place to plot final value
      var $inputs = $(settings.dialog).find('div.content')
        .find('input[name=' + name + '],textarea[name=' + name + '],select[name=' + name + ']');
      // save labels
      var $labels = $(settings.dialog).find('div.content').find('label[for]');    
      // search for a place of change
      var $placeHolder = $(settings.parentFinder).find('.' + name);
      if($placeHolder.length == 0) return;
      // treat data by inputs 
      $inputs.each(function(index) {
        // checkbox
        // determine label, send label if checked
        if($(this).is("input[type=checkbox]")) {
          if($(this).is(":checked")) {
            var $label = $labels.filter('label[for=frmVal_' + name + ']');
            if($label.length > 0) {
              hodnota = $label.html(); 
            }
          }
        // radio  
        // determine correct radio due to label and mark
        } else if($(this).is("input[type=radio]")) {
          if($(this).is(":checked")) {
            var $label = $labels.filter('label[for=frmVal_' + name + '_' + $(this).val() + ']');
            if($label.length > 0) {
              hodnota = $label.html(); 
            }
          }
        // select
        // use options to match value
        } else if($(this).is("select")) {
          var $option = $(this).find('option:selected');          
          if($option.length > 0) {
            hodnota = $option.html();    
          }
        // normal input / textarea, use val()
        } else {
          hodnota = $(this).val();  
        }
      });
      $placeHolder.html(hodnota);
    };
    
    // PUBLIC: data converter item->form
    var convertDataToForm = function(name, settings) {
      var $placeHolder = $(settings.parentFinder).find('.' + name);
      if($placeHolder.length == 0) return;
      var hodnota = $placeHolder.html();
      
      // detect all inputs 
      var $inputs = $(settings.dialog).find('div.content')
        .find('input[name=' + name + '],textarea[name=' + name + '],select[name=' + name + ']');
    
      // detect all labels
      var $labels = $(settings.dialog).find('div.content').find('label[for]');
    
      $inputs.each(function(index) {
        // checkbox
        // determine label and check the box if contained
        if($(this).is("input[type=checkbox]")) {
          var $label = $labels.filter('label[for=frmVal_' + name + ']');
          if($label.length > 0) {
            $(this).removeAttr('checked');
            if(hodnota.indexOf($label.html()) > -1) {
              $(this).attr('checked', 'checked');
            }
          }
        // radio  
        // determine correct radio due to label and mark
        } else if($(this).is("input[type=radio]")) {
          var $label = $labels.filter('label[for=frmVal_' + name + '_' + $(this).val() + ']');          
          if($label.length > 0) {
            $(this).removeAttr('checked');
            if(hodnota.indexOf($label.html()) > -1) {
              // helper: clear all radios that are checked of that name              
              $(this).attr('checked', 'checked');
            }
          }  
        // select
        // use options to match value
        } else if($(this).is("select")) {
          var $options = $(this).find('option');          
          $options.each(function(index){
            $(this).removeAttr('selected');
            if(hodnota.indexOf($(this).html()) > -1) {
              $(this).attr('selected', 'selected');
            }    
          });
        // normal input / textarea, use val()
        } else {
          $(this).val(hodnota);  
        }
      });
    }
    
    // !PUBLIC: initial settings
    var ajaxFormDefaults = {
      dialog: '#dialog',    // selector to display as dialog.
                            // we expect a "div.wait" and "div.content" in them,
                            // which will be switched as needed.      
      transfer: [],         // array of form field names to match. will be searched in "div.content".
                            // if not specified, will be filled automatically due to form contents
      
      parentFinder: $(document),   // element on which to search for transfer classess
      
      // callback for getting data on
      // tries to auto-obtain data from parentFinder
      // !PUBLIC
      getData:  function() {      
        var self = this;
        $.each(this.transfer, function(index, value) {
          convertDataToForm(value, self);
        });
      },  
      
      // callback after window init
      afterInit:  function() {
        // define your code
      },             
      
      // callback after form sent & response obtained
      // @param: data - obtained JSON response 
      afterPost:  function(data) {
        // define your code
      },
      
      // callback for data save (ajax form post)
      // @param: postData - ajaxForm passess a collection of POST data                            
      saveData: function(postData) {
        $.createServiceAlert('Programmer error', 'save data handler not defined');
        $(this.dialog).dialog("close");           
      },
  
      // function to finish after response from AJAX
      // !PUBLIC
      finish: function(data) {
        set.afterPost(data);
        set.setData(data);
        $(set.dialog).dialog("close");
      },    
  
      // function to reopen the form after error
      error: function() {
        set.enable();
      }, 
  
      // callback for data set after back-retrieve
      // @param: data - json object 
      // !PUBLIC
      setData: function(data) {        
        $.each(set.transfer, function(index, value) {
          var $placeHolder = $(set.parentFinder).find('.' + value);
          if($placeHolder.length == 0) return;             
          var changed = false;
          if($.isPlainObject(data.ret)) {
            if(typeof data.ret[value] == 'string') {
              $placeHolder.html(data.ret[value]);
              changed = true;
            }
          }
          if(!changed) convertFormToData(value, set);  
        });
      },
  
      // !PUBLIC
      enable: function() {       
        $(this.dialog).find('div.waiting').hide();
        $(this.dialog).find('div.content').show();   
      },   // handler to enable form in dialog
      
      // !PUBLIC
      disable: function() {       
        $(this.dialog).find('div.content').hide();
        $(this.dialog).find('div.waiting').show();   
      },   // handler to enable form in dialog 
      
      // !PUBLIC
      doDataPost: function() {
        set.disable();
        var postData = {};
        $.each(set.transfer, function(index, value){
          var extendBlock = {};
          extendBlock[value] = $(set.dialog).find('div.content').find('input[name=' + value + '],textarea[name=' + value + '],select[name=' + value + ']').val(); 
          $.extend(postData, extendBlock);                
        });
        // call SAVE DATA handler
        set.saveData(postData);
      },
      
                           
      width: 300,
      position: 'center',
      buttonName: 'Změnit',
      formName: "",
      onlineChecking: true
    
    };

    var dialogOn = [];
    var set = null;

    // PUBLIC:
    // main function, call with settings as you wish 
    $.ajaxForm = function( settings ) {        
        var s = $.extend({}, ajaxFormDefaults, settings);
        // check for same dialog already on
        if($.inArray(s.dialog, dialogOn) !== -1) {
          return;
        } else {
          dialogOn.push(s.dialog);
        }
        set = s;
        
        s.disable();
        // define dialog of entry
        $(s.dialog).dialog({
          title: s.formName,
          width: s.width,
          position: s.position,
          close: function(event) {
            // remove dialog from active ones
            var index = $.inArray(s.dialog, dialogOn);
            if(index > -1) {
              dialogOn.splice(index, 1);
            }
            s.disable();
          },
          buttons: [
            // SAVE DATA BUTTON
            { text: s.buttonName, 
              click: function() {
                // prepare POST collection of values
                if(s.onlineChecking) {
                  $(s.dialog).onlineCheckSubmit(s.doDataPost, s.dialog); 
                } else {
                  s.doDataPost();
                }                      
              }
            } 
          ]  
        });
        $(s.dialog).data('onlineForm', 1);
        if(s.onlineChecking) {
          // install focusout on all&every
          $(s.dialog).find(chkSelector).focusout(function(event) {
            $(this).checkValue(null, s.dialog);
          });
        }
        // define transfer if not defined 
        if(s.transfer.length == 0) {
          $(s.dialog).find('div.content').find('input[name],select[name],textarea[name]').each(function(index){
            var name = $(this).attr('name');
            if($.inArray(name, s.transfer) === -1) {
              s.transfer.push(name);
            }
          });
        }
        s.getData();
        s.afterInit();
        s.enable();
    }  
}(jQuery));

// checking support
(function($){
    // check lang definition for both client & server
    $.langChecks = {
        cz: {
          chk_mandatory: 'Tento prvek je povinný a musíte jej vyplnit',
          chk_mandatoryallstates: 'Tento prvek je povinný a musíte jej vyplnit',
          chk_number: 'Musíte vložit číslo',
          chk_negativenumber: 'Musíte vložit (možno i záporné) číslo',
          chk_usernick: 'Pouze znaky a-z, A-Z, 0-9, pomlčka a podtržítko jsou povoleny',
          chk_lowerusernick: 'Pouze znaky a-z, 0-9, pomlčka a podtržítko jsou povoleny',
          chk_identify: 'Pouze znaky a-z, 0-9 a pomlčka jsou povoleny',
          chk_float: 'Musíte vložit číslo (možno i v desetinné formě, vč. záporných)',
          chk_tel: 'Musíte vložit telefonní číslo - akceptujeme pouze číslice, mezery a znak +',
          chk_email: 'Musíte vložit emailovou adresu',
          chk_httpurl: 'Musíte vložit URL odkaz na webovou stránku (včetně http://)',
          chk_realname: 'Pouze znaky z abecedy, čísla 0-9, tečka, mezera, čárka a pomlčka jsou povoleny',
          chk_date: 'Vyžadováno platné datum ve formátu RRRR-MM-DD',
          chk_captcha: 'Chybně opsaný kontrolní kód',
          chk_dateDMY: 'Datum je chybné. Zadejte korektně v DD.MM.RRRR formátu.',
          chk_minlen: 'Minimální délka je %%NUM%% znak(ů)',
          chk_exactlen: 'Délka musí být přesně %%NUM%% znak(ů)',
          chk_maxlen: 'Maximální délka je %%NUM%% znak(ů)' 
        },
        en: {          
          chk_mandatory: 'Item is required, but no value entered.',
          chk_mandatoryallstates: 'Item is required, but no value entered.',
          chk_number: 'Item is not a decimal number',
          chk_negativenumber: 'Item is not decimal (possibly negative) number',
          chk_usernick: 'Only characters a-z, A-Z, 0-9, dash and underscore are allowed',
          chk_lowerusernick: 'Only characters a-z, 0-9, dash and underscore are allowed',
          chk_identify: 'Only characters a-z, 0-9 and dash are allowed',
          chk_float: 'Item is not a real number. Please enter real number in natural form (with , or . as decimal separator, possibly negative)',
          chk_tel: 'Item is not a telephone number. Telephone number in international format can only contain digits, whitespaces and + sign.',
          chk_email: 'Item is not a valid email address.',
          chk_httpurl: 'Item is not a valid URL of HTTP protocol. In order to insert correct URL address we advise you to copy it directly from the location bar of your web browser.',
          chk_realname: 'Only characters from alphabet, digits 0-9, ".", "-", "," and whitespaces are allowed.',
          chk_date: 'Valid date in the format of YYYY-MM-DD is required.',
          chk_captcha: 'Wrongly typed CAPTCHA code.',
          chk_dateDMY: 'Date not valid - expecting in proper DD.MM.YYYY format.',
          chk_minlen: 'Item must be at least %%NUM%% character(s) long',
          chk_exactlen: 'Item length must be EXACTLY %%NUM%% character(s)',
          chk_maxlen: 'Item length is limited to %%NUM%% character(s)'
        }
    }; 
    // check client functions
    $.clientChecks = {
        chk_mandatory: function(value) { return (value != ''); },
        chk_mandatoryallstates: function(value) { return /^.+$/.test(value); },
        chk_number: function(value) { return /^[0-9]+$/.test(value); },
        chk_negativenumber: function(value) { return /^-?[0-9]*$/.test(value); },
        chk_usernick: function(value) { return /^[a-zA-Z0-9_\-]+$/.test(value); },
        chk_lowerusernick: function(value) { return /^[a-z0-9\-\_]+$/.test(value); },
        chk_identify: function(value) { return /^[a-z0-9\-]+$/.test(value); },
        chk_float: function(value) { return /^-?[0-9]*[\,\.]?[0-9]*$/.test(value); },
        chk_tel: function(value) { return /^[\d\+\s]+$/.test(value); },
        chk_email: function(value) { return /^([*+!.&#$¦\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,4})$/i.test(value); },
        chk_httpurl: function(value) { return /^http\:\/\/[a-zA-Z0-9\.\-\/\,\?\'\\\+&%\$#\=\~\_\-\@]*$/.test(value); }   
    };       
    // check server-side scripts
    $.serverChecks = {
        chk_realname: { module: 'generic', script: 'checkRealName' },
        chk_captcha: { module: 'generic', script: 'checkCaptcha' },
        chk_dateDMY: { module: 'generic', script: 'checkDateDMY' },
        chk_date: { module: 'generic', script: 'checkDate' }
    };
    // returns state of the element
    // values:
    //  1 -- checking in progress
    //  2 -- error
    //  3 -- waiting for AJAX response(s)
    //  4 -- item is OK     
    $.fn.errorState = function(state) {
        $(this).data('checkStatus', state);
        if($(this).data('checkStatus') == 4) {
            $(this).addClass('correct');
        } else {
            $(this).removeClass('correct');
        } 
        return this;     
    };

    // add an error if not already having one
    $.fn.throwError = function(errorString) {
        $(this).data('checkStatus', 2); // has error    
        $(this).data('checkError', errorString);            
        var w = $(this).width(); 
        if($(this).parent('div.frmError').length == 0) {
            $(this).removeClass('correct');
            $(this).wrap('<div class="frmError"></div>');
            if($(this).attr('type')=='checkbox') {
                $(this).after('<span style="width: auto;">' + errorString + '</span>');
            } else {
                $(this).after('<span style="width: ' +  w + 'px">' + errorString + '</span>');
            }
        }    
        return this;    
    };
    
    $.fn.clearErrors = function() {
        $(this).data('checkStatus', 1);
        $(this).data('checkError', ''); 
        if($(this).parent('div.frmError').length > 0) {
            $(this).next('span').remove();
            $(this).unwrap();
        }       
    };        
    
    $.fn.checkValue = function(setFunction, par) {
        var $self = $(this);
        if($self.errorState() > 2) {
            return $self;
        }
        $self.clearErrors();         
        // get all checks
        var classes = $self.attr('class');
        var clArray = classes.split(' ');  
        // different on checkbox
        var formValue;
        if($self.attr('type') == "checkbox") {
            if($self.is(':checked')) {
                formValue = $.trim($self.val()); 
            } else {
                formValue = '0';
            }
        } else {
            formValue = $.trim($self.val());    
        }       
        $self.attr('disabled', true);
        var serverLookups = [];
        var resultStatus = true;
        $.each(clArray, function(i, val) {
            if(!resultStatus) return;
            // find all checks           
            if(val.indexOf('chk_', 0) != -1) {
                // is it one of the maxlen, minlens, exactlens?
                if(val.indexOf('chk_minlen', 0) == 0) {
                    var chars = parseInt(val.substring(10));
                    if(!isNaN(chars)) {
                        if(formValue.length < chars) {
                            resultStatus = false;
                            $self.throwError($.strReplace("%%NUM%%", chars, $.langChecks[LANG]['chk_minlen']));
                        } 
                    }
                } else if(val.indexOf('chk_maxlen', 0) == 0) {
                    var chars = parseInt(val.substring(10));
                    if(!isNaN(chars)) {
                        if(formValue.length > chars) {
                            resultStatus = false;
                            $self.throwError($.strReplace("%%NUM%%", chars, $.langChecks[LANG]['chk_maxlen']));
                        } 
                    }
                } else if(val.indexOf('chk_exactlen', 0) == 0) {                    
                    var chars = parseInt(val.substring(12));
                    if(!isNaN(chars)) {
                        if(formValue.length != chars) {
                            resultStatus = false;
                            $self.throwError($.strReplace("%%NUM%%", chars, $.langChecks[LANG]['chk_exactlen']));
                        } 
                    }
                } else if(typeof $.clientChecks[val] == 'function') {
                    // test client-side checks
                    if(!(resultStatus = $.clientChecks[val](formValue))) {
                        $self.throwError($.langChecks[LANG][val]);
                    }       
                } else {
                    // NOT FOUND IN CLIENT-SIDE?
                    // store them for latter testing
                    serverLookups.push(val);
                }    
            }
        }); 
        // only do this if all client-side checks are OK
        if(resultStatus) {             
            $self.errorState(3);
            if(serverLookups.length > 0) {
                $self.data('numberLookups', 0);
                $.each(serverLookups, function(i, val) {
                    // search for server-side scripts of that name                    
                    if($.isPlainObject($.serverChecks[val])) {
                        // found! let's call it by AJAX
                        $self.data('numberLookups', $self.data('numberLookups') + 1);
                        $.triax({value: formValue}, $.serverChecks[val].module, $.serverChecks[val].script, function(data) {                            
                            // success: pass check result into $self
                            if(typeof data['result'] == 'number') {
                                if(data.result == 0) {
                                    $self.throwError($.langChecks[LANG][val]);
                                    var $form = $self.closest("form");
                                    if($form.length > 0) {
                                        if($form.data('firstError') == -1) {
                                            $form.data('firstError', Math.max(($self.offset().top - (Math.round(($(window).height() / 2) - ($(window).height()/4)))), 0));    
                                        }
                                    }                                                                                                              
                                }
                            }
                            // erase or not
                            if($self.data('numberLookups') > 1) {
                                $self.data('numberLookups', $self.data('numberLookups') - 1);     
                            } else {
                                $self.data('numberLookups', 0);                                
                                if($self.data('checkStatus') == 3) {
                                    $self.errorState(4);                                                                    
                                }
                                finishChecking($self, setFunction, par);                                    
                            }
                            //console.log($self.data());    
                        }, function() {
                            // custom error handling: do not throw error, but state success
                            $.createServiceAlert('Checking error', 'Error in connection, online check not working properly');
                            if($self.data('numberLookups') > 1) {
                                $self.data('numberLookups', $self.data('numberLookups') - 1);     
                            } else {
                                $self.data('numberLookups', 0);
                                if($self.data('checkStatus') != 2) {
                                    $self.errorState(4);
                                }                                    
                                finishChecking($self, setFunction, par);
                            }
                        });                                 
                    }
                });
                // no server-side checkers found, bail out with success
                if($self.data('numberLookups') == 0) {
                    $self.errorState(4);                    
                    $self.attr('disabled', false);                         
                }
            } else {
                $self.errorState(4);                
                $self.attr('disabled', false);                    
            }            
        } else {
            $self.attr('disabled', false);
        }
        return this;       
    };
    // what happens after checking 
    var finishChecking = function(element, setFunction, par) {   
        // find parent form
        var $form;
        if(typeof par == 'undefined') {
           $form = $(element).closest("form");
        } else {
           $form = $(par);
        }
        // remove write protection
        $(element).attr('disabled', false);
        // test if form control in progress
        if($form.data('checking') == 1) {
            //console.log($form.data());
            //console.log(element);
            // returned ERROR?
            // if so, cease all checking, empty waitingFor
            if($(element).data('checkStatus') == 2) {
                $form.data('checking', 0);                
                $form.data('waitingFor', []);
                if($(self).data('firstError') > -1) {
                    $(window).scrollTo($(self).data('firstError'), 500)
                }
                $(self).data('firstError', -1);
                //console.log('ajax gave error, form check exit - ' + $(element).attr('name'));
                return;    
            } else {
                if(typeof $form.data('waitingFor') == 'object') {                
                    var index = $.inArray($(element).attr('name'), $form.data('waitingFor'));
                    if(index > -1) {
                        // splice it out
                        $form.data('waitingFor').splice(index, 1);
                        //console.log('removed AJAX from waiting for... ' + $(element).attr('name'));                                              
                    }
                    // alles empty? time to submit
                    if($form.data('waitingFor').length == 0) {
                        // log ok
                        //console.log('success in submit');
                        if($form.data('onlineForm') == 1) {
                          setFunction();  
                        } else {
                          //console.log('submit here');
                          $form.data('checking', 2);
                          $(self).data('firstError', -1);
                          $form.submit();
                        }                        
                    }               
                }       
            }            
        }
    }    
}(jQuery));

// extending
// how to: 
// for client-side: add into collection 
//  chk_something: function(value) {
//      return result_of_value_check - true,1 (OK) OR 0,false (WRONG);
//  }
//                  
// for server-side: add chk_something: {module: 'ajax_module_name', 'ajax_script_name'}
//     AJAX is obtained a "value" in $_POST and after checking 
//      is supposed to return a JSON with "->result" stating 1 (OK) OR 0 (WRONG) 
/*
(function(){
    // sample extend of server-side checking
    $.extend($.serverChecks, {chk_advisory: {module: 'generic', script: 'sample'}});
    // sample extend of client-side checking
    $.extend($.clientChecks, {chk_dumb: function(value) {return true;}});
}(jQuery));
*/

(function(){
    // select all forms with checks
    // alter their onSubmit
    $.fn.onlineCheckSubmit =  function(setFunction, par){       
        var self;
        if(typeof par == 'undefined') {
          self = this;
        } else {
          self = par;
        }
        
        if($(self).data('checking') == 1) return; else {
            $(self).data('checking', 1);
            $(self).data('firstError', -1);
        }
        // determine all checkpoints and check their status values
        var $inputs = $(self).find(chkSelector);
        var waitingFor = [];
        var ok = true;

        $.each($inputs, function(idx, element) {
            if(!ok) return;
            var index = $.inArray($(element).attr('name'), waitingFor);
            switch($(element).data('checkStatus')) {
                // error found. bail out
                case 2:
                    ok = false;
                    if($(self).data('firstError') == -1) {
                        $(self).data('firstError', Math.max(($(element).offset().top - (Math.round(($(window).height() / 2) - ($(window).height()/4)))), 0));    
                    }
                    //console.log('error in already present: ' + $(element).attr('name')) ;
                // item is ok
                case 4:
                    // remove from waitingFor if present
                    if(index > -1) {
                        waitingFor.splice(index, 1);   
                    }
                    return; break;                
                // ajax going on
                case 3:                    
                    if(index == -1) {
                        waitingFor.push($(element).attr('name'));
                        //console.log('added AJAX to waiting for...' + $(element).attr('name'))           
                    }
                    break;
                // item has not been checked. Do check. Store if ajax replied.
                default:          
                    $(element).checkValue(setFunction, par);
                    switch($(element).data('checkStatus')) {
                        case 3:
                            if(index == -1) {
                                waitingFor.push($(element).attr('name'));
                                //console.log('added AJAX from waiting for...' + $(element).attr('name'))         
                            }   
                            return; break;
                        case 2:
                            if($(self).data('firstError') == -1) {
                                $(self).data('firstError', Math.max(($(element).offset().top - (Math.round(($(window).height() / 2) - ($(window).height()/4)))), 0));    
                            }
                            ok = false;
                            //console.log('error from just controlled: ' + $(element).attr('name'));
                        case 4:                            
                            if(index > -1) {
                                waitingFor.splice(index, 1);   
                            }    
                            return; break;
                        default:
                            if($(self).data('firstError') == -1) {
                                $(self).data('firstError', Math.max(($(element).offset().top - (Math.round(($(window).height() / 2) - ($(window).height()/4)))), 0));    
                            }
                            ok = false;
                            return;                    
                    }                                       
            }

        });        
        // result of progress: do we have an OK == false?
        if(ok == false) {
            $(self).data('checking', 0);
            $(self).data('waitingFor', []);
            if($(self).data('firstError') > -1) {
                $(window).scrollTo($(self).data('firstError'), 500)
            }
            $(self).data('firstError', -1);
            //console.log('form check wrong...')       
            return;
        } else {
            // is array of waitings empty?            
            if(waitingFor.length == 0) {
                // success!
                $(self).data('checking', 0);
                $(self).data('waitingFor', []);
                if(setFunction == null) {                                   
                  $(self).data('checking', 2);
                  $(self).data('firstError', -1);
                  self.submit();
                } else {
                  $(self).data('firstError', -1); 
                  setFunction();
                }   
                //console.log('success in submit');
            } else {
                //store waitingFor                
                $(self).data('waitingFor', waitingFor);
                //console.log('form check not finished, put into wait mode..')       
            } 
        }                            
    };
}(jQuery));

var chkSelector = 'input[class*="chk_"],select[class*="chk_"],textarea[class*="chk_"]';    

// startup - enable on ALL form items 
$(document).ready(function(){
 
    var $frms = $('form').has(chkSelector);    
    var $inputs = $(chkSelector);
    
    // for submit, exclude online forms
    $frms.submit(function(event) {
      if($(this).data('checking') == 2) {        
        this.submit();  
      } else {
        if(event.preventDefault) event.preventDefault(); else event.returnValue = false;
        if($(this).data('onlineForm') != 1) {
            $(this).onlineCheckSubmit(null);
          }
      }
          
    }); 
    // for focus out (everytime)
    $inputs.focusout(function(event) {
        
        if($(this).closest("form").length > 0) {
          $(this).checkValue();
        } 
    });
});

// functions for state switch in Forms 
$(document).ready(function(){
    // switch form to different state, send it
    var formStateSwitch = function(event) {
        // first find parent FORM of this mess
        var $form = $(this).parents('form:first');
        if($form.length > 0) {
            // find form_state_switch
            $input = $form.find('input[name="form_state_switch"]');
            if($input.length > 0) {
                $input.val($(this).attr('rel'));
                $form.submit();
            }
        }
    };
    
    $('input[type=button]').filter('.languageStateChanger').click(formStateSwitch)
    
});
