﻿jQuery.fn.ReadyValidate = function(settings) {
  //Udvider settings
  settings = jQuery.extend({
    //Af typen function
    //Hvis valideringen mislykkes fyres denne event.
    onValidateFalse: null,
    /*
    Af typen function eller string
    Hvis valideringen mislykkes fyres denne event
    for hvert failede felt
    String'en vil blive sat på elementet, som
    klasse. Functionen vil blive fyret når fejlen sker
    */
    onFieldValidateFalse: "invalid",
    //Af typen function
    //Hvis valideringen går godt fyres denne event.
    onValidateTrue: null,
    /*
    Af typen function eller string
    Hvis valideringen går godt fyres denne event
    for hvert felt
    String'en vil blive sat på elementet, som
    klasse. Functionen vil blive fyret efter validering
    */
    onFieldValidateTrue: "valid",
    //valiederingsparametrene
    valArr: null,
    //The fields that can be validated
    fieldSelect: "input, select, textarea",
    /*
    Sæt til false hvis du ikke ønsker at
    pluginet skal åbne en alert hvis
    valideringen fejler.
    */
    fireAlert: true,
    /*
    Default er "a-z"
    Ved at skrive noget andet kan du selv definere valide
    alphakarakterer. Det skal angives i regex formatet.
    Pluginet sørger automatisk for at tage både store 
    og små bogstaver med
    */
    allAlpha: null,
    /*
    Default er "\\d"
    Ved at skrive noget andet kan du selv definere valide
    tal. Det skal angives i regex formatet.
    Pluginet sørger automatisk for at tage både store 
    og små bogstaver med
    */
    allNumeric: null,
    /*
    Default er "áàâåãäæçéèêëíìîïñóòôøõößúùûüÿ"
    Ved at skrive noget andet kan du selv definere valide
    ekstrakarakterer. Det skal angives i regex formatet.
    Pluginet sørger automatisk for at tage både store 
    og små bogstaver med.
    */
    allExtra: null,
    /*
    Hvis din submitbutton fx er en grafik kan du skrive 
    selectoren på den, ind her og dermed tilmelde den
    som submitknap.
    */
    submitBtn: null,
    /*
    Sæt til true hvis default value skal valideres som en indtastet tekst.
    */
    allowDefaultValue: false
  }, settings);
  Validater.allAlpha = settings.allAlpha ? settings.allAlpha : Validater.allAlpha;
  Validater.allNumeric = settings.allNumeric ? settings.allNumeric : Validater.allNumeric;
  Validater.allExtra = settings.allExtra ? settings.allExtra : Validater.allExtra;
  //Hvis nogle formularer er valgt gør vi videre
  if (this[0]) {
    //Hver formular behandles selvstændigt.
    //Det er altså muligt at håndtere flere formularer på samme side.
    this.each(function() {
      //formularens egen submit gemmes
      var submit = this.onsubmit,
      //formularen jQueryfiseres
          jQform = jQuery(this),
          submitBtn = jQform.find(settings.submitBtn);
      //formularens egen submit fjernes
      this.onsubmit = null;
      /*
      Test om der er en knap vi skal tilmeldevores event
      Dette er i realiteten et hack for at klare dynamicweb
      formularer.
      */
      if (submitBtn[0]) {
        submitBtn.each(function() {
          /*
          Vi fjerner events der allerede er tilknyttet knappen
          Dette gøres hovedsageligt for at tækkes dynamicweb,
          der syntes den er verdensmester i at styre sådan noget.
          */
          this.onclick = null;
          jQuery(this).click(function () { return Validater.submitForm(settings, jQform, submit, settings.allowDefaultValue); });
        });
      }
      //Vi binder vores egen event til formularens onSubmit
      jQform.bind("submit", function () { return Validater.submitForm(settings, jQform, submit, settings.allowDefaultValue); });

      //vælge alle felterne

      var allfields = jQform.find(settings.fieldSelect);
      allfields.each(function(i) {
        var jQele = jQuery(this);

        for (var y = 0; y < settings.valArr.length; y++) {
          if (jQele.filter(settings.valArr[y][1])[0]) {
            jQele.attr("valIndex", i);
            if (jQele.attr("valID") && jQele.attr("valID") !== "") {
              jQele.attr("valID", jQele.attr("valID") + "," + y);

            } else {
              jQele.attr("valID", y);
            }
            jQele.bind("blur", function() {
              Validater.submitForm(settings, jQform, submit, jQuery(this), settings.allowDefaultValue);
            });

          }
        }
      });
    });
  }
  return this;
};

/*
Validater er en klasse med statiske metoder.
*/
Validater = {
  allAlpha: "a-z",
  allNumeric: "\\d",
  allExtra: "áàâåãäæçéèêëíìîïñóòôøõößúùûüÿ_",
  // returnerer true hvis det er en ægte email
  ismail: function(str) {
    var t = Validater.allAlpha + Validater.allNumeric + Validater.allExtra;
    var regexp = new RegExp("^[" + t + "][" + t + "\\.\\-]*@[" + t + "][" + t + "\\.\\-]*\\.[" + Validater.allAlpha + "]{2,6}$", "i");
    return !(!this.notempty(str) || !regexp.test(str) || /(\.@|\-@|@\.|@\-|\-\-|\.\.|\-\.|\.\-)/g.test(str));
  },
  // returnerer true hvis telefonnummeret er korrekt
  isphonenumber: function(str) {
    return !(this.notempty(str) || !str.match(/^[0-9]{8}$/));
  },
  // returnerer true hvis string'en ikke er tom
  notempty: function (str) {
    return (str !== null) && (str.length > 0);
  },
  // returnerer true hvis string'en kun indeholder disse karakterer A-Å eller a-å
  isalpha: function(str, allAlpha) {
    var re = new RegExp("[^" + Validater.allAlpha + Validater.allExtra + "]", "gi");
    return !re.test(str);
  },
  // returnerer true hvis string'en kun indeholder tal fra 0-9
  isnumeric: function(str) {
    var re = /[\D]/g;
    return !re.test(str);
  },
  // returnerer true hvis string'en kun indeholder disse karakterer eller tal
  // A-Å, a-å or 0-9
  isalphanumeric: function(str) {
    var re = new RegExp("[^" + Validater.allAlpha + Validater.allExtra + Validater.allNumeric + "]", "gi");
    return !re.test(str);
  },
  // returnerer true hvis string'ens længde er præcis "len"
  islength: function(str, len) {
    return str.length === len;
  },
  // returnerer true hvis string'ens længde er mellem "min" og "max"
  islengthbetween: function(str, min, max) {
    return (str.length >= min) && (str.length <= max);
  },
  // returnerer true hvis string'en er en dato i et af formaterne...
  // mm dd yyyy, mm/dd/yyyy, mm.dd.yyyy, mm-dd-yyyy
  // dd mm yyyy, dd/mm/yyyy, dd.mm.yyyy, dd-mm-yyyy
  isdate: function(str, monthFirst) {
    var re = /^(\d{1,2})[\s\.\/-](\d{1,2})[\s\.\/-](\d{4})$/;

    if (!re.test(str)) { return false; }
    var result = str.match(re);
    try {
      var d = parseInt(result[1]);
      var m = parseInt(result[2]);
      var y = parseInt(result[3]);
      if (monthFirst) {
        var m = parseInt(result[1]);
        var d = parseInt(result[2]);
        var y = parseInt(result[3]);
      }
      if (m < 1 || m > 12 || y < 1900 || y > 2100) { return false; }
      var daysInMonth = [null, 31, y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
      return (d >= 1 && d <= daysInMonth[m]);
    } catch (ex) {
      return false;
    }
  },
  // returnerer true hvis "str1" er den samme som "str2"
  ismatch: function(str1, str2) {
    return str1 === str2;
  },
  // returnerer true hvis string'en kun indeholder whitespaces
  // cannot check a password type input for whitespace
  iswhitespace: function(str) { // NOT USED IN FORM VALIDATION
    var re = /[\S]/g;
    return !re.test(str);
  },
  // returnerer true hvis customtjekket bliver overholdt
  customcheck: function(str, re) {
    return !re.test(str);
  }
};

Validater.submitForm = function (settings, jQform, submit, lastEle, allowDefaultValue) {
  /*
  Når formularen submittes kommer vi hertil
  Valideringsarrayet køres igennem og for 
  hver af dem tjekker vi om feltet skal
  valideres og om det så også validerer.
  */
  var invalids = [],
      valids = [],
      allfields = jQform.find(settings.fieldSelect),
      invalidTxts = "";
  for (var i = 0; i < allfields.length; i++) {
    var jQele = jQuery(allfields[i]);
    if (jQele.attr("valID") && jQele.attr("valID") !== "") {
      var invalidTxt = Validater.validateField(jQele, settings.valArr, allowDefaultValue);
      if (invalidTxt !== "") {
        invalidTxts += invalidTxt;
        invalids.push([jQele, settings.valArr]);
      } else {
        valids.push([jQele, settings.valArr]);
      }
      if (lastEle && lastEle.attr("valIndex") === i.toString()) {
        break;
      }
    }
  };

  //Hvis der er sendt et lastEle med skal alerten
  //ikke vises
  if (!lastEle) {
    //Tjekker om nogen felter fejlede valideringen
    if (invalids.length == 0) {
      //Hvis ingen felter fejlede, fyres onValidateTrue
      //hvis ellers den indeholder en metode
      if (settings.onValidateTrue) { settings.onValidateTrue(this); }
      //Har formularen i forvejen en submitmetode
      //tilmeldt fyres den her. Ellers returnerer
      //vi bare true, da formularen så kan sende
      //sit indhold til serveren
      if (submit) {
        return submit(this);
      } else {
        return true;
      }
    }

    //Valideringsteksten alertes og onValidateFalse fyres
    alert(invalidTxts);
  }
  //Advarer alle success felter
  for (var i = 0; i < valids.length; i++) {
    Validater.fieldSuccess(settings, valids[i][0], valids[i][1][2]);
  }
  //Advarer alle fejlede felter
  for (var i = 0; i < invalids.length; i++) {
    Validater.fieldFailed(settings, invalids[i][0], invalids[i][1][2]);
  }

  if (!lastEle && settings.onValidateFalse) { settings.onValidateFalse(this); }
  return false;
};
/*
Denne statiske metode sørger for at den valgte failting sker.
*/
Validater.fieldFailed = function(settings, ele, failStr) {
  var jQele = jQuery(ele).removeClass(settings.onFieldValidateTrue);
  if (settings.onFieldValidateFalse && typeof settings.onFieldValidateFalse === "string") {
    jQele.addClass(settings.onFieldValidateFalse);
  } else if (settings.onFieldValidateFalse && typeof settings.onFieldValidateFalse === "function") {
    settings.onFieldValidateFalse(ele, failStr);
  }
};
/*
Denne statiske metode sørger for at den valgte successting sker.
*/
Validater.fieldSuccess = function(settings, ele) {
  var jQele = jQuery(ele).removeClass(settings.onFieldValidateFalse);
  if (settings.onFieldValidateTrue && typeof settings.onFieldValidateTrue === "string") {
    jQele.addClass(settings.onFieldValidateTrue);
  } else if (settings.onFieldValidateTrue && typeof settings.onFieldValidateTrue === "function") {
    settings.onFieldValidateTrue(ele);
  }
};
/*
Denne statiske metode validerer et enkelt felt
*/
Validater.validateField = function (jQele, valArr, allowDefaultValue) {
  var str = jQele.val(),
      valIDs = jQele.attr("valID").split(","),
      validationText = "";
  if (jQele[0] && !allowDefaultValue && str === jQele[0].defaultValue) { 
    str = "";
  }
  for (var i = 0; i < valIDs.length; i++) {
    var y = parseInt(valIDs[i]),
    /*
    Her benyttes Validater klassen til at tjekke
    om feltet validerer. Det udnyttes af alle 
    objekter også kan findes på deres string navn.
    */
    isValid = Validater[valArr[y][0].toLowerCase()](str, valArr[y][3], valArr[y][4]);
    if (!isValid) {
      //Der laves den samlede valideringstekst
      validationText += valArr[y][2] + "\n";
    }
  }
  return validationText;
};
