fmsystem-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Fmsystem-commits] [14419] API: update form-validator from upstream


From: Sigurd Nes
Subject: [Fmsystem-commits] [14419] API: update form-validator from upstream
Date: Thu, 19 Nov 2015 10:13:25 +0000

Revision: 14419
          http://svn.sv.gnu.org/viewvc/?view=rev&root=fmsystem&revision=14419
Author:   sigurdne
Date:     2015-11-19 10:13:24 +0000 (Thu, 19 Nov 2015)
Log Message:
-----------
API: update form-validator from upstream

Modified Paths:
--------------
    branches/dev-syncromind/phpgwapi/inc/class.jquery.inc.php
    branches/dev-syncromind/phpgwapi/js/form-validator/README.md
    branches/dev-syncromind/phpgwapi/js/form-validator/date.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/date.js
    branches/dev-syncromind/phpgwapi/js/form-validator/file.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/file.js
    branches/dev-syncromind/phpgwapi/js/form-validator/html5.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/html5.js
    branches/dev-syncromind/phpgwapi/js/form-validator/jquery.form-validator.js
    
branches/dev-syncromind/phpgwapi/js/form-validator/jquery.form-validator.min.js
    branches/dev-syncromind/phpgwapi/js/form-validator/jsconf.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/jsconf.js
    branches/dev-syncromind/phpgwapi/js/form-validator/location.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/location.js
    branches/dev-syncromind/phpgwapi/js/form-validator/security.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/security.js
    branches/dev-syncromind/phpgwapi/js/form-validator/sweden.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/sweden.js
    branches/dev-syncromind/phpgwapi/js/form-validator/uk.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/uk.js

Added Paths:
-----------
    branches/dev-syncromind/phpgwapi/js/form-validator/brazil.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/brazil.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/cz.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/cz.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/de.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/de.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/es.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/es.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/fr.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/fr.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/it.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/it.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/no.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/no.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/pl.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/pl.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/pt.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/pt.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/ro.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/ro.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/ru.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/ru.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/sv.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/lang/sv.js
    branches/dev-syncromind/phpgwapi/js/form-validator/sanitize.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/sanitize.js
    branches/dev-syncromind/phpgwapi/js/form-validator/theme-default.css
    branches/dev-syncromind/phpgwapi/js/form-validator/theme-default.min.css
    branches/dev-syncromind/phpgwapi/js/form-validator/toggleDisabled.dev.js
    branches/dev-syncromind/phpgwapi/js/form-validator/toggleDisabled.js

Removed Paths:
-------------
    branches/dev-syncromind/phpgwapi/js/form-validator/form-test.html
    branches/dev-syncromind/phpgwapi/js/form-validator/qunit.html

Modified: branches/dev-syncromind/phpgwapi/inc/class.jquery.inc.php
===================================================================
--- branches/dev-syncromind/phpgwapi/inc/class.jquery.inc.php   2015-11-19 
00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/inc/class.jquery.inc.php   2015-11-19 
10:13:24 UTC (rev 14419)
@@ -203,57 +203,16 @@
                        $errorMessagePosition = "'top'";
                }
 
-               $translation = '';
-               if(!$times_loaded)//first time only
-               {
-                       //TODO: add translations
-                       $translation = <<<JS
-
-                       var validateLanguage = {
-                                errorTitle : 'Form submission failed!',
-                                requiredFields : 'You have not answered all 
required fields',
-                                badTime : 'You have not given a correct time',
-                                badEmail : 'You have not given a correct 
e-mail address',
-                                badTelephone : 'You have not given a correct 
phone number',
-                                badSecurityAnswer : 'You have not given a 
correct answer to the security question',
-                                badDate : 'You have not given a correct date',
-                                lengthBadStart : 'You must give an answer 
between ',
-                                lengthBadEnd : ' characters',
-                                lengthTooLongStart : 'You have given an answer 
longer than ',
-                                lengthTooShortStart : 'You have given an 
answer shorter than ',
-                                notConfirmed : 'Values could not be confirmed',
-                                badDomain : 'Incorrect domain value',
-                                badUrl : 'The answer you gave was not a 
correct URL',
-                                badCustomVal : 'You gave an incorrect answer',
-                                badInt : 'The answer you gave was not a 
correct number',
-                                badSecurityNumber : 'Your social security 
number was incorrect',
-                                badUKVatAnswer : 'Incorrect UK VAT Number',
-                                badStrength : 'The password isn\'t strong 
enough',
-                                badNumberOfSelectedOptionsStart : 'You have to 
choose at least ',
-                                badNumberOfSelectedOptionsEnd : ' answers',
-                                badAlphaNumeric : 'The answer you gave must 
contain only alphanumeric characters ',
-                                badAlphaNumericExtra: ' and ',
-                                wrongFileSize : 'The file you are trying to 
upload is too large',
-                                wrongFileType : 'The file you are trying to 
upload is of wrong type',
-                                groupCheckedRangeStart : 'Please choose 
between ',
-                                groupCheckedTooFewStart : 'Please choose at 
least ',
-                                groupCheckedTooManyStart : 'Please choose a 
maximum of ',
-                                groupCheckedEnd : ' item(s)'
-                          };
-JS;
-               }
-
                $js = <<<JS
-                       {$translation}
                        $(document).ready(function () 
                        {
                                $.validate({
+                                       lang: 
'{$GLOBALS['phpgw_info']['user']['preferences']['common']['lang']}', // 
(supported languages are fr, de, se, sv, en, pt, no)
                                        modules : {$modules_js},
                                        form: '#{$form_id}',
                                        validateOnBlur : false,
                                        scrollToTopOnError : false,
-                                       errorMessagePosition : 
{$errorMessagePosition},
-                                       language : validateLanguage
+                                       errorMessagePosition : 
{$errorMessagePosition}
                                });
                        });
 JS;

Modified: branches/dev-syncromind/phpgwapi/js/form-validator/README.md
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/README.md        
2015-11-19 00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/README.md        
2015-11-19 10:13:24 UTC (rev 14419)
@@ -1,12 +1,8 @@
 # jQuery Form Validator
 
-With this feature rich jQuery plugin it becomes easy to validate user input 
while keeping your
- HTML markup clean from javascript code. Even though this plugin has **a wide 
range of validation functions**
-it's designed to require as little bandwidth as possible. This is achieved by 
grouping together validation functions
-in "modules", making it possible for the programmer to load **only those 
functions that's needed** to validate a
-particular form.
+jQuery Form Validator is a **feature rich and multilingual** jQuery plugin 
that makes it easy to validate user input while keeping your HTML markup clean 
from javascript code. Even though this plugin has a wide range of validation 
functions it's **designed to require as little network traffic as possible**. 
This is achieved by grouping together validation functions in "modules", making 
it possible to load only those functions that's needed to validate a particular 
form.
 
-**Form demos and full documentation is available at http://formvalidator.net/**
+**Form demos and full documentation available at http://formvalidator.net/**
 
 *Usage example*
 
@@ -40,7 +36,7 @@
 
 ### Support for HTML5
 
-As of version 2.2 (unreleased) you can use this plugin as a fallback solution 
for the validation attributes in the HTML5 spec. Add the module `html5` to the 
module string and you can use the following native features:
+As of version 2.2 (unreleased) you can use this plugin as a fallback solution 
for the validation attributes in the HTML5 spec. Add the module `html5` to the 
module declaration and you can use the following native features:
 
 **Attributes**: require, pattern, maxlength, min, max, placeholder
 
@@ -78,6 +74,7 @@
  * **CVV**
  * **strength** — *Validate the strength of a password*
  * **server** — *Validate value of input on server side*
+ * **letternumeric** — *Validate that the input value consists out of only 
letters and/or numbers*
 
 Read the documentation for the security module at 
[http://formvalidator.net/#security-validators](http://formvalidator.net/#security-validators)
 
@@ -99,7 +96,8 @@
 ### Module: file
  * **mime**
  * **extension**
- * **size**
+ * **size** (file size)
+ * **dimension** (size dimension and ratio)
 
 Read the documentation for the file module at 
[http://formvalidator.net/#file-validators](http://formvalidator.net/#file-validators)
 
@@ -118,7 +116,26 @@
 
 Read the documentation for the UK module at 
[http://formvalidator.net/#uk-validators](http://formvalidator.net/#uk-validators)
 
+### Module: brazil
+ * **brphone** — Validate a brazilian telephone number
+ * **cep**
+ * **cpf** 
 
+### Module: sanitation
+ * **trim**
+ * **trimLeft**
+ * **trimRight**
+ * **upper**  — (convert all letters to upper case)
+ * **lower**  — (convert all letters to lower case)
+ * **capitalize**  — (convert the first letter in all words to upper case)
+ * **insertRight**  — (declare a text that should be inserted at the end of 
the value, attribute data-sanitize-insert-right)
+ * **insertLeft**  — (declare a text that should be inserted at the beginning 
of the value, attribute data-sanitize-insert-left)
+ * **escape**  — (convert < > & ' " to html entities)
+ * **numberFormat**  — (declare the attribute data-sanitize-number-format with 
any of the formats described on http://numeraljs.com/. Note that this rule 
requires that numeral.js is included in the page)
+
+Read the documentation for the sanitation module at 
[http://formvalidator.net/#data-sanitation](http://formvalidator.net/#data-sanitation)
+
+
 ## Writing a custom validator
 You can use the function `$.formUtils.addValidator()` to add your own 
validation function. Here's an example of a validator
 that checks if the input contains an even number.
@@ -215,75 +232,14 @@
 
 Read about how to customize this plugin over at 
[http://formvalidator.net/#configuration](http://formvalidator.net/#configuration)
 
+### Validate On Event ###
+You can cause an element to be validated upon the firing of an event, by 
attaching an attribute to the form input element named 
`data-validation-event="click"`. When the configuration settings have 
`validateOnEvent : true`, the click event will trigger the onBlur validaton for 
that element. Possible use case: Checkboxes. Instead of waiting for the 
checkbox to lose focus (blur) and waiting for a validation to occurr, you can 
specify that elements validation should occur as soon as that checkbox element 
is clicked.
+
 ## Localization
-This plugin contains a set of error dialogs. In case you don't define an 
inline error message the plugin
-will fall back on one of the dialogs below. You can how ever add the attribute 
*data-validation-error-msg* to an
-element, and that message will be displayed instead. All error dialogs can be 
overwritten by passing an
-object into the validation function.
 
-```javascript
-var enErrorDialogs = {
-    errorTitle : 'Form submission failed!',
-    requiredFields : 'You have not answered all required fields',
-    badTime : 'You have not given a correct time',
-    badEmail : 'You have not given a correct e-mail address',
-    badTelephone : 'You have not given a correct phone number',
-    badSecurityAnswer : 'You have not given a correct answer to the security 
question',
-    badDate : 'You have not given a correct date',
-    lengthBadStart : 'You must give an answer between ',
-    lengthBadEnd : 'characters',
-    lengthTooLongStart : 'You have given an answer longer than ',
-    lengthTooShortStart : 'You have given an answer shorter than ',
-    notConfirmed : 'Values could not be confirmed',
-    badDomain : 'Incorrect domain value',
-    badUrl : 'The answer you gave was not a correct URL',
-    badCustomVal : 'You gave an incorrect answer',
-    badInt : 'The answer you gave was not a correct number',
-    badSecurityNumber : 'Your social security number was incorrect',
-    badUKVatAnswer : 'Incorrect UK VAT Number',
-    badStrength : 'The password isn\'t strong enough',
-    badNumberOfSelectedOptionsStart : 'You have to choose at least ',
-    badNumberOfSelectedOptionsEnd : ' answers',
-    badAlphaNumeric : 'The answer you gave must contain only alphanumeric 
characters ',
-    badAlphaNumericExtra: ' and ',
-    wrongFileSize : 'The file you are trying to upload is too large',
-    wrongFileType : 'The file you are trying to upload is of wrong type',
-    groupCheckedTooFewStart : 'Please choose at least ',
-    groupCheckedTooManyStart : 'Please choose a maximum of ', 
-    groupCheckedRangeStart : 'Please choose between ',
-    groupCheckedEnd : ' item(s)'
-};
-```
+This plugin comes with translations for English, German, French Spanish and 
Swedish. You can also choose to override the error
+dialogs yourself. Here you can read more about 
[localization](http://formvalidator.net/#localization)
 
-```html
-<form action="script.php">
-    ...
-</form>
-<script src="js/jquery.min.js"></script>
-<script src="js/form-validator/jquery.form-validator.min.js"></script>
-<script src="js/form-validator/locale.en.js"></script>
-<script>
-  $.validate({
-    language : enErrorDialogs
-  });
-</script>
-...
-```
-
-It's also possible to add inline error messages. If you add attribute 
`data-validation-error-msg` to an element the value of
-that attribute will be displayed instead of the error dialog that the 
validation function refers to.
-
-## Input length restriction
-```html
-<p>
-  History (<span id="maxlength">50</span> characters left)
-  <textarea rows="3" id="area"></textarea>
-</p>
-<script type="text/javascript">
-  $('#area').restrictLength( $('#maxlength') );
-</script>
-```
-
 ## Program Flow
 Form submit() event is bound to jQ func **validateForm()** when the form is 
submitted, it calls
 jQ func **$.formUtils.validateInput**, which calls **validatorFunction** for 
the specific validation
@@ -295,7 +251,30 @@
 
 ## Changelog
 
-#### 2.2.0 (unreleased)
+#### 2.3.0 (unreleased)
+- New translations (Polish, Romanian, Czech, Russian, Italian)
+- Several improvements made to already existing translations
+
+#### 2.2.8
+- The plugin is now again possible to install via bower.
+- Portoguese language pack and validators
+- New module used for data-sanitiation
+- E-mail addresses now validated in accordance to rfc 6531
+- Now possible to use $.fn.validate to programmatically validate inputs
+- Hidden inputs won't get validated by default (can be overriden using option 
validateHiddenInputs)
+
+
+#### 2.2.43
+- Fixed min/max parse error in HTML5 module
+- Now also supports Twitter bootstraps horizontal forms
+- This plugin now also distributes a default CSS theme including success/fail 
icons (used on formvalidator.net)
+- Email validation now won't fail if email begins with a number
+- This plugin now comes with error dialogs translated to English, French, 
German, Spanish and English.
+- New validator `letternumeric`. Validates that input consists out of any type 
of letter (not only alphanumeric) and/or numbers
+- You can now validate image dimension and ratio
+- ... and a bunch of other smaller bug fixes and improvements.
+
+#### 2.2.0
 * Now possible to define an error message for each validation rule on a 
certain input (issue #113)
 * This plugin now serves as a html5 fallback. You can now use the native 
attributes to declare which type
 of validation that should be applied.
@@ -305,8 +284,15 @@
 * Use the attribute data-validation-confirm to declare which input that should 
be confirmed when using validation=confirmation (issue #112)
 * Validation "required" now supports inputs of type radio
 * $.validateForm is now deprecated, use $.isValid instead
+* Possible to check if form is valid programmatically without showing error 
messages
+* Select elements can now be validated server-side
+* Cleaned up dialog messages
+* Various IE8 fixes
+* Possible to send along parameters to the server when using server side 
validation
+* Now possible to set your own parameter name when using server side validation
+* Improved/simplified URL validation
+* ... and a whole lot more small improvements
 
-
 #### 2.1.47
 * Incorrect error-styling when using datepicker or suggestions is now fixed
 * Incorrect error-styling of select elements is now fixed
@@ -332,22 +318,22 @@
  * Correction of the US states in validation "federatestate"
  * Fixed bug in server validation
 
-#### 2.1.9
+#### 2.1.09
  * File validation now support multiple files
  * Length validation can now be used to validate the number of uploaded files 
using a file input that supports multiple files
  * Validation classes is no longer applied on inputs that for some reason 
shouldn't become validated
 
-#### 2.1.8
+#### 2.1.08
  * Now possible to configure the decimal separator when validating float 
values. Use either the
  attribute *data-validation-decimal-separator* or the property 
*decimalSeparator* when
 calling $.validate()
  * $.validationSetup is renamed to $.validate. You will still be able to 
initiate the validation by calling
  the $.validationSetup but it's considered deprecated.
 
-#### 2.1.6
- * Modules can now be loaded from remote website
+#### 2.1.06
+ * Modules can now be loaded from remote websites
 
-#### 2.1.5
+#### 2.1.05
  * Fixed language bug (issue #43 on github)
  * Validation on server side is now triggered by the blur event
  * Now using class names that's compliant with twitter bootstrap 3.x

Added: branches/dev-syncromind/phpgwapi/js/form-validator/brazil.dev.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/brazil.dev.js            
                (rev 0)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/brazil.dev.js    
2015-11-19 10:13:24 UTC (rev 14419)
@@ -0,0 +1,115 @@
+/**
+ * jQuery Form Validator Module: Brazil
+ * ------------------------------------------
+ * Created by Eduardo Cuducos <http://cuducos.me/>
+ *
+ * This form validation module adds validators typically used on
+ * websites in the Brazil. This module adds the following validators:
+ *  - cpf
+ *  - cep
+ *  - brphone
+ *
+ * @website http://formvalidator.net/#brazil-validators
+ * @license MIT
+ * @version 2.2.83
+ */
+
+$.formUtils.addValidator({
+    name : 'cpf',
+    validatorFunction : function(string) {
+
+        // Based on this post from DevMedia:
+        // http://www.devmedia.com.br/validar-cpf-com-javascript/23916
+
+        // clean up the input (digits only) and set some support vars
+        var cpf = string.replace(/\D/g,'');
+        var sum1 = 0;
+        var sum2 = 0;
+        var remainder1 = 0;
+        var remainder2 = 0;
+
+        // skip special cases
+        if (cpf.length !== 11 || cpf === '00000000000') {
+            return false;
+        }
+
+        // check 1st verification digit
+        for (i = 1; i<= 9; i++) {
+            sum1 += parseInt(cpf.substring(i - 1, i)) * (11 - i);
+        }
+        remainder1 = (sum1 * 10) % 11;
+        if (remainder1 >= 10) {
+            remainder1 = 0;
+        }
+        if (remainder1 !== parseInt(cpf.substring(9, 10))) {
+            return false;
+        }
+
+        // check 2nd verification digit
+        for (i = 1; i <= 10; i++) {
+            sum2 += parseInt(cpf.substring(i - 1, i)) * (12 - i);
+        }
+        remainder2 = (sum2 * 10) % 11;
+        if (remainder2 >= 10) {
+            remainder2 = 0;
+        }
+        if (remainder2 !== parseInt(cpf.substring(10, 11))) {
+            return false;
+        }
+
+        return true;
+
+    },
+    errorMessage : '',
+    errorMessageKey: 'badBrazilCPFAnswer'
+
+});
+
+$.formUtils.addValidator({
+    name : 'brphone',
+    validatorFunction : function(string) {
+
+        // validates telefones such as (having X as numbers):
+        // (XX) XXXX-XXXX
+        // (XX) XXXXX-XXXX
+        // XX XXXXXXXX
+        // XX XXXXXXXXX
+        // XXXXXXXXXX
+        // XXXXXXXXXXX
+        // +XX XX XXXXX-XXXX
+        // +X XX XXXX-XXXX
+        // And so on…
+
+        if 
(string.match(/^(\+[\d]{1,3}[\s]{0,1}){0,1}(\(){0,1}(\d){2}(\)){0,1}(\s){0,1}(\d){4,5}([-.
 ]){0,1}(\d){4}$/g)) {
+            return true;
+        }
+
+        return false;
+
+    },
+    errorMessage : '',
+    errorMessageKey: 'badBrazilTelephoneAnswer'
+
+});
+
+$.formUtils.addValidator({
+    name : 'cep',
+    validatorFunction : function(string) {
+
+        // validates CEP  such as (having X as numbers):
+        // XXXXX-XXX
+        // XXXXX.XXX
+        // XXXXX XXX
+        // XXXXXXXX
+
+        if (string.match(/^(\d){5}([-. ]){0,1}(\d){3}$/g)) {
+            return true;
+        }
+
+        return false;
+
+    },
+    errorMessage : '',
+    errorMessageKey: 'badBrazilCEPAnswer'
+
+});

Added: branches/dev-syncromind/phpgwapi/js/form-validator/brazil.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/brazil.js                
                (rev 0)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/brazil.js        
2015-11-19 10:13:24 UTC (rev 14419)
@@ -0,0 +1,8 @@
+/**
+ *  JQUERY-FORM-VALIDATOR
+ *
+ *  @website by 
+ *  @license MIT
+ *  @version 2.2.83
+ */
+$.formUtils.addValidator({name:"cpf",validatorFunction:function(a){var 
b=a.replace(/\D/g,""),c=0,d=0,e=0,f=0;if(11!==b.length||"00000000000"===b)return!1;for(i=1;i<=9;i++)c+=parseInt(b.substring(i-1,i))*(11-i);if(e=10*c%11,e>=10&&(e=0),e!==parseInt(b.substring(9,10)))return!1;for(i=1;i<=10;i++)d+=parseInt(b.substring(i-1,i))*(12-i);return
 
f=10*d%11,f>=10&&(f=0),f!==parseInt(b.substring(10,11))?!1:!0},errorMessage:"",errorMessageKey:"badBrazilCPFAnswer"}),$.formUtils.addValidator({name:"brphone",validatorFunction:function(a){return
 
a.match(/^(\+[\d]{1,3}[\s]{0,1}){0,1}(\(){0,1}(\d){2}(\)){0,1}(\s){0,1}(\d){4,5}([-.
 
]){0,1}(\d){4}$/g)?!0:!1},errorMessage:"",errorMessageKey:"badBrazilTelephoneAnswer"}),$.formUtils.addValidator({name:"cep",validatorFunction:function(a){return
 a.match(/^(\d){5}([-. 
]){0,1}(\d){3}$/g)?!0:!1},errorMessage:"",errorMessageKey:"badBrazilCEPAnswer"});
\ No newline at end of file

Modified: branches/dev-syncromind/phpgwapi/js/form-validator/date.dev.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/date.dev.js      
2015-11-19 00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/date.dev.js      
2015-11-19 10:13:24 UTC (rev 14419)
@@ -9,8 +9,8 @@
  *  - Birth date
  *
  * @website http://formvalidator.net/#location-validators
- * @license Dual licensed under the MIT or GPL Version 2 licenses
- * @version 2.2.beta.58
+ * @license MIT
+ * @version 2.2.83
  */
 (function($) {
 
@@ -45,7 +45,7 @@
             if($el.valAttr('format')) {
                 dateFormat = $el.valAttr('format');
             }
-            else if(typeof conf.dateFormat != 'undefined') {
+            else if(typeof conf.dateFormat !== 'undefined') {
                 dateFormat = conf.dateFormat;
             }
 
@@ -78,4 +78,4 @@
         errorMessageKey: 'badDate'
     });
 
-})(jQuery);
\ No newline at end of file
+})(jQuery);

Modified: branches/dev-syncromind/phpgwapi/js/form-validator/date.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/date.js  2015-11-19 
00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/date.js  2015-11-19 
10:13:24 UTC (rev 14419)
@@ -1 +1,8 @@
-(function($){$.formUtils.addValidator({name:"time",validatorFunction:function(time){if(time.match(/^(\d{2}):(\d{2})$/)===null){return
 false}else{var hours=parseInt(time.split(":")[0],10);var 
minutes=parseInt(time.split(":")[1],10);if(hours>23||minutes>59){return 
false}}return 
true},errorMessage:"",errorMessageKey:"badTime"});$.formUtils.addValidator({name:"birthdate",validatorFunction:function(val,$el,conf){var
 
dateFormat="yyyy-mm-dd";if($el.valAttr("format")){dateFormat=$el.valAttr("format")}else
 if(typeof conf.dateFormat!="undefined"){dateFormat=conf.dateFormat}var 
inputDate=$.formUtils.parseDate(val,dateFormat);if(!inputDate){return false}var 
d=new Date;var currentYear=d.getFullYear();var year=inputDate[0];var 
month=inputDate[1];var day=inputDate[2];if(year===currentYear){var 
currentMonth=d.getMonth()+1;if(month===currentMonth){var 
currentDay=d.getDate();return day<=currentDay}else{return 
month<currentMonth}}else{return 
year<currentYear&&year>currentYear-124}},errorMessage:"",errorMessageKey:"badDate"})})(jQuery);
+/**
+ *  JQUERY-FORM-VALIDATOR
+ *
+ *  @website by 
+ *  @license MIT
+ *  @version 2.2.83
+ */
+!function(a){a.formUtils.addValidator({name:"time",validatorFunction:function(a){if(null===a.match(/^(\d{2}):(\d{2})$/))return!1;var
 b=parseInt(a.split(":")[0],10),c=parseInt(a.split(":")[1],10);return 
b>23||c>59?!1:!0},errorMessage:"",errorMessageKey:"badTime"}),a.formUtils.addValidator({name:"birthdate",validatorFunction:function(b,c,d){var
 e="yyyy-mm-dd";c.valAttr("format")?e=c.valAttr("format"):"undefined"!=typeof 
d.dateFormat&&(e=d.dateFormat);var 
f=a.formUtils.parseDate(b,e);if(!f)return!1;var g=new 
Date,h=g.getFullYear(),i=f[0],j=f[1],k=f[2];if(i===h){var 
l=g.getMonth()+1;if(j===l){var m=g.getDate();return m>=k}return l>j}return 
h>i&&i>h-124},errorMessage:"",errorMessageKey:"badDate"})}(jQuery);
\ No newline at end of file

Modified: branches/dev-syncromind/phpgwapi/js/form-validator/file.dev.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/file.dev.js      
2015-11-19 00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/file.dev.js      
2015-11-19 10:13:24 UTC (rev 14419)
@@ -8,49 +8,78 @@
  *  - file size
  *  - file extension
  *
- * @website http://formvalidator.net/
- * @license Dual licensed under the MIT or GPL Version 2 licenses
- * @version 2.2.beta.58
+ * @website http://formvalidator.net/#file-validators
+ * @license MIT
+ * @version 2.2.83
  */
 (function($, window) {
 
     'use strict';
 
-    var SUPPORTS_FILE_READER = typeof window.FileReader != 'undefined',
+    var SUPPORTS_FILE_READER = typeof window.FileReader !== 'undefined',
 
-        /**
-         * @return {Array}
-         */
-            _getTypes = function($input) {
-            var allowedTypes = $.split( ($input.valAttr('allowing') || 
'').toLowerCase() );
+      /**
+      * @return {Array}
+      */
+      _getTypes = function($input) {
+        var allowedTypes = $.split( ($input.valAttr('allowing') || 
'').toLowerCase() );
+        if ($.inArray('jpg', allowedTypes) > -1 && $.inArray('jpeg', 
allowedTypes) === -1) {
+          allowedTypes.push('jpeg');
+        }
+        else if ($.inArray('jpeg', allowedTypes) > -1 && $.inArray('jpg', 
allowedTypes) === -1) {
+          allowedTypes.push('jpg');
+        }
+        return allowedTypes;
+      },
 
-            if( $.inArray('jpg', allowedTypes) > -1 && $.inArray('jpeg', 
allowedTypes) == -1)
-                allowedTypes.push('jpeg');
-            else if( $.inArray('jpeg', allowedTypes) > -1 && $.inArray('jpg', 
allowedTypes) == -1)
-                allowedTypes.push('jpg');
-            return allowedTypes;
-        },
+      /**
+      * @param {Object} obj
+      * @param {String} key
+      * @param {String} insert
+      * @param {Object} lang
+      */
+      _generateErrorMsg = function(obj, key, insert, lang) {
+        var msg = lang[key] || '';
+        obj.errorMessageKey = ''; // only use message attached to this object
+        obj.errorMessage = msg.replace('\%s', insert);
+      },
 
-        /**
-         * @param {Object} obj
-         * @param {String} key
-         * @param {String} insert
-         * @param {Object} lang
-         */
-            _generateErrorMsg = function(obj, key, insert, lang) {
-            var msg = lang[key];
-            obj.errorMessageKey = ''; // only use message attached to this 
object
-            obj.errorMessage = msg.replace('\%s', insert);
-        },
+      /**
+      * @param {String} msg
+      */
+      _log = function(msg) {
+        if( window.console && window.console.log ) {
+          window.console.log(msg);
+        }
+      },
 
-        /**
-         * @param {String} msg
-         */
-            _log = function(msg) {
-            if( window.console && window.console.log ) {
-                window.console.log(msg);
-            }
+      /**
+       * @param {String} imgPath
+       * @param {Function} successCallback
+       * @param {Function} errCallback
+       * @private
+       */
+      _loadImage = function(imgPath, successCallback, errCallback) {
+        var reader = new FileReader(),
+          image  = new Image();
+
+        reader.readAsDataURL(imgPath);
+
+        reader.onload = function(fileObj) {
+
+          image.onload = function() {
+            $(window).trigger('imageValidation', [this]);
+            successCallback(this);
+          };
+
+          image.onerror= function() {
+            errCallback();
+          };
+
+          image.src = fileObj.target.result;
+
         };
+      };
 
     /*
      * Validate mime type (falls back on validate_extension in older browsers)
@@ -88,7 +117,7 @@
 
             } else {
                 _log('FileReader not supported by browser, will check file 
extension');
-                return 
$.formUtils.validators.validate_extension.validatorFunction(str, $input);
+                return 
$.formUtils.validators.validate_extension.validatorFunction(str, $input, conf, 
language);
             }
         },
         errorMessage : '',
@@ -106,15 +135,16 @@
                 allowedTypes = _getTypes($input);
 
             $.each($input.get(0).files || [value], function(i, file) {
-                var val = typeof file == 'string' ? file : (file.value || 
file.fileName || file.name),
+                var val = typeof file === 'string' ? file : (file.value || 
file.fileName || file.name),
                     ext = val.substr( val.lastIndexOf('.')+1 );
 
-                if( $.inArray(ext.toLowerCase(), allowedTypes) == -1 ) {
+                if( $.inArray(ext.toLowerCase(), allowedTypes) === -1 ) {
                     valid = false;
                     _generateErrorMsg(_this, 'wrongFileType', 
allowedTypes.join(', '), language);
                     return false;
                 }
             });
+
             return valid;
         },
         errorMessage : '',
@@ -159,19 +189,207 @@
      */
     $.formUtils.convertSizeNameToBytes = function(sizeName) {
         sizeName = sizeName.toUpperCase();
-        if( sizeName.substr(sizeName.length-1, 1) == 'M' ) {
+        if( sizeName.substr(sizeName.length-1, 1) === 'M' ) {
             return parseInt(sizeName.substr(0, sizeName.length-1), 10) * 1024 
* 1024;
-        } else if( sizeName.substr(sizeName.length-2, 2) == 'MB' ) {
+        } else if( sizeName.substr(sizeName.length-2, 2) === 'MB' ) {
             return parseInt(sizeName.substr(0, sizeName.length-2), 10) * 1024 
* 1024;
-        } else if( sizeName.substr(sizeName.length-2, 2) == 'KB' ) {
+        } else if( sizeName.substr(sizeName.length-2, 2) === 'KB' ) {
             return parseInt(sizeName.substr(0, sizeName.length-2), 10) * 1024;
-        } else if( sizeName.substr(sizeName.length-1, 1) == 'B' ) {
+        } else if( sizeName.substr(sizeName.length-1, 1) === 'B' ) {
             return parseInt(sizeName.substr(0, sizeName.length-1), 10);
         } else {
             return parseInt(sizeName, 10);
         }
     };
 
+    var disableFormSubmit = function() {
+      return false;
+    };
+
+   /**
+    * Attach dimension check onto formUtils only for unit testing purpose
+    * @param {HTMLImageElement} img
+    * @param {String} dimDeclaration
+    * @param {Boolean|String} Returns error message if image was invalid, 
false otherwise
+    */
+    $.formUtils.checkImageDimension = function(img, dimDeclaration, language) {
+      var error = false,
+          restrictedDim = {width:0, height:0},
+          getDimRestriction = function(dimDeclaration) {
+            dimDeclaration = dimDeclaration.replace('min', '').replace('max', 
'');
+            var chunks = dimDeclaration.split('x');
+            restrictedDim.width = chunks[0];
+            restrictedDim.height = chunks[1] ? chunks[1] : chunks[0];
+          },
+          minDeclaration = false,
+          maxDeclaration = false,
+          declarationParts = dimDeclaration.split('-');
+
+      if( declarationParts.length === 1 ) {
+        if( declarationParts[0].indexOf('min') === 0 ) {
+          minDeclaration = declarationParts[0];
+        } else {
+          maxDeclaration = declarationParts[0];
+        }
+      } else {
+        minDeclaration = declarationParts[0];
+        maxDeclaration = declarationParts[1];
+      }
+
+      if( minDeclaration ) {
+        // check min
+        getDimRestriction(minDeclaration);
+        if( img.width < restrictedDim.width || img.height < 
restrictedDim.height )  {
+          error = language.imageTooSmall + ' ('+language.min+' 
'+restrictedDim.width+'x'+restrictedDim.height+'px)';
+        }
+      }
+
+      if( !error && maxDeclaration ) {
+        // Check max
+        getDimRestriction(maxDeclaration);
+        if( img.width > restrictedDim.width || img.height > 
restrictedDim.height ) {
+          if( img.width > restrictedDim.width ) {
+            error = language.imageTooWide +' '+restrictedDim.width+'px';
+          } else {
+            error = language.imageTooTall +' '+restrictedDim.height+'px';
+          }
+          error += ' ('+language.max+' 
'+restrictedDim.width+'x'+restrictedDim.height+'px)';
+        }
+      }
+
+      return error;
+    };
+
+    /**
+     * Attach ratio validation onto formUtils only for unit testing purpose
+     * @param {HTMLImageElement} img
+     * @param {String} dimDeclaration
+     * @param {Boolean|String} Returns error message if image was invalid, 
false otherwise
+     */
+    $.formUtils.checkImageRatio = function(img, ratioDeclaration, language) {
+      var ratio = img.width / img.height,
+          calculateRatio = function(declaration) {
+            var dims = declaration.replace('max', '').replace('min', 
'').split(':');
+            return dims[0] / dims[1];
+          },
+          declarationParts = ratioDeclaration.split('-'),
+          isWithin = function(val, min, max) {
+            return val >= min && val <= max;
+          };
+
+      if ( declarationParts.length === 1 ) {
+        if ( ratio !== calculateRatio(declarationParts[0]) ) {
+          return language.imageRatioNotAccepted;
+        }
+      }
+      else if( declarationParts.length === 2 && !isWithin(ratio, 
calculateRatio(declarationParts[0]), calculateRatio(declarationParts[1])) ) {
+        return language.imageRatioNotAccepted;
+      }
+      return false;
+    };
+
+    /**
+     * Validate image dimension
+     */
+    $.formUtils.addValidator({
+      name : 'dimension',
+      validatorFunction : function(val, $input, conf, language, $form) {
+        var hasCorrectDim = false;
+        if( SUPPORTS_FILE_READER ) {
+          var file = $input.get(0).files || [];
+          hasCorrectDim = true;
+
+          if( $input.attr('data-validation').indexOf('mime') === -1) {
+            alert('You should validate file type being jpg, gif or png on 
input '+$input[0].name);
+            return false;
+          }
+          else if( file.length > 1 ) {
+            alert('Validating image dimensions does not support inputs 
allowing multiple files');
+            return false;
+          } else if( file.length === 0) {
+            return true;
+          }
+
+          if( $input.valAttr('has-valid-dim') ) {
+            return true;
+          }
+          else if( $input.valAttr('has-not-valid-dim') ) {
+            this.errorMessage = language.wrongFileDim + ' ' + 
$input.valAttr('has-not-valid-dim');
+            return false;
+          }
+          else if($.formUtils.eventType === 'keyup') {
+            return null;
+          }
+
+          var wasFormSubmit = false;
+
+          if( $.formUtils.isValidatingEntireForm ) {
+            wasFormSubmit = true;
+            $.formUtils.haltValidation = true;
+            $form
+              .bind('submit', disableFormSubmit)
+              .addClass('on-blur');
+          }
+
+          _loadImage(file[0], function(img) {
+            var error = false;
+
+            if ( $input.valAttr('dimension') ) {
+              error = $.formUtils.checkImageDimension(img, 
$input.valAttr('dimension'), language);
+            }
+
+            if ( !error && $input.valAttr('ratio') ) {
+              error = $.formUtils.checkImageRatio(img, 
$input.valAttr('ratio'), language);
+            }
+
+            // Set validation result flag on input
+            if( error ) {
+              $input.valAttr('has-not-valid-dim', error);
+            }
+            else {
+              $input.valAttr('has-valid-dim', 'true');
+            }
+
+            // Remove validation flag when input changed
+            if( !$input.valAttr('has-keyup-event') ) {
+              $input
+                .valAttr('has-keyup-event', '1')
+                .bind('keyup change', function(evt) {
+                  if( evt.keyCode !== 9 && evt.keyCode !== 16 ) {
+                    $(this)
+                      .valAttr('has-not-valid-dim', false)
+                      .valAttr('has-valid-dim', false);
+                  }
+                });
+            }
+
+            if( wasFormSubmit ) {
+              $.formUtils.haltValidation = false;
+              $form
+                .removeClass('on-blur')
+                .get(0).onsubmit = function() {};
+
+              $form.unbind('submit', disableFormSubmit);
+              $form.trigger('submit'); // fire submit once more
+
+            } else {
+              $input.trigger('blur'); // triggers the validation once more
+            }
+
+          }, function(err) {
+            throw err;
+          });
+
+          return true;
+        }
+
+        return hasCorrectDim;
+      },
+      errorMessage : '',
+      errorMessageKey: '' // error message created dynamically
+    //  errorMessageKey: 'wrongFileDim'
+    });
+
     /*
      * This event listener will remove error messages for file
      * inputs when file changes
@@ -192,4 +410,4 @@
         });
     });
 
-})(jQuery, window);
\ No newline at end of file
+})(jQuery, window);

Modified: branches/dev-syncromind/phpgwapi/js/form-validator/file.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/file.js  2015-11-19 
00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/file.js  2015-11-19 
10:13:24 UTC (rev 14419)
@@ -1 +1,8 @@
-(function($,window){"use strict";var SUPPORTS_FILE_READER=typeof 
window.FileReader!="undefined",_getTypes=function($input){var 
allowedTypes=$.split(($input.valAttr("allowing")||"").toLowerCase());if($.inArray("jpg",allowedTypes)>-1&&$.inArray("jpeg",allowedTypes)==-1)allowedTypes.push("jpeg");else
 
if($.inArray("jpeg",allowedTypes)>-1&&$.inArray("jpg",allowedTypes)==-1)allowedTypes.push("jpg");return
 allowedTypes},_generateErrorMsg=function(obj,key,insert,lang){var 
msg=lang[key];obj.errorMessageKey="";obj.errorMessage=msg.replace("%s",insert)},_log=function(msg){if(window.console&&window.console.log){window.console.log(msg)}};$.formUtils.addValidator({name:"mime",validatorFunction:function(str,$input,conf,language){if(SUPPORTS_FILE_READER){var
 
valid=true,files=$input.get(0).files||[],mime="",allowedTypes=_getTypes($input);if(files.length){$.each(files,function(i,file){valid=false;mime=file.type||"";$.each(allowedTypes,function(j,type){valid=mime.indexOf(type)>-1;if(valid){return
 false}});return valid});if(!valid){_log("Trying to upload a file with mime 
type "+mime+" which is not 
allowed");_generateErrorMsg(this,"wrongFileType",allowedTypes.join(", 
"),language)}}return valid}else{_log("FileReader not supported by browser, will 
check file extension");return 
$.formUtils.validators.validate_extension.validatorFunction(str,$input)}},errorMessage:"",errorMessageKey:"wrongFileType"});$.formUtils.addValidator({name:"extension",validatorFunction:function(value,$input,conf,language){var
 
valid=true,_this=this,allowedTypes=_getTypes($input);$.each($input.get(0).files||[value],function(i,file){var
 val=typeof 
file=="string"?file:file.value||file.fileName||file.name,ext=val.substr(val.lastIndexOf(".")+1);if($.inArray(ext.toLowerCase(),allowedTypes)==-1){valid=false;_generateErrorMsg(_this,"wrongFileType",allowedTypes.join(",
 "),language);return false}});return 
valid},errorMessage:"",errorMessageKey:"wrongFileType"});$.formUtils.addValidator({name:"size",validatorFunction:function(val,$input,conf,language){var
 maxSize=$input.valAttr("max-size");if(!maxSize){_log('Input 
"'+$input.attr("name")+'" is missing data-validation-max-size 
attribute');return true}else if(!SUPPORTS_FILE_READER){return true}var 
maxBytes=$.formUtils.convertSizeNameToBytes(maxSize),valid=true;$.each($input.get(0).files||[],function(i,file){valid=file.size<=maxBytes;return
 
valid});if(!valid){_generateErrorMsg(this,"wrongFileSize",maxSize,language)}return
 
valid},errorMessage:"",errorMessageKey:"wrongFileSize"});$.formUtils.convertSizeNameToBytes=function(sizeName){sizeName=sizeName.toUpperCase();if(sizeName.substr(sizeName.length-1,1)=="M"){return
 parseInt(sizeName.substr(0,sizeName.length-1),10)*1024*1024}else 
if(sizeName.substr(sizeName.length-2,2)=="MB"){return 
parseInt(sizeName.substr(0,sizeName.length-2),10)*1024*1024}else 
if(sizeName.substr(sizeName.length-2,2)=="KB"){return 
parseInt(sizeName.substr(0,sizeName.length-2),10)*1024}else 
if(sizeName.substr(sizeName.length-1,1)=="B"){return 
parseInt(sizeName.substr(0,sizeName.length-1),10)}else{return 
parseInt(sizeName,10)}};$(window).one("validatorsLoaded 
formValidationSetup",function(evt,$form){var 
$inputs;if($form){$inputs=$form.find('input[type="file"]')}else{$inputs=$('input[type="file"]')}$inputs.filter("*[data-validation]").bind("change",function(){$(this).removeClass("error").parent().find(".form-error").remove()})})})(jQuery,window);
+/**
+ *  JQUERY-FORM-VALIDATOR
+ *
+ *  @website by 
+ *  @license MIT
+ *  @version 2.2.83
+ */
+!function(a,b){"use strict";var c="undefined"!=typeof 
b.FileReader,d=function(b){var 
c=a.split((b.valAttr("allowing")||"").toLowerCase());return 
a.inArray("jpg",c)>-1&&-1===a.inArray("jpeg",c)?c.push("jpeg"):a.inArray("jpeg",c)>-1&&-1===a.inArray("jpg",c)&&c.push("jpg"),c},e=function(a,b,c,d){var
 
e=d[b]||"";a.errorMessageKey="",a.errorMessage=e.replace("%s",c)},f=function(a){b.console&&b.console.log&&b.console.log(a)},g=function(c,d,e){var
 f=new FileReader,g=new 
Image;f.readAsDataURL(c),f.onload=function(c){g.onload=function(){a(b).trigger("imageValidation",[this]),d(this)},g.onerror=function(){e()},g.src=c.target.result}};a.formUtils.addValidator({name:"mime",validatorFunction:function(b,g,h,i){if(c){var
 j=!0,k=g.get(0).files||[],l="",m=d(g);return 
k.length&&(a.each(k,function(b,c){return 
j=!1,l=c.type||"",a.each(m,function(a,b){return j=l.indexOf(b)>-1,j?!1:void 
0}),j}),j||(f("Trying to upload a file with mime type "+l+" which is not 
allowed"),e(this,"wrongFileType",m.join(", "),i))),j}return f("FileReader not 
supported by browser, will check file 
extension"),a.formUtils.validators.validate_extension.validatorFunction(b,g,h,i)},errorMessage:"",errorMessageKey:"wrongFileType"}),a.formUtils.addValidator({name:"extension",validatorFunction:function(b,c,f,g){var
 h=!0,i=this,j=d(c);return a.each(c.get(0).files||[b],function(b,c){var 
d="string"==typeof 
c?c:c.value||c.fileName||c.name,f=d.substr(d.lastIndexOf(".")+1);return-1===a.inArray(f.toLowerCase(),j)?(h=!1,e(i,"wrongFileType",j.join(",
 "),g),!1):void 
0}),h},errorMessage:"",errorMessageKey:"wrongFileType"}),a.formUtils.addValidator({name:"size",validatorFunction:function(b,d,g,h){var
 i=d.valAttr("max-size");if(!i)return f('Input "'+d.attr("name")+'" is missing 
data-validation-max-size attribute'),!0;if(!c)return!0;var 
j=a.formUtils.convertSizeNameToBytes(i),k=!0;return 
a.each(d.get(0).files||[],function(a,b){return 
k=b.size<=j}),k||e(this,"wrongFileSize",i,h),k},errorMessage:"",errorMessageKey:"wrongFileSize"}),a.formUtils.convertSizeNameToBytes=function(a){return
 
a=a.toUpperCase(),"M"===a.substr(a.length-1,1)?1024*parseInt(a.substr(0,a.length-1),10)*1024:"MB"===a.substr(a.length-2,2)?1024*parseInt(a.substr(0,a.length-2),10)*1024:"KB"===a.substr(a.length-2,2)?1024*parseInt(a.substr(0,a.length-2),10):"B"===a.substr(a.length-1,1)?parseInt(a.substr(0,a.length-1),10):parseInt(a,10)};var
 h=function(){return!1};a.formUtils.checkImageDimension=function(a,b,c){var 
d=!1,e={width:0,height:0},f=function(a){a=a.replace("min","").replace("max","");var
 
b=a.split("x");e.width=b[0],e.height=b[1]?b[1]:b[0]},g=!1,h=!1,i=b.split("-");return
 
1===i.length?0===i[0].indexOf("min")?g=i[0]:h=i[0]:(g=i[0],h=i[1]),g&&(f(g),(a.width<e.width||a.height<e.height)&&(d=c.imageTooSmall+"
 ("+c.min+" 
"+e.width+"x"+e.height+"px)")),!d&&h&&(f(h),(a.width>e.width||a.height>e.height)&&(d=a.width>e.width?c.imageTooWide+"
 "+e.width+"px":c.imageTooTall+" "+e.height+"px",d+=" ("+c.max+" 
"+e.width+"x"+e.height+"px)")),d},a.formUtils.checkImageRatio=function(a,b,c){var
 d=a.width/a.height,e=function(a){var 
b=a.replace("max","").replace("min","").split(":");return 
b[0]/b[1]},f=b.split("-"),g=function(a,b,c){return 
a>=b&&c>=a};if(1===f.length){if(d!==e(f[0]))return c.imageRatioNotAccepted}else 
if(2===f.length&&!g(d,e(f[0]),e(f[1])))return 
c.imageRatioNotAccepted;return!1},a.formUtils.addValidator({name:"dimension",validatorFunction:function(b,d,e,f,i){var
 j=!1;if(c){var 
k=d.get(0).files||[];if(j=!0,-1===d.attr("data-validation").indexOf("mime"))return
 alert("You should validate file type being jpg, gif or png on input 
"+d[0].name),!1;if(k.length>1)return alert("Validating image dimensions does 
not support inputs allowing multiple 
files"),!1;if(0===k.length)return!0;if(d.valAttr("has-valid-dim"))return!0;if(d.valAttr("has-not-valid-dim"))return
 this.errorMessage=f.wrongFileDim+" 
"+d.valAttr("has-not-valid-dim"),!1;if("keyup"===a.formUtils.eventType)return 
null;var l=!1;return 
a.formUtils.isValidatingEntireForm&&(l=!0,a.formUtils.haltValidation=!0,i.bind("submit",h).addClass("on-blur")),g(k[0],function(b){var
 
c=!1;d.valAttr("dimension")&&(c=a.formUtils.checkImageDimension(b,d.valAttr("dimension"),f)),!c&&d.valAttr("ratio")&&(c=a.formUtils.checkImageRatio(b,d.valAttr("ratio"),f)),c?d.valAttr("has-not-valid-dim",c):d.valAttr("has-valid-dim","true"),d.valAttr("has-keyup-event")||d.valAttr("has-keyup-event","1").bind("keyup
 
change",function(b){9!==b.keyCode&&16!==b.keyCode&&a(this).valAttr("has-not-valid-dim",!1).valAttr("has-valid-dim",!1)}),l?(a.formUtils.haltValidation=!1,i.removeClass("on-blur").get(0).onsubmit=function(){},i.unbind("submit",h),i.trigger("submit")):d.trigger("blur")},function(a){throw
 a}),!0}return 
j},errorMessage:"",errorMessageKey:""}),a(b).one("validatorsLoaded 
formValidationSetup",function(b,c){var 
d;d=c?c.find('input[type="file"]'):a('input[type="file"]'),d.filter("*[data-validation]").bind("change",function(){a(this).removeClass("error").parent().find(".form-error").remove()})})}(jQuery,window);
\ No newline at end of file

Deleted: branches/dev-syncromind/phpgwapi/js/form-validator/form-test.html
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/form-test.html   
2015-11-19 00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/form-test.html   
2015-11-19 10:13:24 UTC (rev 14419)
@@ -1,422 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <meta charset="utf-8" />
-    <title>Form Test</title>
-    <link rel="stylesheet" 
href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-wip/css/bootstrap.min.css" />
-    <link rel="stylesheet" 
href="//code.jquery.com/ui/1.10.4/themes/black-tie/jquery-ui.css" />
-    <style>
-
-        /* Form and inputs */
-        form {
-            width: 500px;
-            margin: 0 auto;
-            padding: 20px;
-            display: block;
-        }
-
-        input.form-control {
-            width: 375px;
-        }
-
-        button, input[type="submit"], .button {
-            margin-bottom: 8px;
-        }
-
-        /* While server is being requested */
-        form.validating-server-side {
-            background: #F2F2F2;
-        }
-
-        input.validating-server-side {
-            opacity: 0.5;
-            background: lightgoldenrodyellow;
-        }
-
-        /* modify inputs for password strength */
-        .password-strength input.form-control {
-            width: 375px;
-            margin-right: 4px;
-            display: inline;
-        }
-
-        .password-strength label {
-            display: block;
-        }
-
-        /* Checkboxes */
-        .form-group.check-boxes input {
-            margin-left: 10px;
-        }
-
-        span.help {
-            color: #999 !important;
-        }
-
-        /* Error container for form C */
-
-        #error-container div {
-            color: red;
-            line-height: 140%;
-        }
-
-        #error-container div:last-child {
-            padding-bottom: 10px;
-        }
-
-    </style>
-</head>
-<body>
-<div>
-    <form action="" id="form-a" role="form">
-        <div class="form-group">
-            <label class="control-label" for="inline-suggestions">Inline 
suggestions</label>
-            <input name="inline suggestions" type="text" 
id="inline-suggestions" class="form-control" data-suggestions="Monkey, Horse, 
Hound, Fox, Tiger, Elephant" />
-        </div>
-
-        <div class="form-group">
-            <label class="control-label" for="country-suggestions">Country 
suggestions</label>
-            <input name="country suggestions" data-validation="country" 
type="text" id="country-suggestions" class="form-control" />
-        </div>
-
-        <div class="form-group">
-            <label class="control-label" for="country-suggestions">Swedish 
county suggestions</label>
-            <input name="Swedish county suggestion" 
data-validation="swecounty" type="text" id="swedish-county-suggestions" 
class="form-control" />
-        </div>
-
-        <div class="form-group">
-            <label class="control-label">Year</label>
-            <input name="birth" class="form-control"
-                   data-validation="date"
-                   data-validation-format="yyyy/mm/dd"
-                   data-suggestions="2014/01/15,2014/01/16,2014/01/17" />
-        </div>
-
-        <div class="form-group">
-            <label class="control-label">Datepicker</label>
-            <input name="birth2" class="form-control"
-                   data-validation="date"
-                   data-validation-format="mm/dd/yyyy"
-                   id="datepicker" />
-        </div>
-
-        <div class="form-group">
-            <label class="control-label">Number 0-10 (accepting floats with 
comma)</label>
-            <input name="floats" class="form-control"
-                   data-validation="number"
-                   data-validation-allowing="range[0;10], float"
-                   data-validation-decimal-separator=","
-                    />
-        </div>
-
-        <div class="form-group password-strength">
-            <label class="control-label" for="password">Display password 
strength (only strong)</label>
-            <input name="password" type="password" id="password" 
class="form-control" data-validation="strength" data-validation-strength="3" />
-        </div>
-
-        <div class="form-group">
-            <label class="control-label">Alphanumeric and -_ and spaces</label>
-            <input name="alphanumeric with spaces" class="form-control" 
name="test" data-validation="alphanumeric" data-validation-allowing="-_ " />
-        </div>
-
-        <div class="form-group">
-            <label class="control-label">Alphanumeric only</label>
-            <input name="aplhanumeric only" class="form-control" name="test2" 
data-validation="alphanumeric" />
-        </div>
-
-        <div class="checkbox form-group">
-            <label>
-                <input name="checkbox" type="checkbox" 
data-validation="required" /> Must be checked
-            </label>
-        </div>
-
-        <div class="form-group">
-            <label class="control-label">Must choose one</label>
-            <br />
-            <input name="radio" type="radio" data-validation="required" 
value="1" /> A
-            <input name="radio" type="radio" value="1" /> B
-            <input name="radio" type="radio" value="1" /> C
-            <input name="radio" type="radio" value="1" /> D
-        </div>
-
-        <div class="form-group">
-            <label class="control-label">Even numbers only</label>
-            <input name="even numbers" class="form-control" name="test4" 
data-validation="even_number" />
-        </div>
-
-        <div class="form-group">
-            <label class="control-label">Make a choice</label>
-            <br />
-            <select name="choice" data-validation="required" 
data-validation-error-msg="Please make a choice">
-                <option value="">- - Choose - -</option>
-                <option>A</option>
-                <option>B</option>
-                <option>C</option>
-                <option>D</option>
-            </select>
-        </div>
-
-        <div class="form-group">
-            <label class="control-label">Text</label>
-            (<span id="max-len">20</span> chars left)<br />
-            <textarea id="text-area" class="form-control" 
name="some-text"></textarea>
-        </div>
-        <div class="form-group">
-            <label class="control-label">Server validation</label>
-            <input class="form-control" name="code" value="secret"
-                   data-validation-helssp="The word is &quot;secret&quot;"
-                   data-validation="server"
-                   
data-validation-url="http://formvalidator.net/validate-email.php"; />
-        </div>
-        <div class="form-group">
-            <label class="control-label">File validation</label>
-            <input type="file" name="some-file1" class="form-control"
-                   data-validation="size mime required"
-                   data-validation-error-msg-size="The file cant be larger 
than 400kb"
-                   data-validation-error-msg="You must upload an image file 
(max 400 kb)"
-                   data-validation-allowing="jpg, png, ico"
-                   data-validation-max-size="400kb" />
-        </div>
-        <div class="form-group">
-            <label class="control-label">File name</label>
-            <input type="text" name="some-file2" class="form-control"
-                   data-validation="extension required"
-                   data-validation-error-msg="You must write a file name with 
extension jpg|png|ico"
-                   data-validation-allowing="jpg, png, ico"
-                    />
-        </div>
-        <div class="form-group">
-            <label class="control-label">
-                Callback validation, set this value to &quot;1&quot; and
-                validation will fail
-            </label>
-            <input id="callback" class="form-control" />
-        </div>
-
-        <div class="form-group check-boxes">
-            <label>Checkbox group</label><br />
-            <label>
-                <input type="checkbox" name="box" value="1"
-                       data-validation="checkbox_group"
-                       data-validation-qty="1-2" /> 1
-            </label>
-            <label>
-                <input type="checkbox" name="box" value="2" /> 2
-            </label>
-            <label>
-                <input type="checkbox" name="box" value="3" /> 3
-            </label>
-            <label>
-                <input type="checkbox" name="box" value="4" /> 4
-            </label>
-            <label>
-                <input type="checkbox" name="box" value="5" /> 5
-            </label>
-        </div>
-
-        <p style="line-height: 200%">
-            <input type="submit" class="button">
-            <br />
-            <button class="button" type="button"
-                    onclick="alert('Form a is ' + ( $('#form-a').isValid({}, 
{}, false) ? 'VALID':'NOT VALID'));">
-                Test validation via js (<strong>without error 
messages</strong>)
-            </button>
-            <br />
-            <button class="button" type="button"
-                    onclick="alert('Form a is ' + ( $('#form-a').isValid() ? 
'VALID':'NOT VALID'));">
-                Test validation via js (showing error messages)
-            </button>
-            <br />
-            <input type="reset" class="button">
-        </p>
-    </form>
-    <hr />
-    <form id="form-b">
-        <div class="form-group">
-            <label class="control-label">Test</label>
-            <input name="test" data-validation="number" type="text" />
-        </div>
-        <div class="form-group">
-            <label class="control-label">Password</label>
-            <input name="pass" data-validation="confirmation" type="password" 
/>
-        </div>
-        <div class="form-group">
-            <label class="control-label">Password again</label>
-            <input name="pass_confirmation" type="password" />
-        </div>
-        <p>
-            <input type="submit" class="button">
-            <input type="reset" class="button">
-        </p>
-    </form>
-    <hr />
-    <form id="form-c">
-        <div class="form-group">
-            <label class="control-label">Country</label>
-            <input name="test" data-validation="country" 
data-validation-error-msg="No valid country given" />
-        </div>
-        <div class="form-group">
-            <label class="control-label">E-mail</label>
-            <input name="testmail" data-validation="email" 
data-validation-error-msg="E-mail is not valid" />
-        </div>
-        <div class="form-group">
-            <label class="control-label">Confirm e-mail</label>
-            <input name="test" data-validation="confirmation" 
data-validation-confirm="testmail" />
-        </div>
-        <div class="form-group">
-            <label class="control-label">Alphanumeric (will only be validated 
if the checkbox is checked)</label>
-            <input name="test2"
-                    data-validation="alphanumeric"
-                    data-validation-error-msg="Invalid..."
-                    data-validation-if-checked="checker" />
-            <br />
-            <input type="checkbox" name="checker" />
-        </div>
-        <div id="error-container">
-
-        </div>
-        <p>
-            <input type="submit" class="button">
-            <input type="reset" class="button">
-        </p>
-    </form>
-    <hr />
-    <form id="form-d">
-        <h2>HTML5 attributes</h2>
-        <div class="form-group">
-            <label class="control-label">type="email"</label>
-            <input type="text" required="required" list="mejl" />
-            <datalist id="mejl">
-                <option value="Test">Test</option>
-                <option value="test2">test2</option>
-                <option value="test3">test3</option>
-            </datalist>
-        </div>
-        <div class="form-group">
-            <label class="control-label">type="url" (optional)</label>
-            <input type="url" />
-        </div>
-        <div class="form-group">
-            <label class="control-label">type="number"</label>
-            <input type="number" required="required" />
-        </div>
-        <div class="form-group">
-            <label class="control-label">type="number"</label>
-            <input type="number" required="required" maxlength="30" />
-        </div>
-        <div class="form-group">
-            <label class="control-label">type="number" range[-5;5]</label>
-            <input type="number" min="-5" max="5" required="required" />
-        </div>
-        <div class="form-group">
-            <label class="control-label">pattern="^([a-z]+)$"</label>
-            <input type="text" name="some-colorz" list="some-colorz" 
pattern="^([a-z]+)$" required="required" />
-            <datalist id="some-colorz" style="display: none">
-                <option value="Green">Green</option>
-                <option value="Blue">Blue</option>
-                <option value="Red">Red</option>
-                <option value="Black">Black</option>
-                <option value="White">White</option>
-            </datalist>
-        </div>
-        <p>
-            <input type="submit" class="button">
-            <input type="reset" class="button">
-        </p>
-    </form>
-</div>
-<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
-<script src="//code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
-<script src="jquery.form-validator.js"></script>
-<script>
-(function($, window) {
-
-    var dev = '.dev'; //window.location.hash.indexOf('dev') > -1 ? '.dev' : '';
-
-    // setup datepicker
-    $("#datepicker").datepicker();
-
-    // Add a new validator
-    $.formUtils.addValidator({
-        name : 'even_number',
-        validatorFunction : function(value, $el, config, language, $form) {
-            return parseInt(value, 10) % 2 === 0;
-        },
-        borderColorOnError : '',
-        errorMessage : 'You have to give an even number',
-        errorMessageKey: 'badEvenNumber'
-    });
-
-    window.applyValidation = function(validateOnBlur, forms, messagePosition) {
-        if( !forms )
-            forms = 'form';
-        if( !messagePosition )
-            messagePosition = 'top';
-
-        $.validate({
-            form : forms,
-            language : {
-                requiredFields: 'Du måste bocka för denna'
-            },
-            validateOnBlur : validateOnBlur,
-            errorMessagePosition : messagePosition,
-            scrollToTopOnError : true,
-            borderColorOnError : 'purple',
-            modules : 'security'+dev+', location'+dev+', sweden'+dev+', 
html5'+dev+', file'+dev+', uk'+dev,
-            onModulesLoaded: function() {
-                $('#country-suggestions').suggestCountry();
-                $('#swedish-county-suggestions').suggestSwedishCounty();
-                $('#password').displayPasswordStrength();
-            },
-            onValidate : function($f) {
-
-                console.log('about to validate form '+$f.attr('id'));
-
-                var $callbackInput = $('#callback');
-                if( $callbackInput.val() == 1 ) {
-                    return {
-                        element : $callbackInput,
-                        message : 'This validation was made in a callback'
-                    };
-                }
-            },
-            onError : function($form) {
-                alert('Invalid '+$form.attr('id'));
-            },
-            onSuccess : function($form) {
-                alert('Valid '+$form.attr('id'));
-                return false;
-            }
-        });
-    };
-
-    $('#text-area').restrictLength($('#max-len'));
-
-    window.applyValidation(true, '#form-a', 'top');
-    window.applyValidation(false, '#form-b', 'element');
-    window.applyValidation(true, '#form-c', $('#error-container'));
-    window.applyValidation(true, '#form-d', 'element');
-
-    // Load one module outside $.validate() even though you do not have to
-    $.formUtils.loadModules('date'+dev+'.js', false, false);
-
-    $('input')
-        .on('beforeValidation', function() {
-            console.log('About to validate input "'+this.name+'"');
-        })
-        .on('validation', function(evt, isValid) {
-            var validationResult = '';
-            if( isValid === null ) {
-                validationResult = 'not validated';
-            } else if( isValid ) {
-                validationResult = 'VALID';
-            } else {
-                validationResult = 'INVALID';
-            }
-            console.log('Input '+this.name+' is '+validationResult);
-        });
-
-})(jQuery, window);
-</script>
-<body>
-</html>
\ No newline at end of file

Modified: branches/dev-syncromind/phpgwapi/js/form-validator/html5.dev.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/html5.dev.js     
2015-11-19 00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/html5.dev.js     
2015-11-19 10:13:24 UTC (rev 14419)
@@ -16,129 +16,151 @@
  *  - placeholders
  *
  * @website http://formvalidator.net/
- * @license Dual licensed under the MIT or GPL Version 2 licenses
- * @version 2.2.beta.58
+ * @license MIT
+ * @version 2.2.83
  */
 (function($, window) {
 
-    "use strict";
+  'use strict';
 
     var SUPPORTS_PLACEHOLDER = 'placeholder' in 
document.createElement('INPUT'),
-        SUPPORTS_DATALIST = 'options' in document.createElement('DATALIST');
+        SUPPORTS_DATALIST = 'options' in document.createElement('DATALIST'),
+        hasLoadedDateModule = false,
+        setupValidationUsingHTML5Attr = function($form) {
 
-    $(window).bind('validatorsLoaded formValidationSetup', function(evt, 
$form) {
+          $form.each(function() {
+            var $f = $(this),
+              $formInputs = $f.find('input,textarea,select'),
+              foundHtml5Rule = false;
 
-        if( !$form ) {
-            $form = $('form');
-        }
+            $formInputs.each(function() {
+              var validation = [],
+                $input = $(this),
+                isRequired = $input.attr('required'),
+                attrs = {};
 
-        var hasLoadedDateModule = false;
+              switch ( ($input.attr('type') || '').toLowerCase() ) {
+                case 'time':
+                  validation.push('time');
+                  if( !$.formUtils.validators.validate_date && 
!hasLoadedDateModule ) {
+                    hasLoadedDateModule = true;
+                    $.formUtils.loadModules('date');
+                  }
+                  break;
+                case 'url':
+                  validation.push('url');
+                  break;
+                case 'email':
+                  validation.push('email');
+                  break;
+                case 'date':
+                  validation.push('date');
+                  break;
+                case 'number':
+                  validation.push('number');
+                  var max = $input.attr('max'),
+                    min = $input.attr('min');
+                  if( min || max ) {
+                    if ( !min ) {
+                      min = '0';
+                    }
+                    if ( !max ) {
+                      max = '9007199254740992'; // js max int
+                    }
 
-        $form.each(function() {
-            var $f = $(this),
-                $formInputs = $f.find('input,textarea,select'),
-                foundHtml5Rule = false;
+                    attrs['data-validation-allowing'] = 
'range['+min+';'+max+']';
+                    if( min.indexOf('-') === 0 || max.indexOf('-') === 0 ) {
+                      attrs['data-validation-allowing'] += ',negative';
+                    }
+                    if( min.indexOf('.') > -1 || max.indexOf('.') > -1 ) {
+                      attrs['data-validation-allowing'] += ',float';
+                    }
+                  }
+                  break;
+              }
 
-            $formInputs.each(function() {
-                var validation = [],
-                    $input = $(this),
-                    isRequired = $input.attr('required'),
-                    attrs = {};
+              if( $input.attr('pattern') ) {
+                validation.push('custom');
+                attrs['data-validation-regexp'] = $input.attr('pattern');
+              }
+              if( $input.attr('maxlength') ) {
+                validation.push('length');
+                attrs['data-validation-length'] = 
'max'+$input.attr('maxlength');
+              }
 
-                switch ( ($input.attr('type') || '').toLowerCase() ) {
-                    case 'time':
-                        validation.push('time');
-                        if( !$.formUtils.validators.validate_date && 
!hasLoadedDateModule ) {
-                            hasLoadedDateModule = true;
-                            $.formUtils.loadModules('date');
-                        }
-                        break;
-                    case 'url':
-                        validation.push('url');
-                        break;
-                    case 'email':
-                        validation.push('email');
-                        break;
-                    case 'date':
-                        validation.push('date');
-                        break;
-                    case 'number':
-                        validation.push('number');
-                        var max = $input.attr('max'),
-                            min = $input.attr('min');
-                        if( min || max ) {
-                            if( !min )
-                                min = 0;
-                            if( !max )
-                                max = 9007199254740992; // js max int
+              if( !SUPPORTS_DATALIST && $input.attr('list') ) {
+                var suggestions = [],
+                  $list = $('#'+$input.attr('list'));
 
-                            attrs['data-validation-allowing'] = 
'range['+min+';'+max+']';
-                            if( min.indexOf('-') === 0 || max.indexOf('-') === 
0 ) {
-                                attrs['data-validation-allowing'] += 
',negative';
-                            }
-                            if( min.indexOf('.') > -1 || max.indexOf('.') > -1 
) {
-                                attrs['data-validation-allowing'] += ',float';
-                            }
-                        }
-                        break;
-                }
+                $list.find('option').each(function() {
+                  suggestions.push($(this).text());
+                });
 
-                if( $input.attr('pattern') ) {
-                    validation.push('custom');
-                    attrs['data-validation-regexp'] = $input.attr('pattern');
+                if( suggestions.length === 0 ) {
+                  // IE fix
+                  var opts = 
$.trim($('#'+$input.attr('list')).text()).split('\n');
+                  $.each(opts, function(i, option) {
+                    suggestions.push($.trim(option));
+                  });
                 }
-                if( $input.attr('maxlength') ) {
-                    validation.push('length');
-                    attrs['data-validation-length'] = 
'max'+$input.attr('maxlength');
-                }
 
-                if( !SUPPORTS_DATALIST && $input.attr('list') ) {
-                    var suggestions = [];
-                    $('#'+$input.attr('list')+' option').each(function() {
-                        var $opt = $(this);
-                        suggestions.push($opt.attr('value') || $opt.text());
-                    });
-                    $.formUtils.suggest( $input, suggestions );
-                }
+                $list.remove();
 
-                if( validation.length ) {
-                    if( !isRequired ) {
-                        attrs['data-validation-optional'] = 'true';
-                    }
+                $.formUtils.suggest( $input, suggestions );
+              }
 
-                    foundHtml5Rule = true;
-                    $input.attr('data-validation', validation.join(' '));
+              if ( isRequired && validation.length === 0 ) {
+                validation.push('required');
+              }
 
-                    $.each(attrs, function(attrName, attrVal) {
-                        $input.attr(attrName, attrVal);
-                    });
+              if( validation.length ) {
+                if( !isRequired ) {
+                  attrs['data-validation-optional'] = 'true';
                 }
+
+                foundHtml5Rule = true;
+                $input.attr('data-validation', validation.join(' '));
+
+                $.each(attrs, function(attrName, attrVal) {
+                  $input.attr(attrName, attrVal);
+                });
+              }
             });
 
             if( foundHtml5Rule ) {
-                $f.trigger('html5ValidationAttrsFound');
+              $f.trigger('html5ValidationAttrsFound');
             }
 
             if( !SUPPORTS_PLACEHOLDER ) {
-                $formInputs.filter('input[placeholder]').each(function() {
-                    this.defaultValue = this.getAttribute('placeholder');
-                    $(this)
-                        .bind('focus', function() {
-                            if(this.value == this.defaultValue) {
-                                this.value = '';
-                                $(this).removeClass('showing-placeholder');
-                            }
-                        })
-                        .bind('blur', function() {
-                            if($.trim(this.value) == '') {
-                                this.value = this.defaultValue;
-                                $(this).addClass('showing-placeholder');
-                            }
-                        });
-                });
+              $formInputs.filter('input[placeholder]').each(function() {
+                this.defaultValue = this.getAttribute('placeholder');
+                $(this)
+                  .bind('focus', function() {
+                    if(this.value === this.defaultValue) {
+                      this.value = '';
+                      $(this).removeClass('showing-placeholder');
+                    }
+                  })
+                  .bind('blur', function() {
+                    if($.trim(this.value) === '') {
+                      this.value = this.defaultValue;
+                      $(this).addClass('showing-placeholder');
+                    }
+                  });
+              });
             }
 
-        });
+          });
+        };
+
+    $(window).bind('validatorsLoaded formValidationSetup', function(evt, 
$form) {
+        if( !$form ) {
+            $form = $('form');
+        }
+        setupValidationUsingHTML5Attr($form);
     });
 
-})(jQuery, window);
\ No newline at end of file
+    // Make this method available outside the module
+    $.formUtils.setupValidationUsingHTML5Attr = setupValidationUsingHTML5Attr;
+
+})(jQuery, window);

Modified: branches/dev-syncromind/phpgwapi/js/form-validator/html5.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/html5.js 2015-11-19 
00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/html5.js 2015-11-19 
10:13:24 UTC (rev 14419)
@@ -1 +1,8 @@
-(function($,window){"use strict";var SUPPORTS_PLACEHOLDER="placeholder"in 
document.createElement("INPUT"),SUPPORTS_DATALIST="options"in 
document.createElement("DATALIST");$(window).bind("validatorsLoaded 
formValidationSetup",function(evt,$form){if(!$form){$form=$("form")}var 
hasLoadedDateModule=false;$form.each(function(){var 
$f=$(this),$formInputs=$f.find("input,textarea,select"),foundHtml5Rule=false;$formInputs.each(function(){var
 
validation=[],$input=$(this),isRequired=$input.attr("required"),attrs={};switch(($input.attr("type")||"").toLowerCase()){case"time":validation.push("time");if(!$.formUtils.validators.validate_date&&!hasLoadedDateModule){hasLoadedDateModule=true;$.formUtils.loadModules("date")}break;case"url":validation.push("url");break;case"email":validation.push("email");break;case"date":validation.push("date");break;case"number":validation.push("number");var
 
max=$input.attr("max"),min=$input.attr("min");if(min||max){if(!min)min=0;if(!max)max=9007199254740992;attrs["data-validation-allowing"]="range["+min+";"+max+"]";if(min.indexOf("-")===0||max.indexOf("-")===0){attrs["data-validation-allowing"]+=",negative"}if(min.indexOf(".")>-1||max.indexOf(".")>-1){attrs["data-validation-allowing"]+=",float"}}break}if($input.attr("pattern")){validation.push("custom");attrs["data-validation-regexp"]=$input.attr("pattern")}if($input.attr("maxlength")){validation.push("length");attrs["data-validation-length"]="max"+$input.attr("maxlength")}if(!SUPPORTS_DATALIST&&$input.attr("list")){var
 suggestions=[];$("#"+$input.attr("list")+" option").each(function(){var 
$opt=$(this);suggestions.push($opt.attr("value")||$opt.text())});$.formUtils.suggest($input,suggestions)}if(validation.length){if(!isRequired){attrs["data-validation-optional"]="true"}foundHtml5Rule=true;$input.attr("data-validation",validation.join("
 
"));$.each(attrs,function(attrName,attrVal){$input.attr(attrName,attrVal)})}});if(foundHtml5Rule){$f.trigger("html5ValidationAttrsFound")}if(!SUPPORTS_PLACEHOLDER){$formInputs.filter("input[placeholder]").each(function(){this.defaultValue=this.getAttribute("placeholder");$(this).bind("focus",function(){if(this.value==this.defaultValue){this.value="";$(this).removeClass("showing-placeholder")}}).bind("blur",function(){if($.trim(this.value)==""){this.value=this.defaultValue;$(this).addClass("showing-placeholder")}})})}})})})(jQuery,window);
+/**
+ *  JQUERY-FORM-VALIDATOR
+ *
+ *  @website by 
+ *  @license MIT
+ *  @version 2.2.83
+ */
+!function(a,b){"use strict";var c="placeholder"in 
document.createElement("INPUT"),d="options"in 
document.createElement("DATALIST"),e=!1,f=function(b){b.each(function(){var 
b=a(this),f=b.find("input,textarea,select"),g=!1;f.each(function(){var 
b=[],c=a(this),f=c.attr("required"),h={};switch((c.attr("type")||"").toLowerCase()){case"time":b.push("time"),a.formUtils.validators.validate_date||e||(e=!0,a.formUtils.loadModules("date"));break;case"url":b.push("url");break;case"email":b.push("email");break;case"date":b.push("date");break;case"number":b.push("number");var
 
i=c.attr("max"),j=c.attr("min");(j||i)&&(j||(j="0"),i||(i="9007199254740992"),h["data-validation-allowing"]="range["+j+";"+i+"]",(0===j.indexOf("-")||0===i.indexOf("-"))&&(h["data-validation-allowing"]+=",negative"),(j.indexOf(".")>-1||i.indexOf(".")>-1)&&(h["data-validation-allowing"]+=",float"))}if(c.attr("pattern")&&(b.push("custom"),h["data-validation-regexp"]=c.attr("pattern")),c.attr("maxlength")&&(b.push("length"),h["data-validation-length"]="max"+c.attr("maxlength")),!d&&c.attr("list")){var
 
k=[],l=a("#"+c.attr("list"));if(l.find("option").each(function(){k.push(a(this).text())}),0===k.length){var
 
m=a.trim(a("#"+c.attr("list")).text()).split("\n");a.each(m,function(b,c){k.push(a.trim(c))})}l.remove(),a.formUtils.suggest(c,k)}f&&0===b.length&&b.push("required"),b.length&&(f||(h["data-validation-optional"]="true"),g=!0,c.attr("data-validation",b.join("
 
")),a.each(h,function(a,b){c.attr(a,b)}))}),g&&b.trigger("html5ValidationAttrsFound"),c||f.filter("input[placeholder]").each(function(){this.defaultValue=this.getAttribute("placeholder"),a(this).bind("focus",function(){this.value===this.defaultValue&&(this.value="",a(this).removeClass("showing-placeholder"))}).bind("blur",function(){""===a.trim(this.value)&&(this.value=this.defaultValue,a(this).addClass("showing-placeholder"))})})})};a(b).bind("validatorsLoaded
 
formValidationSetup",function(b,c){c||(c=a("form")),f(c)}),a.formUtils.setupValidationUsingHTML5Attr=f}(jQuery,window);
\ No newline at end of file

Modified: 
branches/dev-syncromind/phpgwapi/js/form-validator/jquery.form-validator.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/form-validator/jquery.form-validator.js 
2015-11-19 00:28:05 UTC (rev 14418)
+++ branches/dev-syncromind/phpgwapi/js/form-validator/jquery.form-validator.js 
2015-11-19 10:13:24 UTC (rev 14419)
@@ -1,347 +1,399 @@
 /**
-* jQuery Form Validator
-* ------------------------------------------
-* Created by Victor Jonsson <http://www.victorjonsson.se>
-*
-* @website http://formvalidator.net/
-* @license Dual licensed under the MIT or GPL Version 2 licenses
-* @version 2.2.beta.58
-*/
-(function($) {
+ * jQuery Form Validator
+ * ------------------------------------------
+ * Created by Victor Jonsson <http://www.victorjonsson.se>
+ *
+ * @website http://formvalidator.net/
+ * @license MIT
+ * @version 2.2.83
+ */
+(function ($) {
 
-    'use strict';
+  'use strict';
 
-    var $window = $(window),
-        _applyErrorStyle = function($elem, conf) {
-            $elem
-                .addClass(conf.errorElementClass)
-                .removeClass('valid');
+  var $window = $(window),
+    _getInputParentContainer = function ($elem) {
+      if ($elem.valAttr('error-msg-container')) {
+        return $($elem.valAttr('error-msg-container'));
+      } else {
+        var $parent = $elem.parent();
+        if ( !$parent.hasClass('form-group') && 
!$parent.closest('form').hasClass('form-horizontal') ) {
+          var $formGroup = $parent.closest('.form-group');
+          if ($formGroup.length) {
+            return $formGroup.eq(0);
+          }
+        }
+        return $parent;
+      }
+    },
+    _applyErrorStyle = function ($elem, conf) {
+      $elem
+        .addClass(conf.errorElementClass)
+        .removeClass('valid');
 
-            var $parent = $elem.parent();
-            if($parent.hasClass("input-group"))
-                $parent = $parent.parent();
-            
-            $parent
-               .addClass(conf.inputParentClassOnError)
-                .removeClass(conf.inputParentClassOnSuccess);
+      _getInputParentContainer($elem)
+        .addClass(conf.inputParentClassOnError)
+        .removeClass(conf.inputParentClassOnSuccess);
 
-            if(conf.borderColorOnError !== '') {
-                $elem.css('border-color', conf.borderColorOnError);
-            }
-        },
-        _removeErrorStyle = function($elem, conf) {
-            $elem.each(function() {
-                var $this = $(this),
-                    $parent = $this.parent();
+      if (conf.borderColorOnError !== '') {
+        $elem.css('border-color', conf.borderColorOnError);
+      }
+    },
+    _removeErrorStyle = function ($elem, conf) {
+      $elem.each(function () {
+        var $this = $(this);
 
-                if($parent.hasClass("input-group"))
-                    $parent = $parent.parent();
+        _setInlineErrorMessage($this, '', conf, conf.errorMessagePosition);
 
-                _setInlineErrorMessage($this, '', conf, 
conf.errorMessagePosition);
+        $this
+          .removeClass('valid')
+          .removeClass(conf.errorElementClass)
+          .css('border-color', '');
 
-                $this
-                    .removeClass('valid')
-                    .removeClass(conf.errorElementClass)
-                    .css('border-color', '');
+        _getInputParentContainer($this)
+          .removeClass(conf.inputParentClassOnError)
+          .removeClass(conf.inputParentClassOnSuccess)
+          .find('.' + conf.errorMessageClass) // remove inline span holding 
error message
+            .remove();
+      });
+    },
+    _setInlineErrorMessage = function ($input, mess, conf, $messageContainer) {
+      var custom = document.getElementById($input.attr('name') + '_err_msg'),
+          setErrorMessage = function($elem) {
+            $window.trigger('validationErrorDisplay', [$input, $elem]);
+            $elem.html(mess);
+          },
+          $mess = {};
 
-                $parent
-                    .removeClass(conf.inputParentClassOnError)
-                           .removeClass(conf.inputParentClassOnSuccess)
-                    .find('.'+conf.errorMessageClass) // remove inline span 
holding error message
-                        .remove();
-            });
-        },
-        _setInlineErrorMessage = function($input, mess, conf, 
$messageContainer) {
-            var custom = _getInlineErrorElement($input);
-            
-            if( custom ) {
-                custom.innerHTML = mess;
-            }
-            else if( typeof $messageContainer == 'object' ) {
-                var $found = false;
-                
$messageContainer.find('.'+conf.errorMessageClass).each(function() {
-                    if( this.inputReferer == $input[0] ) {
-                        $found = $(this);
-                        return false;
-                    }
-                });
-                if( $found ) {
-                    if( !mess ) {
-                        $found.remove();
-                    } else {
-                        $found.html(mess);
-                    }
-                } else {
-                    var $mess = $('<div 
class="'+conf.errorMessageClass+'">'+mess+'</div>');
-                    $mess[0].inputReferer = $input[0];
-                    $messageContainer.prepend($mess);
-                }
-            }
-            else {
-               var $parent = $input.parent();
-                   if($parent.hasClass("input-group")) $parent = 
$parent.parent();
-                var $mess = 
$parent.find('.'+conf.errorMessageClass+'.help-block');
-                if( $mess.length == 0 ) {
-                    $mess = 
$('<span></span>').addClass('help-block').addClass(conf.errorMessageClass);
-                    $mess.appendTo($parent);
-                }
-                $mess.html(mess);
-            }
-        },
-        _getInlineErrorElement = function($input, conf) {
-            return document.getElementById($input.attr('name')+'_err_msg');
-        },
-        _templateMessage = function($form, title, errorMessages, conf) {
-            var messages = 
conf.errorMessageTemplate.messages.replace(/\{errorTitle\}/g, title);
-            var fields = [];
-            $.each(errorMessages, function(i, msg) {
-                
fields.push(conf.errorMessageTemplate.field.replace(/\{msg\}/g, msg));
-            });
-            messages = messages.replace(/\{fields\}/g, fields.join(''));
-            var container = 
conf.errorMessageTemplate.container.replace(/\{errorMessageClass\}/g, 
conf.errorMessageClass);
-            container = container.replace(/\{messages\}/g, messages);
-            $form.children().eq(0).before(container);
-        };
+      if (custom) {
+        setErrorMessage($(custom));
+      }
+      else if (typeof $messageContainer === 'object') {
+        var $found = false;
+        $messageContainer.find('.' + conf.errorMessageClass).each(function () {
+          if (this.inputReferer === $input[0]) {
+            $found = $(this);
+            return false;
+          }
+        });
+        if ($found) {
+          if (!mess) {
+            $found.remove();
+          } else {
+            setErrorMessage($found);
+          }
+        } else {
+          $mess = $('<div class="' + conf.errorMessageClass + '"></div>');
+          setErrorMessage($mess);
+          $mess[0].inputReferer = $input[0];
+          $messageContainer.prepend($mess);
+        }
+      }
+      else {
+        var $parent = _getInputParentContainer($input);
+        $mess = $parent.find('.' + conf.errorMessageClass + '.help-block');
 
-    /**
-    * Assigns validateInputOnBlur function to elements blur event
-    *
-    * @param {Object} language Optional, will override $.formUtils.LANG
-    * @param {Object} settings Optional, will override the default settings
-    * @return {jQuery}
-    */
-    $.fn.validateOnBlur = function(language, settings) {
-        
this.find('input[data-validation],textarea[data-validation],select[data-validation]')
-            .bind('blur.validation', function() {
-                $(this).validateInputOnBlur(language, settings, true, 'blur');
-            });
-        if(settings.validateCheckboxRadioOnClick) {
-        // bind click event to validate on click for radio & checkboxes for 
nice UX
-        
this.find('input[type=checkbox][data-validation],input[type=radio][data-validation]')
-            .bind('click.validation', function() {
-                $(this).validateInputOnBlur(language, settings, true, 'click');
-            });
+        if ($mess.length === 0) {
+          $mess = 
$('<span></span>').addClass('help-block').addClass(conf.errorMessageClass);
+          $mess.appendTo($parent);
         }
 
-        return this;
+        setErrorMessage($mess);
+      }
+    },
+    _templateMessage = function ($form, title, errorMessages, conf) {
+      var messages = 
conf.errorMessageTemplate.messages.replace(/\{errorTitle\}/g, title),
+          fields = [],
+          container;
+
+      $.each(errorMessages, function (i, msg) {
+        fields.push(conf.errorMessageTemplate.field.replace(/\{msg\}/g, msg));
+      });
+
+      messages = messages.replace(/\{fields\}/g, fields.join(''));
+      container = 
conf.errorMessageTemplate.container.replace(/\{errorMessageClass\}/g, 
conf.errorMessageClass);
+      container = container.replace(/\{messages\}/g, messages);
+      $form.children().eq(0).before(container);
     };
 
-       /*
-        * Assigns validateInputOnBlur function to elements custom event
-        * @param {Object} language Optional, will override $.formUtils.LANG
-        * @param {Object} settings Optional, will override the default settings
-        * * @return {jQuery}   
-        */
-       $.fn.validateOnEvent = function(language, settings) {
-        
this.find('input[data-validation][data-validation-event],textarea[data-validation][data-validation-event],select[data-validation][data-validation-event]')
-                       .each(function(){
-                               var $el = $(this),
-                                   etype = $el.valAttr("event");
-                               if (etype){
-                                       $el.bind(etype + ".validation", 
function(){
-                               $(this).validateInputOnBlur(language, settings, 
true, etype);
-                                       });
-                               }
-                       });
-               return this;
-       };
 
-    /**
-    * fade in help message when input gains focus
-    * fade out when input loses focus
-    * <input data-help="The info that I want to display for the user when 
input is focused" ... />
-    *
-    * @param {String} attrName - Optional, default is data-help
-    * @return {jQuery}
-    */
-    $.fn.showHelpOnFocus = function(attrName) {
-        if(!attrName) {
-            attrName = 'data-validation-help';
+  /**
+   * Assigns validateInputOnBlur function to elements blur event
+   *
+   * @param {Object} language Optional, will override $.formUtils.LANG
+   * @param {Object} conf Optional, will override the default settings
+   * @return {jQuery}
+   */
+  $.fn.validateOnBlur = function (language, conf) {
+    this.find('*[data-validation]')
+      .bind('blur.validation', function () {
+        $(this).validateInputOnBlur(language, conf, true, 'blur');
+      });
+    if (conf.validateCheckboxRadioOnClick) {
+      // bind click event to validate on click for radio & checkboxes for nice 
UX
+      
this.find('input[type=checkbox][data-validation],input[type=radio][data-validation]')
+        .bind('click.validation', function () {
+          $(this).validateInputOnBlur(language, conf, true, 'click');
+        });
+    }
+
+    return this;
+  };
+
+  /*
+   * Assigns validateInputOnBlur function to elements custom event
+   * @param {Object} language Optional, will override $.formUtils.LANG
+   * @param {Object} settings Optional, will override the default settings
+   * * @return {jQuery}
+   */
+  $.fn.validateOnEvent = function (language, settings) {
+    this.find('*[data-validation-event]')
+      .each(function () {
+        var $el = $(this),
+            etype = $el.valAttr('event');
+        if (etype) {
+          $el
+            .unbind(etype + '.validation')
+            .bind(etype + '.validation', function () {
+              $(this).validateInputOnBlur(language, settings, true, etype);
+            });
         }
+      });
+    return this;
+  };
 
-        // Remove previously added event listeners
-        this.find('.has-help-txt')
-                .valAttr('has-keyup-event', false)
-                .removeClass('has-help-txt');
+  /**
+   * fade in help message when input gains focus
+   * fade out when input loses focus
+   * <input data-help="The info that I want to display for the user when input 
is focused" ... />
+   *
+   * @param {String} attrName - Optional, default is data-help
+   * @return {jQuery}
+   */
+  $.fn.showHelpOnFocus = function (attrName) {
+    if (!attrName) {
+      attrName = 'data-validation-help';
+    }
 
-        // Add help text listeners
-        this.find('textarea,input').each(function() {
-            var $elem = $(this),
-                className = 'jquery_form_help_' + ($elem.attr('name') || 
'').replace( /(:|\.|\[|\])/g, "" ),
-                help = $elem.attr(attrName);
+    // Remove previously added event listeners
+    this.find('.has-help-txt')
+      .valAttr('has-keyup-event', false)
+      .removeClass('has-help-txt');
 
-            if(help) {
-                $elem
-                    .addClass('has-help-txt')
-                    .unbind('focus.help')
-                    .bind('focus.help', function() {
-                        var $help = $elem.parent().find('.'+className);
-                        if($help.length == 0) {
-                            $help = $('<span />')
-                                        .addClass(className)
-                                        .addClass('help')
-                                        .addClass('help-block') // twitter bs
-                                        .text(help)
-                                        .hide();
+    // Add help text listeners
+    this.find('textarea,input').each(function () {
+      var $elem = $(this),
+          className = 'jquery_form_help_' + ($elem.attr('name') || 
'').replace(/(:|\.|\[|\])/g, ''),
+          help = $elem.attr(attrName);
 
-                            $elem.after($help);
+      if (help) {
+        $elem
+          .addClass('has-help-txt')
+          .unbind('focus.help')
+          .bind('focus.help', function () {
+            var $help = $elem.parent().find('.' + className);
+            if ($help.length === 0) {
+              $help = $('<span />')
+                        .addClass(className)
+                        .addClass('help')
+                        .addClass('help-block') // twitter bs
+                        .text(help)
+                        .hide();
 
-                        }
-                        $help.fadeIn();
-                    })
-                    .unbind('blur.help')
-                    .bind('blur.help', function() {
-                        $(this)
-                            .parent()
-                            .find('.'+className)
-                                .fadeOut('slow');
-                    });
+              $elem.after($help);
             }
-        });
+            $help.fadeIn();
+          })
+          .unbind('blur.help')
+          .bind('blur.help', function () {
+            $(this)
+              .parent()
+              .find('.' + className)
+              .fadeOut('slow');
+          });
+      }
+    });
 
-        return this;
-    };
+    return this;
+  };
 
-    /**
-    * Validate single input when it loses focus
-    * shows error message in a span element 
-    * that is appended to the parent element
-    *
-    * @param {Object} [language] Optional, will override $.formUtils.LANG
-    * @param {Object} [conf] Optional, will override the default settings
-    * @param {Boolean} attachKeyupEvent Optional
-    * @param {String} eventType
-    * @return {jQuery}
-    */
-    $.fn.validateInputOnBlur = function(language, conf, attachKeyupEvent, 
eventType) {
+  /**
+   * @param {Function} cb
+   * @param {Object} [conf]
+   * @param {Object} [lang]
+   */
+  $.fn.validate = function(cb, conf, lang) {
+    var language = $.extend({}, $.formUtils.LANG, lang || {});
+    this.each(function() {
+      var $elem = $(this),
+          formDefaultConfig = $elem.closest('form').get(0).validationConfig || 
{};
 
-        $.formUtils.eventType = eventType;
+      $elem.one('validation', function(evt, isValid) {
+        if ( typeof cb === 'function' ) {
+          cb(isValid, this, evt);
+        }
+      });
 
-        if( (this.valAttr('suggestion-nr') || this.valAttr('postpone') || 
this.hasClass('hasDatepicker')) && !window.postponedValidation ) {
-            // This validation has to be postponed
-            var _self = this,
-                postponeTime = this.valAttr('postpone') || 200;
+      $elem.validateInputOnBlur(
+          language,
+          $.extend({}, formDefaultConfig, conf || {}),
+          true
+        );
+    });
+  };
 
-            window.postponedValidation = function() {
-                _self.validateInputOnBlur(language, conf, attachKeyupEvent, 
eventType);
-                window.postponedValidation = false;
-            };
-            setTimeout(function() {
-                if( window.postponedValidation ) {
-                    window.postponedValidation();
-                }
-            }, postponeTime);
+  /**
+   * Tells whether or not validation of this input will have to postpone the 
form submit ()
+   * @returns {Boolean}
+   */
+  $.fn.willPostponeValidation = function() {
+    return (this.valAttr('suggestion-nr') ||
+            this.valAttr('postpone') ||
+            this.hasClass('hasDatepicker')) &&
+            !window.postponedValidation;
+  };
 
-            return this;
-        }
+  /**
+   * Validate single input when it loses focus
+   * shows error message in a span element
+   * that is appended to the parent element
+   *
+   * @param {Object} [language] Optional, will override $.formUtils.LANG
+   * @param {Object} [conf] Optional, will override the default settings
+   * @param {Boolean} attachKeyupEvent Optional
+   * @param {String} eventType
+   * @return {jQuery}
+   */
+  $.fn.validateInputOnBlur = function (language, conf, attachKeyupEvent, 
eventType) {
 
-        language = $.extend({}, $.formUtils.LANG, language || {});
-        _removeErrorStyle(this, conf);
-        var $elem = this,
-            $form = $elem.closest("form"),
-            validationRule = $elem.attr(conf.validationRuleAttribute),
-            validation = $.formUtils.validateInput(
-                            $elem,
-                            language,
-                            $.extend({}, conf, 
{errorMessagePosition:'element'}),
-                            $form,
-                            eventType
-                        );
-        
-        if(validation === true) {
-            $elem
-                .addClass('valid')
-                .parent()
-                    .addClass(conf.inputParentClassOnSuccess); 
-                    
-        } else if(validation !== null) {
+    $.formUtils.eventType = eventType;
 
-            _applyErrorStyle($elem, conf);
-            _setInlineErrorMessage($elem, validation, conf, 
conf.errorMessagePosition);
+    if ( this.willPostponeValidation() ) {
+      // This validation has to be postponed
+      var _self = this,
+          postponeTime = this.valAttr('postpone') || 200;
 
-            if(attachKeyupEvent) {
-                $elem
-                    .unbind('keyup.validation')
-                    .bind('keyup.validation', function() {
-                        $(this).validateInputOnBlur(language, conf, false, 
'keyup');
-                    });
-            }
+      window.postponedValidation = function () {
+        _self.validateInputOnBlur(language, conf, attachKeyupEvent, eventType);
+        window.postponedValidation = false;
+      };
+
+      setTimeout(function () {
+        if (window.postponedValidation) {
+          window.postponedValidation();
         }
+      }, postponeTime);
 
-        return this;
-    };
+      return this;
+    }
 
-    /**
-     * Short hand for fetching/adding/removing element attributes
-     * prefixed with 'data-validation-'
-     *
-     * @param {String} name
-     * @param {String|Boolean} [val]
-     * @return string|undefined
-     * @protected
-     */
-    $.fn.valAttr = function(name, val) {
-        if( val === undefined ) {
-            return this.attr('data-validation-'+name);
-        } else if( val === false || val === null ) {
-            return this.removeAttr('data-validation-'+name);
-        } else {
-            if(name.length > 0) name='-'+name;
-            return this.attr('data-validation'+name, val);
-        }
-    };
+    language = $.extend({}, $.formUtils.LANG, language || {});
+    _removeErrorStyle(this, conf);
+    var $elem = this,
+        $form = $elem.closest('form'),
+        result = $.formUtils.validateInput(
+                    $elem,
+                    language,
+                    conf,
+                    $form,
+                    eventType
+                  );
 
-    /**
-     * Function that validates all inputs in active form
-     *
-     * @param {Object} [language]
-     * @param {Object} [conf]
-     * @param {Boolean} [displayError] Defaults to true
-     */
-    $.fn.isValid = function(language, conf, displayError) {
+    if ( result.isValid ) {
+      if( result.shouldChangeDisplay ) {
+          $elem.addClass('valid');
+          _getInputParentContainer($elem)
+            .addClass(conf.inputParentClassOnSuccess);
+      }
+    }
+    else if (!result.isValid) {
 
-        if ($.formUtils.isLoadingModules) {
-            var $self = this;
-            setTimeout(function () {
-                $self.isValid(language, conf, displayError);
-            }, 200);
-            return null;
-        }
+      _applyErrorStyle($elem, conf);
+      _setInlineErrorMessage($elem, result.errorMsg, conf, 
conf.errorMessagePosition);
 
-        conf = $.extend({}, $.formUtils.defaultConfig(), conf || {});
-        language = $.extend({}, $.formUtils.LANG, language || {});
-        displayError = displayError !== false;
+      if (attachKeyupEvent) {
+        $elem
+          .unbind('keyup.validation')
+          .bind('keyup.validation', function () {
+            $(this).validateInputOnBlur(language, conf, false, 'keyup');
+          });
+      }
+    }
 
-        if($.formUtils.errorDisplayPreventedWhenHalted) {
-            // isValid() was called programmatically with argument 
displayError set
-            // to false when the validation was halted by any of the validators
-            delete $.formUtils.errorDisplayPreventedWhenHalted
-            displayError = false;
-        }
+    return this;
+  };
 
+  /**
+   * Short hand for fetching/adding/removing element attributes
+   * prefixed with 'data-validation-'
+   *
+   * @param {String} name
+   * @param {String|Boolean} [val]
+   * @return string|undefined
+   * @protected
+   */
+  $.fn.valAttr = function (name, val) {
+    if (val === undefined) {
+      return this.attr('data-validation-' + name);
+    } else if (val === false || val === null) {
+      return this.removeAttr('data-validation-' + name);
+    } else {
+      name = ((name.length > 0) ? '-' + name : '');
+      return this.attr('data-validation' + name, val);
+    }
+  };
 
-        $.formUtils.isValidatingEntireForm = true;
-        $.formUtils.haltValidation = false;
+  /**
+   * Function that validates all inputs in active form
+   *
+   * @param {Object} [language]
+   * @param {Object} [conf]
+   * @param {Boolean} [displayError] Defaults to true
+   */
+  $.fn.isValid = function (language, conf, displayError) {
 
-        /**
-         * Adds message to error message stack if not already in the message 
stack
-         *
-         * @param {String} mess
-         * @para {jQuery} $elem
-         */
-        var addErrorMessage = function(mess, $elem) {
-            if ($.inArray(mess, errorMessages) < 0) {
-                errorMessages.push(mess);
-            }
-            errorInputs.push($elem);
-            $elem.attr('current-error', mess);
-            if( displayError )
-                _applyErrorStyle($elem, conf);
+    if ($.formUtils.isLoadingModules) {
+      var $self = this;
+      setTimeout(function () {
+        $self.isValid(language, conf, displayError);
+      }, 200);
+      return null;
+    }
+
+    conf = $.extend({}, $.formUtils.defaultConfig(), conf || {});
+    language = $.extend({}, $.formUtils.LANG, language || {});
+    displayError = displayError !== false;
+
+    if ($.formUtils.errorDisplayPreventedWhenHalted) {
+      // isValid() was called programmatically with argument displayError set
+      // to false when the validation was halted by any of the validators
+      delete $.formUtils.errorDisplayPreventedWhenHalted;
+      displayError = false;
+    }
+
+    $.formUtils.isValidatingEntireForm = true;
+    $.formUtils.haltValidation = false;
+
+    /**
+     * Adds message to error message stack if not already in the message stack
+     *
+     * @param {String} mess
+     * @para {jQuery} $elem
+     */
+    var addErrorMessage = function (mess, $elem) {
+          if ($.inArray(mess, errorMessages) < 0) {
+            errorMessages.push(mess);
+          }
+          errorInputs.push($elem);
+          $elem.attr('current-error', mess);
+          if (displayError) {
+            _applyErrorStyle($elem, conf);
+          }
         },
 
         /** Holds inputs (of type checkox or radio) already validated, to 
prevent recheck of mulitple checkboxes & radios */
         checkedInputs = [],
-       
+
         /** Error messages for this validation */
         errorMessages = [],
 
@@ -351,1308 +403,1429 @@
         /** Form instance */
         $form = this,
 
-        /**
-         * Tells whether or not to validate element with this name and of this 
type
-         *
-         * @param {String} name
-         * @param {String} type
-         * @return {Boolean}
-         */
-        ignoreInput = function(name, type) {
-            if (type === 'submit' || type === 'button' || type == 'reset') {
-                return true;
-            }
-            return $.inArray(name, conf.ignore || []) > -1;
-        };
-
-        // Reset style and remove error class
-        if( displayError ) {
-            $form.find('.'+conf.errorMessageClass+'.alert').remove();
-            
_removeErrorStyle($form.find('.'+conf.errorElementClass+',.valid'), conf);
+      /**
+       * Tells whether or not to validate element with this name and of this 
type
+       *
+       * @param {String} name
+       * @param {String} type
+       * @return {Boolean}
+       */
+        ignoreInput = function (name, type) {
+        if (type === 'submit' || type === 'button' || type === 'reset') {
+          return true;
         }
+        return $.inArray(name, conf.ignore || []) > -1;
+      };
 
-        // Validate element values
-        
$form.find('input,textarea,select').filter(':not([type="submit"],[type="button"])').each(function()
 {
-            var $elem = $(this),
-                elementType = $elem.attr('type'),
-                isCheckboxOrRadioBtn = elementType == 'radio' || elementType 
== 'checkbox',
-                elementName = $elem.attr('name');
+    // Reset style and remove error class
+    if (displayError) {
+      $form.find('.' + conf.errorMessageClass + '.alert').remove();
+      _removeErrorStyle($form.find('.' + conf.errorElementClass + ',.valid'), 
conf);
+    }
 
-            if (!ignoreInput(elementName, elementType) && 
(!isCheckboxOrRadioBtn || $.inArray(elementName, checkedInputs) < 0) ) {
+    // Validate element values
+    
$form.find('input,textarea,select').filter(':not([type="submit"],[type="button"])').each(function
 () {
+      var $elem = $(this),
+        elementType = $elem.attr('type'),
+        isCheckboxOrRadioBtn = elementType === 'radio' || elementType === 
'checkbox',
+        elementName = $elem.attr('name');
 
-                if( isCheckboxOrRadioBtn )
-                    checkedInputs.push(elementName);
+      if (!ignoreInput(elementName, elementType) && (!isCheckboxOrRadioBtn || 
$.inArray(elementName, checkedInputs) < 0)) {
 
-                var validation = $.formUtils.validateInput(
-                                $elem,
-                                language,
-                                conf,
-                                $form,
-                                'submit'
+        if (isCheckboxOrRadioBtn) {
+          checkedInputs.push(elementName);
+        }
+
+        var result = $.formUtils.validateInput(
+                              $elem,
+                              language,
+                              conf,
+                              $form,
+                              'submit'
                             );
 
-                if(validation != null) {
-                    if(validation !== true) {
-                        addErrorMessage(validation, $elem);
-                    } else {
-                        $elem
-                            .valAttr('current-error', false)
-                            .addClass('valid')
-                            .parent()
-                            .addClass('has-success');
-                    }
-                }
-            }
+        if( result.shouldChangeDisplay ) {
+          if ( !result.isValid ) {
+            addErrorMessage(result.errorMsg, $elem);
+          } else if( result.isValid ) {
+            $elem
+              .valAttr('current-error', false)
+              .addClass('valid');
+
+            _getInputParentContainer($elem)
+              .addClass(conf.inputParentClassOnSuccess);
+          }
+        }
+      }
+    });
+
+    // Run validation callback
+    if (typeof conf.onValidate === 'function') {
+      var errors = conf.onValidate($form);
+      if ($.isArray(errors)) {
+        $.each(errors, function (i, err) {
+          addErrorMessage(err.message, err.element);
         });
+      }
+      else if (errors && errors.element && errors.message) {
+        addErrorMessage(errors.message, errors.element);
+      }
+    }
 
-        // Run validation callback
-        if( typeof conf.onValidate == 'function' ) {
-            var errors = conf.onValidate($form);
-            if( $.isArray(errors) ) {
-                $.each(errors, function(i, err) {
-                    addErrorMessage(err.message, err.element);
-                });
-            }
-            else if( errors && errors.element && errors.message ) {
-                addErrorMessage(errors.message, errors.element);
-            }
+    // Reset form validation flag
+    $.formUtils.isValidatingEntireForm = false;
+
+    // Validation failed
+    if (!$.formUtils.haltValidation && errorInputs.length > 0) {
+
+      if (displayError) {
+        // display all error messages in top of form
+        if (conf.errorMessagePosition === 'top') {
+          _templateMessage($form, language.errorTitle, errorMessages, conf);
         }
+        // Customize display message
+        else if (conf.errorMessagePosition === 'custom') {
+          if (typeof conf.errorMessageCustom === 'function') {
+            conf.errorMessageCustom($form, language.errorTitle, errorMessages, 
conf);
+          }
+        }
+        // Display error message below input field or in defined container
+        else {
+          $.each(errorInputs, function (i, $input) {
+            _setInlineErrorMessage($input, $input.attr('current-error'), conf, 
conf.errorMessagePosition);
+          });
+        }
 
-        // Reset form validation flag
-        $.formUtils.isValidatingEntireForm = false;
+        if (conf.scrollToTopOnError) {
+          $window.scrollTop($form.offset().top - 20);
+        }
+      }
 
-        // Validation failed
-        if ( !$.formUtils.haltValidation && errorInputs.length > 0 ) {
+      return false;
+    }
 
-            if( displayError ) {
-                // display all error messages in top of form
-                if (conf.errorMessagePosition === 'top') {
-                    _templateMessage($form, language.errorTitle, 
errorMessages, conf);
-                }
-                // Customize display message
-                else if(conf.errorMessagePosition === 'custom') {
-                    if( typeof conf.errorMessageCustom === 'function' ) {
-                        conf.errorMessageCustom($form, language.errorTitle, 
errorMessages, conf);
-                    }
-                }
-                // Display error message below input field or in defined 
container
-                else  {
-                    $.each(errorInputs, function(i, $input) {
-                        _setInlineErrorMessage($input, 
$input.attr('current-error'), conf, conf.errorMessagePosition);
-                    });
-                }
+    if (!displayError && $.formUtils.haltValidation) {
+      $.formUtils.errorDisplayPreventedWhenHalted = true;
+    }
 
-                if(conf.scrollToTopOnError) {
-                    $window.scrollTop($form.offset().top - 20);
-                }
+    return !$.formUtils.haltValidation;
+  };
+
+  /**
+   * @deprecated
+   * @param language
+   * @param conf
+   */
+  $.fn.validateForm = function (language, conf) {
+    if (window.console && typeof window.console.warn === 'function') {
+      window.console.warn('Use of deprecated function $.validateForm, use 
$.isValid instead');
+    }
+    return this.isValid(language, conf, true);
+  };
+
+  /**
+   * Plugin for displaying input length restriction
+   */
+  $.fn.restrictLength = function (maxLengthElement) {
+    new $.formUtils.lengthRestriction(this, maxLengthElement);
+    return this;
+  };
+
+  /**
+   * Add suggestion dropdown to inputs having data-suggestions with a comma
+   * separated string with suggestions
+   * @param {Array} [settings]
+   * @returns {jQuery}
+   */
+  $.fn.addSuggestions = function (settings) {
+    var sugs = false;
+    this.find('input').each(function () {
+      var $field = $(this);
+
+      sugs = $.split($field.attr('data-suggestions'));
+
+      if (sugs.length > 0 && !$field.hasClass('has-suggestions')) {
+        $.formUtils.suggest($field, sugs, settings);
+        $field.addClass('has-suggestions');
+      }
+    });
+    return this;
+  };
+
+  /**
+   * A bit smarter split function
+   * delimiter can be space, comma, dash or pipe
+   * @param {String} val
+   * @param {Function|String} [callback]
+   * @returns {Array|void}
+   */
+  $.split = function (val, callback) {
+    if (typeof callback !== 'function') {
+      // return array
+      if (!val) {
+        return [];
+      }
+      var values = [];
+      $.each(val.split(callback ? callback : /[,|\-\s]\s*/g),
+        function (i, str) {
+          str = $.trim(str);
+          if (str.length) {
+            values.push(str);
+          }
+        }
+      );
+      return values;
+    } else if (val) {
+      // exec callback func on each
+      $.each(val.split(/[,|\-\s]\s*/g),
+        function (i, str) {
+          str = $.trim(str);
+          if (str.length) {
+            return callback(str, i);
+          }
+        }
+      );
+    }
+  };
+
+  /**
+   * Short hand function that makes the validation setup require less code
+   * @param conf
+   */
+  $.validate = function (conf) {
+
+    var defaultConf = $.extend($.formUtils.defaultConfig(), {
+      form: 'form',
+      /*
+       * Enable custom event for validation
+       */
+      validateOnEvent: false,
+      validateOnBlur: true,
+      validateCheckboxRadioOnClick: true,
+      showHelpOnFocus: true,
+      addSuggestions: true,
+      modules: '',
+      onModulesLoaded: null,
+      language: false,
+      onSuccess: false,
+      onError: false,
+      onElementValidate: false,
+    });
+
+    conf = $.extend(defaultConf, conf || {});
+
+    if( conf.lang && conf.lang !== 'en' ) {
+      var langModule = 'lang/'+conf.lang+'.js';
+      conf.modules += conf.modules.length ? ','+langModule : langModule;
+    }
+
+    // Add validation to forms
+    $(conf.form).each(function (i, form) {
+
+      // Make a reference to the config for this form
+      form.validationConfig = conf;
+
+      // Trigger jQuery event that we're about to setup va
+      var $form = $(form);
+      $window.trigger('formValidationSetup', [$form, conf]);
+
+      // Remove classes and event handlers that might have been
+      // added by a previous call to $.validate
+      $form.find('.has-help-txt')
+          .unbind('focus.validation')
+          .unbind('blur.validation');
+
+      $form
+        .removeClass('has-validation-callback')
+        .unbind('submit.validation')
+        .unbind('reset.validation')
+        .find('input[data-validation],textarea[data-validation]')
+          .unbind('blur.validation');
+
+      // Validate when submitted
+      $form.bind('submit.validation', function () {
+
+        var $form = $(this);
+
+        if ($.formUtils.haltValidation) {
+          // pressing several times on submit button while validation is halted
+          return false;
+        }
+
+        if ($.formUtils.isLoadingModules) {
+          setTimeout(function () {
+            $form.trigger('submit.validation');
+          }, 200);
+          return false;
+        }
+
+        var valid = $form.isValid(conf.language, conf);
+
+        if ($.formUtils.haltValidation) {
+          // Validation got halted by one of the validators
+          return false;
+        } else {
+          if (valid && typeof conf.onSuccess === 'function') {
+            var callbackResponse = conf.onSuccess($form);
+            if (callbackResponse === false) {
+              return false;
             }
-
+          } else if (!valid && typeof conf.onError === 'function') {
+            conf.onError($form);
             return false;
+          } else {
+            return valid;
+          }
         }
+      })
+      .bind('reset.validation', function () {
+        // remove messages
+        $(this).find('.' + conf.errorMessageClass + '.alert').remove();
+        _removeErrorStyle($(this).find('.' + conf.errorElementClass + 
',.valid'), conf);
+      })
+      .addClass('has-validation-callback');
 
-        if( !displayError && $.formUtils.haltValidation ) {
-            $.formUtils.errorDisplayPreventedWhenHalted = true;
+      if (conf.showHelpOnFocus) {
+        $form.showHelpOnFocus();
+      }
+      if (conf.addSuggestions) {
+        $form.addSuggestions();
+      }
+      if (conf.validateOnBlur) {
+        $form.validateOnBlur(conf.language, conf);
+        $form.bind('html5ValidationAttrsFound', function () {
+          $form.validateOnBlur(conf.language, conf);
+        });
+      }
+      if (conf.validateOnEvent) {
+        $form.validateOnEvent(conf.language, conf);
+      }
+    });
+
+    if (conf.modules !== '') {
+      $.formUtils.loadModules(conf.modules, false, function() {
+        if (typeof conf.onModulesLoaded === 'function') {
+          conf.onModulesLoaded();
         }
+        $window.trigger('validatorsLoaded', [typeof conf.form === 'string' ? 
$(conf.form) : conf.form, conf]);
+      });
+    }
+  };
 
-        return !$.formUtils.haltValidation;
-    };
+  /**
+   * Object containing utility methods for this plugin
+   */
+  $.formUtils = {
 
     /**
-     * @deprecated
-     * @param language
-     * @param conf
+     * Default config for $(...).isValid();
      */
-    $.fn.validateForm = function(language, conf) {
-        if( window.console && typeof window.console.warn == 'function' ) {
-            window.console.warn('Use of deprecated function $.validateForm, 
use $.isValid instead');
-        }
-        return this.isValid(language, conf, true);
-    }
+    defaultConfig: function () {
+      return {
+        ignore: [], // Names of inputs not to be validated even though node 
attribute containing the validation rules tells us to
+        errorElementClass: 'error', // Class that will be put on elements 
which value is invalid
+        borderColorOnError: '#b94a48', // Border color of elements which value 
is invalid, empty string to not change border color
+        errorMessageClass: 'form-error', // class name of div containing error 
messages when validation fails
+        validationRuleAttribute: 'data-validation', // name of the attribute 
holding the validation rules
+        validationErrorMsgAttribute: 'data-validation-error-msg', // define 
custom err msg inline with element
+        errorMessagePosition: 'element', // Can be either "top" or "element" 
or "custom"
+        errorMessageTemplate: {
+          container: '<div class="{errorMessageClass} alert 
alert-danger">{messages}</div>',
+          messages: '<strong>{errorTitle}</strong><ul>{fields}</ul>',
+          field: '<li>{msg}</li>'
+        },
+        errorMessageCustom: _templateMessage,
+        scrollToTopOnError: true,
+        dateFormat: 'yyyy-mm-dd',
+        addValidClassOnAll: false, // whether or not to apply class="valid" 
even if the input wasn't validated
+        decimalSeparator: '.',
+        inputParentClassOnError: 'has-error', // twitter-bootstrap default 
class name
+        inputParentClassOnSuccess: 'has-success', // twitter-bootstrap default 
class name
+        validateHiddenInputs: false, // whether or not hidden inputs should be 
validated
+      };
+    },
 
     /**
-    * Plugin for displaying input length restriction
-    */
-    $.fn.restrictLength = function(maxLengthElement) {
-        new $.formUtils.lengthRestriction(this, maxLengthElement);
-        return this;
-    };
+     * Available validators
+     */
+    validators: {},
 
     /**
-     * Add suggestion dropdown to inputs having data-suggestions with a comma
-     * separated string with suggestions
-     * @param {Array} [settings]
-     * @returns {jQuery}
+     * Events triggered by form validator
      */
-    $.fn.addSuggestions = function(settings) {
-        var sugs = false;
-        this.find('input').each(function() {
-            var $field = $(this);
+    _events: {load: [], valid: [], invalid: []},
 
-            sugs = $.split($field.attr('data-suggestions'));
+    /**
+     * Setting this property to true during validation will
+     * stop further validation from taking place and form will
+     * not be sent
+     */
+    haltValidation: false,
 
-            if( sugs.length > 0 && !$field.hasClass('has-suggestions') ) {
-                $.formUtils.suggest($field, sugs, settings);
-                $field.addClass('has-suggestions');
-            }
-        });
-        return this;
-    };
+    /**
+     * This variable will be true $.fn.isValid() is called
+     * and false when $.fn.validateOnBlur is called
+     */
+    isValidatingEntireForm: false,
 
     /**
-     * A bit smarter split function
-     * delimiter can be space, comma, dash or pipe
-     * @param {String} val
-     * @param {Function|String} [func]
-     * @returns {Array|void}
+     * Function for adding a validator
+     * @param {Object} validator
      */
-    $.split = function(val, func) {
-        if( typeof func != 'function' ) {
-            // return array
-            if( !val )
-                return [];
-            var values = [];
-            $.each(val.split(func ? func: /[,|\-\s]\s*/g ),
-                function(i,str) {
-                    str = $.trim(str);
-                    if( str.length )
-                        values.push(str);
-                }
-            );
-            return values;
-        } else if( val ) {
-            // exec callback func on each
-            $.each(val.split(/[,|\-\s]\s*/g),
-                function(i, str) {
-                    str = $.trim(str);
-                    if( str.length )
-                        return func(str, i);
-                }
-            );
-        }
-    };
+    addValidator: function (validator) {
+      // prefix with "validate_" for backward compatibility reasons
+      var name = validator.name.indexOf('validate_') === 0 ? validator.name : 
'validate_' + validator.name;
+      if (validator.validateOnKeyUp === undefined) {
+        validator.validateOnKeyUp = true;
+      }
+      this.validators[name] = validator;
+    },
 
     /**
-     * Short hand function that makes the validation setup require less code
-     * @param conf
+     * @var {Boolean}
      */
-    $.validate = function(conf) {
+    isLoadingModules: false,
 
-        var defaultConf = $.extend($.formUtils.defaultConfig(), {
-            form : 'form',
-                       /*
-                        * Enable custom event for validation
-                        */
-            validateOnEvent : true,
-            validateOnBlur : true,
-            validateCheckboxRadioOnClick : true,
-            showHelpOnFocus : true,
-            addSuggestions : true,
-            modules : '',
-            onModulesLoaded : null,
-            language : false,
-            onSuccess : false,
-            onError : false,
-            onElementValidate : false,
-        });
+    /**
+     * @var {Object}
+     */
+    loadedModules: {},
 
-        conf = $.extend(defaultConf, conf || {});
+    /**
+     * @example
+     *  $.formUtils.loadModules('date, security.dev');
+     *
+     * Will load the scripts date.js and security.dev.js from the
+     * directory where this script resides. If you want to load
+     * the modules from another directory you can use the
+     * path argument.
+     *
+     * The script will be cached by the browser unless the module
+     * name ends with .dev
+     *
+     * @param {String} modules - Comma separated string with module file names 
(no directory nor file extension)
+     * @param {String} [path] - Optional, path where the module files is 
located if their not in the same directory as the core modules
+     * @param {Boolean|function} [fireEvent] - Optional, whether or not to 
fire event 'load' when modules finished loading
+     */
+    loadModules: function (modules, path, fireEvent) {
 
-        // Add validation to forms
-        $(conf.form).each(function(i, form) {
+      if (fireEvent === undefined) {
+        fireEvent = true;
+      }
 
-            var $form  = $(form);
-            $window.trigger('formValidationSetup', [$form]);
+      if ($.formUtils.isLoadingModules) {
+        setTimeout(function () {
+          $.formUtils.loadModules(modules, path, fireEvent);
+        });
+        return;
+      }
 
-            // Remove all event listeners previously added
-            $form.find('.has-help-txt')
-                .unbind('focus.validation')
-                .unbind('blur.validation');
-            $form
-                .removeClass('has-validation-callback')
-                .unbind('submit.validation')
-                .unbind('reset.validation')
-                .find('input[data-validation],textarea[data-validation]')
-                    .unbind('blur.validation');
+      var hasLoadedAnyModule = false,
+        loadModuleScripts = function (modules, path) {
 
-            // Validate when submitted
-            $form.bind('submit.validation', function() {
-                var $form = $(this);
-
-                if( $.formUtils.haltValidation ) {
-                    // pressing several times on submit button while 
validation is halted
-                    return false;
+          var moduleList = $.split(modules),
+            numModules = moduleList.length,
+            moduleLoadedCallback = function () {
+              numModules--;
+              if (numModules === 0) {
+                $.formUtils.isLoadingModules = false;
+                if (fireEvent && hasLoadedAnyModule) {
+                  if( typeof fireEvent === 'function' ) {
+                    fireEvent();
+                  } else {
+                    $window.trigger('validatorsLoaded');
+                  }
                 }
+              }
+            };
 
-                if($.formUtils.isLoadingModules) {
-                    setTimeout(function() {
-                        $form.trigger('submit.validation');
-                    }, 200);
-                    return false;
-                }
 
-                var valid = $form.isValid(conf.language, conf);
+          if (numModules > 0) {
+            $.formUtils.isLoadingModules = true;
+          }
 
-                if( $.formUtils.haltValidation ) {
-                    // Validation got halted by one of the validators
-                    return false;
-                } else {
-                    if( valid && typeof conf.onSuccess == 'function') {
-                        var callbackResponse = conf.onSuccess($form);
-                        if( callbackResponse === false )
-                            return false;
-                    } else if ( !valid && typeof conf.onError == 'function' ) {
-                        conf.onError($form);
-                        return false;
-                    } else {
-                        return valid;
-                    }
-                }
-            })
-            .bind('reset.validation', function() {
-                // remove messages
-                $(this).find('.'+conf.errorMessageClass+'.alert').remove();
-                
_removeErrorStyle($(this).find('.'+conf.errorElementClass+',.valid'), conf);
-            })
-            .addClass('has-validation-callback');
+          var cacheSuffix = '?_=' + ( new Date().getTime() ),
+            appendToElement = document.getElementsByTagName('head')[0] || 
document.getElementsByTagName('body')[0];
 
-            if( conf.showHelpOnFocus ) {
-                $form.showHelpOnFocus();
+          $.each(moduleList, function (i, modName) {
+            modName = $.trim(modName);
+            if (modName.length === 0) {
+              moduleLoadedCallback();
             }
-            if( conf.addSuggestions ) {
-                $form.addSuggestions();
+            else {
+              var scriptUrl = path + modName + (modName.slice(-3) === '.js' ? 
'' : '.js'),
+                script = document.createElement('SCRIPT');
+
+              if (scriptUrl in $.formUtils.loadedModules) {
+                // already loaded
+                moduleLoadedCallback();
+              }
+              else {
+
+                // Remember that this script is loaded
+                $.formUtils.loadedModules[scriptUrl] = 1;
+                hasLoadedAnyModule = true;
+
+                // Load the script
+                script.type = 'text/javascript';
+                script.onload = moduleLoadedCallback;
+                script.src = scriptUrl + ( scriptUrl.slice(-7) === '.dev.js' ? 
cacheSuffix : '' );
+                script.onerror = function() {
+                  if( 'console' in window && window.console.log ) {
+                    window.console.log('Unable to load form validation module 
'+scriptUrl);
+                  }
+                };
+                script.onreadystatechange = function () {
+                  // IE 7 fix
+                  if (this.readyState === 'complete' || this.readyState === 
'loaded') {
+                    moduleLoadedCallback();
+                    // Handle memory leak in IE
+                    this.onload = null;
+                    this.onreadystatechange = null;
+                  }
+                };
+                appendToElement.appendChild(script);
+              }
             }
-            if( conf.validateOnBlur ) {
-                $form.validateOnBlur(conf.language, conf);
-                $form.bind('html5ValidationAttrsFound', function() {
-                    $form.validateOnBlur(conf.language, conf);
-                })
+          });
+        };
+
+      if (path) {
+        loadModuleScripts(modules, path);
+      } else {
+        var findScriptPathAndLoadModules = function () {
+          var foundPath = false;
+          $('script[src*="form-validator"]').each(function () {
+            foundPath = this.src.substr(0, this.src.lastIndexOf('/')) + '/';
+            if (foundPath === '/') {
+              foundPath = '';
             }
-            if( conf.validateOnEvent ){
-              $form.validateOnEvent(conf.language, conf);
-                             }
-        });
+            return false;
+          });
 
-        if( conf.modules != '' ) {
-            if( typeof conf.onModulesLoaded == 'function' ) {
-                $window.one('validatorsLoaded', conf.onModulesLoaded);
-            }
-            $.formUtils.loadModules(conf.modules);
+          if (foundPath !== false) {
+            loadModuleScripts(modules, foundPath);
+            return true;
+          }
+          return false;
+        };
+
+        if (!findScriptPathAndLoadModules()) {
+          $(findScriptPathAndLoadModules);
         }
-    };
+      }
+    },
 
     /**
-     * Object containing utility methods for this plugin
+     * Validate the value of given element according to the validation rules
+     * found in the attribute data-validation. Will return an object 
representing
+     * a validation result, having the props shouldChangeDisplay, isValid and 
errorMsg
+     * @param {jQuery} $elem
+     * @param {Object} language ($.formUtils.LANG)
+     * @param {Object} conf
+     * @param {jQuery} $form
+     * @param {String} [eventContext]
+     * @return {Object}
      */
-    $.formUtils = {
+    validateInput: function ($elem, language, conf, $form, eventContext) {
 
-        /**
-         * Default config for $(...).isValid();
-         */
-        defaultConfig :  function() {
-            return {
-                ignore : [], // Names of inputs not to be validated even 
though node attribute containing the validation rules tells us to
-                errorElementClass : 'error', // Class that will be put on 
elements which value is invalid
-                borderColorOnError : 'red', // Border color of elements which 
value is invalid, empty string to not change border color
-                errorMessageClass : 'form-error', // class name of div 
containing error messages when validation fails
-                validationRuleAttribute : 'data-validation', // name of the 
attribute holding the validation rules
-                validationErrorMsgAttribute : 'data-validation-error-msg', // 
define custom err msg inline with element
-                errorMessagePosition : 'element', // Can be either "top" or 
"element" or "custom"
-                errorMessageTemplate : {
-                    container: '<div class="{errorMessageClass} alert 
alert-danger">{messages}</div>',
-                    messages: '<strong>{errorTitle}</strong><ul>{fields}</ul>',
-                    field: '<li>{msg}</li>'
-                },
-                errorMessageCustom: _templateMessage,
-                scrollToTopOnError : true,
-                dateFormat : 'yyyy-mm-dd',
-                addValidClassOnAll : false, // whether or not to apply 
class="valid" even if the input wasn't validated
-                decimalSeparator : '.',
-                inputParentClassOnError : 'has-error', // twitter-bootstrap 
default class name
-                inputParentClassOnSuccess : 'has-success' // twitter-bootstrap 
default class name
-            }
-        },
+      $elem.trigger('beforeValidation');
+      conf = conf || $.formUtils.defaultConfig();
+      language = language || $.formUtils.LANG;
 
-        /**
-        * Available validators
-        */
-        validators : {},
+      var value = $elem.val() || '',
+          result = {isValid: true, shouldChangeDisplay:true, errorMsg:''},
+          optional = $elem.valAttr('optional'),
 
-        /**
-         * Events triggered by form validator
-         */
-        _events : {load : [], valid: [], invalid:[]},
+          // test if a checkbox forces this element to be validated
+          validationDependsOnCheckedInput = false,
+          validationDependentInputIsChecked = false,
+          validateIfCheckedElement = false,
 
-        /**
-         * Setting this property to true during validation will
-         * stop further validation from taking place and form will
-         * not be sent
-         */
-        haltValidation : false,
+          // get value of this element's attribute "... if-checked"
+          validateIfCheckedElementName = $elem.valAttr('if-checked'),
+          // get expected radio button value for "if-checked" optional 
validation
+          validateIfCheckedElementValue = $elem.valAttr('if-checked-value');
 
-        /**
-         * This variable will be true $.fn.isValid() is called
-         * and false when $.fn.validateOnBlur is called
-         */
-        isValidatingEntireForm : false,
 
-        /**
-        * Function for adding a validator
-        * @param {Object} validator
-        */
-        addValidator : function(validator) {
-            // prefix with "validate_" for backward compatibility reasons
-            var name = validator.name.indexOf('validate_') === 0 ? 
validator.name : 'validate_'+validator.name;
-            if( validator.validateOnKeyUp === undefined )
-                validator.validateOnKeyUp = true;
-            this.validators[name] = validator;
-        },
+      if ($elem.attr('disabled') || (!$elem.is(':visible') && 
!conf.validateHiddenInputs)) {
+        result.shouldChangeDisplay = false;
+        return result;
+      }
 
-        /**
-         * @var {Boolean}
-         */
-        isLoadingModules : false,
+      // make sure we can proceed
+      if (validateIfCheckedElementName != null) {
 
-        /**
-         * @var {Object}
-         */
-        loadedModules : {},
+        // Set the boolean telling us that the validation depends
+        // on another input being checked
+        validationDependsOnCheckedInput = true;
 
-        /**
-        * @example
-        *  $.formUtils.loadModules('date, security.dev');
-        *
-        * Will load the scripts date.js and security.dev.js from the
-        * directory where this script resides. If you want to load
-        * the modules from another directory you can use the
-        * path argument.
-        *
-        * The script will be cached by the browser unless the module
-        * name ends with .dev
-        *
-        * @param {String} modules - Comma separated string with module file 
names (no directory nor file extension)
-        * @param {String} [path] - Optional, path where the module files is 
located if their not in the same directory as the core modules
-        * @param {Boolean} [fireEvent] - Optional, whether or not to fire 
event 'load' when modules finished loading
-        */
-        loadModules : function(modules, path, fireEvent) {
+        // select the checkbox type element in this form
+        validateIfCheckedElement = $form.find('input[name="' + 
validateIfCheckedElementName + '"]');
 
-            if( fireEvent === undefined )
-                fireEvent = true;
-
-            if( $.formUtils.isLoadingModules ) {
-                setTimeout(function() {
-                    $.formUtils.loadModules(modules, path, fireEvent);
-                });
-                return;
+        // test if check input value
+        if (validateIfCheckedElementValue != null) {
+          validateIfCheckedElement.each(function(index, el) {
+            // test if it's property "checked" is checked and value equals 
expected value
+            if ($(el).prop('checked') && $(el).val() === 
validateIfCheckedElementValue) {
+              validationDependentInputIsChecked = true;
             }
+          });
+        }
+        else {
+          // test if it's property "checked" is checked
+          if (validateIfCheckedElement.prop('checked')) {
+            // set value for validation checkpoint
+            validationDependentInputIsChecked = true;
+          }
+        }
+      }
 
-            var hasLoadedAnyModule = false,
-                loadModuleScripts = function(modules, path) {
+      // validation checkpoint
+      // if empty AND optional attribute is present
+      // OR depending on a checkbox being checked AND checkbox is checked, 
return true
+      var isInvalidNumberInput = !value && $elem[0].type === 'number';
+      if ((!value && optional === 'true' && !isInvalidNumberInput) || 
(validationDependsOnCheckedInput && !validationDependentInputIsChecked)) {
+        result.shouldChangeDisplay = conf.addValidClassOnAll;
+        return result;
+      }
 
-                    var moduleList = $.split(modules),
-                        numModules = moduleList.length,
-                        moduleLoadedCallback = function() {
-                            numModules--;
-                            if( numModules == 0 ) {
-                                $.formUtils.isLoadingModules = false;
-                                if( fireEvent && hasLoadedAnyModule ) {
-                                    $window.trigger('validatorsLoaded');
-                                }
-                            }
-                        };
+      var validationRules = $elem.attr(conf.validationRuleAttribute),
 
-                    if( numModules > 0 ) {
-                        $.formUtils.isLoadingModules = true;
-                    }
+        // see if form element has inline err msg attribute
+        validationErrorMsg = true;
 
-                    var cacheSuffix = '?__='+( new Date().getTime() ),
-                        appendToElement = 
document.getElementsByTagName('head')[0] || 
document.getElementsByTagName('body')[0];
+      if (!validationRules) {
+        result.shouldChangeDisplay = conf.addValidClassOnAll;
+        return result;
+      }
 
-                    $.each(moduleList, function(i, modName) {
-                        modName = $.trim(modName);
-                        if( modName.length == 0 ) {
-                            moduleLoadedCallback();
-                        }
-                        else {
-                            var scriptUrl = path + modName + 
(modName.substr(-3) == '.js' ? '':'.js'),
-                                script = document.createElement('SCRIPT');
+      $.split(validationRules, function (rule) {
+        if (rule.indexOf('validate_') !== 0) {
+          rule = 'validate_' + rule;
+        }
 
-                            if( scriptUrl in $.formUtils.loadedModules ) {
-                                // already loaded
-                                moduleLoadedCallback();
-                            }
-                            else {
+        var validator = $.formUtils.validators[rule];
 
-                                // Remember that this script is loaded
-                                $.formUtils.loadedModules[scriptUrl] = 1;
-                                hasLoadedAnyModule = true;
+        if (validator && typeof validator.validatorFunction === 'function') {
 
-                                // Load the script
-                                script.type = 'text/javascript';
-                                script.onload = moduleLoadedCallback;
-                                script.src = scriptUrl + ( 
scriptUrl.substr(-7) == '.dev.js' ? cacheSuffix:'' );
-                                script.onreadystatechange = function() {
-                                    // IE 7 fix
-                                    if( this.readyState == 'complete' || 
this.readyState == 'loaded' ) {
-                                        moduleLoadedCallback();
-                                        // Handle memory leak in IE
-                                        this.onload = null;
-                                        this.onreadystatechange = null;
-                                    }
-                                };
-                                appendToElement.appendChild( script );
-                            }
-                        }
-                    });
-                };
+          // special change of element for checkbox_group rule
+          if (rule === 'validate_checkbox_group') {
+            // set element to first in group, so error msg attr doesn't need 
to be set on all elements in group
+            $elem = $form.find('[name="' + $elem.attr('name') + '"]:eq(0)');
+          }
 
-            if( path ) {
-                loadModuleScripts(modules, path);
-            } else {
-                var findScriptPathAndLoadModules = function() {
-                    var foundPath = false;
-                    $('script[src*="form-validator"]').each(function() {
-                        foundPath = this.src.substr(0, 
this.src.lastIndexOf('/')) + '/';
-                        if( foundPath == '/' )
-                            foundPath = '';
-                        return false;
-                    });
+          var isValid = null;
+          if (eventContext !== 'keyup' || validator.validateOnKeyUp) {
+            isValid = validator.validatorFunction(value, $elem, conf, 
language, $form);
+          }
 
-                    if( foundPath !== false) {
-                        loadModuleScripts(modules, foundPath);
-                        return true;
-                    }
-                    return false;
-                };
-
-                if( !findScriptPathAndLoadModules() ) {
-                    $(findScriptPathAndLoadModules);
+          if (!isValid) {
+            validationErrorMsg = null;
+            if (isValid !== null) {
+              validationErrorMsg = $elem.attr(conf.validationErrorMsgAttribute 
+ '-' + rule.replace('validate_', ''));
+              if (!validationErrorMsg) {
+                validationErrorMsg = 
$elem.attr(conf.validationErrorMsgAttribute);
+                if (!validationErrorMsg) {
+                  if (typeof validator.errorMessageKey !== 'function') {
+                    validationErrorMsg = language[validator.errorMessageKey];
+                  }
+                  else {
+                    validationErrorMsg = 
language[validator.errorMessageKey(conf)];
+                  }
+                  if (!validationErrorMsg) {
+                    validationErrorMsg = validator.errorMessage;
+                  }
                 }
+              }
             }
-        },
+            return false; // break iteration
+          }
 
-        /**
-        * Validate the value of given element according to the validation rules
-        * found in the attribute data-validation. Will return null if no 
validation
-        * should take place, returns true if valid or error message if not 
valid
-        *
-        * @param {jQuery} $elem
-        * @param {Object} language ($.formUtils.LANG)
-        * @param {Object} conf
-        * @param {jQuery} $form
-        * @param {String} [eventContext]
-        * @return {String|Boolean}
-        */
-        validateInput : function($elem, language, conf, $form, eventContext) {
+        } else {
+          throw new Error('Using undefined validator "' + rule + '"');
+        }
 
-            if( $elem.attr('disabled') )
-                return null; // returning null will prevent that the valid 
class gets applied to the element
+      }, ' ');
 
-            $elem.trigger('beforeValidation');
+      if (typeof validationErrorMsg === 'string') {
+        $elem.trigger('validation', false);
+        result.errorMsg = validationErrorMsg;
+        result.isValid = false;
+        result.shouldChangeDisplay = true;
+      } else if (validationErrorMsg === null) {
+        result.shouldChangeDisplay = conf.addValidClassOnAll;
+      } else {
+        $elem.trigger('validation', true);
+        result.shouldChangeDisplay = true;
+      }
 
-            var value = $elem.val() || '',
-                optional = $elem.valAttr('optional'),
+      // Run element validation callback
+      if (typeof conf.onElementValidate === 'function' && validationErrorMsg 
!== null) {
+        conf.onElementValidate(result.isValid, $elem, $form, 
validationErrorMsg);
+      }
 
-                // test if a checkbox forces this element to be validated
-                validationDependsOnCheckedInput = false,
-                validationDependentInputIsChecked = false,
-                validateIfCheckedElement = false,
+      return result;
+    },
 
-                // get value of this element's attribute "... if-checked"
-                validateIfCheckedElementName = $elem.valAttr("if-checked");
+    /**
+     * Is it a correct date according to given dateFormat. Will return false 
if not, otherwise
+     * an array 0=>year 1=>month 2=>day
+     *
+     * @param {String} val
+     * @param {String} dateFormat
+     * @return {Array}|{Boolean}
+     */
+    parseDate: function (val, dateFormat) {
+      var divider = dateFormat.replace(/[a-zA-Z]/gi, '').substring(0, 1),
+        regexp = '^',
+        formatParts = dateFormat.split(divider || null),
+        matches, day, month, year;
 
-            // make sure we can proceed
-            if (validateIfCheckedElementName != null) {
+      $.each(formatParts, function (i, part) {
+        regexp += (i > 0 ? '\\' + divider : '') + '(\\d{' + part.length + '})';
+      });
 
-                // Set the boolean telling us that the validation depends
-                // on another input being checked
-                validationDependsOnCheckedInput = true;
+      regexp += '$';
 
-                // select the checkbox type element in this form
-                validateIfCheckedElement = $form.find('input[name="' + 
validateIfCheckedElementName + '"]');
+      matches = val.match(new RegExp(regexp));
+      if (matches === null) {
+        return false;
+      }
 
-                // test if it's property "checked" is checked
-                if ( validateIfCheckedElement.prop('checked') ) {
-                    // set value for validation checkpoint
-                    validationDependentInputIsChecked = true;
-                }
-            }
+      var findDateUnit = function (unit, formatParts, matches) {
+        for (var i = 0; i < formatParts.length; i++) {
+          if (formatParts[i].substring(0, 1) === unit) {
+            return $.formUtils.parseDateInt(matches[i + 1]);
+          }
+        }
+        return -1;
+      };
 
-            // validation checkpoint
-            // if empty AND optional attribute is present
-            // OR depending on a checkbox being checked AND checkbox is 
checked, return true
-            if ((!value && optional === 'true') || 
(validationDependsOnCheckedInput && !validationDependentInputIsChecked)) {
-                return conf.addValidClassOnAll ? true:null;
-            }
+      month = findDateUnit('m', formatParts, matches);
+      day = findDateUnit('d', formatParts, matches);
+      year = findDateUnit('y', formatParts, matches);
 
-            var validationRules = $elem.attr(conf.validationRuleAttribute),
+      if ((month === 2 && day > 28 && (year % 4 !== 0 || year % 100 === 0 && 
year % 400 !== 0)) ||
+      (month === 2 && day > 29 && (year % 4 === 0 || year % 100 !== 0 && year 
% 400 === 0)) ||
+      month > 12 || month === 0) {
+        return false;
+      }
+      if ((this.isShortMonth(month) && day > 30) || (!this.isShortMonth(month) 
&& day > 31) || day === 0) {
+        return false;
+      }
 
-                // see if form element has inline err msg attribute
-                validationErrorMsg = true;
+      return [year, month, day];
+    },
 
-            if( !validationRules ) {
-                return conf.addValidClassOnAll ? true:null;
-            }
+    /**
+     * skum fix. är talet 05 eller lägre ger parseInt rätt int annars får man 
0 när man kör parseInt?
+     *
+     * @param {String} val
+     * @param {Number}
+     */
+    parseDateInt: function (val) {
+      if (val.indexOf('0') === 0) {
+        val = val.replace('0', '');
+      }
+      return parseInt(val, 10);
+    },
 
-            $.split(validationRules, function(rule) {
-                if( rule.indexOf('validate_') !== 0 ) {
-                    rule = 'validate_' + rule;
-                }
+    /**
+     * Has month only 30 days?
+     *
+     * @param {Number} m
+     * @return {Boolean}
+     */
+    isShortMonth: function (m) {
+      return (m % 2 === 0 && m < 7) || (m % 2 !== 0 && m > 7);
+    },
 
-                var validator = $.formUtils.validators[rule];
+    /**
+     * Restrict input length
+     *
+     * @param {jQuery} $inputElement Jquery Html object
+     * @param {jQuery} $maxLengthElement jQuery Html Object
+     * @return void
+     */
+    lengthRestriction: function ($inputElement, $maxLengthElement) {
+      // read maxChars from counter display initial text value
+      var maxChars = parseInt($maxLengthElement.text(), 10),
+        charsLeft = 0,
 
-                if( validator && typeof validator['validatorFunction'] == 
'function' ) {
-                    
-                    // special change of element for checkbox_group rule
-                    if ( rule == 'validate_checkbox_group' ) {
-                        // set element to first in group, so error msg attr 
doesn't need to be set on all elements in group
-                            $elem = $("[name='"+$elem.attr('name')+"']:eq(0)");
-                    }
-                    
-                    var isValid = null;
-                    if( eventContext != 'keyup' || validator.validateOnKeyUp ) 
{
-                        isValid = validator.validatorFunction(value, $elem, 
conf, language, $form);
-                    }
+      // internal function does the counting and sets display value
+        countCharacters = function () {
+          var numChars = $inputElement.val().length;
+          if (numChars > maxChars) {
+            // get current scroll bar position
+            var currScrollTopPos = $inputElement.scrollTop();
+            // trim value to max length
+            $inputElement.val($inputElement.val().substring(0, maxChars));
+            $inputElement.scrollTop(currScrollTopPos);
+          }
+          charsLeft = maxChars - numChars;
+          if (charsLeft < 0) {
+            charsLeft = 0;
+          }
 
-                    if(!isValid) {
-                        validationErrorMsg = null;
-                        if( isValid !== null ) {
-                            validationErrorMsg =  
$elem.attr(conf.validationErrorMsgAttribute+'-'+rule.replace('validate_', ''));
-                            if( !validationErrorMsg ) {
-                                validationErrorMsg =  
$elem.attr(conf.validationErrorMsgAttribute);
-                                if( !validationErrorMsg ) {
-                                    validationErrorMsg = 
language[validator.errorMessageKey];
-                                    if( !validationErrorMsg )
-                                        validationErrorMsg = 
validator.errorMessage;
-                                }
-                            }
-                        }
-                        return false; // breaks the iteration
-                    }
+          // set counter text
+          $maxLengthElement.text(charsLeft);
+        };
 
-                } else {
-                    throw new Error('Using undefined validator "'+rule+'"');
-                }
+      // bind events to this element
+      // setTimeout is needed, cut or paste fires before val is available
+      $($inputElement).bind('keydown keyup keypress focus blur', 
countCharacters)
+        .bind('cut paste', function () {
+          setTimeout(countCharacters, 100);
+        });
 
-            }, ' ');
+      // count chars on pageload, if there are prefilled input-values
+      $(document).bind('ready', countCharacters);
+    },
 
-            var result;
+    /**
+     * Test numeric against allowed range
+     *
+     * @param $value int
+     * @param $rangeAllowed str; (1-2, min1, max2, 10)
+     * @return array
+     */
+    numericRangeCheck: function (value, rangeAllowed) {
+      // split by dash
+      var range = $.split(rangeAllowed),
+          // min or max
+          minmax = parseInt(rangeAllowed.substr(3), 10);
 
-            if( typeof validationErrorMsg == 'string' ) {
-                $elem.trigger('validation', false);
-                result = validationErrorMsg;
-            } else if( validationErrorMsg === null && !conf.addValidClassOnAll 
) {
-                result = null;
-            } else {
-                $elem.trigger('validation', true);
-                result = true;
-            }
+      if( range.length === 1 && rangeAllowed.indexOf('min') === -1 && 
rangeAllowed.indexOf('max') === -1 ) {
+        range = [rangeAllowed, rangeAllowed]; // only a number, checking 
agains an exact number of characters
+      }
 
-            // Run element validation callback
-            if( typeof conf.onElementValidate == 'function' && result !== null 
) {
-                conf.onElementValidate((result === true), $elem, $form, 
validationErrorMsg);
-            }
+      // range ?
+      if (range.length === 2 && (value < parseInt(range[0], 10) || value > 
parseInt(range[1], 10) )) {
+        return [ 'out', range[0], range[1] ];
+      } // value is out of range
+      else if (rangeAllowed.indexOf('min') === 0 && (value < minmax )) // min
+      {
+        return ['min', minmax];
+      } // value is below min
+      else if (rangeAllowed.indexOf('max') === 0 && (value > minmax )) // max
+      {
+        return ['max', minmax];
+      } // value is above max
+      // since no other returns executed, value is in allowed range
+      return [ 'ok' ];
+    },
 
-            return result;
-        },
 
-       /**
-        * Is it a correct date according to given dateFormat. Will return 
false if not, otherwise
-        * an array 0=>year 1=>month 2=>day
-        *
-        * @param {String} val
-        * @param {String} dateFormat
-        * @return {Array}|{Boolean}
-        */
-        parseDate : function(val, dateFormat) {
-            var divider = dateFormat.replace(/[a-zA-Z]/gi, '').substring(0,1),
-                regexp = '^',
-                formatParts = dateFormat.split(divider || null),
-                matches, day, month, year;
+    _numSuggestionElements: 0,
+    _selectedSuggestion: null,
+    _previousTypedVal: null,
 
-            $.each(formatParts, function(i, part) {
-               regexp += (i > 0 ? '\\'+divider:'') + '(\\d{'+part.length+'})';
-            });
-
-            regexp += '$';
-            
-            matches = val.match(new RegExp(regexp));
-            if (matches === null) {
-                return false;
-            }
-        
-            var findDateUnit = function(unit, formatParts, matches) {
-                for(var i=0; i < formatParts.length; i++) {
-                    if(formatParts[i].substring(0,1) === unit) {
-                        return $.formUtils.parseDateInt(matches[i+1]);
-                    }
-                }
-                return -1;
-            };
-        
-            month = findDateUnit('m', formatParts, matches);
-            day = findDateUnit('d', formatParts, matches);
-            year = findDateUnit('y', formatParts, matches);
-        
-            if ((month === 2 && day > 28 && (year % 4 !== 0  || year % 100 === 
0 && year % 400 !== 0)) 
-               || (month === 2 && day > 29 && (year % 4 === 0 || year % 100 
!== 0 && year % 400 === 0))
-               || month > 12 || month === 0) {
-                return false;
-            }
-            if ((this.isShortMonth(month) && day > 30) || 
(!this.isShortMonth(month) && day > 31) || day === 0) {
-                return false;
-            }
-        
-            return [year, month, day];
+    /**
+     * Utility function that can be used to create plugins that gives
+     * suggestions when inputs is typed into
+     * @param {jQuery} $elem
+     * @param {Array} suggestions
+     * @param {Object} settings - Optional
+     * @return {jQuery}
+     */
+    suggest: function ($elem, suggestions, settings) {
+      var conf = {
+          css: {
+            maxHeight: '150px',

@@ Diff output truncated at 153600 characters. @@



reply via email to

[Prev in Thread] Current Thread [Next in Thread]