|
--- assets/js/min/front-end-deps.js |
|
+++ assets/js/min/front-end-deps.js |
|
@@ -73,14 +73,26 @@ |
|
var fieldID = jQuery( this ).data( 'fieldid' ); |
|
if ( typeof window[ callback ] !== 'function' ){ |
|
window[ callback ] = function( response ) { |
|
+ nfRecaptcha.DEBUG && console.group(callback); |
|
+ nfRecaptcha.DEBUG && console.log('fieldID:', fieldID); |
|
+ nfRecaptcha.DEBUG && console.log('response:', response); |
|
+ |
|
nfRadio.channel( 'recaptcha' ).request( 'update:response', response, fieldID ); |
|
+ nfRadio.channel( 'captcha' ).request( 'update:response', response, fieldID ); |
|
+ |
|
+ nfRecaptcha.DEBUG && console.groupEnd(); |
|
}; |
|
} |
|
} ); |
|
} ); |
|
|
|
var nfRecaptcha = Marionette.Object.extend( { |
|
- initialize: function() { |
|
+ /** @var {boolean} - Validate only one reCAPTCHA at a time. */ |
|
+ isBusy: false, |
|
+ /** @var {?{ninja-forms:FormModel}} - Track which form is submitting. */ |
|
+ isSubmitting: null, |
|
+ |
|
+ initialize: function () { |
|
/* |
|
* If we've already rendered our form view, render our recaptcha fields. |
|
*/ |
|
@@ -91,33 +103,199 @@ |
|
* We haven't rendered our form view, so hook into the view render radio message, and then render. |
|
*/ |
|
this.listenTo( nfRadio.channel( 'form' ), 'render:view', this.renderCaptcha ); |
|
- this.listenTo( nfRadio.channel( 'captcha' ), 'reset', this.renderCaptcha ); |
|
+ this.listenTo( nfRadio.channel( 'captcha' ), 'reset', this.renderCaptcha ); |
|
+ this.listenTo( nfRadio.channel( 'submit' ), 'validate:field', this.validateCaptcha ); |
|
+ }, |
|
+ |
|
+ /** |
|
+ * @param {ninja-forms:FormModel} formModel - The Ninja Forms form model. |
|
+ */ |
|
+ beforeSubmit: function ( formModel ) { |
|
+ var DEBUG = nfRecaptcha.DEBUG; |
|
+ |
|
+ DEBUG && console.group('nfRecaptcha.beforeSubmit'); |
|
+ |
|
+ this.isSubmitting = formModel; |
|
+ DEBUG && console.log('Form:', formModel); |
|
+ |
|
+ DEBUG && console.groupEnd(); |
|
}, |
|
|
|
- renderCaptcha: function() { |
|
+ renderCaptcha: function () { |
|
+ var nfController = this, |
|
+ DEBUG = nfRecaptcha.DEBUG; |
|
+ |
|
+ DEBUG && console.group('nfRecaptcha.renderCaptcha'); |
|
+ |
|
jQuery( '.g-recaptcha:empty' ).each( function() { |
|
+ DEBUG && console.group('.g-recaptcha', this); |
|
+ |
|
+ var fieldID = jQuery( this ).data( 'fieldid' ); |
|
+ DEBUG && console.log( 'Field:', fieldID ); |
|
+ |
|
var opts = { |
|
- fieldid: jQuery( this ).data( 'fieldid' ), |
|
+ fieldid: fieldID, |
|
size: jQuery( this ).data( 'size' ), |
|
theme: jQuery( this ).data( 'theme' ), |
|
sitekey: jQuery( this ).data( 'sitekey' ), |
|
callback: jQuery( this ).data( 'callback' ) |
|
}; |
|
|
|
- var grecaptchaID = grecaptcha.render( jQuery( this )[0], opts ); |
|
+ DEBUG && console.log( 'Size:', opts.size ); |
|
+ DEBUG && console.log( 'Callback:', opts.callback ); |
|
+ |
|
+ var grecaptchaID = grecaptcha.render( this, opts ); |
|
+ DEBUG && console.log( 'reCAPTCHA:', grecaptchaID ); |
|
|
|
if ( opts.size === 'invisible' ) { |
|
- try { |
|
- nf_reprocess_recaptcha( grecaptchaID ); |
|
- setInterval(nf_reprocess_recaptcha, 110000, grecaptchaID); |
|
- } catch( e ){ |
|
- console.log( 'Notice: Error trying to execute grecaptcha.' ); |
|
+ var fieldModel = nfRadio.channel( 'fields' ).request( 'get:field', fieldID ); |
|
+ |
|
+ if ( ! fieldModel ) { |
|
+ DEBUG && console.log( 'Skipping; Missing Field Model' ); |
|
+ DEBUG && console.groupEnd(); |
|
+ return; |
|
} |
|
- } |
|
+ |
|
+ fieldModel.set( 'grecaptchaID', grecaptchaID ); |
|
+ |
|
+ nfController.listenTo( nfRadio.channel( 'form-' + fieldModel.get( 'formID' ) ), 'before:submit', nfController.beforeSubmit ); |
|
+ |
|
+ nfRadio.channel( 'captcha' ).reply( 'update:response', nfController.updateValidation, nfController ); |
|
+ } |
|
+ |
|
+ DEBUG && console.groupEnd(); |
|
} ); |
|
+ |
|
+ DEBUG && console.groupEnd(); |
|
+ }, |
|
+ |
|
+ /** |
|
+ * @param {string} response - The reCAPTCHA response value. |
|
+ * @param {string|number} fieldID - The Ninja Forms CAPTCHA field ID. |
|
+ */ |
|
+ updateValidation: function ( response, fieldID ) { |
|
+ var DEBUG = nfRecaptcha.DEBUG; |
|
+ |
|
+ DEBUG && console.group('nfRecaptcha.updateValidation'); |
|
+ |
|
+ var fieldModel = nfRadio.channel( 'fields' ).request( 'get:field', fieldID ); |
|
+ DEBUG && console.log('Field:', fieldModel); |
|
+ |
|
+ if ( ! fieldModel ) { |
|
+ DEBUG && console.log( 'Skipping; Missing Field Model' ); |
|
+ DEBUG && console.groupEnd(); |
|
+ return; |
|
+ } |
|
+ |
|
+ nfRadio.channel( 'fields' ).request( 'remove:error', fieldID, 'recaptcha-processing' ); |
|
+ |
|
+ var formModel = this.isSubmitting; |
|
+ |
|
+ this.isSubmitting = null; |
|
+ this.isBusy = false; |
|
+ |
|
+ if ( formModel ) { |
|
+ DEBUG && console.log( 'Attempting to re-submit form' ); |
|
+ nfRadio.channel( 'form-' + formModel.id ).request( 'submit', formModel ); |
|
+ } else { |
|
+ DEBUG_CONTROLLER && console.log( 'Failed; Missing Form' ); |
|
+ } |
|
+ |
|
+ DEBUG && console.groupEnd(); |
|
+ }, |
|
+ |
|
+ /** |
|
+ * @param {NFFieldModel} fieldModel |
|
+ */ |
|
+ validateCaptcha: function ( fieldModel ) { |
|
+ var DEBUG = nfRecaptcha.DEBUG; |
|
+ |
|
+ DEBUG && console.group('nfRecaptcha.validateCaptcha --', 'Field:', fieldModel.id); |
|
+ |
|
+ var fieldID = fieldModel.id; |
|
+ var fieldType = fieldModel.get( 'type' ); |
|
+ var fieldSize = fieldModel.get( 'size' ); |
|
+ var grecaptchaID = fieldModel.get( 'grecaptchaID' ); |
|
+ |
|
+ if ( this.isBusy ) { |
|
+ DEBUG && console.log( 'Skipping; Busy' ); |
|
+ DEBUG && console.groupEnd(); |
|
+ return; |
|
+ } |
|
+ |
|
+ if ( ! this.isSubmitting ) { |
|
+ DEBUG && console.log( 'Skipping; Not Submitting' ); |
|
+ DEBUG && console.groupEnd(); |
|
+ return; |
|
+ } |
|
+ |
|
+ if ( |
|
+ fieldType !== 'recaptcha' || |
|
+ fieldSize !== 'invisible' || |
|
+ fieldModel.get( 'clean' ) |
|
+ ) { |
|
+ DEBUG && console.log( 'Skipping; Not reCAPTCHA Field' ); |
|
+ DEBUG && console.groupEnd(); |
|
+ return; |
|
+ } |
|
+ |
|
+ if ( grecaptchaID == null ) { |
|
+ DEBUG && console.log( 'Skipping; Missing reCAPTCHA Widget ID' ); |
|
+ DEBUG && console.groupEnd(); |
|
+ return; |
|
+ } |
|
+ |
|
+ this.isBusy = true; |
|
+ |
|
+ var fieldValue = fieldModel.get( 'value' ); |
|
+ var fieldOldValue = fieldModel.get( 'old_value' ); |
|
+ DEBUG && console.log( 'New Value:', fieldValue ); |
|
+ DEBUG && console.log( 'Old Value:', fieldOldValue ); |
|
+ |
|
+ nfRadio.channel( 'fields' ).request( 'remove:error', fieldID, 'required-error' ); |
|
+ |
|
+ if ( fieldOldValue != null && fieldValue ) { |
|
+ fieldModel.set( 'old_value', null ); |
|
+ |
|
+ this.isBusy = false; |
|
+ DEBUG && console.log( 'Validated: Same Value' ); |
|
+ DEBUG && console.groupEnd(); |
|
+ return; |
|
+ } |
|
+ |
|
+ fieldModel.set( 'old_value', fieldValue ); |
|
+ |
|
+ var formModel = nfRadio.channel( 'form-' + fieldModel.get( 'formID' ) ).request( 'get:form' ); |
|
+ if ( ! formModel ) { |
|
+ this.isBusy = false; |
|
+ DEBUG && console.log( 'Skipping; Missing Form Model' ); |
|
+ DEBUG && console.groupEnd(); |
|
+ return; |
|
+ } |
|
+ |
|
+ nfRadio.channel( 'fields' ).request( |
|
+ 'add:error', |
|
+ fieldID, |
|
+ 'recaptcha-processing', |
|
+ formModel.get('settings').recaptchaProcessing |
|
+ ); |
|
+ |
|
+ try { |
|
+ DEBUG && console.log( 'Attempting to execute reCAPTCHA' ); |
|
+ nf_reprocess_recaptcha( grecaptchaID ); |
|
+ } catch ( e ) { |
|
+ this.isBusy = false; |
|
+ console.log( 'Notice: Error trying to execute grecaptcha.' ); |
|
+ DEBUG && console.log( 'Caught error:', e ); |
|
+ } |
|
+ |
|
+ DEBUG && console.groupEnd(); |
|
} |
|
} ); |
|
|
|
+/** @var {boolean} - Display debug information in console. */ |
|
+nfRecaptcha.DEBUG = true; |
|
+ |
|
var nfRenderRecaptcha = function() { |
|
new nfRecaptcha(); |
|
} |