1;(function ( $ ) { 2"use strict"; 3 4/* Defaul options */ 5var defaults = { 6 rules: {}, 7 messages: {}, 8 error: { 9 scroll: true, 10 highlight: true, 11 inBlock: false, 12 inTooltip: false, 13 underField: true, 14 inTooltipClass: "j-tooltip-right-top", 15 }, 16 success: { 17 highlight: true, 18 }, 19 validationEvent: { 20 onsubmit: true, 21 onchange: true, 22 onkeyup: true, 23 }, 24 formType: { 25 modal: false, 26 multistep: false, 27 }, 28 formRedirect: { 29 redirect: false, 30 address: "http://codecanyon.net/user/" 31 }, 32 formHide: { 33 hide: false, 34 closeBtn: false 35 }, 36 formTotalData: false, 37 timeoutSuccessMsg: 5000, 38 repeatSubmission: true, 39 submit: true, 40 debug: false, 41 debugArr: [], 42 afterInitHandler:function() { return true; }, 43 beforeSubmitHandler:function() { return true; }, 44 afterSubmitHandler:function() { return true; }, 45 dict: { 46 debugError: "Oops! Debug errors occurred. Enable debug mode for JavaScript code", 47 rulesError: "User settings: You have to specify validation rules for a form", 48 messagesError: "User settings: You have to specify validation messages for a form", 49 modalOpenError: "Could not find a link/button with class='j-modal-open' to open modal form", 50 responseBlockError: "Could not find a block with class='j-response' for server response", 51 submitBtnError: "Could not find a button[type='submit'] for form submission", 52 totalDataBlockError: "Could not find a block with class='j-total-data' for total form data", 53 multistepOneStepError: "Multistep form has only one step. At least two steps are required!", 54 rulesUnknownRuleError: "User settings -> 'rules' array: Unknown validation rule: ", 55 rulesNotAllowedValueError: "User settings -> 'rules' array -> Not allowed value: ", 56 rulesMessagesMismatchError: "User settings: field names in 'rules' and 'messages' are mismatched", 57 formDataError: "FormData is not supported in this browser. Please update it to the latest version or use another browser", 58 disabledBtn: "Thanks!", 59 multistepNextBtn: "Next", 60 multistepPrevBtn: "Back", 61 errorBlockText: "Oops! The following errors occurred:", 62 successBlockText: "Thank you! We got your email successfully", 63 }, 64 mimeTypes: { 65 "jpeg": "image/jpeg", 66 "tiff": "image/tiff", 67 "jpg": "image/jpg", 68 "png": "image/png", 69 "gif": "image/gif", 70 "ico": "image/vnd.microsoft.icon", 71 "doc": "application/msword", 72 "xls": "application/vnd.ms-excel", 73 "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", 74 "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 75 "txt": "text/plain", 76 "csv": "text/csv", 77 "zip": "application/zip", 78 "gzip": "application/gzip", 79 "rar": "application/x-rar-compressed", 80 "odf": ["application/vnd.oasis.opendocument.text", 81 "application/vnd.oasis.opendocument.spreadsheet", 82 "application/vnd.oasis.opendocument.presentation", 83 "application/vnd.oasis.opendocument.graphics"], 84 "pdf": "application/pdf", 85 "powerpoint": ["application/vnd.ms-powerpoint", 86 "application/vnd.openxmlformats-officedocument.presentationml.presentation"], 87 "mpeg": ["audio/mpeg","video/mpeg"], 88 "mp4": ["audio/mp4","video/mp4"], 89 "ogg": ["audio/ogg","video/ogg","application/ogg"], 90 }, 91}; 92 93/* File validation */ 94function _fileCheck( fileObj, rules, messages, mimeTypes ) { 95 var type, len, i, 96 file = fileObj[0].files[0], 97 required = rules.required, 98 validate = rules.validate, 99 extension = rules.extension.toLowerCase(), 100 size = rules.size * 1024 * 1024, 101 allowedTypes = [], 102 extensionArr = extension.split("|"); 103 104 // Add required valid types 105 for ( type in mimeTypes ) { 106 if ( extensionArr.indexOf(type) === -1 ) { 107 continue; 108 } 109 if ( $.isArray( mimeTypes[type] ) ) { 110 len = mimeTypes[type].length; 111 for ( i=0; i<len; i++ ) { 112 allowedTypes.push( mimeTypes[type][i] ); 113 } 114 continue; 115 } 116 allowedTypes.push( mimeTypes[type] ); 117 } 118 119 // Validation 120 if ( validate || required ) { 121 // If file is required 122 if ( required ) { 123 // If file is empty 124 if ( !file ) { 125 return messages.required; 126 } 127 } 128 // If file is not required 129 // Validate file only if it exists 130 if ( file ) { 131 // Check allowed file types 132 if ( allowedTypes.indexOf(file.type) === -1 ) { 133 return messages.size_extension; 134 } 135 // Check allowed file size 136 if ( file.size > size) { 137 return messages.size_extension; 138 } 139 return false;
140 } 141 } 142} 143 144/* Email validation */ 145function _emailCheck( value ) { 146 var re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i; 147 return !re.test( value ); 148} 149 150/* Url validation */ 151function _urlCheck( value ){ 152 var re = /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i; 153 return !re.test( value ); 154} 155 156/* EqualTo validation */ 157function _equalToCheck( value, targetValue ) { 158 return ( value.trim() !== targetValue.trim() ) ? true : false; 159} 160 161/* Min value validation */ 162function _minValueCheck( value, minVal ) { 163 var val = value.trim(); 164 165 if ( _numberCheck( val ) ) { 166 return true; 167 } 168 return ( val < minVal ) ? true : false; 169} 170 171/* Max value validation */ 172function _maxValueCheck( value, maxVal ) { 173 var val = value.trim(); 174 175 if ( _numberCheck( val ) ) { 176 return true; 177 } 178 return ( val > maxVal ) ? true : false; 179} 180 181/* Range value validation */ 182function _rangeValueCheck( value, rangeVal ) { 183 var val = value.trim(); 184 185 if ( _numberCheck( val ) ) { 186 return true; 187 } 188 return ( val < rangeVal[0] || val > rangeVal[1] ) ? true : false; 189} 190 191/* Min length validation */ 192function _minLengthCheck( value, minLen ) { 193 return ( value.trim().length < minLen ) ? true : false; 194} 195 196/* Max length validation */ 197function _maxLengthCheck( value, maxLen ) { 198 return ( value.trim().length > maxLen ) ? true : false; 199} 200 201/* Range length validation */ 202function _rangeLengthCheck( value, rangeLen ) { 203 var val = value.trim().length; 204 return ( val < rangeLen[0] || val > rangeLen[1] ) ? true : false; 205} 206 207/* Integer validation */ 208function _integerCheck( value ) { 209 var re = /^-?\d+$/; 210 return !re.test( value ); 211} 212 213/* Number validation */ 214function _numberCheck( value ) { 215 var re = /^-?\d+(?:\.\d+)?$/; 216 return !re.test( value ); 217} 218 219/* Validate rules object */ 220function _rulesCheck( obj ) { 221 var self = this, 222 config = self.config, 223 message = self.config.dict.rulesNotAllowedValueError; 224 225 $.each(obj, function( name, value ) { 226 $.each(value, function( rule, val ) { 227 switch( rule ) { 228 case "required": 229 case "email": 230 case "url": 231 case "integer": 232 case "number": 233 case "validate": 234 if ( $.type( val ) !== "boolean" ) { 235 config.debugArr.push( _errorMsg( message, rule, val ) ); 236 } 237 break; 238 case "minlength": 239 case "maxlength": 240 if ( _integerCheck( val ) || val < 0 ) { 241 config.debugArr.push( _errorMsg( message, rule, val ) ); 242 } 243 break; 244 case "minvalue": 245 case "maxvalue": 246 if ( _numberCheck( val ) ) { 247 config.debugArr.push( _errorMsg( message, rule, val ) ); 248 } 249 break; 250 case "rangelength": 251 if ( !$.isArray( val ) || 252 val.length !== 2 || 253 _integerCheck( val[0] ) || 254 _integerCheck( val[1] ) || 255 val[0] > val[1] 256 ) { 257 config.debugArr.push( _errorMsg( message, rule, val ) ); 258 } 259 break; 260 case "rangevalue": 261 if ( !$.isArray( val ) || 262 val.length !== 2 || 263 _numberCheck( val[0] ) || 264 _numberCheck( val[1] ) || 265 val[0] > val[1] 266 ) { 267 config.debugArr.push( _errorMsg( message, rule, val ) ); 268 } 269 break; 270 case "size": 271 if ( _numberCheck( val ) || val <= 0 ) { 272 config.debugArr.push( _errorMsg( message, rule, val ) ); 273 } 274 break; 275 case "extension": 276 case "equalTo": 277 if ( $.type( val ) !== "string" ) { 278 config.debugArr.push( _errorMsg( message, rule, val ) ); 279 } 280 break; 281 case "requiredFromGroup": 282 if ( !$.isArray( val ) || 283 val.length !== 2 || 284 _integerCheck( val[0] ) || 285 $.type( val[1] ) !== "string" 286 ) { 287 config.debugArr.push( _errorMsg( message, rule, val ) ); 288 } 289 break; 290 default: 291 config.debugArr.push( config.dict.rulesUnknownRuleError + rule ); 292 } 293 }); 294 }); 295} 296 297/* Validate messages object */ 298function _messagesCheck( obj ) { 299 var rKeys = Object.keys( obj.rules ).sort(), 300 mKeys = Object.keys( obj.messages ).sort(); 301 302 if ( JSON.stringify( rKeys ) !== JSON.stringify( mKeys ) ) { 303 this.config.debugArr.push( this.config.dict.rulesMessagesMismatchError ); 304 } 305} 306 307/* Config check error message */ 308function _errorMsg( message, rule, val ) { 309 return message + rule + ": " + val +" ( " + $.type(val) + " )"; 310} 311 312/* Get field value */ 313function _getValue( obj ) { 314 var res; 315 316 obj.each( function() { 317 if ( $( this ).is( ":checkbox" ) || $( this ).is( ":radio" ) ) { 318 if ( $( this ).is( ":checked" ) ) { 319 if ( res !== undefined ) { 320 res += ", "+$( this ).val(); 321 } else { 322 res = $( this ).val(); 323 } 324 } 325 } else { 326 res = $( this ).val(); 327 } 328 }); 329 330 if ( $.isArray( res ) ) { 331 res = res.join(", "); 332 } 333 return ( res === undefined || res === null ) ? "" : res; 334} 335 336/* Check if field is hidden or has "display:none;" */ 337function _hiddenCheck( field ) { 338 if ( $( field ).css("display") === "none" || 339 $( field ).css("visibility") === "hidden" || 340 $( field ).is(":disabled") ){ 341 return true; 342 } 343 return false;
344} 345 346/* Constructor */ 347function JustFormsPro( obj, options ) { 348 this.config = $.extend( true, {}, defaults, options ); 349 this.form = obj[0]; 350 this.$form = obj; 351 this.$formObj = {}; 352 this.$formObjActiveStep = {}; 353 this.errorExists = false; 354 this.errorMessages = {}; 355 356 // Form elements processing 357 this.$formResponseBlock = this.$form.find( ".j-response" ); 358 this.$submitBtn = this.$form.find( "button[type='submit']" ); 359 360 // Form plugin init 361 this.init(); 362} 363 364JustFormsPro.prototype = { 365 366 /* Init */ 367 init: function() { 368 var self = this, 369 $form = self.$form, 370 config = self.config, 371 $formObj = self.$formObj, 372 str, $el; 373 374 // FormData support 375 if ( typeof window.FormData === "undefined" ) { 376 config.debugArr.push( config.dict.formDataError ); 377 } 378 379 // User input validaion 380 if ( $.isEmptyObject( config.rules ) ) { 381 config.debugArr.push( config.dict.rulesError ); 382 } else { 383 _rulesCheck.call( self, config.rules ); 384 } 385 if ( $.isEmptyObject( config.messages ) ) { 386 config.debugArr.push( config.dict.messagesError ); 387 } else { 388 _messagesCheck.call( self, config ); 389 } 390 391 // Response block availability 392 if ( !self.$formResponseBlock.length ){ 393 config.debugArr.push( config.dict.responseBlockError ); 394 } 395 396 // Submit button availability 397 if ( !self.$submitBtn.length ){ 398 config.debugArr.push( config.dict.submitBtnError ); 399 } 400 401 // Hide form 402 if ( config.formHide.hide ) { 403 self.initHideForm(); 404 } 405 406 // Modal form 407 if ( config.formType.modal ) { 408 self.initModalForm(); 409 } 410 411 // Multistep form 412 if ( config.formType.multistep ) { 413 self.initMultistepForm(); 414 } 415 416 // Init total form data 417 if ( config.formTotalData ) { 418 self.initTotalData(); 419 } 420 421 // Debug result 422 if ( config.debugArr.length ) { 423 if ( !config.debug ){ 424 console.log( config.dict.debugError ); 425 $form.on( "submit", false ); 426 return false; 427 } 428 str = config.debugArr.join( '\n -------------- \n' ); 429 console.warn( str ); 430 console.log( str ); 431 config.debugArr = []; 432 $form.on( "submit", false ); 433 return false; 434 } 435 436 // Object with html entities 437 $.each( config.rules, function( name, rules ) { 438 $el = $form.find( "[name='"+name+"']" ); 439 if ( $el.length ) { 440 $formObj[name] = $el; 441 } 442 }); 443 444 // Events 445 if ( config.validationEvent.onchange || config.validationEvent.onkeyup ) { 446 self.initEvent(); 447 } 448 449 // Processing total form data 450 if ( config.formTotalData ) { 451 self.processingTotalData(); 452 } 453 454 // Bind submit event 455 $form.on( "submit", self.submitForm.bind(self) ); 456 }, 457 458 /* Init events */ 459 initEvent: function() { 460 var self = this, 461 config = self.config, 462 $formObj = self.$formObj, 463 eventsArr = []; 464 465 // Create events 466 if ( config.validationEvent.onchange ) { 467 eventsArr.push("change"); 468 } 469 if ( config.validationEvent.onkeyup ) { 470 eventsArr.push("keyup"); 471 } 472 473 // Add events 474 eventsArr.forEach( function(event) { 475 self.$form.on( event, ":input", function() { 476 self.clearField( this ); 477 self.validateField( this ); 478 }); 479 $.each( config.rules, function( name, rules ) { 480 $.each( rules, function( rule, value ){ 481 if ( rule === "equalTo" ) { 482 $( value ).on( event, function(){ 483 self.clearField( $formObj[name][0] ); 484 self.validateField( $formObj[name][0] ); 485 }); 486 } 487 }); 488 }); 489 }); 490 }, 491 492 /* Submit a form */ 493 submitForm: function(e) { 494 var self = this, 495 config = self.config, 496 $prevBtn = self.$prevBtn, 497 $submitBtn = self.$submitBtn; 498 499 if (e) { 500 e.preventDefault(); 501 e.stopPropagation(); 502 } 503 504 // After init custom handler 505 if ( !config.afterInitHandler() ) { 506 return false; 507 } 508 509 // Form validation 510 if ( config.validationEvent.onsubmit ) { 511 // Buttons disabled 512 var formid = this.form.id; 513 if(formid == 'signupjpro' || formid == 'singninpro' || formid == 'forgotpro'){ 514 515 } else { 516 $submitBtn.toggleClass( "j-processing", true ).attr( "disabled", true ); 517 } 518 if ( config.formType.multistep ) { 519 $prevBtn.attr( "disabled", true ); 520 } 521 522 // Clear a form 523 self.clearForm(); 524 525 // Validate form 526 self.validateForm(); 527 } 528 529 // If errors exist 530 if ( self.errorExists ) { 531 // Scroll to first element with error 532 if ( config.error.scroll ) { 533 self.scrollToError(); 534 } 535 536 // Show errors within an error block 537 if ( config.error.inBlock ) { 538 self.createErrorBlock( self.errorMessages ); 539 } 540 541 // Buttons enabled 542 $submitBtn.toggleClass( "j-processing", false ).removeAttr( "disabled" ); 543 if ( config.formType.multistep ) { 544 $prevBtn.removeAttr( "disabled" ); 545 } 546 return false;
547 } 548 549 // Before submit custom handler 550 if ( !config.submit || !config.beforeSubmitHandler() ) { 551 // Buttons enabled 552 $submitBtn.toggleClass( "j-processing", false ).removeAttr( "disabled" ); 553 if ( self.config.formType.multistep ) { 554 $prevBtn.removeAttr( "disabled" ); 555 } 556 return false; 557 } 558 559 // Send form data 560 self.getServerResponse(); 561 }, 562 563 /* AJAX request */ 564 sendFormDataAsync: function() { 565 566 var self = this, 567 form = self.form, 568 formData; 569 570 // Form data 571 formData = new FormData( form ); 572 var formid = this.form.id; 573 if(formid == 'signupjpro' || formid == 'singninpro' || formid == 'forgotpro'){ 574 575 } else { 576 this.form.submit(); 577 } 578 579 // return $.ajax({ 580 // url: form.action, 581 // type: form.method, 582 // contentType: false, 583 // processData: false, 584 // data: formData 585 // }); 586 }, 587 588 /* Send form data */ 589 getServerResponse: function() { 590 var self = this, 591 config = self.config, 592 $prevBtn = self.$prevBtn, 593 $submitBtn = self.$submitBtn, 594 $formResponseBlock = self.$formResponseBlock, 595 result; 596 597 self.sendFormDataAsync().then(function( data ) { 598 599 // Server error processing 600 if ( config.debug ) { 601 console.warn( data ); 602 } 603 604 result = $.parseJSON( data ); 605 606 // Error message from server 607 if ( result.error ) { 608 609 // Add class "j-error-message" 610 $formResponseBlock.toggleClass( "j-error-message j-unit", true ); 611 $formResponseBlock.html( result.error ); 612 613 // Buttons enabled 614 $submitBtn.removeClass( "j-processing" ).removeAttr( "disabled" ); 615 if ( config.formType.multistep ) { 616 $prevBtn.removeAttr( "disabled" ); 617 } 618 } 619 620 // Success message from server 621 if ( result.success ) { 622 623 // Custom function applied after submission 624 if ( !config.afterSubmitHandler() ) { 625 // Buttons enabled 626 $submitBtn.removeClass( "j-processing" ).removeAttr( "disabled" ); 627 if ( config.formType.multistep ) { 628 $prevBtn.removeAttr( "disabled" ); 629 } 630 return false; 631 } 632 633 // Hide form after successful submitting 634 if ( config.formHide.hide ) { 635 self.processingHideForm(); 636 return false; 637 } 638 639 // Redirect form after success submitting 640 if ( config.formRedirect.redirect ) { 641 self.redirectForm(); 642 return false; 643 } 644 645 // Clear a form 646 // Show success message 647 self.resetForm(); 648 self.createSuccessBlock( result.success ); 649 } 650 }); 651 }, 652 653 /* Validate field */ 654 validateField: function( field ) { 655 var self = this, 656 config = self.config, 657 $formObj = self.$formObj, 658 fieldName = $( field ).attr( "name" ), 659 fieldValue; 660 661 // If a form does not have a field 662 if ( $formObj[fieldName] === undefined || $formObj[fieldName] === null ) { 663 return false; 664 } 665 666 fieldValue = _getValue( $formObj[fieldName] ); 667 668 self.validation( config.rules[fieldName], field, fieldValue, fieldName); 669 670 // Show errors within an error block 671 if ( config.error.inBlock ) { 672 self.createErrorBlock(); 673 } 674 }, 675 676 /* Validate all form fields */ 677 validateForm: function() { 678 var self = this, 679 config = self.config, 680 $formObj, fieldValue; 681 682 // If form is mulultistep 683 // Get fields from "active" step only 684 if ( config.formType.multistep ) { 685 self.$formObjActiveStep = {}; 686 self.getActiveStepField(); 687 $formObj = self.$formObjActiveStep; 688 } else { 689 $formObj = self.$formObj; 690 } 691 692 $.each( config.rules, function( name, rules ) { 693 694 // If a form does not have a field 695 if ( $formObj[name] === undefined || $formObj[name] === null ) { 696 return; 697 } 698 699 // Skip the validation if field is hidden 700 if ( _hiddenCheck( $formObj[name] ) ){ 701 return; 702 } 703 704 // Get field value 705 fieldValue = _getValue( $formObj[name] ); 706 707 // Fields processing 708 self.validation( rules, $formObj[name], fieldValue, name ); 709 }); 710 }, 711 712 /* Validation functions */ 713 validation: function( rules, field, fieldValue, fieldName ) { 714 var self = this, 715 config = self.config, 716 count = 0, 717 groupObj = {}, 718 res, groupClass, id; 719 720 // Files processing 721 if ( $( field ).attr( "type" ) && $( field ).attr( "type" ) === "file" ) { 722 if ( config.rules[fieldName].required === true || 723 config.rules[fieldName].validate === true ) { 724 725 res = _fileCheck( $( field ), config.rules[fieldName], 726 config.messages[fieldName], config.mimeTypes ); 727 728 if ( res ) { 729 self.setErrorState( $( field ), res ); 730 return false;
731 } 732 self.setSuccessState( field ); 733 } 734 } 735 736 // Fields processing 737 $.each( rules, function( rule, ruleValue ){ 738 switch( rule ) { 739 case "required": 740 if ( ruleValue === true ) { 741 if ( _minLengthCheck( fieldValue, 1 ) ) { 742 self.setErrorState( field, config.messages[fieldName][rule] ); 743 return false; 744 } 745 self.setSuccessState( field ); 746 } 747 break; 748 case "email": 749 if ( ruleValue === true ) { 750 if ( _emailCheck( fieldValue ) ) { 751 self.setErrorState( field, config.messages[fieldName][rule] ); 752 return false; 753 } 754 self.setSuccessState( field ); 755 } 756 break; 757 case "url": 758 if ( ruleValue === true ) { 759 if ( _urlCheck( fieldValue ) ) { 760 self.setErrorState( field, config.messages[fieldName][rule] ); 761 return false; 762 } 763 self.setSuccessState( field ); 764 } 765 break; 766 case "integer": 767 if ( ruleValue === true ) { 768 if ( _integerCheck( fieldValue ) ) { 769 self.setErrorState( field, config.messages[fieldName][rule] ); 770 return false; 771 } 772 self.setSuccessState( field ); 773 } 774 break; 775 case "number": 776 if ( ruleValue === true ) { 777 if ( _numberCheck( fieldValue ) ) { 778 self.setErrorState( field, config.messages[fieldName][rule] ); 779 return false; 780 } 781 self.setSuccessState( field ); 782 } 783 break; 784 case "minlength": 785 if ( _minLengthCheck( fieldValue, config.rules[fieldName][rule] ) ) { 786 self.setErrorState( field, config.messages[fieldName][rule] ); 787 return false; 788 } 789 self.setSuccessState( field ); 790 break; 791 case "maxlength": 792 if ( _maxLengthCheck( fieldValue, config.rules[fieldName][rule] ) ) { 793 self.setErrorState( field, config.messages[fieldName][rule] ); 794 return false; 795 } 796 self.setSuccessState( field ); 797 break; 798 case "rangelength": 799 if ( _rangeLengthCheck( fieldValue, config.rules[fieldName][rule] ) ) { 800 self.setErrorState( field, config.messages[fieldName][rule] ); 801 return false; 802 } 803 self.setSuccessState( field ); 804 break; 805 case "minvalue": 806 if ( _minValueCheck( fieldValue, config.rules[fieldName][rule] ) ) { 807 self.setErrorState( field, config.messages[fieldName][rule] ); 808 return false; 809 } 810 self.setSuccessState( field ); 811 break; 812 case "maxvalue": 813 if ( _maxValueCheck( fieldValue, config.rules[fieldName][rule] ) ) { 814 self.setErrorState( field, config.messages[fieldName][rule] ); 815 return false; 816 } 817 self.setSuccessState( field ); 818 break; 819 case "rangevalue": 820 if ( _rangeValueCheck( fieldValue, config.rules[fieldName][rule] ) ) { 821 self.setErrorState( field, config.messages[fieldName][rule] ); 822 return false; 823 } 824 self.setSuccessState( field ); 825 break; 826 case "equalTo": 827 828 // Get id 829 id = ruleValue.slice(1); 830 831 // Get element's value with id 832 $.each( self.$formObj, function(){ 833 if ( this.attr( "id" ) === id ) { 834 res = this.val(); 835 } 836 }); 837 if ( _equalToCheck( fieldValue, res ) ) { 838 self.setErrorState( field, config.messages[fieldName][rule] ); 839 return false; 840 } 841 self.setSuccessState( field ); 842 break; 843 case "requiredFromGroup": 844 845 // Get class name 846 groupClass = ruleValue[1].slice(1); 847 848 // Get elements with class 849 $.each( self.$formObj, function( fieldName, fieldObj ){ 850 if ( fieldObj.hasClass( groupClass ) ) { 851 groupObj[fieldName] = fieldObj; 852 self.clearField( fieldObj ); 853 } 854 }); 855 856 // Validation 857 $.each( groupObj, function(){ 858 if ( !_minLengthCheck( _getValue( this ), 1 ) ) { 859 count++; 860 } 861 }); 862 863 // Add error state 864 if ( count < ruleValue[0] ) { 865 $.each( groupObj, function(){ 866 self.setErrorState( this, config.messages[fieldName][rule] ); 867 }); 868 return false; 869 } 870 871 // Add success state 872 $.each( groupObj, function(){ 873 self.setSuccessState( this ); 874 }); 875 break; 876 } 877 }); 878 }, 879 880 /* Set error conditions for form fields */ 881 setErrorState: function( field, msg ) { 882 var self = this, 883 config = self.config, 884 $input = $( field ).closest( ".j-input" ), 885 elem; 886 887 // Error exists 888 self.errorExists = true; 889 890 /* Remove class "j-success-view" */ 891 $input.toggleClass( "j-success-view", false ); 892 893 // Add class "j-error-view" 894 if ( config.error.highlight ) { 895 $input.addClass( "j-error-view" ); 896 } 897 898 // Show errors in tooltips 899 if ( config.error.inTooltip ) { 900 elem = $( "<span />", { 901 class: "j-tooltip j-error-view " + config.error.inTooltipClass, 902 text: msg 903 }); 904 $input.append( elem ); 905 } 906 907 // Show errors under appropriate fields 908 if ( config.error.underField ) { 909 elem = $( "<span />", { 910 class: "j-error-view", 911 text: msg 912 }); 913 $input.append( elem ); 914 } 915 916 // Add error message into an array 917 // For showing into error block 918 if ( config.error.inBlock ) { 919 var fieldName = $( field ).attr( "name" ); 920 self.errorMessages[fieldName] = msg; 921 } 922 }, 923 924 /* Set success conditions for form fields */ 925 setSuccessState: function( field ) { 926 var self = this, 927 $input = $( field ).closest( ".j-input" ); 928 929 // Add class "j-success-view" 930 if ( self.config.success.highlight ) { 931 $input.toggleClass( "j-success-view", true ); 932 } 933 }, 934 935 /* Init total form data */ 936 initTotalData: function() { 937 var self = this; 938 939 self.$totalDataBlock = self.$form.find( ".j-total-data" ); 940 if ( !self.$totalDataBlock.length ){ 941 self.config.debugArr.push( self.config.dict.totalDataBlockError ); 942 } 943 }, 944 945 /* Total form data processing */ 946 processingTotalData: function() { 947 var self = this, 948 $formObj = self.$formObj, 949 $totalDataBlock = self.$totalDataBlock,
950 $totalDataList, $totalDataValue, $fieldName, $elem; 951 952 // List of fields to insert data in 953 $totalDataList = $totalDataBlock.find("span[data-field]"); 954 955 $.each( $totalDataList, function(){ 956 957 // Get form field with the name 958 $fieldName = $( this ).attr("data-field"); 959 $elem = self.$form.find( "[name='"+$fieldName+"']" ); 960 961 if ( $elem.length ) { 962 963 if ( $formObj[$fieldName] === undefined || $formObj[$fieldName] === null ){ 964 return; 965 } 966 967 // Add event listener 968 $elem.on("change", (function(obj, name){ 969 return function(){ 970 $totalDataValue = _getValue( obj[name] ); 971 $totalDataBlock.find( "span[data-field='"+name+"']" ).html( $totalDataValue ); 972 }; 973 })($formObj, $fieldName)); 974 } 975 }); 976 }, 977 978 /* Init multistep form */ 979 initMultistepForm: function() { 980 var self = this, 981 $form = self.$form; 982 983 self.$nextBtn = $form.find( ".j-multi-next-btn" ); 984 self.$prevBtn = $form.find( ".j-multi-prev-btn" ); 985 self.$stepTitleList = $form.find( ".j-step-title" ); 986 self.$contentBlock = $form.children( ".j-content" ); 987 self.$footerBlock = $form.children( ".j-footer" ); 988 self.$stepList = self.$contentBlock.children( "fieldset" ); 989 990 self.createMultistepForm(); 991 self.processingMultistepForm(); 992 }, 993 994 /* Make a layout for multistep form */ 995 createMultistepForm: function() { 996 var self = this, 997 $form = self.$form, 998 $stepTitleBlock, $elem, $elems, $elemsLen, $tempStep, $tempStepList, i; 999 1000 // Add class "j-multistep" 1001 $form.toggleClass( "j-multistep", true ); 1002 1003 // If a form doesn't have "next" button 1004 if ( !self.$nextBtn.length ) { 1005 $elem = $("<button />", { 1006 type: "button", 1007 class: "j-primary-btn j-multi-next-btn", 1008 text: self.config.dict.multistepNextBtn 1009 }); 1010 if ( self.$footerBlock.length ) { 1011 self.$footerBlock.append( $elem ); 1012 } else { 1013 self.$contentBlock.append( $elem ); 1014 } 1015 self.$nextBtn = self.$form.find( ".j-multi-next-btn" ); 1016 } 1017 1018 // If a form doesn't have "previous" button 1019 if ( !self.$prevBtn.length ) { 1020 $elem = $("<button />", { 1021 type: "button", 1022 class: "j-secondary-btn j-multi-prev-btn", 1023 text: self.config.dict.multistepPrevBtn 1024 }); 1025 if ( self.$footerBlock.length ) { 1026 self.$footerBlock.append( $elem ); 1027 } else { 1028 self.$contentBlock.append( $elem ); 1029 } 1030 self.$prevBtn = self.$form.find( ".j-multi-prev-btn" ); 1031 } 1032 1033 // If a form doesn't have fieldsets 1034 if ( !self.$stepList.length ) { 1035 1036 // Find form fields 1037 $elems = self.$contentBlock.children( ".j-unit, .j-row" ).filter(":not(.j-step-titles)"); 1038 $stepTitleBlock = self.$contentBlock.children( ".j-step-titles" ); 1039 1040 $elemsLen = $elems.length; 1041 1042 // Cerate steps for every set of fields 1043 for ( i=0; i<$elemsLen; i+=3 ) { 1044 1045 // Add fields to a step 1046 $tempStep = $( "<fieldset />" ).append( $elems.slice( i, i+3 ) ); 1047 1048 // Add step to a form 1049 $tempStepList = self.$contentBlock.children( "fieldset" ); 1050 if ( !$tempStepList.length ){ 1051 if ( !$stepTitleBlock.length ){ 1052 self.$contentBlock.prepend( $tempStep ); 1053 continue; 1054 } 1055 $tempStep.insertAfter( $stepTitleBlock ); 1056 continue; 1057 } 1058 $tempStep.insertAfter( $tempStepList.last() ); 1059 } 1060 self.$stepList = self.$contentBlock.children( "fieldset" ); 1061 } 1062 }, 1063 1064 /* Multistep form processing */ 1065 processingMultistepForm: function() { 1066 var self = this, 1067 config = self.config, 1068 $stepList = self.$stepList, 1069 $nextBtn = self.$nextBtn, 1070 $prevBtn = self.$prevBtn, 1071 $submitBtn = self.$submitBtn, 1072 $stepTitleList = self.$stepTitleList, 1073 len = self.$stepList.length; 1074 1075 // If multistep form has one step only 1076 if ( len === 1 ){ 1077 config.debugArr.push( config.dict.multistepOneStepError ); 1078 $stepList.eq( 0 ).addClass( "j-active-fieldset" ); 1079 return false; 1080 } 1081 1082 // Processing of the first fieldset 1083 $stepList.eq( 0 ).addClass( "j-active-fieldset" ); 1084 $submitBtn.addClass( "j-hiddenBtn" ); 1085 $prevBtn.addClass( "j-hiddenBtn" ); 1086 1087 // Set active step title 1088 if ( $stepTitleList.length ){ 1089 $stepTitleList.eq(0).addClass( "j-active-step" ); 1090 } 1091 1092 // Click on the "next" button 1093 $nextBtn.on( "click", function( e ){ 1094 if ( e ) { 1095 e.preventDefault(); 1096 e.stopPropagation(); 1097 } 1098 1099 // Clear a form 1100 self.clearForm(); 1101 1102 // Form validation 1103 self.validateForm(); 1104 1105 // If errors don"t exist 1106 if ( !self.errorExists ) { 1107 1108 // Switch the "active" class to the next fieldset 1109 $stepList.filter( ".j-active-fieldset" ).removeClass( "j-active-fieldset" ). 1110 next( "fieldset" ).addClass( "j-active-fieldset" ); 1111 1112 // Switch the "active" class to the next step 1113 if ( $stepTitleList.length ) { 1114 $stepTitleList.filter( ".j-active-step" ).removeClass( "j-active-step" ). 1115 addClass( "j-passed-step" ).next( ".j-step-title" ).addClass( "j-active-step" ); 1116 } 1117 1118 // Display "prev" button 1119 $prevBtn.removeClass( "j-hiddenBtn" ); 1120 1121 // If active fieldset is a last 1122 // processing the buttons 1123 if ( $stepList.eq( len-1 ).hasClass( "j-active-fieldset" ) ) { 1124 $submitBtn.removeClass( "j-hiddenBtn" ); 1125 $nextBtn.addClass( "j-hiddenBtn" ); 1126 } 1127 1128 // If current fieldset has validation errors 1129 } else { 1130 // Scroll to first element with error 1131 if ( config.error.scroll ) { 1132 self.scrollToError(); 1133 } 1134 // Show errors within an error block 1135 if ( config.error.inBlock ) { 1136 self.createErrorBlock(); 1137 } 1138 return false;
1139 } 1140 }); 1141 1142 // Click on the "prev" button 1143 $prevBtn.on( "click", function( e ){ 1144 if ( e ) { 1145 e.preventDefault(); 1146 e.stopPropagation(); 1147 } 1148 1149 // Clear a form 1150 self.clearForm(); 1151 1152 // Switch the "active" class to the previous fieldset 1153 $stepList.filter( ".j-active-fieldset" ).removeClass( "j-active-fieldset" ). 1154 prev( "fieldset" ).addClass( "j-active-fieldset" ); 1155 1156 1157 // Switch the "active" class to the next step 1158 if ( $stepTitleList.length ) { 1159 $stepTitleList.filter( ".j-active-step" ).removeClass( "j-active-step" ). 1160 prev( ".j-step-title" ).removeClass( "j-passed-step" ).addClass( "j-active-step" ); 1161 } 1162 1163 // If active fieldset is a first 1164 // processing the buttons 1165 if ( $stepList.eq(0).hasClass( "j-active-fieldset" ) ) { 1166 $prevBtn.addClass( "j-hiddenBtn" ); 1167 } 1168 1169 // If active fieldset is a penultimate 1170 // processing the buttons 1171 if ( $stepList.eq( len-2 ).hasClass( "j-active-fieldset" ) ) { 1172 $submitBtn.addClass( "j-hiddenBtn" ); 1173 $nextBtn.removeClass( "j-hiddenBtn" ); 1174 } 1175 1176 // Get fields from active step 1177 self.getActiveStepField(); 1178 }); 1179 }, 1180 1181 /* Get fields from active step only */ 1182 getActiveStepField: function() { 1183 var self = this, 1184 config = self.config, 1185 $form = self.$form, 1186 $el; 1187 1188 if ( config.formType.multistep ) { 1189 $.each( config.rules, function( name, rules ) { 1190 $el = $form.find( "fieldset.j-active-fieldset [name='"+name+"']" ); 1191 if ( $el.length ) { 1192 self.$formObjActiveStep[name] = $el; 1193 } 1194 }); 1195 } 1196 }, 1197 1198 /* Init modal form */ 1199 initModalForm: function() { 1200 var self = this, 1201 $form = self.$form; 1202 1203 self.$modalWrap = $form.closest( ".j-modal-form" ); 1204 self.$modalClose = $form.find( ".j-modal-close" ); 1205 self.$modalOpen = $( document ).find( ".j-modal-open" ); 1206 1207 // If modal links dont exist 1208 if ( !self.$modalOpen.length ) { 1209 self.config.debugArr.push( self.config.dict.modalOpenError ); 1210 return false; 1211 } 1212 1213 self.createModalForm(); 1214 self.processingModalForm(); 1215 }, 1216 1217 /* Make a layout for modal form */ 1218 createModalForm: function() { 1219 var self = this, 1220 $form = self.$form, 1221 $elem, $formWrap; 1222 1223 // If a form doesn't have modal wrapper 1224 if ( !self.$modalWrap.length ) { 1225 $formWrap = $form.closest( ".j-wrapper" ); 1226 1227 // Modal wrapper 1228 $elem = $( "<div />", { 1229 class: "j-modal-form", 1230 id: "j-modalwrap-" + $form.attr( "id" ) 1231 }); 1232 1233 // Wrap a form with modal wrapper 1234 $formWrap.wrap( $elem ); 1235 self.$modalWrap = $form.closest( ".j-modal-form" ); 1236 } 1237 1238 // If a form doesn't have modal close button 1239 if ( !self.$modalClose.length ) { 1240 1241 // Close button 1242 $elem = $( "<label />", { 1243 class: "j-modal-close" 1244 }).append( "<i></i>" ); 1245 1246 // Add close modal button to form 1247 $form.append( $elem ); 1248 self.$modalClose = $form.find( ".j-modal-close" ); 1249 } 1250 }, 1251 1252 /* Modal form processing */ 1253 processingModalForm: function() { 1254 var self = this; 1255 1256 // Modal links processing 1257 self.$modalOpen.each( function(){ 1258 $( this ).on( "click", function( e ){ 1259 if ( e ) { 1260 e.preventDefault(); 1261 e.stopPropagation(); 1262 } 1263 1264 // Show modal form for approriate modal link 1265 if ( $( this ).data( "modal-wrap" ) === self.$modalWrap.attr( "id" ) ) { 1266 self.$modalWrap.addClass( "j-modal-visible" ); 1267 $( "body" ).addClass( "j-modal-scroll" ); 1268 } 1269 }); 1270 }); 1271 1272 // Close button processing 1273 self.$modalClose.on( "click", function(){ 1274 self.$modalWrap.removeClass( "j-modal-visible" ); 1275 $( "body" ).removeClass( "j-modal-scroll" ); 1276 }); 1277 }, 1278 1279 /* Init hide form feature */ 1280 initHideForm: function() { 1281 var self = this; 1282 1283 self.$finalBlock = $( document ).find( ".j-final-block" ); 1284 self.$finalBlockCloseBtn = self.$finalBlock.find( ".j-close" ); 1285 1286 self.createHideForm(); 1287 }, 1288 1289 /* Make a layout for final block after form hidding */ 1290 createHideForm: function() { 1291 var self = this, 1292 config = self.config, 1293 $form = self.$form, 1294 $elem; 1295 1296 // If final block doesn't exist 1297 if ( !self.$finalBlock.length ) { 1298 $elem = $("<div />", { 1299 class: "j-final-block j-hidden" 1300 }); 1301 $form.after( $elem.html( config.dict.successBlockText ) ); 1302 self.$finalBlock = $form.siblings( ".j-final-block" ); 1303 } 1304 1305 // If "Close" btn doesn't exist 1306 if ( !self.$finalBlockCloseBtn.length ) { 1307 if ( config.formHide.closeBtn ) { 1308 $elem = $( "<label />", { 1309 class: "j-close" 1310 }).append( "<i></i>" ); 1311 self.$finalBlock.append( $elem ); 1312 self.$finalBlockCloseBtn = self.$finalBlock.find( ".j-close" ); 1313 } 1314 } else { 1315 if ( !config.formHide.closeBtn ) { 1316 self.$finalBlockCloseBtn.addClass( "j-hidden" ); 1317 } 1318 } 1319 }, 1320 1321 /* Hide form processing */ 1322 processingHideForm: function() { 1323 var self = this, 1324 $finalBlock = self.$finalBlock, 1325 $finalBlockCloseBtn = self.$finalBlockCloseBtn; 1326 1327 self.$form.addClass( "j-hidden" ); 1328 $finalBlock.removeClass( "j-hidden" ); 1329 1330 if ( $finalBlockCloseBtn.length ) { 1331 $finalBlockCloseBtn.on("click", function() { 1332 if ( self.config.formType.modal ) { 1333 1334 var $modalForm = $( document ).find( "div.j-modal-form" ); 1335 if ( $modalForm.hasClass( "j-modal-visible" ) ) { 1336 $modalForm.removeClass( "j-modal-visible" ); 1337 $( "body" ).removeClass( "j-modal-scroll" ); 1338 } 1339 } else { 1340 $finalBlock.addClass( "j-hidden" ); 1341 } 1342 }); 1343 } 1344 }, 1345 1346 /* Reset form */ 1347 resetForm: function() { 1348 var self = this,
1349 config = self.config, 1350 $input, $totalDataList; 1351 1352 // Reset a form 1353 self.form.reset(); 1354 1355 // Remove success condition from the fields 1356 if ( config.success.highlight ){ 1357 $input = self.$form.find( ".j-input" ); 1358 $input.each( function(){ 1359 $( this ).toggleClass( "j-success-view", false ); 1360 }); 1361 } 1362 1363 // Clear total form data block 1364 if ( config.formTotalData ){ 1365 $totalDataList = self.$totalDataBlock.find("span[data-field]"); 1366 $.each( $totalDataList, function(){ 1367 $( this ).html( "" ); 1368 }); 1369 } 1370 }, 1371 1372 /* Redirect form */ 1373 redirectForm: function() { 1374 var self = this; 1375 1376 $( location ).attr( "href", self.config.formRedirect.address ); 1377 }, 1378 1379 /* Scroll to first element with error */ 1380 scrollToError: function() { 1381 var self = this, 1382 $form = self.$form, 1383 $err = $form.find( ".j-error-view" ).eq(0), 1384 $modalWrap, $wrapper, $offset; 1385 1386 if ( !$err.length ) { 1387 return false; 1388 } 1389 1390 // Scroll modal form 1391 if ( self.config.formType.modal ){ 1392 1393 $modalWrap = $( document ).find( "#j-modalwrap-"+$form.attr("id") ); 1394 $wrapper = $( document ).find(".j-wrapper"); 1395 $offset = $wrapper.offset().top - $err.offset().top; 1396 1397 $modalWrap.animate({ 1398 scrollTop: -$offset - 60 1399 }, 500); 1400 return false; 1401 } 1402 1403 // Scroll not modal form 1404 $("html, body").animate({ 1405 scrollTop: $err.offset().top - 60 1406 }, 500); 1407 }, 1408 1409 /* Create a block with error messages */ 1410 createErrorBlock: function() { 1411 var self = this, 1412 $ul = $( "<ul></ul>" ), 1413 elems = false, 1414 $formResponseBlock = self.$formResponseBlock, 1415 $li; 1416 1417 // If error object contains error messages 1418 $.each( self.errorMessages, function( key, val ) { 1419 if ( val !== null ) { 1420 elems = true; 1421 return false; 1422 } 1423 }); 1424 1425 if ( elems ) { 1426 1427 // Add class "j-error-message" 1428 $formResponseBlock.toggleClass( "j-error-message j-unit", true ); 1429 $formResponseBlock.text( self.config.dict.errorBlockText ).append( $ul ); 1430 1431 $.each( self.errorMessages, function( name, mes ) { 1432 if ( mes !== null ) { 1433 $li = $( "<li></li>" ).text( mes ); 1434 $ul.append( $li ); 1435 } 1436 }); 1437 } else { 1438 self.clearBlock(); 1439 } 1440 }, 1441 1442 /* Create a block with success message */ 1443 createSuccessBlock: function( msg ) { 1444 var self = this, 1445 config = self.config, 1446 $submitBtn = self.$submitBtn, 1447 $formResponseBlock = self.$formResponseBlock, 1448 $recaptcha = self.$form.find(".g-recaptcha"); 1449 1450 // Clear response block 1451 if ( $formResponseBlock.hasClass( "j-error-message" ) ) { 1452 self.clearBlock(); 1453 } 1454 1455 // Add success message 1456 $formResponseBlock.addClass( "j-success-message j-unit" ).text( msg ); 1457 1458 // Button enabled 1459 $submitBtn.removeClass( "j-processing" ); 1460 1461 // If repeated form submission is not allowed 1462 if ( !config.repeatSubmission ) { 1463 1464 // Disable submit button 1465 $submitBtn.addClass( "j-disabled-view" ).html( config.dict.disabledBtn ); 1466 } 1467 1468 setTimeout(function(){ 1469 1470 self.clearBlock(); 1471 1472 // Google reCaptcha reloading 1473 if ( $recaptcha.length ) { 1474 grecaptcha.reset(); 1475 } 1476 1477 // If repeated form submission is allowed 1478 if ( config.repeatSubmission ) { 1479 $submitBtn.removeAttr( "disabled" ); 1480 } 1481 1482 // Modal form processing 1483 if ( config.formType.modal ) { 1484 $( "div.j-modal-form" ).removeClass( "j-modal-visible" ); 1485 $( "body" ).removeClass( "j-modal-scroll" ); 1486 } 1487 1488 // Multistep form processing 1489 if ( config.formType.multistep ) { 1490 1491 // Buttons processing 1492 self.$prevBtn.removeAttr( "disabled" ).addClass( "j-hiddenBtn" ); 1493 self.$nextBtn.removeClass( "j-hiddenBtn" ); 1494 $submitBtn.addClass( "j-hiddenBtn" ); 1495 1496 // Steps processing 1497 self.$stepList.removeClass( "j-active-fieldset" ).eq( 0 ).addClass( "j-active-fieldset" ); 1498 1499 // Step titles processing 1500 if ( self.$stepTitleList.length ){ 1501 self.$stepTitleList.removeClass('j-active-step j-passed-step').eq(0).addClass('j-active-step'); 1502 } 1503 } 1504 }, config.timeoutSuccessMsg); 1505 }, 1506 1507 /* Delete all error messages, all "error" CSS classes */ 1508 clearForm: function() { 1509 var self = this, 1510 $form = self.$form, 1511 config = self.config, 1512 $spanErr, $tooltipErr, $input; 1513 1514 // Clear error variables 1515 self.errorExists = false;
1516 self.errorMessages = {}; 1517 1518 // Delete error messages under the fields 1519 if ( config.error.underField ) { 1520 $spanErr = $form.find("span.j-error-view"); 1521 $spanErr.each(function(){ 1522 $( this ).remove(); 1523 }); 1524 } 1525 1526 // Delete error messages from an error block 1527 if ( config.error.inBlock ) { 1528 self.clearBlock(); 1529 } 1530 1531 // Remove error condition from the fields 1532 if ( config.error.highlight ) { 1533 $input = $form.find( ".j-input" ); 1534 $input.each( function(){ 1535 $( this ).toggleClass( "j-error-view", false ); 1536 }); 1537 } 1538 1539 // Delete tooltip error messages 1540 if ( config.error.inTooltip ) { 1541 $tooltipErr = $form.find( "span.j-tooltip.j-error-view" ); 1542 $tooltipErr.each(function(){ 1543 $( this ).remove(); 1544 }); 1545 } 1546 }, 1547 1548 /* Delete field's error message, field's "error" CSS classes */ 1549 clearField: function( field ) { 1550 var self = this, 1551 config = self.config, 1552 errorMessages = self.errorMessages, 1553 fieldName = $( field ).attr("name"), 1554 $input, $span, $tooltip; 1555 1556 // If a form does not have a field 1557 if ( self.$formObj[fieldName] === undefined || self.$formObj[fieldName] === null ){ 1558 return false; 1559 } 1560 1561 self.errorExists = false; 1562 $input = $( field ).closest( ".j-input" ); 1563 1564 // Delete error messages under the fields 1565 if ( config.error.underField ){ 1566 $span = $input.find( "span.j-error-view" ); 1567 if ( $span.length ) { 1568 $span.remove(); 1569 } 1570 } 1571 1572 // Remove error condition from the fields 1573 if ( config.error.highlight ) { 1574 $input.toggleClass( "j-error-view", false ); 1575 } 1576 1577 // Delete tooltip error messages 1578 if ( config.error.inTooltip ) { 1579 $tooltip = $input.find( "span.j-tooltip.j-error-view" ); 1580 if ( $tooltip.length ) { 1581 $tooltip.remove(); 1582 } 1583 } 1584 1585 // Delete error message from error object 1586 if ( config.error.inBlock ){ 1587 if ( errorMessages[fieldName] !== undefined && errorMessages[fieldName] !== null ) { 1588 errorMessages[fieldName] = null; 1589 } 1590 } 1591 }, 1592 1593 /* Clear a block with validation result */ 1594 clearBlock: function() { 1595 var self = this; 1596 1597 self.$formResponseBlock.removeClass( "j-error-message j-success-message j-unit" ).html( "" ); 1598 }, 1599}; 1600 1601$.fn.justFormsPro = function( options ){ 1602 new JustFormsPro( this, options ); 1603 return this; 1604}; 1605}( jQuery ));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.