components
7 years ago
admin-builder-conditional-logic-core.js
7 years ago
admin-builder-providers.js
6 years ago
admin-builder.js
6 years ago
admin-editor.js
9 years ago
admin-utils.js
7 years ago
admin.js
6 years ago
admin.min.js
6 years ago
chart.min.js
7 years ago
choices.min.js
8 years ago
flatpickr.min.js
7 years ago
jquery.conditionals.min.js
8 years ago
jquery.inputmask.bundle.min.js
7 years ago
jquery.insert-at-caret.min.js
10 years ago
jquery.jquery-confirm.min.js
8 years ago
jquery.matchHeight-min.js
8 years ago
jquery.minicolors.min.js
8 years ago
jquery.payment.min.js
10 years ago
jquery.serialize-object.min.js
10 years ago
jquery.timepicker.min.js
9 years ago
jquery.tooltipster.min.js
7 years ago
jquery.validate.js
6 years ago
jquery.validate.min.js
7 years ago
list.min.js
8 years ago
mailcheck.min.js
7 years ago
moment-with-locales.min.js
7 years ago
moment.min.js
7 years ago
wpforms-confirmation.js
7 years ago
wpforms.js
6 years ago
wpforms.js
1629 lines
| 1 | /* global wpforms_settings, grecaptcha, wpformsRecaptchaCallback, wpforms_validate, wpforms_datepicker, wpforms_timepicker, Mailcheck */ |
| 2 | |
| 3 | 'use strict'; |
| 4 | |
| 5 | var wpforms = window.wpforms || ( function( document, window, $ ) { |
| 6 | |
| 7 | var app = { |
| 8 | |
| 9 | /** |
| 10 | * Start the engine. |
| 11 | * |
| 12 | * @since 1.2.3 |
| 13 | */ |
| 14 | init: function() { |
| 15 | |
| 16 | // Document ready. |
| 17 | $( document ).ready( app.ready ); |
| 18 | |
| 19 | // Page load. |
| 20 | $( window ).on( 'load', app.load ); |
| 21 | |
| 22 | app.bindUIActions(); |
| 23 | app.bindOptinMonster(); |
| 24 | }, |
| 25 | |
| 26 | /** |
| 27 | * Document ready. |
| 28 | * |
| 29 | * @since 1.2.3 |
| 30 | */ |
| 31 | ready: function() { |
| 32 | |
| 33 | // Clear URL - remove wpforms_form_id. |
| 34 | app.clearUrlQuery(); |
| 35 | |
| 36 | // Set user identifier. |
| 37 | app.setUserIndentifier(); |
| 38 | |
| 39 | app.loadValidation(); |
| 40 | app.loadDatePicker(); |
| 41 | app.loadTimePicker(); |
| 42 | app.loadInputMask(); |
| 43 | app.loadSmartPhoneField(); |
| 44 | app.loadPayments(); |
| 45 | app.loadMailcheck(); |
| 46 | |
| 47 | // Randomize elements. |
| 48 | $( '.wpforms-randomize' ).each( function() { |
| 49 | var $list = $( this ), |
| 50 | $listItems = $list.children(); |
| 51 | while ( $listItems.length ) { |
| 52 | $list.append( $listItems.splice( Math.floor( Math.random() * $listItems.length ), 1 )[0] ); |
| 53 | } |
| 54 | } ); |
| 55 | |
| 56 | $( document ).trigger( 'wpformsReady' ); |
| 57 | }, |
| 58 | |
| 59 | /** |
| 60 | * Page load. |
| 61 | * |
| 62 | * @since 1.2.3 |
| 63 | */ |
| 64 | load: function() { |
| 65 | |
| 66 | }, |
| 67 | |
| 68 | //--------------------------------------------------------------------// |
| 69 | // Initializing |
| 70 | //--------------------------------------------------------------------// |
| 71 | |
| 72 | /** |
| 73 | * Remove wpforms_form_id from URL. |
| 74 | * |
| 75 | * @since 1.5.2 |
| 76 | */ |
| 77 | clearUrlQuery: function() { |
| 78 | var loc = window.location, |
| 79 | query = loc.search; |
| 80 | |
| 81 | if ( query.indexOf( 'wpforms_form_id=' ) !== -1 ) { |
| 82 | query = query.replace( /([&?]wpforms_form_id=[0-9]*$|wpforms_form_id=[0-9]*&|[?&]wpforms_form_id=[0-9]*(?=#))/, '' ); |
| 83 | history.replaceState( {}, null, loc.origin + loc.pathname + query ); |
| 84 | } |
| 85 | }, |
| 86 | |
| 87 | |
| 88 | /** |
| 89 | * Load jQuery Validation. |
| 90 | * |
| 91 | * @since 1.2.3 |
| 92 | */ |
| 93 | loadValidation: function() { |
| 94 | |
| 95 | // Only load if jQuery validation library exists. |
| 96 | if ( typeof $.fn.validate !== 'undefined' ) { |
| 97 | |
| 98 | // jQuery Validation library will not correctly validate |
| 99 | // fields that do not have a name attribute, so we use the |
| 100 | // `wpforms-input-temp-name` class to add a temporary name |
| 101 | // attribute before validation is initialized, then remove it |
| 102 | // before the form submits. |
| 103 | $( '.wpforms-input-temp-name' ).each( function( index, el ) { |
| 104 | var random = Math.floor( Math.random() * 9999 ) + 1; |
| 105 | $( this ).attr( 'name', 'wpf-temp-' + random ); |
| 106 | } ); |
| 107 | |
| 108 | // Prepend URL field contents with http:// if user input doesn't contain a schema. |
| 109 | $( '.wpforms-validate input[type=url]' ).change( function() { |
| 110 | var url = $( this ).val(); |
| 111 | if ( ! url ) { |
| 112 | return false; |
| 113 | } |
| 114 | if ( url.substr( 0, 7 ) !== 'http://' && url.substr( 0, 8 ) !== 'https://' ) { |
| 115 | $( this ).val( 'http://' + url ); |
| 116 | } |
| 117 | } ); |
| 118 | |
| 119 | $.validator.messages.required = wpforms_settings.val_required; |
| 120 | $.validator.messages.url = wpforms_settings.val_url; |
| 121 | $.validator.messages.email = wpforms_settings.val_email; |
| 122 | $.validator.messages.number = wpforms_settings.val_number; |
| 123 | |
| 124 | // Payments: Validate method for Credit Card Number. |
| 125 | if ( typeof $.fn.payment !== 'undefined' ) { |
| 126 | $.validator.addMethod( 'creditcard', function( value, element ) { |
| 127 | |
| 128 | //var type = $.payment.cardType(value); |
| 129 | var valid = $.payment.validateCardNumber( value ); |
| 130 | return this.optional( element ) || valid; |
| 131 | }, wpforms_settings.val_creditcard ); |
| 132 | |
| 133 | // @todo validate CVC and expiration |
| 134 | } |
| 135 | |
| 136 | // Validate method for file extensions. |
| 137 | $.validator.addMethod( 'extension', function( value, element, param ) { |
| 138 | param = 'string' === typeof param ? param.replace( /,/g, '|' ) : 'png|jpe?g|gif'; |
| 139 | return this.optional( element ) || value.match( new RegExp( '\\.(' + param + ')$', 'i' ) ); |
| 140 | }, wpforms_settings.val_fileextension ); |
| 141 | |
| 142 | // Validate method for file size. |
| 143 | $.validator.addMethod( 'maxsize', function( value, element, param ) { |
| 144 | var maxSize = param, |
| 145 | optionalValue = this.optional( element ), |
| 146 | i, len, file; |
| 147 | if ( optionalValue ) { |
| 148 | return optionalValue; |
| 149 | } |
| 150 | if ( element.files && element.files.length ) { |
| 151 | i = 0; |
| 152 | len = element.files.length; |
| 153 | for ( ; i < len; i++ ) { |
| 154 | file = element.files[i]; |
| 155 | if ( file.size > maxSize ) { |
| 156 | return false; |
| 157 | } |
| 158 | } |
| 159 | } |
| 160 | return true; |
| 161 | }, wpforms_settings.val_filesize ); |
| 162 | |
| 163 | // Validate email addresses. |
| 164 | $.validator.methods.email = function( value, element ) { |
| 165 | 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 ); |
| 166 | }; |
| 167 | |
| 168 | // Validate confirmations. |
| 169 | $.validator.addMethod( 'confirm', function( value, element, param ) { |
| 170 | return $.validator.methods.equalTo.call( this, value, element, param ); |
| 171 | }, wpforms_settings.val_confirm ); |
| 172 | |
| 173 | // Validate required payments. |
| 174 | $.validator.addMethod( 'required-payment', function( value, element ) { |
| 175 | return app.amountSanitize( value ) > 0; |
| 176 | }, wpforms_settings.val_requiredpayment ); |
| 177 | |
| 178 | // Validate 12-hour time. |
| 179 | $.validator.addMethod( 'time12h', function( value, element ) { |
| 180 | return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value ); |
| 181 | }, wpforms_settings.val_time12h ); |
| 182 | |
| 183 | // Validate 24-hour time. |
| 184 | $.validator.addMethod( 'time24h', function( value, element ) { |
| 185 | return this.optional( element ) || /^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(\ ?[AP]M)?$/i.test( value ); |
| 186 | }, wpforms_settings.val_time24h ); |
| 187 | |
| 188 | // Validate checkbox choice limit. |
| 189 | $.validator.addMethod( 'check-limit', function( value, element ) { |
| 190 | var $ul = $( element ).closest( 'ul' ), |
| 191 | $checked = $ul.find( 'input[type="checkbox"]:checked' ), |
| 192 | choiceLimit = parseInt( $ul.attr( 'data-choice-limit' ) || 0, 10 ); |
| 193 | |
| 194 | if ( 0 === choiceLimit ) { |
| 195 | return true; |
| 196 | } |
| 197 | return $checked.length <= choiceLimit; |
| 198 | }, function( params, element ) { |
| 199 | var choiceLimit = parseInt( $( element ).closest( 'ul' ).attr( 'data-choice-limit' ) || 0, 10 ); |
| 200 | return wpforms_settings.val_checklimit.replace( '{#}', choiceLimit ); |
| 201 | } ); |
| 202 | |
| 203 | // Validate Smart Phone Field. |
| 204 | if ( typeof $.fn.intlTelInput !== 'undefined' ) { |
| 205 | $.validator.addMethod( 'smart-phone-field', function( value, element ) { |
| 206 | return this.optional( element ) || $( element ).intlTelInput( 'isValidNumber' ); |
| 207 | }, wpforms_settings.val_smart_phone ); |
| 208 | } |
| 209 | |
| 210 | // Finally load jQuery Validation library for our forms. |
| 211 | $( '.wpforms-validate' ).each( function() { |
| 212 | var form = $( this ), |
| 213 | formID = form.data( 'formid' ), |
| 214 | properties; |
| 215 | |
| 216 | // TODO: cleanup this BC with wpforms_validate. |
| 217 | if ( typeof window['wpforms_' + formID] !== 'undefined' && window['wpforms_' + formID].hasOwnProperty( 'validate' ) ) { |
| 218 | properties = window['wpforms_' + formID].validate; |
| 219 | } else if ( typeof wpforms_validate !== 'undefined' ) { |
| 220 | properties = wpforms_validate; |
| 221 | } else { |
| 222 | properties = { |
| 223 | errorClass: 'wpforms-error', |
| 224 | validClass: 'wpforms-valid', |
| 225 | errorPlacement: function( error, element ) { |
| 226 | if ( 'radio' === element.attr( 'type' ) || 'checkbox' === element.attr( 'type' ) ) { |
| 227 | if ( element.hasClass( 'wpforms-likert-scale-option' ) ) { |
| 228 | if ( element.closest( 'table' ).hasClass( 'single-row' ) ) { |
| 229 | element.closest( 'table' ).after( error ); |
| 230 | } else { |
| 231 | element.closest( 'tr' ).find( 'th' ).append( error ); |
| 232 | } |
| 233 | } else if ( element.hasClass( 'wpforms-net-promoter-score-option' ) ) { |
| 234 | element.closest( 'table' ).after( error ); |
| 235 | } else { |
| 236 | element.closest( '.wpforms-field-checkbox' ).find( 'label.wpforms-error' ).remove(); |
| 237 | element.parent().parent().parent().append( error ); |
| 238 | } |
| 239 | } else if ( element.is( 'select' ) && element.attr( 'class' ).match( /date-month|date-day|date-year/ ) ) { |
| 240 | if ( 0 === element.parent().find( 'label.wpforms-error:visible' ).length ) { |
| 241 | element.parent().find( 'select:last' ).after( error ); |
| 242 | } |
| 243 | } else if ( element.hasClass( 'wpforms-smart-phone-field' ) ) { |
| 244 | element.parent().after( error ); |
| 245 | } else { |
| 246 | error.insertAfter( element ); |
| 247 | } |
| 248 | }, |
| 249 | highlight: function( element, errorClass, validClass ) { |
| 250 | var $element = $( element ), |
| 251 | $field = $element.closest( '.wpforms-field' ), |
| 252 | inputName = $element.attr( 'name' ); |
| 253 | if ( 'radio' === $element.attr( 'type' ) || 'checkbox' === $element.attr( 'type' ) ) { |
| 254 | $field.find( 'input[name=\'' + inputName + '\']' ).addClass( errorClass ).removeClass( validClass ); |
| 255 | } else { |
| 256 | $element.addClass( errorClass ).removeClass( validClass ); |
| 257 | } |
| 258 | $field.addClass( 'wpforms-has-error' ); |
| 259 | }, |
| 260 | unhighlight: function( element, errorClass, validClass ) { |
| 261 | var $element = $( element ), |
| 262 | $field = $element.closest( '.wpforms-field' ), |
| 263 | inputName = $element.attr( 'name' ); |
| 264 | if ( 'radio' === $element.attr( 'type' ) || 'checkbox' === $element.attr( 'type' ) ) { |
| 265 | $field.find( 'input[name=\'' + inputName + '\']' ).addClass( validClass ).removeClass( errorClass ); |
| 266 | } else { |
| 267 | $element.addClass( validClass ).removeClass( errorClass ); |
| 268 | } |
| 269 | $field.removeClass( 'wpforms-has-error' ); |
| 270 | }, |
| 271 | submitHandler: function( form ) { |
| 272 | |
| 273 | var $form = $( form ), |
| 274 | $submit = $form.find( '.wpforms-submit' ), |
| 275 | altText = $submit.data( 'alt-text' ), |
| 276 | recaptchaID = $submit.get( 0 ).recaptchaID; |
| 277 | |
| 278 | if ( ! app.empty( recaptchaID ) || recaptchaID === 0 ) { |
| 279 | |
| 280 | // Form contains invisible reCAPTCHA. |
| 281 | grecaptcha.execute( recaptchaID ); |
| 282 | return false; |
| 283 | } |
| 284 | |
| 285 | // Normal form. |
| 286 | if ( altText ) { |
| 287 | $submit.text( altText ); |
| 288 | } |
| 289 | |
| 290 | $submit.prop( 'disabled', true ); |
| 291 | |
| 292 | // Remove name attributes if needed. |
| 293 | $( '.wpforms-input-temp-name' ).removeAttr( 'name' ); |
| 294 | |
| 295 | app.formSubmit( $form ); |
| 296 | }, |
| 297 | onkeyup: function( element, event ) { |
| 298 | |
| 299 | // This code is copied from JQuery Validate 'onkeyup' method with only one change: 'wpforms-novalidate-onkeyup' class check. |
| 300 | var excludedKeys = [ 16, 17, 18, 20, 35, 36, 37, 38, 39, 40, 45, 144, 225 ]; |
| 301 | |
| 302 | if ( $( element ).hasClass( 'wpforms-novalidate-onkeyup' ) ) { |
| 303 | return; // Disable onkeyup validation for some elements (e.g. remote calls). |
| 304 | } |
| 305 | |
| 306 | if ( 9 === event.which && '' === this.elementValue( element ) || $.inArray( event.keyCode, excludedKeys ) !== -1 ) { |
| 307 | return; |
| 308 | } else if ( element.name in this.submitted || element.name in this.invalid ) { |
| 309 | this.element( element ); |
| 310 | } |
| 311 | }, |
| 312 | onfocusout: function( element ) { |
| 313 | |
| 314 | // This code is copied from JQuery Validate 'onfocusout' method with only one change: 'wpforms-novalidate-onkeyup' class check. |
| 315 | var validate = false; |
| 316 | |
| 317 | if ( $( element ).hasClass( 'wpforms-novalidate-onkeyup' ) && ! element.value ) { |
| 318 | validate = true; // Empty value error handling for elements with onkeyup validation disabled. |
| 319 | } |
| 320 | |
| 321 | if ( ! this.checkable( element ) && ( element.name in this.submitted || ! this.optional( element ) ) ) { |
| 322 | validate = true; |
| 323 | } |
| 324 | |
| 325 | if ( validate ) { |
| 326 | this.element( element ); |
| 327 | } |
| 328 | }, |
| 329 | onclick: function( element ) { |
| 330 | var validate = false; |
| 331 | |
| 332 | if ( 'checkbox' === ( element || {} ).type ) { |
| 333 | $( element ).closest( '.wpforms-field-checkbox' ).find( 'label.wpforms-error' ).remove(); |
| 334 | validate = true; |
| 335 | } |
| 336 | |
| 337 | if ( validate ) { |
| 338 | this.element( element ); |
| 339 | } |
| 340 | }, |
| 341 | }; |
| 342 | } |
| 343 | form.validate( properties ); |
| 344 | } ); |
| 345 | } |
| 346 | }, |
| 347 | |
| 348 | /** |
| 349 | * Load jQuery Date Picker. |
| 350 | * |
| 351 | * @since 1.2.3 |
| 352 | */ |
| 353 | loadDatePicker: function() { |
| 354 | |
| 355 | // Only load if jQuery datepicker library exists. |
| 356 | if ( typeof $.fn.flatpickr !== 'undefined' ) { |
| 357 | $( '.wpforms-datepicker' ).each( function() { |
| 358 | var element = $( this ), |
| 359 | form = element.closest( '.wpforms-form' ), |
| 360 | formID = form.data( 'formid' ), |
| 361 | fieldID = element.closest( '.wpforms-field' ).data( 'field-id' ), |
| 362 | properties; |
| 363 | |
| 364 | if ( typeof window['wpforms_' + formID + '_' + fieldID] !== 'undefined' && window['wpforms_' + formID + '_' + fieldID].hasOwnProperty( 'datepicker' ) ) { |
| 365 | properties = window['wpforms_' + formID + '_' + fieldID].datepicker; |
| 366 | } else if ( typeof window['wpforms_' + formID] !== 'undefined' && window['wpforms_' + formID].hasOwnProperty( 'datepicker' ) ) { |
| 367 | properties = window['wpforms_' + formID].datepicker; |
| 368 | } else if ( typeof wpforms_datepicker !== 'undefined' ) { |
| 369 | properties = wpforms_datepicker; |
| 370 | } else { |
| 371 | properties = { |
| 372 | disableMobile: true, |
| 373 | }; |
| 374 | } |
| 375 | |
| 376 | // Redefine locale only if user doesn't do that manually and we have the locale. |
| 377 | if ( |
| 378 | ! properties.hasOwnProperty( 'locale' ) && |
| 379 | typeof wpforms_settings !== 'undefined' && |
| 380 | wpforms_settings.hasOwnProperty( 'locale' ) |
| 381 | ) { |
| 382 | properties.locale = wpforms_settings.locale; |
| 383 | } |
| 384 | |
| 385 | element.flatpickr( properties ); |
| 386 | } ); |
| 387 | } |
| 388 | }, |
| 389 | |
| 390 | /** |
| 391 | * Load jQuery Time Picker. |
| 392 | * |
| 393 | * @since 1.2.3 |
| 394 | */ |
| 395 | loadTimePicker: function() { |
| 396 | |
| 397 | // Only load if jQuery timepicker library exists. |
| 398 | if ( typeof $.fn.timepicker !== 'undefined' ) { |
| 399 | $( '.wpforms-timepicker' ).each( function() { |
| 400 | var element = $( this ), |
| 401 | form = element.closest( '.wpforms-form' ), |
| 402 | formID = form.data( 'formid' ), |
| 403 | fieldID = element.closest( '.wpforms-field' ).data( 'field-id' ), |
| 404 | properties; |
| 405 | |
| 406 | if ( |
| 407 | typeof window['wpforms_' + formID + '_' + fieldID] !== 'undefined' && |
| 408 | window['wpforms_' + formID + '_' + fieldID].hasOwnProperty( 'timepicker' ) |
| 409 | ) { |
| 410 | properties = window['wpforms_' + formID + '_' + fieldID].timepicker; |
| 411 | } else if ( |
| 412 | typeof window['wpforms_' + formID] !== 'undefined' && |
| 413 | window['wpforms_' + formID].hasOwnProperty( 'timepicker' ) |
| 414 | ) { |
| 415 | properties = window['wpforms_' + formID].timepicker; |
| 416 | } else if ( typeof wpforms_timepicker !== 'undefined' ) { |
| 417 | properties = wpforms_timepicker; |
| 418 | } else { |
| 419 | properties = { |
| 420 | scrollDefault: 'now', |
| 421 | forceRoundTime: true, |
| 422 | }; |
| 423 | } |
| 424 | |
| 425 | element.timepicker( properties ); |
| 426 | } ); |
| 427 | } |
| 428 | }, |
| 429 | |
| 430 | /** |
| 431 | * Load jQuery input masks. |
| 432 | * |
| 433 | * @since 1.2.3 |
| 434 | */ |
| 435 | loadInputMask: function() { |
| 436 | |
| 437 | // Only load if jQuery input mask library exists. |
| 438 | if ( typeof $.fn.inputmask !== 'undefined' ) { |
| 439 | $( '.wpforms-masked-input' ).inputmask(); |
| 440 | } |
| 441 | }, |
| 442 | |
| 443 | /** |
| 444 | * Load smart phone field. |
| 445 | * |
| 446 | * @since 1.5.2 |
| 447 | */ |
| 448 | loadSmartPhoneField: function() { |
| 449 | |
| 450 | // Only load if library exists. |
| 451 | if ( typeof $.fn.intlTelInput === 'undefined' ) { |
| 452 | return; |
| 453 | } |
| 454 | |
| 455 | var inputOptions = {}; |
| 456 | |
| 457 | // Determine the country by IP if no GDPR restrictions enabled. |
| 458 | if ( ! wpforms_settings.gdpr ) { |
| 459 | inputOptions.geoIpLookup = app.currentIpToCountry; |
| 460 | } |
| 461 | |
| 462 | // Try to kick in an alternative solution if GDPR restrictions are enabled. |
| 463 | if ( wpforms_settings.gdpr ) { |
| 464 | var lang = this.getFirstBrowserLanguage(), |
| 465 | countryCode = lang.indexOf( '-' ) > -1 ? lang.split( '-' ).pop() : ''; |
| 466 | } |
| 467 | |
| 468 | // Make sure the library recognizes browser country code to avoid console error. |
| 469 | if ( countryCode ) { |
| 470 | var countryData = window.intlTelInputGlobals.getCountryData(); |
| 471 | |
| 472 | countryData = countryData.filter( function( country ) { |
| 473 | return country.iso2 === countryCode.toLowerCase(); |
| 474 | } ); |
| 475 | countryCode = countryData.length ? countryCode : ''; |
| 476 | } |
| 477 | |
| 478 | // Set default country. |
| 479 | inputOptions.initialCountry = wpforms_settings.gdpr && countryCode ? countryCode : 'auto'; |
| 480 | |
| 481 | $( '.wpforms-smart-phone-field' ).each( function( i, el ) { |
| 482 | |
| 483 | var $el = $( el ); |
| 484 | |
| 485 | // Hidden input allows to include country code into submitted data. |
| 486 | inputOptions.hiddenInput = $el.closest( '.wpforms-field-phone' ).data( 'field-id' ); |
| 487 | inputOptions.utilsScript = wpforms_settings.wpforms_plugin_url + 'pro/assets/js/vendor/jquery.intl-tel-input-utils.js'; |
| 488 | |
| 489 | $el.intlTelInput( inputOptions ); |
| 490 | |
| 491 | // Remove original input name not to interfere with a hidden input. |
| 492 | $el.removeAttr( 'name' ); |
| 493 | |
| 494 | $el.blur( function() { |
| 495 | if ( $el.intlTelInput( 'isValidNumber' ) ) { |
| 496 | $el.siblings( 'input[type="hidden"]' ).val( $el.intlTelInput( 'getNumber' ) ); |
| 497 | } |
| 498 | } ); |
| 499 | } ); |
| 500 | }, |
| 501 | |
| 502 | /** |
| 503 | * Payments: Do various payment-related tasks on load. |
| 504 | * |
| 505 | * @since 1.2.6 |
| 506 | */ |
| 507 | loadPayments: function() { |
| 508 | |
| 509 | // Update Total field(s) with latest calculation. |
| 510 | $( '.wpforms-payment-total' ).each( function( index, el ) { |
| 511 | app.amountTotal( this ); |
| 512 | } ); |
| 513 | |
| 514 | // Credit card validation. |
| 515 | if ( typeof $.fn.payment !== 'undefined' ) { |
| 516 | $( '.wpforms-field-credit-card-cardnumber' ).payment( 'formatCardNumber' ); |
| 517 | $( '.wpforms-field-credit-card-cardcvc' ).payment( 'formatCardCVC' ); |
| 518 | } |
| 519 | }, |
| 520 | |
| 521 | /** |
| 522 | * Load mailcheck. |
| 523 | * |
| 524 | * @since 1.5.3 |
| 525 | */ |
| 526 | loadMailcheck: function() { |
| 527 | |
| 528 | // Skip loading if `wpforms_mailcheck_enabled` filter return false. |
| 529 | if ( ! wpforms_settings.mailcheck_enabled ) { |
| 530 | return; |
| 531 | } |
| 532 | |
| 533 | // Only load if library exists. |
| 534 | if ( typeof $.fn.mailcheck === 'undefined' ) { |
| 535 | return; |
| 536 | } |
| 537 | |
| 538 | if ( wpforms_settings.mailcheck_domains.length > 0 ) { |
| 539 | Mailcheck.defaultDomains = Mailcheck.defaultDomains.concat( wpforms_settings.mailcheck_domains ); |
| 540 | } |
| 541 | if ( wpforms_settings.mailcheck_toplevel_domains.length > 0 ) { |
| 542 | Mailcheck.defaultTopLevelDomains = Mailcheck.defaultTopLevelDomains.concat( wpforms_settings.mailcheck_toplevel_domains ); |
| 543 | } |
| 544 | |
| 545 | // Mailcheck suggestion. |
| 546 | $( document ).on( 'blur', '.wpforms-field-email input', function() { |
| 547 | var $t = $( this ), |
| 548 | id = $t.attr( 'id' ); |
| 549 | |
| 550 | $t.mailcheck( { |
| 551 | suggested: function( el, suggestion ) { |
| 552 | $( '#' + id + '_suggestion' ).remove(); |
| 553 | var sugg = '<a href="#" class="mailcheck-suggestion" data-id="' + id + '" title="' + wpforms_settings.val_email_suggestion_title + '">' + suggestion.full + '</a>'; |
| 554 | sugg = wpforms_settings.val_email_suggestion.replace( '{suggestion}', sugg ); |
| 555 | $( el ).after( '<label class="wpforms-error mailcheck-error" id="' + id + '_suggestion">' + sugg + '</label>' ); |
| 556 | }, |
| 557 | empty: function() { |
| 558 | $( '#' + id + '_suggestion' ).remove(); |
| 559 | }, |
| 560 | } ); |
| 561 | } ); |
| 562 | |
| 563 | // Apply Mailcheck suggestion. |
| 564 | $( document ).on( 'click', '.wpforms-field-email .mailcheck-suggestion', function( e ) { |
| 565 | var $t = $( this ), |
| 566 | id = $t.attr( 'data-id' ); |
| 567 | e.preventDefault(); |
| 568 | $( '#' + id ).val( $t.text() ); |
| 569 | $t.parent().remove(); |
| 570 | } ); |
| 571 | |
| 572 | }, |
| 573 | |
| 574 | //--------------------------------------------------------------------// |
| 575 | // Binds. |
| 576 | //--------------------------------------------------------------------// |
| 577 | |
| 578 | /** |
| 579 | * Element bindings. |
| 580 | * |
| 581 | * @since 1.2.3 |
| 582 | */ |
| 583 | bindUIActions: function() { |
| 584 | |
| 585 | // Pagebreak navigation. |
| 586 | $( document ).on( 'click', '.wpforms-page-button', function( event ) { |
| 587 | event.preventDefault(); |
| 588 | app.pagebreakNav( $( this ) ); |
| 589 | } ); |
| 590 | |
| 591 | // Payments: Update Total field(s) when latest calculation. |
| 592 | $( document ).on( 'change input', '.wpforms-payment-price', function() { |
| 593 | app.amountTotal( this, true ); |
| 594 | } ); |
| 595 | |
| 596 | // Payments: Restrict user input payment fields. |
| 597 | $( document ).on( 'input', '.wpforms-payment-user-input', function() { |
| 598 | var $this = $( this ), |
| 599 | amount = $this.val(); |
| 600 | $this.val( amount.replace( /[^0-9.,]/g, '' ) ); |
| 601 | } ); |
| 602 | |
| 603 | // Payments: Sanitize/format user input amounts. |
| 604 | $( document ).on( 'focusout', '.wpforms-payment-user-input', function() { |
| 605 | var $this = $( this ), |
| 606 | amount = $this.val(), |
| 607 | sanitized = app.amountSanitize( amount ), |
| 608 | formatted = app.amountFormat( sanitized ); |
| 609 | $this.val( formatted ); |
| 610 | } ); |
| 611 | |
| 612 | // Payments: Update Total field(s) when conditials are processed. |
| 613 | $( document ).on( 'wpformsProcessConditionals', function( e, el ) { |
| 614 | app.amountTotal( el, true ); |
| 615 | } ); |
| 616 | |
| 617 | // Payment radio/checkbox fields: preselect the selected payment (from dynamic/fallback population). |
| 618 | $( document ).ready( function() { |
| 619 | |
| 620 | // Radios. |
| 621 | $( '.wpforms-field-radio .wpforms-image-choices-item input:checked' ).change(); |
| 622 | $( '.wpforms-field-payment-multiple .wpforms-image-choices-item input:checked' ).change(); |
| 623 | |
| 624 | // Checkboxes. |
| 625 | $( '.wpforms-field-checkbox .wpforms-image-choices-item input' ).change(); |
| 626 | $( '.wpforms-field-payment-checkbox .wpforms-image-choices-item input' ).change(); |
| 627 | } ); |
| 628 | |
| 629 | // Rating field: hover effect. |
| 630 | $( '.wpforms-field-rating-item' ).hover( |
| 631 | function() { |
| 632 | $( this ).parent().find( '.wpforms-field-rating-item' ).removeClass( 'selected hover' ); |
| 633 | $( this ).prevAll().andSelf().addClass( 'hover' ); |
| 634 | }, |
| 635 | function() { |
| 636 | $( this ).parent().find( '.wpforms-field-rating-item' ).removeClass( 'selected hover' ); |
| 637 | $( this ).parent().find( 'input:checked' ).parent().prevAll().andSelf().addClass( 'selected' ); |
| 638 | } |
| 639 | ); |
| 640 | |
| 641 | // Rating field: toggle selected state. |
| 642 | $( document ).on( 'change', '.wpforms-field-rating-item input', function() { |
| 643 | |
| 644 | var $this = $( this ), |
| 645 | $wrap = $this.closest( '.wpforms-field-rating-items' ), |
| 646 | $items = $wrap.find( '.wpforms-field-rating-item' ); |
| 647 | |
| 648 | $items.removeClass( 'hover selected' ); |
| 649 | $this.parent().prevAll().andSelf().addClass( 'selected' ); |
| 650 | } ); |
| 651 | |
| 652 | // Rating field: preselect the selected rating (from dynamic/fallback population). |
| 653 | $( document ).ready( function() { |
| 654 | $( '.wpforms-field-rating-item input:checked' ).change(); |
| 655 | } ); |
| 656 | |
| 657 | // Checkbox/Radio/Payment checkbox: make labels keyboard-accessible. |
| 658 | $( document ).on( 'keypress', '.wpforms-image-choices-item label', function( event ) { |
| 659 | var $this = $( this ), |
| 660 | $field = $this.closest( '.wpforms-field' ); |
| 661 | |
| 662 | if ( $field.hasClass( 'wpforms-conditional-hide' ) ) { |
| 663 | event.preventDefault(); |
| 664 | return false; |
| 665 | } |
| 666 | |
| 667 | // Cause the input to be clicked when clicking the label. |
| 668 | if ( 13 === event.which ) { |
| 669 | $( '#' + $this.attr( 'for' ) ).click(); |
| 670 | } |
| 671 | } ); |
| 672 | |
| 673 | $( document ).on( 'change', '.wpforms-field-checkbox input, .wpforms-field-radio input, .wpforms-field-payment-multiple input, .wpforms-field-payment-checkbox input, .wpforms-field-gdpr-checkbox input', function( event ) { |
| 674 | |
| 675 | var $this = $( this ), |
| 676 | $field = $this.closest( '.wpforms-field' ); |
| 677 | |
| 678 | if ( $field.hasClass( 'wpforms-conditional-hide' ) ) { |
| 679 | event.preventDefault(); |
| 680 | return false; |
| 681 | } |
| 682 | |
| 683 | switch ( $this.attr( 'type' ) ) { |
| 684 | case 'radio': |
| 685 | $this.closest( 'ul' ).find( 'li' ).removeClass( 'wpforms-selected' ).find( 'input[type=radio]' ).removeProp( 'checked' ); |
| 686 | $this |
| 687 | .prop( 'checked', true ) |
| 688 | .closest( 'li' ).addClass( 'wpforms-selected' ); |
| 689 | break; |
| 690 | |
| 691 | case 'checkbox': |
| 692 | if ( $this.is( ':checked' ) ) { |
| 693 | $this.closest( 'li' ).addClass( 'wpforms-selected' ); |
| 694 | $this.prop( 'checked', true ); |
| 695 | } else { |
| 696 | $this.closest( 'li' ).removeClass( 'wpforms-selected' ); |
| 697 | $this.prop( 'checked', false ); |
| 698 | } |
| 699 | break; |
| 700 | } |
| 701 | } ); |
| 702 | |
| 703 | // Upload fields: Check combined file size. |
| 704 | $( document ).on( 'change', '.wpforms-field-file-upload input', function() { |
| 705 | var $this = $( this ), |
| 706 | $uploads = $this.closest( 'form.wpforms-form' ).find( '.wpforms-field-file-upload input' ), |
| 707 | totalSize = 0, |
| 708 | postMaxSize = Number( wpforms_settings.post_max_size ), |
| 709 | errorMsg = '<div class="wpforms-error-container-post_max_size">' + wpforms_settings.val_post_max_size + '</div>', |
| 710 | errorCntTpl = '<div class="wpforms-error-container">{errorMsg}</span></div>', |
| 711 | $submitCnt = $this.closest( 'form.wpforms-form' ).find( '.wpforms-submit-container' ), |
| 712 | $submitBtn = $submitCnt.find( 'button.wpforms-submit' ), |
| 713 | $errorCnt = $submitCnt.prev(); |
| 714 | |
| 715 | // Calculating totalSize. |
| 716 | $uploads.each( function() { |
| 717 | var $upload = $( this ), |
| 718 | i = 0, |
| 719 | len = $upload[0].files.length; |
| 720 | for ( ; i < len; i++ ) { |
| 721 | totalSize += $upload[0].files[i].size; |
| 722 | } |
| 723 | } ); |
| 724 | |
| 725 | // Checking totalSize. |
| 726 | if ( totalSize > postMaxSize ) { |
| 727 | |
| 728 | // Convert sizes to Mb. |
| 729 | totalSize = Number( ( totalSize / 1048576 ).toFixed( 3 ) ); |
| 730 | postMaxSize = Number( ( postMaxSize / 1048576 ).toFixed( 3 ) ); |
| 731 | |
| 732 | // Preparing error message. |
| 733 | errorMsg = errorMsg.replace( /{totalSize}/, totalSize ).replace( /{maxSize}/, postMaxSize ); |
| 734 | |
| 735 | // Output error message. |
| 736 | if ( $errorCnt.hasClass( 'wpforms-error-container' ) ) { |
| 737 | $errorCnt.find( '.wpforms-error-container-post_max_size' ).remove(); |
| 738 | $errorCnt.append( errorMsg ); |
| 739 | } else { |
| 740 | $submitCnt.before( errorCntTpl.replace( /{errorMsg}/, errorMsg ) ); |
| 741 | } |
| 742 | |
| 743 | // Disable submit button. |
| 744 | $submitBtn.prop( 'disabled', true ); |
| 745 | } else { |
| 746 | |
| 747 | // Remove error and release submit button. |
| 748 | $errorCnt.find( '.wpforms-error-container-post_max_size' ).remove(); |
| 749 | $submitBtn.prop( 'disabled', false ); |
| 750 | } |
| 751 | |
| 752 | } ); |
| 753 | |
| 754 | // Enter key event. |
| 755 | $( document ).on( 'keydown', '.wpforms-form input', function( e ) { |
| 756 | |
| 757 | if ( e.keyCode !== 13 ) { |
| 758 | return; |
| 759 | } |
| 760 | |
| 761 | var $t = $( this ), |
| 762 | $page = $t.closest( '.wpforms-page' ); |
| 763 | |
| 764 | if ( $page.length === 0 ) { |
| 765 | return; |
| 766 | } |
| 767 | |
| 768 | if ( [ 'text', 'tel', 'number', 'email', 'url', 'radio', 'checkbox' ].indexOf( $t.attr( 'type' ) ) < 0 ) { |
| 769 | return; |
| 770 | } |
| 771 | |
| 772 | if ( $t.hasClass( 'wpforms-datepicker' ) ) { |
| 773 | $t.flatpickr( 'close' ); |
| 774 | } |
| 775 | |
| 776 | if ( $page.hasClass( 'last' ) ) { |
| 777 | $page.closest( '.wpforms-form' ).find( '.wpforms-submit' ).click(); |
| 778 | return; |
| 779 | } |
| 780 | |
| 781 | e.preventDefault(); |
| 782 | $page.find( '.wpforms-page-next' ).click(); |
| 783 | } ); |
| 784 | |
| 785 | }, |
| 786 | |
| 787 | /** |
| 788 | * Update Pagebreak navigation. |
| 789 | * |
| 790 | * @since 1.2.2 |
| 791 | * |
| 792 | * @param {jQuery} el jQuery element object. |
| 793 | */ |
| 794 | pagebreakNav: function( el ) { |
| 795 | |
| 796 | var $this = $( el ), |
| 797 | valid = true, |
| 798 | action = $this.data( 'action' ), |
| 799 | page = $this.data( 'page' ), |
| 800 | page2 = page, |
| 801 | next = page + 1, |
| 802 | prev = page - 1, |
| 803 | formID = $this.data( 'formid' ), |
| 804 | $form = $this.closest( '.wpforms-form' ), |
| 805 | $page = $form.find( '.wpforms-page-' + page ), |
| 806 | $submit = $form.find( '.wpforms-submit-container' ), |
| 807 | $indicator = $form.find( '.wpforms-page-indicator' ), |
| 808 | $reCAPTCHA = $form.find( '.wpforms-recaptcha-container' ), |
| 809 | pageScroll = false; |
| 810 | |
| 811 | // Page scroll. |
| 812 | // TODO: cleanup this BC with wpform_pageScroll. |
| 813 | if ( false === window.wpforms_pageScroll ) { |
| 814 | pageScroll = false; |
| 815 | } else if ( ! app.empty( window.wpform_pageScroll ) ) { |
| 816 | pageScroll = window.wpform_pageScroll; |
| 817 | } else { |
| 818 | pageScroll = 75; |
| 819 | } |
| 820 | |
| 821 | // Toggling between pages. |
| 822 | if ( 'next' === action ) { |
| 823 | |
| 824 | // Validate. |
| 825 | if ( typeof $.fn.validate !== 'undefined' ) { |
| 826 | $page.find( ':input' ).each( function( index, el ) { |
| 827 | if ( ! $( el ).valid() ) { |
| 828 | valid = false; |
| 829 | } |
| 830 | } ); |
| 831 | |
| 832 | // Scroll to first/top error on page. |
| 833 | var $topError = $page.find( '.wpforms-error' ).first(); |
| 834 | if ( $topError.length ) { |
| 835 | app.animateScrollTop( $topError.offset().top - 75, 750, $topError.focus ); |
| 836 | } |
| 837 | } |
| 838 | |
| 839 | // Move to next page. |
| 840 | if ( valid ) { |
| 841 | page2 = next; |
| 842 | $page.hide(); |
| 843 | var $nextPage = $form.find( '.wpforms-page-' + next ); |
| 844 | $nextPage.show(); |
| 845 | if ( $nextPage.hasClass( 'last' ) ) { |
| 846 | $reCAPTCHA.show(); |
| 847 | $submit.show(); |
| 848 | } |
| 849 | if ( pageScroll ) { |
| 850 | |
| 851 | // Scroll to top of the form. |
| 852 | app.animateScrollTop( $form.offset().top - pageScroll ); |
| 853 | } |
| 854 | $this.trigger( 'wpformsPageChange', [ page2, $form ] ); |
| 855 | } |
| 856 | } else if ( 'prev' === action ) { |
| 857 | |
| 858 | // Move to prev page. |
| 859 | page2 = prev; |
| 860 | $page.hide(); |
| 861 | $form.find( '.wpforms-page-' + prev ).show(); |
| 862 | $reCAPTCHA.hide(); |
| 863 | $submit.hide(); |
| 864 | if ( pageScroll ) { |
| 865 | |
| 866 | // Scroll to top of the form. |
| 867 | app.animateScrollTop( $form.offset().top - pageScroll ); |
| 868 | } |
| 869 | $this.trigger( 'wpformsPageChange', [ page2, $form ] ); |
| 870 | } |
| 871 | |
| 872 | if ( $indicator ) { |
| 873 | var theme = $indicator.data( 'indicator' ), |
| 874 | color = $indicator.data( 'indicator-color' ); |
| 875 | if ( 'connector' === theme || 'circles' === theme ) { |
| 876 | $indicator.find( '.wpforms-page-indicator-page' ).removeClass( 'active' ); |
| 877 | $indicator.find( '.wpforms-page-indicator-page-' + page2 ).addClass( 'active' ); |
| 878 | $indicator.find( '.wpforms-page-indicator-page-number' ).removeAttr( 'style' ); |
| 879 | $indicator.find( '.active .wpforms-page-indicator-page-number' ).css( 'background-color', color ); |
| 880 | if ( 'connector' === theme ) { |
| 881 | $indicator.find( '.wpforms-page-indicator-page-triangle' ).removeAttr( 'style' ); |
| 882 | $indicator.find( '.active .wpforms-page-indicator-page-triangle' ).css( 'border-top-color', color ); |
| 883 | } |
| 884 | } else if ( 'progress' === theme ) { |
| 885 | var $pageTitle = $indicator.find( '.wpforms-page-indicator-page-title' ), |
| 886 | $pageSep = $indicator.find( '.wpforms-page-indicator-page-title-sep' ), |
| 887 | totalPages = $form.find( '.wpforms-page' ).length, |
| 888 | width = ( page2 / totalPages ) * 100; |
| 889 | $indicator.find( '.wpforms-page-indicator-page-progress' ).css( 'width', width + '%' ); |
| 890 | $indicator.find( '.wpforms-page-indicator-steps-current' ).text( page2 ); |
| 891 | if ( $pageTitle.data( 'page-' + page2 + '-title' ) ) { |
| 892 | $pageTitle.css( 'display', 'inline' ).text( $pageTitle.data( 'page-' + page2 + '-title' ) ); |
| 893 | $pageSep.css( 'display', 'inline' ); |
| 894 | } else { |
| 895 | $pageTitle.css( 'display', 'none' ); |
| 896 | $pageSep.css( 'display', 'none' ); |
| 897 | } |
| 898 | } |
| 899 | } |
| 900 | }, |
| 901 | |
| 902 | /** |
| 903 | * OptinMonster compatibility. |
| 904 | * |
| 905 | * Re-initialize after OptinMonster loads to accommodate changes that |
| 906 | * have occurred to the DOM. |
| 907 | * |
| 908 | * @since 1.5.0 |
| 909 | */ |
| 910 | bindOptinMonster: function() { |
| 911 | |
| 912 | // OM v5. |
| 913 | document.addEventListener( 'om.Campaign.load', function( event ) { |
| 914 | app.ready(); |
| 915 | app.optinMonsterRecaptchaReset( event.detail.Campaign.data.id ); |
| 916 | } ); |
| 917 | |
| 918 | // OM Legacy. |
| 919 | $( document ).on( 'OptinMonsterOnShow', function( event, data, object ) { |
| 920 | app.ready(); |
| 921 | app.optinMonsterRecaptchaReset( data.optin ); |
| 922 | } ); |
| 923 | }, |
| 924 | |
| 925 | /** |
| 926 | * Reset/recreate reCAPTCHA v2 inside OptinMonster. |
| 927 | * |
| 928 | * @since 1.5.0 |
| 929 | */ |
| 930 | optinMonsterRecaptchaReset: function( optinId ) { |
| 931 | |
| 932 | var $form = $( '#om-' + optinId ).find( '.wpforms-form' ), |
| 933 | $recaptchaContainer = $form.find( '.wpforms-recaptcha-container' ), |
| 934 | $recaptcha = $form.find( '.g-recaptcha' ), |
| 935 | recaptchaSiteKey = $recaptcha.attr( 'data-sitekey' ), |
| 936 | recaptchaID = 'recaptcha-' + Date.now(); |
| 937 | |
| 938 | if ( $form.length && $recaptcha.length ) { |
| 939 | |
| 940 | $recaptcha.remove(); |
| 941 | $recaptchaContainer.prepend( '<div class="g-recaptcha" id="' + recaptchaID + '" data-sitekey="' + recaptchaSiteKey + '"></div>' ); |
| 942 | |
| 943 | grecaptcha.render( |
| 944 | recaptchaID, |
| 945 | { |
| 946 | sitekey: recaptchaSiteKey, |
| 947 | callback: function() { |
| 948 | wpformsRecaptchaCallback( $( '#' + recaptchaID ) ); |
| 949 | }, |
| 950 | } |
| 951 | ); |
| 952 | } |
| 953 | }, |
| 954 | |
| 955 | //--------------------------------------------------------------------// |
| 956 | // Other functions. |
| 957 | //--------------------------------------------------------------------// |
| 958 | |
| 959 | /** |
| 960 | * Payments: Calculate total. |
| 961 | * |
| 962 | * @since 1.2.3 |
| 963 | * @since 1.5.1 Added support for payment-checkbox field. |
| 964 | */ |
| 965 | amountTotal: function( el, validate ) { |
| 966 | |
| 967 | validate = validate || false; |
| 968 | |
| 969 | var $form = $( el ).closest( '.wpforms-form' ), |
| 970 | total = 0, |
| 971 | totalFormatted, |
| 972 | totalFormattedSymbol, |
| 973 | currency = app.getCurrency(); |
| 974 | |
| 975 | $( '.wpforms-payment-price', $form ).each( function( index, el ) { |
| 976 | |
| 977 | var amount = 0, |
| 978 | $this = $( this ); |
| 979 | |
| 980 | if ( $this.closest( '.wpforms-field-payment-single' ).hasClass( 'wpforms-conditional-hide' ) ) { |
| 981 | return; |
| 982 | } |
| 983 | if ( 'text' === $this.attr( 'type' ) || 'hidden' === $this.attr( 'type' ) ) { |
| 984 | amount = $this.val(); |
| 985 | } else if ( ( 'radio' === $this.attr( 'type' ) || 'checkbox' === $this.attr( 'type' ) ) && $this.is( ':checked' ) ) { |
| 986 | amount = $this.data( 'amount' ); |
| 987 | } else if ( $this.is( 'select' ) && $this.find( 'option:selected' ).length > 0 ) { |
| 988 | amount = $this.find( 'option:selected' ).data( 'amount' ); |
| 989 | } |
| 990 | if ( ! app.empty( amount ) ) { |
| 991 | amount = app.amountSanitize( amount ); |
| 992 | total = Number( total ) + Number( amount ); |
| 993 | } |
| 994 | } ); |
| 995 | |
| 996 | totalFormatted = app.amountFormat( total ); |
| 997 | |
| 998 | if ( 'left' === currency.symbol_pos ) { |
| 999 | totalFormattedSymbol = currency.symbol + ' ' + totalFormatted; |
| 1000 | } else { |
| 1001 | totalFormattedSymbol = totalFormatted + ' ' + currency.symbol; |
| 1002 | } |
| 1003 | |
| 1004 | $form.find( '.wpforms-payment-total' ).each( function( index, el ) { |
| 1005 | if ( 'hidden' === $( this ).attr( 'type' ) || 'text' === $( this ).attr( 'type' ) ) { |
| 1006 | $( this ).val( totalFormattedSymbol ); |
| 1007 | if ( 'text' === $( this ).attr( 'type' ) && validate && $form.data( 'validator' ) ) { |
| 1008 | $( this ).valid(); |
| 1009 | } |
| 1010 | } else { |
| 1011 | $( this ).text( totalFormattedSymbol ); |
| 1012 | } |
| 1013 | } ); |
| 1014 | }, |
| 1015 | |
| 1016 | /** |
| 1017 | * Sanitize amount and convert to standard format for calculations. |
| 1018 | * |
| 1019 | * @since 1.2.6 |
| 1020 | */ |
| 1021 | amountSanitize: function( amount ) { |
| 1022 | |
| 1023 | var currency = app.getCurrency(); |
| 1024 | |
| 1025 | amount = amount.toString().replace( /[^0-9.,]/g, '' ); |
| 1026 | |
| 1027 | if ( ',' === currency.decimal_sep && ( amount.indexOf( currency.decimal_sep ) !== -1 ) ) { |
| 1028 | if ( '.' === currency.thousands_sep && amount.indexOf( currency.thousands_sep ) !== -1 ) { |
| 1029 | amount = amount.replace( currency.thousands_sep, '' ); |
| 1030 | } else if ( '' === currency.thousands_sep && amount.indexOf( '.' ) !== -1 ) { |
| 1031 | amount = amount.replace( '.', '' ); |
| 1032 | } |
| 1033 | amount = amount.replace( currency.decimal_sep, '.' ); |
| 1034 | } else if ( ',' === currency.thousands_sep && ( amount.indexOf( currency.thousands_sep ) !== -1 ) ) { |
| 1035 | amount = amount.replace( currency.thousands_sep, '' ); |
| 1036 | } |
| 1037 | |
| 1038 | return app.numberFormat( amount, 2, '.', '' ); |
| 1039 | }, |
| 1040 | |
| 1041 | /** |
| 1042 | * Format amount. |
| 1043 | * |
| 1044 | * @since 1.2.6 |
| 1045 | */ |
| 1046 | amountFormat: function( amount ) { |
| 1047 | |
| 1048 | var currency = app.getCurrency(); |
| 1049 | |
| 1050 | amount = String( amount ); |
| 1051 | |
| 1052 | // Format the amount |
| 1053 | if ( ',' === currency.decimal_sep && ( amount.indexOf( currency.decimal_sep ) !== -1 ) ) { |
| 1054 | var sepFound = amount.indexOf( currency.decimal_sep ), |
| 1055 | whole = amount.substr( 0, sepFound ), |
| 1056 | part = amount.substr( sepFound + 1, amount.strlen - 1 ); |
| 1057 | amount = whole + '.' + part; |
| 1058 | } |
| 1059 | |
| 1060 | // Strip , from the amount (if set as the thousands separator) |
| 1061 | if ( ',' === currency.thousands_sep && ( amount.indexOf( currency.thousands_sep ) !== -1 ) ) { |
| 1062 | amount = amount.replace( ',', '' ); |
| 1063 | } |
| 1064 | |
| 1065 | if ( app.empty( amount ) ) { |
| 1066 | amount = 0; |
| 1067 | } |
| 1068 | |
| 1069 | return app.numberFormat( amount, 2, currency.decimal_sep, currency.thousands_sep ); |
| 1070 | }, |
| 1071 | |
| 1072 | /** |
| 1073 | * Get site currency settings. |
| 1074 | * |
| 1075 | * @since 1.2.6 |
| 1076 | */ |
| 1077 | getCurrency: function() { |
| 1078 | |
| 1079 | var currency = { |
| 1080 | code: 'USD', |
| 1081 | thousands_sep: ',', |
| 1082 | decimal_sep: '.', |
| 1083 | symbol: '$', |
| 1084 | symbol_pos: 'left', |
| 1085 | }; |
| 1086 | |
| 1087 | // Backwards compatibility. |
| 1088 | if ( typeof wpforms_settings.currency_code !== 'undefined' ) { |
| 1089 | currency.code = wpforms_settings.currency_code; |
| 1090 | } |
| 1091 | if ( typeof wpforms_settings.currency_thousands !== 'undefined' ) { |
| 1092 | currency.thousands_sep = wpforms_settings.currency_thousands; |
| 1093 | } |
| 1094 | if ( typeof wpforms_settings.currency_decimal !== 'undefined' ) { |
| 1095 | currency.decimal_sep = wpforms_settings.currency_decimal; |
| 1096 | } |
| 1097 | if ( typeof wpforms_settings.currency_symbol !== 'undefined' ) { |
| 1098 | currency.symbol = wpforms_settings.currency_symbol; |
| 1099 | } |
| 1100 | if ( typeof wpforms_settings.currency_symbol_pos !== 'undefined' ) { |
| 1101 | currency.symbol_pos = wpforms_settings.currency_symbol_pos; |
| 1102 | } |
| 1103 | |
| 1104 | return currency; |
| 1105 | }, |
| 1106 | |
| 1107 | /** |
| 1108 | * Format number. |
| 1109 | * |
| 1110 | * @link http://locutus.io/php/number_format/ |
| 1111 | * @since 1.2.6 |
| 1112 | */ |
| 1113 | numberFormat: function( number, decimals, decimalSep, thousandsSep ) { |
| 1114 | |
| 1115 | number = ( number + '' ).replace( /[^0-9+\-Ee.]/g, '' ); |
| 1116 | var n = ! isFinite( +number ) ? 0 : +number; |
| 1117 | var prec = ! isFinite( +decimals ) ? 0 : Math.abs( decimals ); |
| 1118 | var sep = ( 'undefined' === typeof thousandsSep ) ? ',' : thousandsSep; |
| 1119 | var dec = ( 'undefined' === typeof decimalSep ) ? '.' : decimalSep; |
| 1120 | var s; |
| 1121 | |
| 1122 | var toFixedFix = function( n, prec ) { |
| 1123 | var k = Math.pow( 10, prec ); |
| 1124 | return '' + ( Math.round( n * k ) / k ).toFixed( prec ); |
| 1125 | }; |
| 1126 | |
| 1127 | // @todo: for IE parseFloat(0.55).toFixed(0) = 0; |
| 1128 | s = ( prec ? toFixedFix( n, prec ) : '' + Math.round( n ) ).split( '.' ); |
| 1129 | if ( s[0].length > 3 ) { |
| 1130 | s[0] = s[0].replace( /\B(?=(?:\d{3})+(?!\d))/g, sep ); |
| 1131 | } |
| 1132 | if ( ( s[1] || '' ).length < prec ) { |
| 1133 | s[1] = s[1] || ''; |
| 1134 | s[1] += new Array( prec - s[1].length + 1 ).join( '0' ); |
| 1135 | } |
| 1136 | |
| 1137 | return s.join( dec ); |
| 1138 | }, |
| 1139 | |
| 1140 | /** |
| 1141 | * Empty check similar to PHP. |
| 1142 | * |
| 1143 | * @link http://locutus.io/php/empty/ |
| 1144 | * @since 1.2.6 |
| 1145 | */ |
| 1146 | empty: function( mixedVar ) { |
| 1147 | |
| 1148 | var undef; |
| 1149 | var key; |
| 1150 | var i; |
| 1151 | var len; |
| 1152 | var emptyValues = [ undef, null, false, 0, '', '0' ]; |
| 1153 | |
| 1154 | for ( i = 0, len = emptyValues.length; i < len; i++ ) { |
| 1155 | if ( mixedVar === emptyValues[i] ) { |
| 1156 | return true; |
| 1157 | } |
| 1158 | } |
| 1159 | |
| 1160 | if ( 'object' === typeof mixedVar ) { |
| 1161 | for ( key in mixedVar ) { |
| 1162 | if ( mixedVar.hasOwnProperty( key ) ) { |
| 1163 | return false; |
| 1164 | } |
| 1165 | } |
| 1166 | return true; |
| 1167 | } |
| 1168 | |
| 1169 | return false; |
| 1170 | }, |
| 1171 | |
| 1172 | /** |
| 1173 | * Set cookie container user UUID. |
| 1174 | * |
| 1175 | * @since 1.3.3 |
| 1176 | */ |
| 1177 | setUserIndentifier: function() { |
| 1178 | |
| 1179 | if ( ( ( ! window.hasRequiredConsent && typeof wpforms_settings !== 'undefined' && wpforms_settings.uuid_cookie ) || ( window.hasRequiredConsent && window.hasRequiredConsent() ) ) && ! app.getCookie( '_wpfuuid' ) ) { |
| 1180 | |
| 1181 | // Generate UUID - http://stackoverflow.com/a/873856/1489528 |
| 1182 | var s = new Array( 36 ), |
| 1183 | hexDigits = '0123456789abcdef', |
| 1184 | uuid; |
| 1185 | |
| 1186 | for ( var i = 0; i < 36; i++ ) { |
| 1187 | s[i] = hexDigits.substr( Math.floor( Math.random() * 0x10 ), 1 ); |
| 1188 | } |
| 1189 | s[14] = '4'; |
| 1190 | s[19] = hexDigits.substr( ( s[19] & 0x3 ) | 0x8, 1 ); |
| 1191 | s[8] = s[13] = s[18] = s[23] = '-'; |
| 1192 | |
| 1193 | uuid = s.join( '' ); |
| 1194 | |
| 1195 | app.createCookie( '_wpfuuid', uuid, 3999 ); |
| 1196 | } |
| 1197 | }, |
| 1198 | |
| 1199 | /** |
| 1200 | * Create cookie. |
| 1201 | * |
| 1202 | * @since 1.3.3 |
| 1203 | */ |
| 1204 | createCookie: function( name, value, days ) { |
| 1205 | |
| 1206 | var expires = ''; |
| 1207 | |
| 1208 | // If we have a days value, set it in the expiry of the cookie. |
| 1209 | if ( days ) { |
| 1210 | |
| 1211 | // If -1 is our value, set a session based cookie instead of a persistent cookie. |
| 1212 | if ( '-1' === days ) { |
| 1213 | expires = ''; |
| 1214 | } else { |
| 1215 | var date = new Date(); |
| 1216 | date.setTime( date.getTime() + ( days * 24 * 60 * 60 * 1000 ) ); |
| 1217 | expires = '; expires=' + date.toGMTString(); |
| 1218 | } |
| 1219 | } else { |
| 1220 | expires = '; expires=Thu, 01 Jan 1970 00:00:01 GMT'; |
| 1221 | } |
| 1222 | |
| 1223 | // Write the cookie. |
| 1224 | document.cookie = name + '=' + value + expires + '; path=/'; |
| 1225 | }, |
| 1226 | |
| 1227 | /** |
| 1228 | * Retrieve cookie. |
| 1229 | * |
| 1230 | * @since 1.3.3 |
| 1231 | */ |
| 1232 | getCookie: function( name ) { |
| 1233 | |
| 1234 | var nameEQ = name + '=', |
| 1235 | ca = document.cookie.split( ';' ); |
| 1236 | |
| 1237 | for ( var i = 0; i < ca.length; i++ ) { |
| 1238 | var c = ca[i]; |
| 1239 | while ( ' ' === c.charAt( 0 ) ) { |
| 1240 | c = c.substring( 1, c.length ); |
| 1241 | } |
| 1242 | if ( 0 == c.indexOf( nameEQ ) ) { |
| 1243 | return c.substring( nameEQ.length, c.length ); |
| 1244 | } |
| 1245 | } |
| 1246 | |
| 1247 | return null; |
| 1248 | }, |
| 1249 | |
| 1250 | /** |
| 1251 | * Delete cookie. |
| 1252 | */ |
| 1253 | removeCookie: function( name ) { |
| 1254 | |
| 1255 | app.createCookie( name, '', -1 ); |
| 1256 | }, |
| 1257 | |
| 1258 | /** |
| 1259 | * Get user browser preferred language. |
| 1260 | * |
| 1261 | * @since 1.5.2 |
| 1262 | * |
| 1263 | * @returns {String} Language code. |
| 1264 | */ |
| 1265 | getFirstBrowserLanguage: function() { |
| 1266 | var nav = window.navigator, |
| 1267 | browserLanguagePropertyKeys = [ 'language', 'browserLanguage', 'systemLanguage', 'userLanguage' ], |
| 1268 | i, |
| 1269 | language; |
| 1270 | |
| 1271 | // Support for HTML 5.1 "navigator.languages". |
| 1272 | if ( Array.isArray( nav.languages ) ) { |
| 1273 | for ( i = 0; i < nav.languages.length; i++ ) { |
| 1274 | language = nav.languages[ i ]; |
| 1275 | if ( language && language.length ) { |
| 1276 | return language; |
| 1277 | } |
| 1278 | } |
| 1279 | } |
| 1280 | |
| 1281 | // Support for other well known properties in browsers. |
| 1282 | for ( i = 0; i < browserLanguagePropertyKeys.length; i++ ) { |
| 1283 | language = nav[ browserLanguagePropertyKeys[ i ] ]; |
| 1284 | if ( language && language.length ) { |
| 1285 | return language; |
| 1286 | } |
| 1287 | } |
| 1288 | |
| 1289 | return ''; |
| 1290 | }, |
| 1291 | |
| 1292 | /** |
| 1293 | * Asynchronously fetches country code using current IP |
| 1294 | * and executes a callback provided with a country code parameter. |
| 1295 | * |
| 1296 | * @since 1.5.2 |
| 1297 | * |
| 1298 | * @param {Function} callback Executes once the fetch is completed. |
| 1299 | */ |
| 1300 | currentIpToCountry: function( callback ) { |
| 1301 | |
| 1302 | $.get( 'https://ipapi.co/jsonp', function() {}, 'jsonp' ) |
| 1303 | |
| 1304 | .always( function( resp ) { |
| 1305 | |
| 1306 | var countryCode = ( resp && resp.country ) ? resp.country : ''; |
| 1307 | |
| 1308 | if ( ! countryCode ) { |
| 1309 | var lang = app.getFirstBrowserLanguage(); |
| 1310 | countryCode = lang.indexOf( '-' ) > -1 ? lang.split( '-' ).pop() : ''; |
| 1311 | } |
| 1312 | |
| 1313 | callback( countryCode ); |
| 1314 | } ); |
| 1315 | }, |
| 1316 | |
| 1317 | /** |
| 1318 | * Form submit. |
| 1319 | * |
| 1320 | * @since 1.5.3 |
| 1321 | * |
| 1322 | * @param {jQuery} $form Form element. |
| 1323 | */ |
| 1324 | formSubmit: function( $form ) { |
| 1325 | |
| 1326 | if ( $form.hasClass( 'wpforms-ajax-form' ) && typeof FormData !== 'undefined' ) { |
| 1327 | app.formSubmitAjax( $form ); |
| 1328 | } else { |
| 1329 | app.formSubmitNormal( $form ); |
| 1330 | } |
| 1331 | }, |
| 1332 | |
| 1333 | /** |
| 1334 | * Normal form submit with page reload. |
| 1335 | * |
| 1336 | * @since 1.5.3 |
| 1337 | * |
| 1338 | * @param {jQuery} $form Form element. |
| 1339 | */ |
| 1340 | formSubmitNormal: function( $form ) { |
| 1341 | |
| 1342 | if ( ! $form.length ) { |
| 1343 | return; |
| 1344 | } |
| 1345 | |
| 1346 | var $submit = $form.find( '.wpforms-submit' ), |
| 1347 | recaptchaID = $submit.get( 0 ).recaptchaID; |
| 1348 | |
| 1349 | if ( ! app.empty( recaptchaID ) || recaptchaID === 0 ) { |
| 1350 | $submit.get( 0 ).recaptchaID = false; |
| 1351 | } |
| 1352 | |
| 1353 | $form.get( 0 ).submit(); |
| 1354 | }, |
| 1355 | |
| 1356 | /** |
| 1357 | * Reset form recaptcha. |
| 1358 | * |
| 1359 | * @since 1.5.3 |
| 1360 | * |
| 1361 | * @param {jQuery} $form Form element. |
| 1362 | */ |
| 1363 | resetFormRecaptcha: function( $form ) { |
| 1364 | |
| 1365 | if ( ! $form || ! $form.length ) { |
| 1366 | return; |
| 1367 | } |
| 1368 | |
| 1369 | if ( typeof grecaptcha === 'undefined' ) { |
| 1370 | return; |
| 1371 | } |
| 1372 | |
| 1373 | var recaptchaID; |
| 1374 | |
| 1375 | // Check for invisible recaptcha first. |
| 1376 | recaptchaID = $form.find( '.wpforms-submit' ).get( 0 ).recaptchaID; |
| 1377 | |
| 1378 | // Check for v2 recaptcha if invisible recaptcha is not found. |
| 1379 | if ( app.empty( recaptchaID ) && recaptchaID !== 0 ) { |
| 1380 | recaptchaID = $form.find( '.g-recaptcha' ).data( 'recaptcha-id' ); |
| 1381 | } |
| 1382 | |
| 1383 | // Reset recaptcha. |
| 1384 | if ( ! app.empty( recaptchaID ) || recaptchaID === 0 ) { |
| 1385 | grecaptcha.reset( recaptchaID ); |
| 1386 | } |
| 1387 | }, |
| 1388 | |
| 1389 | /** |
| 1390 | * Console log AJAX error. |
| 1391 | * |
| 1392 | * @since 1.5.3 |
| 1393 | * |
| 1394 | * @param {string} error Error text (optional). |
| 1395 | */ |
| 1396 | consoleLogAjaxError: function( error ) { |
| 1397 | |
| 1398 | if ( error ) { |
| 1399 | console.error( 'WPForms AJAX submit error:\n%s', error ); // eslint-disable-line no-console |
| 1400 | } else { |
| 1401 | console.error( 'WPForms AJAX submit error' ); // eslint-disable-line no-console |
| 1402 | } |
| 1403 | }, |
| 1404 | |
| 1405 | /** |
| 1406 | * Display form AJAX errors. |
| 1407 | * |
| 1408 | * @since 1.5.3 |
| 1409 | * |
| 1410 | * @param {jQuery} $form Form element. |
| 1411 | * @param {object} errors Errors in format { general: { generalErrors }, field: { fieldErrors } }. |
| 1412 | */ |
| 1413 | displayFormAjaxErrors: function( $form, errors ) { |
| 1414 | |
| 1415 | if ( app.empty( errors ) || ( app.empty( errors.general ) && app.empty( errors.field ) ) ) { |
| 1416 | app.consoleLogAjaxError(); |
| 1417 | return; |
| 1418 | } |
| 1419 | |
| 1420 | if ( ! app.empty( errors.general ) ) { |
| 1421 | app.displayFormAjaxGeneralErrors( $form, errors.general ); |
| 1422 | } |
| 1423 | |
| 1424 | if ( ! app.empty( errors.field ) ) { |
| 1425 | app.displayFormAjaxFieldErrors( $form, errors.field ); |
| 1426 | } |
| 1427 | }, |
| 1428 | |
| 1429 | /** |
| 1430 | * Display form AJAX general errors that cannot be displayed using jQuery Validation plugin. |
| 1431 | * |
| 1432 | * @since 1.5.3 |
| 1433 | * |
| 1434 | * @param {jQuery} $form Form element. |
| 1435 | * @param {object} errors Errors in format { errorType: errorText }. |
| 1436 | */ |
| 1437 | displayFormAjaxGeneralErrors: function( $form, errors ) { |
| 1438 | |
| 1439 | if ( ! $form || ! $form.length ) { |
| 1440 | return; |
| 1441 | } |
| 1442 | |
| 1443 | if ( app.empty( errors ) ) { |
| 1444 | return; |
| 1445 | } |
| 1446 | |
| 1447 | $.each( errors, function( type, html ) { |
| 1448 | switch ( type ) { |
| 1449 | case 'header': |
| 1450 | $form.prepend( html ); |
| 1451 | break; |
| 1452 | case 'footer': |
| 1453 | $form.find( '.wpforms-submit-container' ).before( html ); |
| 1454 | break; |
| 1455 | case 'recaptcha': |
| 1456 | $form.find( '.wpforms-recaptcha-container' ).append( html ); |
| 1457 | break; |
| 1458 | } |
| 1459 | } ); |
| 1460 | }, |
| 1461 | |
| 1462 | /** |
| 1463 | * Clear forms AJAX general errors that cannot be cleared using jQuery Validation plugin. |
| 1464 | * |
| 1465 | * @since 1.5.3 |
| 1466 | * |
| 1467 | * @param {jQuery} $form Form element. |
| 1468 | */ |
| 1469 | clearFormAjaxGeneralErrors: function( $form ) { |
| 1470 | |
| 1471 | $form.find( '.wpforms-error-container' ).remove(); |
| 1472 | $form.find( '#wpforms-field_recaptcha-error' ).remove(); |
| 1473 | }, |
| 1474 | |
| 1475 | /** |
| 1476 | * Display form AJAX field errors using jQuery Validation plugin. |
| 1477 | * |
| 1478 | * @since 1.5.3 |
| 1479 | * |
| 1480 | * @param {jQuery} $form Form element. |
| 1481 | * @param {object} errors Errors in format { fieldName: errorText }. |
| 1482 | */ |
| 1483 | displayFormAjaxFieldErrors: function( $form, errors ) { |
| 1484 | |
| 1485 | if ( ! $form || ! $form.length ) { |
| 1486 | return; |
| 1487 | } |
| 1488 | |
| 1489 | if ( app.empty( errors ) ) { |
| 1490 | return; |
| 1491 | } |
| 1492 | |
| 1493 | var validator = $form.data( 'validator' ); |
| 1494 | |
| 1495 | if ( ! validator ) { |
| 1496 | return; |
| 1497 | } |
| 1498 | |
| 1499 | validator.showErrors( errors ); |
| 1500 | validator.focusInvalid(); |
| 1501 | }, |
| 1502 | |
| 1503 | /** |
| 1504 | * Submit a form using AJAX. |
| 1505 | * |
| 1506 | * @since 1.5.3 |
| 1507 | * |
| 1508 | * @param {jQuery} $form Form element. |
| 1509 | * |
| 1510 | * @returns {JQueryXHR|JQueryDeferred} Promise like object for async callbacks. |
| 1511 | */ |
| 1512 | formSubmitAjax: function( $form ) { |
| 1513 | |
| 1514 | if ( ! $form.length ) { |
| 1515 | return $.Deferred().reject(); // eslint-disable-line new-cap |
| 1516 | } |
| 1517 | |
| 1518 | var $container = $form.closest( '.wpforms-container' ), |
| 1519 | $spinner = $form.find( '.wpforms-submit-spinner' ), |
| 1520 | $confirmationScroll, |
| 1521 | formData, |
| 1522 | args; |
| 1523 | |
| 1524 | $container.css( 'opacity', 0.6 ); |
| 1525 | $spinner.show(); |
| 1526 | |
| 1527 | app.clearFormAjaxGeneralErrors( $form ); |
| 1528 | |
| 1529 | formData = new FormData( $form.get( 0 ) ); |
| 1530 | formData.append( 'action', 'wpforms_submit' ); |
| 1531 | |
| 1532 | args = { |
| 1533 | type : 'post', |
| 1534 | dataType : 'json', |
| 1535 | url : wpforms_settings.ajaxurl, |
| 1536 | data : formData, |
| 1537 | cache : false, |
| 1538 | contentType: false, |
| 1539 | processData: false, |
| 1540 | }; |
| 1541 | |
| 1542 | args.success = function( json ) { |
| 1543 | |
| 1544 | if ( ! json ) { |
| 1545 | app.consoleLogAjaxError(); |
| 1546 | return; |
| 1547 | } |
| 1548 | |
| 1549 | if ( ! json.success ) { |
| 1550 | app.resetFormRecaptcha( $form ); |
| 1551 | var errors = json.data && 'errors' in json.data ? json.data.errors : null; |
| 1552 | app.displayFormAjaxErrors( $form, errors ); |
| 1553 | $form.trigger( 'wpformsAjaxSubmitFailed', json ); |
| 1554 | return; |
| 1555 | } |
| 1556 | |
| 1557 | $form.trigger( 'wpformsAjaxSubmitSuccess', json ); |
| 1558 | |
| 1559 | if ( ! json.data ) { |
| 1560 | return; |
| 1561 | } |
| 1562 | |
| 1563 | if ( json.data.redirect_url ) { |
| 1564 | $form.trigger( 'wpformsAjaxSubmitBeforeRedirect', json ); |
| 1565 | window.location = json.data.redirect_url; |
| 1566 | return; |
| 1567 | } |
| 1568 | |
| 1569 | if ( json.data.confirmation ) { |
| 1570 | $container.html( json.data.confirmation ); |
| 1571 | $confirmationScroll = $container.find( 'div.wpforms-confirmation-scroll' ); |
| 1572 | if ( $confirmationScroll.length ) { |
| 1573 | app.animateScrollTop( $confirmationScroll.offset().top - 100 ); |
| 1574 | } |
| 1575 | } |
| 1576 | }; |
| 1577 | |
| 1578 | args.error = function( jqHXR, textStatus, error ) { |
| 1579 | |
| 1580 | app.consoleLogAjaxError( error ); |
| 1581 | |
| 1582 | $form.trigger( 'wpformsAjaxSubmitError', [ jqHXR, textStatus, error ] ); |
| 1583 | }; |
| 1584 | |
| 1585 | args.complete = function( jqHXR, textStatus ) { |
| 1586 | |
| 1587 | var $submit = $form.find( '.wpforms-submit' ), |
| 1588 | submitText = $submit.data( 'submit-text' ); |
| 1589 | |
| 1590 | if ( submitText ) { |
| 1591 | $submit.text( submitText ).prop( 'disabled', false ); |
| 1592 | } |
| 1593 | |
| 1594 | $container.css( 'opacity', '' ); |
| 1595 | $spinner.hide(); |
| 1596 | |
| 1597 | $form.trigger( 'wpformsAjaxSubmitCompleted', [ jqHXR, textStatus ] ); |
| 1598 | }; |
| 1599 | |
| 1600 | $form.trigger( 'wpformsAjaxBeforeSubmit' ); |
| 1601 | |
| 1602 | return $.ajax( args ); |
| 1603 | }, |
| 1604 | |
| 1605 | /** |
| 1606 | * Scroll to position with animation. |
| 1607 | * |
| 1608 | * @since 1.5.3 |
| 1609 | * |
| 1610 | * @param {number} position Position (in pixels) to scroll to, |
| 1611 | * @param {number} duration Animation duration. |
| 1612 | * @param {Function} complete Function to execute after animation is complete. |
| 1613 | * |
| 1614 | * @returns {JQueryPromise} Promise object for async callbacks. |
| 1615 | */ |
| 1616 | animateScrollTop: function( position, duration, complete ) { |
| 1617 | |
| 1618 | duration = duration || 1000; |
| 1619 | return $( 'html, body' ).animate( { scrollTop: position }, duration, complete ).promise(); |
| 1620 | }, |
| 1621 | }; |
| 1622 | |
| 1623 | return app; |
| 1624 | |
| 1625 | }( document, window, jQuery ) ); |
| 1626 | |
| 1627 | // Initialize. |
| 1628 | wpforms.init(); |
| 1629 |