JAVASCRIPT 29
Validator.js Guest on 19th April 2021 08:04:15 PM
  1. /*
  2.  
  3.     Validator v1.1.0
  4.  
  5.     (c) Yair Even Or
  6.  
  7.     https://github.com/yairEO/validator
  8.  
  9.  
  10.  
  11.     MIT-style license.
  12.  
  13. */
  14.  
  15.  
  16.  
  17. var validator = (function($){
  18.  
  19.     var message, tests, checkField, validate, mark, unmark, field, minmax, defaults,
  20.  
  21.         validateWords, lengthRange, lengthLimit, pattern, alertTxt, data,
  22.  
  23.         email_illegalChars = /[\(\)\<\>\,\;\:\\\/\"\[\]]/,
  24.  
  25.         email_filter = /^.+@.+\..{2,6}$/;  // exmaple email "steve@s-i.photo"
  26.  
  27.  
  28.  
  29.     /* general text messages
  30.  
  31.     */
  32.  
  33.     message = {
  34.  
  35.         invalid         : 'invalid input',
  36.  
  37.         checked         : 'must be checked',
  38.  
  39.         empty           : 'please put something here',
  40.  
  41.         min             : 'input is too short',
  42.  
  43.         max             : 'input is too long',
  44.  
  45.         number_min      : 'too low',
  46.  
  47.         number_max      : 'too high',
  48.  
  49.         url             : 'invalid URL',
  50.  
  51.         number          : 'not a number',
  52.  
  53.         email           : 'email address is invalid',
  54.  
  55.         email_repeat    : 'emails do not match',
  56.  
  57.         password_repeat : 'passwords do not match',
  58.  
  59.         repeat          : 'no match',
  60.  
  61.         complete        : 'input is not complete',
  62.  
  63.         select          : 'Please select an option'
  64.  
  65.     };
  66.  
  67.  
  68.  
  69.     if(!window.console){
  70.  
  71.         console={};
  72.  
  73.         console.log=console.warn=function(){ return; }
  74.  
  75.     }
  76.  
  77.  
  78.  
  79.     // defaults
  80.  
  81.     defaults = {
  82.  
  83.         alerts  : true,
  84.  
  85.         classes : {
  86.  
  87.               item    : 'item',
  88.  
  89.               alert   : 'alert',
  90.  
  91.               bad     : 'bad'
  92.  
  93.         }
  94.  
  95.     };
  96.  
  97.  
  98.  
  99.     /* Tests for each type of field (including Select element)
  100.  
  101.     */
  102.  
  103.     tests = {
  104.  
  105.         sameAsPlaceholder : function(a){
  106.  
  107.             return $.fn.placeholder && a.attr('placeholder') !== undefined && data.val == a.prop('placeholder');
  108.  
  109.         },
  110.  
  111.         hasValue : function(a){
  112.  
  113.             if( !a ){
  114.  
  115.                 alertTxt = message.empty;
  116.  
  117.                 return false;
  118.  
  119.             }
  120.  
  121.             return true;
  122.  
  123.         },
  124.  
  125.         // 'linked' is a special test case for inputs which their values should be equal to each other (ex. confirm email or retype password)
  126.  
  127.         linked : function(a,b){
  128.  
  129.             if( b != a ){
  130.  
  131.                 // choose a specific message or a general one
  132.  
  133.                 alertTxt = message[data.type + '_repeat'] || message.no_match;
  134.  
  135.                 return false;
  136.  
  137.             }
  138.  
  139.             return true;
  140.  
  141.         },
  142.  
  143.         email : function(a){
  144.  
  145.             if ( !email_filter.test( a ) || a.match( email_illegalChars ) ){
  146.  
  147.                 alertTxt = a ? message.email : message.empty;
  148.  
  149.                 return false;
  150.  
  151.             }
  152.  
  153.             return true;
  154.  
  155.         },
  156.  
  157.         // a "skip" will skip some of the tests (needed for keydown validation)
  158.  
  159.         text : function(a, skip){
  160.  
  161.             // make sure there are at least X number of words, each at least 2 chars long.
  162.  
  163.             // for example 'john F kenedy' should be at least 2 words and will pass validation
  164.  
  165.             if( validateWords ){
  166.  
  167.                 var words = a.split(' ');
  168.  
  169.                 // iterrate on all the words
  170.  
  171.                 var wordsLength = function(len){
  172.  
  173.                     for( var w = words.length; w--; )
  174.  
  175.                         if( words[w].length < len )
  176.  
  177.                             return false;
  178.  
  179.                     return true;
  180.  
  181.                 };
  182.  
  183.  
  184.  
  185.                 if( words.length < validateWords || !wordsLength(2) ){
  186.  
  187.                     alertTxt = message.complete;
  188.  
  189.                     return false;
  190.  
  191.                 }
  192.  
  193.                 return true;
  194.  
  195.             }
  196.  
  197.             if( !skip && lengthRange && a.length < lengthRange[0] ){
  198.  
  199.                 alertTxt = message.min;
  200.  
  201.                 return false;
  202.  
  203.             }
  204.  
  205.  
  206.  
  207.             // check if there is max length & field length is greater than the allowed
  208.  
  209.             if( lengthRange && lengthRange[1] && a.length > lengthRange[1] ){
  210.  
  211.                 alertTxt = message.max;
  212.  
  213.                 return false;
  214.  
  215.             }
  216.  
  217.  
  218.  
  219.             // check if the field's value should obey any length limits, and if so, make sure the length of the value is as specified
  220.  
  221.             if( lengthLimit && lengthLimit.length ){
  222.  
  223.                 while( lengthLimit.length ){
  224.  
  225.                     if( lengthLimit.pop() == a.length ){
  226.  
  227.                         alertTxt = message.complete;
  228.  
  229.                         return false;
  230.  
  231.                     }
  232.  
  233.                 }
  234.  
  235.             }
  236.  
  237.  
  238.  
  239.             if( pattern ){
  240.  
  241.                 var regex, jsRegex;
  242.  
  243.                 switch( pattern ){
  244.  
  245.                     case 'alphanumeric' :
  246.  
  247.                         regex = /^[a-zA-Z0-9]+$/i;
  248.  
  249.                         break;
  250.  
  251.                     case 'numeric' :
  252.  
  253.                         regex = /^[0-9]+$/i;
  254.  
  255.                         break;
  256.  
  257.                     case 'phone' :
  258.  
  259.                         regex = /^\+?([0-9]|[-|' '])+$/i;
  260.  
  261.                         break;
  262.  
  263.                     default :
  264.  
  265.                         regex = pattern;
  266.  
  267.                 }
  268.  
  269.                 try{
  270.  
  271.                     jsRegex = new RegExp(regex).test(a);
  272.  
  273.                     if( a && !jsRegex )
  274.  
  275.                         return false;
  276.  
  277.                 }
  278.  
  279.                 catch(err){
  280.  
  281.                     console.log(err, field, 'regex is invalid');
  282.  
  283.                     return false;
  284.  
  285.                 }
  286.  
  287.             }
  288.  
  289.  
  290.  
  291.             return true;
  292.  
  293.         },
  294.  
  295.         number : function(a){
  296.  
  297.             // if not not a number
  298.  
  299.             if( isNaN(parseFloat(a)) && !isFinite(a) ){
  300.  
  301.                 alertTxt = message.number;
  302.  
  303.                 return false;
  304.  
  305.             }
  306.  
  307.             // not enough numbers
  308.  
  309.             else if( lengthRange && a.length < lengthRange[0] ){
  310.  
  311.                 alertTxt = message.min;
  312.  
  313.                 return false;
  314.  
  315.             }
  316.  
  317.             // check if there is max length & field length is greater than the allowed
  318.  
  319.             else if( lengthRange && lengthRange[1] && a.length > lengthRange[1] ){
  320.  
  321.                 alertTxt = message.max;
  322.  
  323.                 return false;
  324.  
  325.             }
  326.  
  327.             else if( minmax[0] && (a|0) < minmax[0] ){
  328.  
  329.                 alertTxt = message.number_min;
  330.  
  331.                 return false;
  332.  
  333.             }
  334.  
  335.             else if( minmax[1] && (a|0) > minmax[1] ){
  336.  
  337.                 alertTxt = message.number_max;
  338.  
  339.                 return false;
  340.  
  341.             }
  342.  
  343.             return true;
  344.  
  345.         },
  346.  
  347.         // Date is validated in European format (day,month,year)
  348.  
  349.         date : function(a){
  350.  
  351.             var day, A = a.split(/[-./]/g), i;
  352.  
  353.             // if there is native HTML5 support:
  354.  
  355.             if( field[0].valueAsNumber )
  356.  
  357.                 return true;
  358.  
  359.  
  360.  
  361.             for( i = A.length; i--; ){
  362.  
  363.                 if( isNaN(parseFloat(a)) && !isFinite(a) )
  364.  
  365.                     return false;
  366.  
  367.             }
  368.  
  369.             try{
  370.  
  371.                 day = new Date(A[2], A[1]-1, A[0]);
  372.  
  373.                 if( day.getMonth()+1 == A[1] && day.getDate() == A[0] )
  374.  
  375.                     return day;
  376.  
  377.                 return false;
  378.  
  379.             }
  380.  
  381.             catch(er){
  382.  
  383.                 console.log('date test: ', err);
  384.  
  385.                 return false;
  386.  
  387.             }
  388.  
  389.         },
  390.  
  391.         url : function(a){
  392.  
  393.             // minimalistic URL validation
  394.  
  395.             function testUrl(url){
  396.  
  397.                 return /^(https?:\/\/)?([\w\d\-_]+\.+[A-Za-z]{2,})+\/?/.test( url );
  398.  
  399.             }
  400.  
  401.             if( !testUrl( a ) ){
  402.  
  403.                 alertTxt = a ? message.url : message.empty;
  404.  
  405.                 return false;
  406.  
  407.             }
  408.  
  409.             return true;
  410.  
  411.         },
  412.  
  413.         hidden : function(a){
  414.  
  415.             if( lengthRange && a.length < lengthRange[0] ){
  416.  
  417.                 alertTxt = message.min;
  418.  
  419.                 return false;
  420.  
  421.             }
  422.  
  423.             if( pattern ){
  424.  
  425.                 var regex;
  426.  
  427.                 if( pattern == 'alphanumeric' ){
  428.  
  429.                     regex = /^[a-z0-9]+$/i;
  430.  
  431.                     if( !regex.test(a) ){
  432.  
  433.                         return false;
  434.  
  435.                     }
  436.  
  437.                 }
  438.  
  439.             }
  440.  
  441.             return true;
  442.  
  443.         },
  444.  
  445.         select : function(a){
  446.  
  447.             if( !tests.hasValue(a) ){
  448.  
  449.                 alertTxt = message.select;
  450.  
  451.                 return false;
  452.  
  453.             }
  454.  
  455.             return true;
  456.  
  457.         }
  458.  
  459.     };
  460.  
  461.  
  462.  
  463.     /* marks invalid fields
  464.  
  465.     */
  466.  
  467.     mark = function( field, text ){
  468.  
  469.         if( !text || !field || !field.length )
  470.  
  471.             return false;
  472.  
  473.  
  474.  
  475.         // check if not already marked as a 'bad' record and add the 'alert' object.
  476.  
  477.         // if already is marked as 'bad', then make sure the text is set again because i might change depending on validation
  478.  
  479.         var item = field.closest('.' + defaults.classes.item),
  480.  
  481.             warning;
  482.  
  483.  
  484.  
  485.         if( item.hasClass(defaults.classes.bad) ){
  486.  
  487.             if( defaults.alerts )
  488.  
  489.                 item.find('.'+defaults.classes.alert).html(text);
  490.  
  491.         }
  492.  
  493.  
  494.  
  495.  
  496.  
  497.         else if( defaults.alerts ){
  498.  
  499.             warning = $('<div class="'+ defaults.classes.alert +'">').html( text );
  500.  
  501.             item.append( warning );
  502.  
  503.         }
  504.  
  505.  
  506.  
  507.         item.removeClass(defaults.classes.bad);
  508.  
  509.         // a delay so the "alert" could be transitioned via CSS
  510.  
  511.         setTimeout(function(){
  512.  
  513.             item.addClass(defaults.classes.bad);
  514.  
  515.         }, 0);
  516.  
  517.     };
  518.  
  519.     /* un-marks invalid fields
  520.  
  521.     */
  522.  
  523.     unmark = function( field ){
  524.  
  525.         if( !field || !field.length ){
  526.  
  527.             console.warn('no "field" argument, null or DOM object not found');
  528.  
  529.             return false;
  530.  
  531.         }
  532.  
  533.  
  534.  
  535.         field.closest('.' + defaults.classes.item)
  536.  
  537.              .removeClass(defaults.classes.bad)
  538.  
  539.              .find('.'+ defaults.classes.alert).remove();
  540.  
  541.     };
  542.  
  543.  
  544.  
  545.     function testByType(type, value){
  546.  
  547.         if( type == 'tel' )
  548.  
  549.             pattern = pattern || 'phone';
  550.  
  551.  
  552.  
  553.         if( !type || type == 'password' || type == 'tel' || type == 'search' || type == 'file' )
  554.  
  555.             type = 'text';
  556.  
  557.  
  558.  
  559.  
  560.  
  561.         return tests[type] ? tests[type](value, true) : true;
  562.  
  563.     }
  564.  
  565.  
  566.  
  567.     function prepareFieldData(el){
  568.  
  569.         field = $(el);
  570.  
  571.  
  572.  
  573.         field.data( 'valid', true );                // initialize validity of field
  574.  
  575.         field.data( 'type', field.attr('type') );   // every field starts as 'valid=true' until proven otherwise
  576.  
  577.         pattern = field.attr('pattern');
  578.  
  579.     }
  580.  
  581.  
  582.  
  583.     /* Validations per-character keypress
  584.  
  585.     */
  586.  
  587.     function keypress(e){
  588.  
  589.         prepareFieldData(this);
  590.  
  591.         //  String.fromCharCode(e.charCode)
  592.  
  593.  
  594.  
  595.         if( e.charCode ){
  596.  
  597.             return testByType( this.type, this.value );
  598.  
  599.         }
  600.  
  601.     }
  602.  
  603.  
  604.  
  605.     /* Checks a single form field by it's type and specific (custom) attributes
  606.  
  607.     */
  608.  
  609.     function checkField(){
  610.  
  611.         // skip testing fields whom their type is not HIDDEN but they are HIDDEN via CSS.
  612.  
  613.         if( this.type !='hidden' && $(this).is(':hidden') )
  614.  
  615.             return true;
  616.  
  617.  
  618.  
  619.         prepareFieldData(this);
  620.  
  621.  
  622.  
  623.         field.data( 'val', field[0].value.replace(/^\s+|\s+$/g, "") );  // cache the value of the field and trim it
  624.  
  625.         data = field.data();
  626.  
  627.  
  628.  
  629.         // Check if there is a specific error message for that field, if not, use the default 'invalid' message
  630.  
  631.         alertTxt = message[field.prop('name')] || message.invalid;
  632.  
  633.  
  634.  
  635.         // Special treatment
  636.  
  637.         if( field[0].nodeName.toLowerCase() === "select" ){
  638.  
  639.             data.type = 'select';
  640.  
  641.         }
  642.  
  643.         else if( field[0].nodeName.toLowerCase() === "textarea" ){
  644.  
  645.             data.type = 'text';
  646.  
  647.         }
  648.  
  649.         /* Gather Custom data attributes for specific validation:
  650.  
  651.         */
  652.  
  653.         validateWords   = data['validateWords'] || 0;
  654.  
  655.         lengthRange     = data['validateLengthRange'] ? (data['validateLengthRange']+'').split(',') : [1];
  656.  
  657.         lengthLimit     = data['validateLength'] ? (data['validateLength']+'').split(',') : false;
  658.  
  659.         minmax          = data['validateMinmax'] ? (data['validateMinmax']+'').split(',') : ''; // for type 'number', defines the minimum and/or maximum for the value as a number.
  660.  
  661.  
  662.  
  663.         data.valid = tests.hasValue(data.val);
  664.  
  665.  
  666.  
  667.         if( field.hasClass('optional') && !data.valid )
  668.  
  669.             data.valid = true;
  670.  
  671.  
  672.  
  673.  
  674.  
  675.         // for checkboxes
  676.  
  677.         if( field[0].type === "checkbox" ){
  678.  
  679.             data.valid = field[0].checked;
  680.  
  681.             alertTxt = message.checked;
  682.  
  683.         }
  684.  
  685.  
  686.  
  687.         // check if field has any value
  688.  
  689.         else if( data.valid ){
  690.  
  691.             /* Validate the field's value is different than the placeholder attribute (and attribute exists)
  692.  
  693.             * this is needed when fixing the placeholders for older browsers which does not support them.
  694.  
  695.             * in this case, make sure the "placeholder" jQuery plugin was even used before proceeding
  696.  
  697.             */
  698.  
  699.             if( tests.sameAsPlaceholder(field) ){
  700.  
  701.                 alertTxt = message.empty;
  702.  
  703.                 data.valid = false;
  704.  
  705.             }
  706.  
  707.  
  708.  
  709.             // if this field is linked to another field (their values should be the same)
  710.  
  711.             if( data.validateLinked ){
  712.  
  713.                 var linkedTo = data['validateLinked'].indexOf('#') == 0 ? $(data['validateLinked']) : $(':input[name=' + data['validateLinked'] + ']');
  714.  
  715.                 data.valid = tests.linked( data.val, linkedTo.val() );
  716.  
  717.             }
  718.  
  719.             /* validate by type of field. use 'attr()' is proffered to get the actual value and not what the browsers sees for unsupported types.
  720.  
  721.             */
  722.  
  723.             else if( data.valid || data.type == 'select' )
  724.  
  725.                 data.valid = testByType(data.type, data.val);
  726.  
  727.  
  728.  
  729.         }
  730.  
  731.  
  732.  
  733.         // mark / unmark the field, and set the general 'submit' flag accordingly
  734.  
  735.         if( data.valid )
  736.  
  737.             unmark( field );
  738.  
  739.         else{
  740.  
  741.             mark( field, alertTxt );
  742.  
  743.             submit = false;
  744.  
  745.         }
  746.  
  747.  
  748.  
  749.         return data.valid;
  750.  
  751.     }
  752.  
  753.  
  754.  
  755.     /* vaildates all the REQUIRED fields prior to submiting the form
  756.  
  757.     */
  758.  
  759.     function checkAll( $form ){
  760.  
  761.         $form = $($form);
  762.  
  763.  
  764.  
  765.         if( $form.length == 0 ){
  766.  
  767.             console.warn('element not found');
  768.  
  769.             return false;
  770.  
  771.         }
  772.  
  773.  
  774.  
  775.         var that = this,
  776.  
  777.             submit = true, // save the scope
  778.  
  779.             // get all the input/textareas/select fields which are required or optional (meaning, they need validation only if they were filled)
  780.  
  781.             fieldsToCheck = $form.find(':input').filter('[required=required], .required, .optional').not('[disabled=disabled]');
  782.  
  783.  
  784.  
  785.         fieldsToCheck.each(function(){
  786.  
  787.             // use an AND operation, so if any of the fields returns 'false' then the submitted result will be also FALSE
  788.  
  789.             submit = submit * checkField.apply(this);
  790.  
  791.         });
  792.  
  793.  
  794.  
  795.         return !!submit;  // casting the variable to make sure it's a boolean
  796.  
  797.     }
  798.  
  799.  
  800.  
  801.     return {
  802.  
  803.         defaults    : defaults,
  804.  
  805.         checkField  : checkField,
  806.  
  807.         keypress    : keypress,
  808.  
  809.         checkAll    : checkAll,
  810.  
  811.         mark        : mark,
  812.  
  813.         unmark      : unmark,
  814.  
  815.         message     : message,
  816.  
  817.         tests       : tests
  818.  
  819.     }
  820.  
  821. })(jQuery);

Paste-bin is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.