1/* global wpforms_settings,grecaptcha,wpforms_validate,wpforms_timepicker */ 2 3;(function($) { 4 5 'use strict'; 6 7 var WPForms = { 8 9 /** 10 * Start the engine. 11 * 12 * @since 1.2.3 13 */ 14 init: function() { 15 16 // Document ready 17 $(document).ready(WPForms.ready); 18 19 // Page load 20 $(window).on('load', WPForms.load); 21 22 WPForms.bindUIActions(); 23 WPForms.bindOptinMonster(); 24 }, 25 26 /** 27 * Document ready. 28 * 29 * @since 1.2.3 30 */ 31 ready: function() { 32 33 // Set user identifier 34 WPForms.setUserIndentifier(); 35 36 WPForms.loadValidation(); 37 WPForms.loadDatePicker(); 38 WPForms.loadTimePicker(); 39 WPForms.loadInputMask(); 40 WPForms.loadPayments(); 41 42 // Randomize elements. 43 $( '.wpforms-randomize' ).each( function() { 44 var $list = $( this ), 45 $listItems = $list.children(); 46 while ( $listItems.length ) { 47 $list.append( $listItems.splice( Math.floor( Math.random() * $listItems.length ), 1 )[0] ); 48 } 49 }); 50 51 $(document).trigger('wpformsReady'); 52 }, 53 54 /** 55 * Page load. 56 * 57 * @since 1.2.3 58 */ 59 load: function() { 60 61 }, 62 63 //--------------------------------------------------------------------// 64 // Initializing 65 //--------------------------------------------------------------------// 66 67 /** 68 * Load jQuery Validation. 69 * 70 * @since 1.2.3 71 */ 72 loadValidation: function() { 73 74 // Only load if jQuery validation library exists 75 if (typeof $.fn.validate !== 'undefined') { 76 77 // jQuery Validation library will not correctly validate 78 // fields that do not have a name attribute, so we use the 79 // `wpforms-input-temp-name` class to add a temporary name 80 // attribute before validation is initialized, then remove it 81 // before the form submits. 82 $( '.wpforms-input-temp-name' ).each(function( index, el ) { 83 var random = Math.floor( Math.random() * 9999 ) + 1; 84 $( this ).attr( 'name', 'wpf-temp-' + random ); 85 }); 86 87 // Prepend URL field contents with http:// if user input doesn't contain a schema. 88 $( '.wpforms-validate input[type=url]' ).change( function () { 89 var url = $( this ).val(); 90 if ( ! url ) { 91 return false; 92 } 93 if ( url.substr( 0, 7 ) !== 'http://' && url.substr( 0, 8 ) !== 'https://' ) { 94 $( this ).val( 'http://' + url ); 95 } 96 }); 97 98 $.validator.messages.required = wpforms_settings.val_required; 99 $.validator.messages.url = wpforms_settings.val_url; 100 $.validator.messages.email = wpforms_settings.val_email; 101 $.validator.messages.number = wpforms_settings.val_number; 102 103 // Payments: Validate method for Credit Card Number 104 if(typeof $.fn.payment !== 'undefined') { 105 $.validator.addMethod( "creditcard", function(value, element) { 106 //var type = $.payment.cardType(value); 107 var valid = $.payment.validateCardNumber(value); 108 return this.optional(element) || valid; 109 }, wpforms_settings.val_creditcard); 110 // @todo validate CVC and expiration 111 } 112 113 // Validate method for file extensions 114 $.validator.addMethod( "extension", function(value, element, param) { 115 param = typeof param === "string" ? param.replace( /,/g, "|" ) : "png|jpe?g|gif"; 116 return this.optional(element) || value.match( new RegExp( "\\.(" + param + ")$", "i" ) ); 117 }, wpforms_settings.val_fileextension ); 118 119 // Validate method for file size 120 $.validator.addMethod("maxsize", function(value, element, param) { 121 var maxSize = param, 122 optionalValue = this.optional(element), 123 i, len, file; 124 if (optionalValue) { 125 return optionalValue; 126 } 127 if (element.files && element.files.length) { 128 i = 0; 129 len = element.files.length; 130 for (; i < len; i++) { 131 file = element.files[i]; 132 if (file.size > maxSize) { 133 return false; 134 } 135 } 136 } 137 return true; 138 }, wpforms_settings.val_filesize); 139 140 // Validate email addresses 141 $.validator.methods.email = function( value, element ) { 142 return this.optional( element ) || /^[a-z0-9.!#$%&'*+\/=?^_`{|}~-]+@((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}$/i.test( value ); 143 }; 144 145 // Validate confirmations 146 $.validator.addMethod("confirm", function(value, element, param) { 147 return $.validator.methods.equalTo.call(this, value, element, param); 148 }, wpforms_settings.val_confirm); 149 150 // Validate required payments 151 $.validator.addMethod( "required-payment", function( value, element ) { 152 return WPForms.amountSanitize( value ) > 0; 153 }, wpforms_settings.val_requiredpayment ); 154 155 // Validate 12-hour time 156 $.validator.addMethod( "time12h", function( value, element ) { 157 return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value ); 158 }, wpforms_settings.val_time12h ); 159 160 // Validate 24-hour time 161 $.validator.addMethod( "time24h", function( value, element ) { 162 return this.optional(element) || /^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(\ ?[AP]M)?$/i.test(value); 163 }, wpforms_settings.val_time24h ); 164 165 // Finally load jQuery Validation library for our forms 166 $('.wpforms-validate').each(function() { 167 var form = $(this), 168 formID = form.data('formid'), 169 properties; 170 171 // TODO: cleanup this BC with wpforms_validate. 172 if (typeof window['wpforms_'+formID] !== 'undefined' && window['wpforms_'+formID].hasOwnProperty('val
172idate')) { 173 properties = window['wpforms_'+formID].validate; 174 } else if ( typeof wpforms_validate !== 'undefined') { 175 properties = wpforms_validate; 176 } else { 177 properties = { 178 errorClass: 'wpforms-error', 179 validClass: 'wpforms-valid', 180 errorPlacement: function( error, element ) { 181 if ( element.attr( 'type' ) === 'radio' || element.attr( 'type' ) === 'checkbox' ) { 182 if ( element.hasClass( 'wpforms-likert-scale-option' ) ) { 183 if ( element.closest( 'table' ).hasClass( 'single-row' ) ) { 184 element.closest( 'table' ).after( error ); 185 } else { 186 element.closest( 'tr' ).find( 'th' ).append( error ); 187 } 188 } else if ( element.hasClass( 'wpforms-net-promoter-score-option' ) ) { 189 element.closest( 'table' ).after( error ); 190 } else { 191 element.parent().parent().parent().append( error ); 192 } 193 } else if ( element.is( 'select' ) && element.attr( 'class' ).match( /date-month|date-day|date-year/ ) ) { 194 if ( element.parent().find( 'label.wpforms-error:visible' ).length === 0 ) { 195 element.parent().find( 'select:last' ).after( error ); 196 } 197 } else { 198 error.insertAfter(element); 199 } 200 }, 201 highlight: function( element, errorClass, validClass ) { 202 var $element = $( element ), 203 $field = $element.closest( '.wpforms-field' ), 204 inputName = $element.attr( 'name' ); 205 if ( $element.attr( 'type' ) === 'radio' || $element.attr( 'type' ) === 'checkbox' ) { 206 $field.find( 'input[name=\''+inputName+'\']' ).addClass( errorClass ).removeClass( validClass ); 207 } else { 208 $element.addClass( errorClass ).removeClass( validClass ); 209 } 210 $field.addClass( 'wpforms-has-error' ); 211 }, 212 unhighlight: function( element, errorClass, validClass ) { 213 var $element = $( element ), 214 $field = $element.closest( '.wpforms-field' ), 215 inputName = $element.attr( 'name' ); 216 if ( $element.attr( 'type' ) === 'radio' || $element.attr( 'type' ) === 'checkbox' ) { 217 $field.find( 'input[name=\''+inputName+'\']' ).addClass( validClass ).removeClass( errorClass ); 218 } else { 219 $element.addClass( validClass ).removeClass( errorClass ); 220 } 221 $field.removeClass( 'wpforms-has-error' ); 222 }, 223 submitHandler: function(form) { 224 225 var $form = $(form), 226 $submit = $form.find('.wpforms-submit'), 227 altText = $submit.data('alt-text'); 228 229 if ( WPForms.empty( $submit.get(0).recaptchaID ) && $submit.get(0).recaptchaID !== 0 ) { 230 // Normal form. 231 if (altText) { 232 $submit.text(altText).prop('disabled', true); 233 } 234 235 // Remove name attributes if needed. 236 $( '.wpforms-input-temp-name' ).removeAttr('name'); 237 238 form.submit(); 239 240 } else { 241 // Form contains invisible reCAPTCHA. 242 grecaptcha.execute( $submit.get(0).recaptchaID ); 243 } 244 }, 245 onkeyup: function( element, event ) { 246 // This code is copied from JQuery Validate 'onkeyup' method with only one change: 'wpforms-novalidate-onkeyup' class check. 247 var excludedKeys = [ 16, 17, 18, 20, 35, 36, 37, 38, 39, 40, 45, 144, 225 ]; 248 249 if ( $( element ).hasClass('wpforms-novalidate-onkeyup') ) { 250 return; // Disable onkeyup validation for some elements (e.g. remote calls). 251 } 252 253 if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) { 254 return; 255 } else if ( element.name in this.submitted || element.name in this.invalid ) { 256 this.element( element ); 257 } 258 }, 259 onfocusout: function( element ) { 260 // This code is copied from JQuery Validate 'onfocusout' method with only one change: 'wpforms-novalidate-onkeyup' class check. 261 var validate = false; 262 263 if ( $( element ).hasClass('wpforms-novalidate-onkeyup') && !element.value ) { 264 validate = true; // Empty value error handling for elements with onkeyup validation disabled. 265 } 266 267 if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) { 268 validate = true; 269 } 270 271 if ( validate ) {
272 this.element( element ); 273 } 274 }, 275 } 276 } 277 form.validate( properties ); 278 }); 279 } 280 }, 281 282 /** 283 * Load jQuery Date Picker. 284 * 285 * @since 1.2.3 286 */ 287 loadDatePicker: function() { 288 289 // Only load if jQuery datepicker library exists 290 if (typeof $.fn.flatpickr !== 'undefined') { 291 $('.wpforms-datepicker').each(function() { 292 var element = $(this), 293 form = element.closest('.wpforms-form'), 294 formID = form.data('formid'), 295 fieldID = element.closest('.wpforms-field').data('field-id'), 296 properties; 297 298 if (typeof window['wpforms_'+formID+'_'+fieldID] !== 'undefined' && window['wpforms_'+formID+'_'+fieldID].hasOwnProperty('datepicker')) { 299 properties = window['wpforms_'+formID+'_'+fieldID].datepicker; 300 } else if (typeof window['wpforms_'+formID] !== 'undefined' && window['wpforms_'+formID].hasOwnProperty('datepicker')) { 301 properties = window['wpforms_'+formID].datepicker; 302 } else if (typeof wpforms_datepicker !== 'undefined') { 303 properties = wpforms_datepicker; 304 } else { 305 properties = { 306 disableMobile: true 307 }; 308 } 309 310 // Redefine locale only if user doesn't do that manually and we have the locale. 311 if ( 312 ! properties.hasOwnProperty( 'locale' ) && 313 typeof wpforms_settings !== 'undefined' && 314 wpforms_settings.hasOwnProperty( 'locale' ) 315 ) { 316 properties.locale = wpforms_settings.locale; 317 } 318 319 element.flatpickr(properties) 320 }); 321 } 322 }, 323 324 /** 325 * Load jQuery Time Picker. 326 * 327 * @since 1.2.3 328 */ 329 loadTimePicker: function() { 330 331 // Only load if jQuery timepicker library exists 332 if (typeof $.fn.timepicker !== 'undefined') { 333 $('.wpforms-timepicker').each(function() { 334 var element = $(this), 335 form = element.closest('.wpforms-form'), 336 formID = form.data('formid'), 337 fieldID = element.closest('.wpforms-field').data('field-id'), 338 properties; 339 340 if ( 341 typeof window['wpforms_'+formID+'_'+fieldID] !== 'undefined' && 342 window['wpforms_'+formID+'_'+fieldID].hasOwnProperty('timepicker') 343 ) { 344 properties = window['wpforms_'+formID+'_'+fieldID].timepicker; 345 } else if ( 346 typeof window['wpforms_'+formID] !== 'undefined' && 347 window['wpforms_'+formID].hasOwnProperty('timepicker') 348 ) { 349 properties = window['wpforms_'+formID].timepicker; 350 } else if ( typeof wpforms_timepicker !== 'undefined') { 351 properties = wpforms_timepicker; 352 } else { 353 properties = { 354 scrollDefault: 'now', 355 forceRoundTime: true 356 }; 357 } 358 359 element.timepicker(properties); 360 }); 361 } 362 }, 363 364 /** 365 * Load jQuery input masks. 366 * 367 * @since 1.2.3 368 */ 369 loadInputMask: function() { 370 371 // Only load if jQuery input mask library exists 372 if (typeof $.fn.inputmask !== 'undefined') { 373 $('.wpforms-masked-input').inputmask(); 374 } 375 }, 376 377 /** 378 * Payments: Do various payment-related tasks on load. 379 * 380 * @since 1.2.6 381 */ 382 loadPayments: function() { 383 384 // Update Total field(s) with latest calculation 385 $('.wpforms-payment-total').each(function(index, el) { 386 WPForms.amountTotal(this); 387 }); 388 389 // Credit card validation 390 if(typeof $.fn.payment !== 'undefined') { 391 $('.wpforms-field-credit-card-cardnumber').payment('formatCardNumber'); 392 $('.wpforms-field-credit-card-cardcvc').payment('formatCardCVC'); 393 } 394 }, 395 396 //--------------------------------------------------------------------// 397 // Binds. 398 //--------------------------------------------------------------------// 399 400 /** 401 * Element bindings. 402 * 403 * @since 1.2.3 404 */ 405 bindUIActions: function() { 406 407 // Pagebreak navigation. 408 $(document).on('click', '.wpforms-page-button', function(event) { 409 event.preventDefault(); 410 WPForms.pagebreakNav($(this)); 411 }); 412 413 // Payments: Update Total field(s) when latest calculation. 414 $(document).on('change input', '.wpforms-payment-price', function() { 415 WPForms.amountTotal(this, true); 416 }); 417 418 // Payments: Restrict user input payment fields. 419 $(document).on('input', '.wpforms-payment-user-input', function() { 420 var $this = $(this), 421 amount = $this.val(); 422 $this.val(amount.replace(/[^0-9.,]/g, '')); 423 }); 424 425 // Payments: Sanitize/format user input amounts. 426 $(document).on('focusout', '.wpforms-payment-user-input', function() { 427 var $this = $(this), 428 amount = $this.val(), 429 sanitized = WPForms.amountSanitize(amount), 430 formatted = WPForms.amountFormat(sanitized); 431 $this.val(formatted); 432 }); 433 434 // Payment radio/checkbox fields: preselect the selected payment (from dynamic/fallback population). 435 $( document ).ready( function () { 436 // Radios. 437 $( '.wpforms-field-radio .wpforms-image-choices-item input:checked' ).change(); 438 $( '.wpforms-field-payment-multiple .wpforms-image-choices-item input:checked' ).change(); 439 // Checkboxes. 440 $( '.wpforms-field-checkbox .wpforms-image-choices-item input' ).change(); 441 $( '.wpforms-field-payment-checkbox .wpforms-image-choices-item input' ).change(); 442 } ); 443 444 // Rating field: hover effect. 445 $( '.wpforms-field-rating-item' ).hover( 446 function() { 447 $( this ).parent().find( '.wpforms-field-rating-item' ).removeClass( 'selected hover' ); 448 $( this ).prevAll().andSelf().addClass( 'hover' ); 449 }, 450 function() { 451 $( this ).parent().find( '.wpforms-field-rating-item' ).removeClass( 'selected hover' ); 452 $( this ).parent().find( 'input:checked' ).parent().prevAll().andSelf().addClass( 'selected' ); 453 } 454 ); 455 456 // Rating field: toggle selected state. 457 $( document ).on( 'change', '.wpforms-field-rating-item input', function() { 458 459 var $this = $( this ), 460 $wrap = $this.closest( '.wpforms-field-rating-items' ), 461 $items = $wrap.find( '.wpforms-field-rating-item' ); 462 463 $items.removeClass( 'hover selected' ); 464 $this.parent().prevAll().andSelf().addClass( 'selected' ); 465 } ); 466 467 // Rating field: preselect the selected rating (from dynamic/fallback population). 468 $( document ).ready( function () { 469 $( '.wpforms-field-rating-item input:checked' ).change(); 470 } ); 471 472 // Checkbox/Radio/Payment checkbox: toggle selected state class. 473 $( document ).on( 'change', '.wpforms-field-checkbox input, .wpforms-field-radio input, .wpforms-field-payment-multiple input, .wpforms-field-payment-checkbox input', function() { 474 475 var $this = $( this ); 476 477 switch ( $this.attr( 'type' ) ) { 478 case 'radio': 479 $this.closest( 'ul' ).find( 'li' ).removeClass( 'wpforms-selected' ).find('input[type=radio]').removeAttr( 'checked' ); 480 $this 481 .attr( 'checked', 'checked' ) 482 .closest( 'li' ).addClass( 'wpforms-selected' ); 483 break; 484 485 case 'checkbox': 486 if ( $this.prop( 'checked' ) ) { 487 $this.closest( 'li' ).addClass( 'wpforms-selected' ); 488 $this.attr( 'checked', 'checked' ); 489 } else { 490 $this.closest( 'li' ).removeClass( 'wpforms-selected' ); 491 $this.removeAttr( 'checked' ); 492 } 493 break; 494 } 495 } ); 496 }, 497 498 /** 499 * Update Pagebreak navigation. 500 * 501 * @since 1.2.2 502 */ 503 pagebreakNav: function(el) { 504 505 var $this = $(el), 506 valid = true, 507 action = $this.data('action'), 508 page = $this.data('page'), 509 page2 = page, 510 next = page+1, 511 prev = page-1, 512 formID = $this.data('formid'), 513 $form = $this.closest('.wpforms-form'), 514 $page = $form.find('.wpforms-page-'+page), 515 $submit = $form.find('.wpforms-submit-container'), 516 $indicator = $form.find('.wpforms-page-indicator'), 517 $reCAPTCHA = $form.find('.wpforms-recaptcha-container'), 518 pageScroll = false;
519 520 // Page scroll 521 // TODO: cleanup this BC with wpform_pageScroll. 522 if ( window.wpforms_pageScroll === false ) { 523 pageScroll = false; 524 } else if ( !WPForms.empty( window.wpform_pageScroll ) ) { 525 pageScroll = window.wpform_pageScroll; 526 } else { 527 pageScroll = 75; 528 } 529 530 // Toggling between pages 531 if ( action === 'next' ){ 532 // Validate 533 if (typeof $.fn.validate !== 'undefined') { 534 $page.find('input.wpforms-field-required, select.wpforms-field-required, textarea.wpforms-field-required, .wpforms-field-required input, .wpforms-field-file-upload input').each(function(index, el) { 535 if ( ! $(el).valid() ) { 536 valid = false; 537 } 538 }); 539 // Scroll to first/top error on page 540 var $topError = $page.find('.wpforms-error').first(); 541 if ($topError.length) { 542 $('html, body').animate({ 543 scrollTop: $topError.offset().top-75 544 }, 750, function() { 545 $topError.focus(); 546 }); 547 } 548 } 549 // Move to next page 550 if (valid) { 551 page2 = next; 552 $page.hide(); 553 var $nextPage = $form.find('.wpforms-page-'+next); 554 $nextPage.show(); 555 if ( $nextPage.hasClass('last') ) { 556 $reCAPTCHA.show(); 557 $submit.show(); 558 } 559 if ( pageScroll ) { 560 // Scroll to top of the form 561 $('html, body').animate({ 562 scrollTop: $form.offset().top-pageScroll 563 }, 1000); 564 } 565 $this.trigger('wpformsPageChange', [ page2, $form ] ); 566 } 567 } else if ( action === 'prev' ) { 568 // Move to prev page 569 page2 = prev; 570 $page.hide(); 571 $form.find('.wpforms-page-'+prev).show(); 572 $reCAPTCHA.hide(); 573 $submit.hide(); 574 if ( pageScroll ) { 575 // Scroll to top of the form 576 $('html, body').animate({ 577 scrollTop: $form.offset().top-pageScroll 578 }, 1000); 579 } 580 $this.trigger('wpformsPageChange', [ page2, $form ] ); 581 } 582 583 if ( $indicator ) { 584 var theme = $indicator.data('indicator'), 585 color = $indicator.data('indicator-color'); 586 if ('connector' === theme || 'circles' === theme) { 587 $indicator.find('.wpforms-page-indicator-page').removeClass('active'); 588 $indicator.find('.wpforms-page-indicator-page-'+page2).addClass('active'); 589 $indicator.find('.wpforms-page-indicator-page-number').removeAttr('style'); 590 $indicator.find('.active .wpforms-page-indicator-page-number').css('background-color', color); 591 if ( 'connector' === theme) { 592 $indicator.find('.wpforms-page-indicator-page-triangle').removeAttr('style'); 593 $indicator.find('.active .wpforms-page-indicator-page-triangle').css('border-top-color', color); 594 } 595 } else if ('progress' === theme) { 596 var $pageTitle = $indicator.find('.wpforms-page-indicator-page-title'), 597 $pageSep = $indicator.find('.wpforms-page-indicator-page-title-sep'), 598 totalPages = $form.find('.wpforms-page').length, 599 width = (page2/totalPages)*100; 600 $indicator.find('.wpforms-page-indicator-page-progress').css('width', width+'%'); 601 $indicator.find('.wpforms-page-indicator-steps-current').text(page2); 602 if ($pageTitle.data('page-'+page2+'-title')) { 603 $pageTitle.css('display','inline').text($pageTitle.data('page-'+page2+'-title')); 604 $pageSep.css('display','inline'); 605 } else { 606 $pageTitle.css('display','none'); 607 $pageSep.css('display','none'); 608 } 609 } 610 } 611 }, 612 613 /** 614 * OptinMonster compatibility. 615 * 616 * Re-initialize after OptinMonster loads to accomodate changes that 617 * have occurred to the DOM. 618 * 619 * @since 1.5.0 620 */ 621 bindOptinMonster: function() { 622 623 // OM v5. 624 document.addEventListener( 'om.Campaign.load', function( event ) { 625 WPForms.ready(); 626 WPForms.optinMonsterRecaptchaReset( event.detail.Campaign.data.id ); 627 } ); 628 629 // OM Legacy. 630 $( document ).on( 'OptinMonsterOnShow', function( event, data, object ) { 631 WPForms.ready(); 632 WPForms.optinMonsterRecaptchaReset( data.optin ); 633 } ); 634 }, 635 636 /** 637 * Reset/recreate reCAPTCHA v2 inside OptinMonster. 638 * 639 * @since 1.5.0 640 */ 641 optinMonsterRecaptchaReset: function ( optinId ) { 642 643 var $form = $( '#om-' + optinId ).find( '.wpforms-form' ), 644 $recaptchaContainer = $form.find( '.wpforms-recaptcha-container' ), 645 $recaptcha = $form.find( '.g-recaptcha' ), 646 recaptchaSiteKey = $recaptcha.attr( 'data-sitekey' ), 647 recaptchaID = 'recaptcha-' + Date.now(); 648 649 if ( $form.length && $recaptcha.length ) { 650 651 $recaptcha.remove(); 652 $recaptchaContainer.prepend( '<div class="g-recaptcha" id="' + recaptchaID + '" data-sitekey="' + recaptchaSiteKey + '"></div>' ); 653 654 grecaptcha.render( 655 recaptchaID, 656 { 657 sitekey: recaptchaSiteKey, 658 callback: function(){ 659 wpformsRecaptchaCallback( $( '#' + recaptchaID ) ); 660 } 661 } 662 ); 663 } 664 }, 665 666 //--------------------------------------------------------------------// 667 // Other functions. 668 //--------------------------------------------------------------------// 669 670 /** 671 * Payments: Calculate total. 672 * 673 * @since 1.2.3
674 * @since 1.5.1 Added support for payment-checkbox field. 675 */ 676 amountTotal: function ( el, validate ) { 677 678 var validate = validate || false, 679 $form = $( el ).closest( '.wpforms-form' ), 680 total = 0, 681 totalFormatted = 0, 682 totalFormattedSymbol = 0, 683 currency = WPForms.getCurrency(); 684 685 $( '.wpforms-payment-price', $form ).each( function ( index, el ) { 686 687 var amount = 0, 688 $this = $( this ); 689 690 if ( $this.attr( 'type' ) === 'text' || $this.attr( 'type' ) === 'hidden' ) { 691 amount = $this.val(); 692 } 693 else if ( ( $this.attr( 'type' ) === 'radio' || $this.attr( 'type' ) === 'checkbox' ) && $this.is( ':checked' ) ) { 694 amount = $this.data( 'amount' ); 695 } 696 else if ( $this.is( 'select' ) && $this.find( 'option:selected' ).length > 0 ) { 697 amount = $this.find( 'option:selected' ).data( 'amount' ); 698 } 699 if ( ! WPForms.empty( amount ) ) { 700 amount = WPForms.amountSanitize( amount ); 701 total = Number( total ) + Number( amount ); 702 } 703 } ); 704 705 totalFormatted = WPForms.amountFormat( total ); 706 707 if ( 'left' === currency.symbol_pos ) { 708 totalFormattedSymbol = currency.symbol + ' ' + totalFormatted; 709 } 710 else { 711 totalFormattedSymbol = totalFormatted + ' ' + currency.symbol; 712 } 713 714 $form.find( '.wpforms-payment-total' ).each( function ( index, el ) { 715 if ( 'hidden' === $( this ).attr( 'type' ) || 'text' === $( this ).attr( 'type' ) ) { 716 $( this ).val( totalFormattedSymbol ); 717 if ( 'text' === $( this ).attr( 'type' ) && validate && $form.data( 'validator' ) ) { 718 $( this ).valid(); 719 } 720 } else { 721 $( this ).text( totalFormattedSymbol ); 722 } 723 } ); 724 }, 725 726 /** 727 * Sanitize amount and convert to standard format for calculations. 728 * 729 * @since 1.2.6 730 */ 731 amountSanitize: function(amount) { 732 733 var currency = WPForms.getCurrency(); 734 735 amount = amount.toString().replace(/[^0-9.,]/g,''); 736 737 if ( currency.decimal_sep === ',' && ( amount.indexOf(currency.decimal_sep) !== -1 ) ) { 738 if ( currency.thousands_sep === '.' && amount.indexOf(currency.thousands_sep) !== -1 ) { 739 amount = amount.replace(currency.thousands_sep,''); 740 } else if( currency.thousands_sep === '' && amount.indexOf('.') !== -1 ) { 741 amount = amount.replace('.',''); 742 } 743 amount = amount.replace(currency.decimal_sep,'.'); 744 } else if ( currency.thousands_sep === ',' && ( amount.indexOf(currency.thousands_sep) !== -1 ) ) { 745 amount = amount.replace(currency.thousands_sep,''); 746 } 747 748 return WPForms.numberFormat( amount, 2, '.', '' ); 749 }, 750 751 /** 752 * Format amount. 753 * 754 * @since 1.2.6 755 */ 756 amountFormat: function(amount) { 757 758 var currency = WPForms.getCurrency(); 759 760 amount = String(amount); 761 762 // Format the amount 763 if ( currency.decimal_sep === ',' && ( amount.indexOf(currency.decimal_sep) !== -1 ) ) { 764 var sepFound = amount.indexOf(currency.decimal_sep), 765 whole = amount.substr(0, sepFound), 766 part = amount.substr(sepFound+1, amount.strlen-1); 767 amount = whole + '.' + part; 768 } 769 770 // Strip , from the amount (if set as the thousands separator) 771 if ( currency.thousands_sep === ',' && ( amount.indexOf(currency.thousands_sep) !== -1 ) ) { 772 amount = amount.replace(',',''); 773 } 774 775 if ( WPForms.empty( amount ) ) { 776 amount = 0; 777 } 778 779 return WPForms.numberFormat( amount, 2, currency.decimal_sep, currency.thousands_sep ); 780 }, 781 782 /** 783 * Get site currency settings. 784 * 785 * @since 1.2.6 786 */ 787 getCurrency: function() { 788 789 var currency = { 790 code: 'USD', 791 thousands_sep: ',', 792 decimal_sep: '.', 793 symbol: '$', 794 symbol_pos: 'left' 795 }; 796 797 // Backwards compatibility. 798 if ( typeof wpforms_settings.currency_code !== 'undefined' ) { 799 currency.code = wpforms_settings.currency_code; 800 } 801 if ( typeof wpforms_settings.currency_thousands !== 'undefined' ) { 802 currency.thousands_sep = wpforms_settings.currency_thousands; 803 } 804 if ( typeof wpforms_settings.currency_decimal !== 'undefined' ) { 805 currency.decimal_sep = wpforms_settings.currency_decimal; 806 } 807 if ( typeof wpforms_settings.currency_symbol !== 'undefined' ) { 808 currency.symbol = wpforms_settings.currency_symbol; 809 } 810 if ( typeof wpforms_settings.currency_symbol_pos !== 'undefined' ) { 811 currency.symbol_pos = wpforms_settings.currency_symbol_pos; 812 } 813 814 return currency; 815 }, 816 817 /** 818 * Format number. 819 * 820 * @link http://locutus.io/php/number_format/ 821 * @since 1.2.6 822 */ 823 numberFormat: function (number, decimals, decimalSep, thousandsSep) { 824 825 number = (number + '').replace(/[^0-9+\-Ee.]/g, ''); 826 var n = !isFinite(+number) ? 0 : +number; 827 var prec = !isFinite(+decimals) ? 0 : Math.abs(decimals); 828 var sep = (typeof thousandsSep === 'undefined') ? ',' : thousandsSep; 829 var dec = (typeof decimalSep === 'undefined') ? '.' : decimalSep; 830 var s; 831 832 var toFixedFix = function (n, prec) { 833 var k = Math.pow(10, prec); 834 return '' + (Math.round(n * k) / k).toFixed(prec) 835 }; 836 837 // @todo: for IE parseFloat(0.55).toFixed(0) = 0; 838 s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.'); 839 if (s[0].length > 3) { 840 s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep) 841 } 842 if ((s[1] || '').length < prec) { 843 s[1] = s[1] || ''; 844 s[1] += new Array(prec - s[1].length + 1).join('0') 845 } 846 847 return s.join(dec) 848 }, 849 850 /** 851 * Empty check similar to PHP. 852 * 853 * @link http://locutus.io/php/empty/ 854 * @since 1.2.6 855 */ 856 empty: function(mixedVar) { 857 858 var undef; 859 var key; 860 var i; 861 var len; 862 var emptyValues = [undef, null, false, 0, '', '0']; 863 864 for (i = 0, len = emptyValues.length; i < len; i++) { 865 if (mixedVar === emptyValues[i]) { 866 return true 867 } 868 } 869 870 if (typeof mixedVar === 'object') { 871 for (key in mixedVar) { 872 if (mixedVar.hasOwnProperty(key)) { 873 return false;
874 } 875 } 876 return true; 877 } 878 879 return false; 880 }, 881 882 /** 883 * Set cookie container user UUID. 884 * 885 * @since 1.3.3 886 */ 887 setUserIndentifier: function() { 888 889 if ( ( ( ! window.hasRequiredConsent && typeof wpforms_settings !== 'undefined' && wpforms_settings.uuid_cookie ) || ( window.hasRequiredConsent && window.hasRequiredConsent() ) ) && ! WPForms.getCookie( '_wpfuuid' ) ) { 890 891 // Generate UUID - http://stackoverflow.com/a/873856/1489528 892 var s = new Array(36), 893 hexDigits = '0123456789abcdef', 894 uuid; 895 896 for (var i = 0; i < 36; i++) { 897 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); 898 } 899 s[14] = "4"; 900 s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); 901 s[8] = s[13] = s[18] = s[23] = '-'; 902 903 uuid = s.join(""); 904 905 WPForms.createCookie('_wpfuuid', uuid, 3999); 906 } 907 }, 908 909 /** 910 * Create cookie. 911 * 912 * @since 1.3.3 913 */ 914 createCookie: function(name, value, days) { 915 916 var expires = ''; 917 918 // If we have a days value, set it in the expiry of the cookie. 919 if ( days ) { 920 // If -1 is our value, set a session based cookie instead of a persistent cookie. 921 if ( '-1' === days ) { 922 expires = ''; 923 } else { 924 var date = new Date(); 925 date.setTime(date.getTime() + (days*24*60*60*1000)); 926 expires = '; expires=' + date.toGMTString(); 927 } 928 } else { 929 expires = '; expires=Thu, 01 Jan 1970 00:00:01 GMT'; 930 } 931 932 // Write the cookie. 933 document.cookie = name + '=' + value + expires + '; path=/'; 934 }, 935 936 /** 937 * Retrieve cookie. 938 * 939 * @since 1.3.3 940 */ 941 getCookie: function(name) { 942 943 var nameEQ = name + '=', 944 ca = document.cookie.split(';'); 945 946 for ( var i = 0; i < ca.length; i++ ) { 947 var c = ca[i]; 948 while ( c.charAt(0) === ' ' ) { 949 c = c.substring(1, c.length); 950 } 951 if ( c.indexOf(nameEQ) == 0 ) { 952 return c.substring(nameEQ.length, c.length); 953 } 954 } 955 956 return null; 957 }, 958 959 /** 960 * Delete cookie. 961 */ 962 removeCookie: function(name) { 963 964 WPForms.createCookie(name, '',-1); 965 } 966 }; 967 968 // Initialize. 969 WPForms.init(); 970 971 // Add to global scope. 972 window.wpforms = WPForms; 973 974})(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.