frontend.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. (function($) {
  2. window.onLoadFLReCaptcha = function() {
  3. var reCaptchaFields = $( '.fl-grecaptcha' ),
  4. widgetID;
  5. if ( reCaptchaFields.length > 0 ) {
  6. reCaptchaFields.each( function( i ){
  7. var self = $( this ),
  8. attrWidget = self.attr('data-widgetid'),
  9. newID = $(this).attr('id') + '-' + i;
  10. // Avoid re-rendering as it's throwing API error
  11. if ( (typeof attrWidget !== typeof undefined && attrWidget !== false) ) {
  12. return;
  13. }
  14. else {
  15. // Increment ID to avoid conflict with the same form.
  16. self.attr( 'id', newID );
  17. widgetID = grecaptcha.render( newID, {
  18. sitekey : self.data( 'sitekey' ),
  19. theme : self.data( 'theme' ),
  20. size : self.data( 'validate' ),
  21. callback: function( response ){
  22. if ( response != '' ) {
  23. self.attr( 'data-fl-grecaptcha-response', response );
  24. // Re-submitting the form after a successful invisible validation.
  25. if ( 'invisible' == self.data( 'validate' ) ) {
  26. self.closest( '.fl-contact-form' ).find( 'a.fl-button' ).trigger( 'click' );
  27. }
  28. }
  29. }
  30. });
  31. self.attr( 'data-widgetid', widgetID );
  32. }
  33. });
  34. }
  35. };
  36. FLBuilderContactForm = function( settings )
  37. {
  38. this.settings = settings;
  39. this.nodeClass = '.fl-node-' + settings.id;
  40. this._init();
  41. };
  42. FLBuilderContactForm.prototype = {
  43. settings : {},
  44. nodeClass : '',
  45. _init: function()
  46. {
  47. $( this.nodeClass + ' .fl-button' ).click( $.proxy( this._submit, this ) );
  48. $( this.nodeClass + ' .fl-button' ).on( 'keydown, keyup', $.proxy( this._keyupdown, this ) );
  49. },
  50. _keyupdown: function(e) {
  51. if( e.keyCode === 13 || e.keyCode === 32 ) {
  52. e.preventDefault();
  53. this._submit(e);
  54. }
  55. },
  56. _submit: function( e )
  57. {
  58. var theForm = $(this.nodeClass + ' .fl-contact-form'),
  59. submit = $(this.nodeClass + ' .fl-button'),
  60. name = $(this.nodeClass + ' .fl-name input'),
  61. email = $(this.nodeClass + ' .fl-email input'),
  62. phone = $(this.nodeClass + ' .fl-phone input'),
  63. subject = $(this.nodeClass + ' .fl-subject input'),
  64. message = $(this.nodeClass + ' .fl-message textarea'),
  65. termsCheckbox = $(this.nodeClass + ' .fl-terms-checkbox input'),
  66. reCaptchaField = $(this.nodeClass + ' .fl-grecaptcha'),
  67. reCaptchaValue = reCaptchaField.data( 'fl-grecaptcha-response' ),
  68. ajaxData = null,
  69. ajaxurl = FLBuilderLayoutConfig.paths.wpAjaxUrl,
  70. email_regex = /\S+@\S+\.\S+/,
  71. isValid = true,
  72. postId = theForm.closest( '.fl-builder-content' ).data( 'post-id' ),
  73. layoutId = theForm.find( 'input[name=fl-layout-id]' ).val(),
  74. templateId = theForm.data( 'template-id' ),
  75. templateNodeId = theForm.data( 'template-node-id' ),
  76. nodeId = theForm.closest( '.fl-module' ).data( 'node' ),
  77. nonce = theForm.find('#fl-contact-form-nonce').val();
  78. e.preventDefault();
  79. // End if button is disabled (sent already)
  80. if (submit.hasClass('fl-disabled')) {
  81. return;
  82. }
  83. // validate the name
  84. if(name.length) {
  85. if (name.val() === '') {
  86. isValid = false;
  87. name.parent().addClass('fl-error');
  88. name.attr('aria-invalid', true);
  89. }
  90. else if (name.parent().hasClass('fl-error')) {
  91. name.parent().removeClass('fl-error');
  92. name.attr('aria-invalid', false);
  93. }
  94. }
  95. // validate the email
  96. if(email.length) {
  97. if (email.val() === '' || !email_regex.test(email.val())) {
  98. isValid = false;
  99. email.parent().addClass('fl-error');
  100. email.attr('aria-invalid', true);
  101. }
  102. else if (email.parent().hasClass('fl-error')) {
  103. email.parent().removeClass('fl-error');
  104. email.attr('aria-invalid', false);
  105. }
  106. }
  107. // validate the subject..just make sure it's there
  108. if(subject.length) {
  109. if (subject.val() === '') {
  110. isValid = false;
  111. subject.parent().addClass('fl-error');
  112. subject.attr('aria-invalid', true);
  113. }
  114. else if (subject.parent().hasClass('fl-error')) {
  115. subject.parent().removeClass('fl-error');
  116. subject.attr('aria-invalid', false);
  117. }
  118. }
  119. // validate the phone..just make sure it's there
  120. if(phone.length) {
  121. if (phone.val() === '') {
  122. isValid = false;
  123. phone.parent().addClass('fl-error');
  124. phone.attr('aria-invalid', true);
  125. }
  126. else if (phone.parent().hasClass('fl-error')) {
  127. phone.parent().removeClass('fl-error');
  128. phone.attr('aria-invalid', false);
  129. }
  130. }
  131. // validate the message..just make sure it's there
  132. if (message.val() === '') {
  133. isValid = false;
  134. message.parent().addClass('fl-error');
  135. message.attr('aria-invalid', true);
  136. }
  137. else if (message.parent().hasClass('fl-error')) {
  138. message.parent().removeClass('fl-error');
  139. message.attr('aria-invalid', false);
  140. }
  141. // validate the terms and conditions checkbox if enabled
  142. if ( termsCheckbox.length ) {
  143. if ( ! termsCheckbox.is(':checked') ) {
  144. isValid = false;
  145. termsCheckbox.closest('.fl-terms-checkbox').addClass('fl-error');
  146. }
  147. else if (termsCheckbox.parent().hasClass('fl-error')) {
  148. termsCheckbox.parent().removeClass('fl-error');
  149. }
  150. }
  151. // validate if reCAPTCHA is enabled and checked
  152. if ( reCaptchaField.length > 0 && isValid ) {
  153. if ( 'undefined' === typeof reCaptchaValue || reCaptchaValue === false ) {
  154. if ( 'normal' == reCaptchaField.data( 'validate' ) ) {
  155. reCaptchaField.parent().addClass( 'fl-error' );
  156. } else if ( 'invisible' == reCaptchaField.data( 'validate' ) ) {
  157. // Invoke the reCAPTCHA check.
  158. if ( 'undefined' !== typeof reCaptchaField.data( 'action' ) ) {
  159. // V3
  160. grecaptcha.execute( reCaptchaField.data( 'widgetid' ), {action: reCaptchaField.data( 'action' )} );
  161. }
  162. else {
  163. // V2
  164. grecaptcha.execute( reCaptchaField.data( 'widgetid' ) );
  165. }
  166. }
  167. isValid = false;
  168. } else {
  169. reCaptchaField.parent().removeClass('fl-error');
  170. }
  171. }
  172. // end if we're invalid, otherwise go on..
  173. if (!isValid) {
  174. return false;
  175. }
  176. else {
  177. // disable send button
  178. submit.addClass('fl-disabled');
  179. ajaxData = {
  180. action : 'fl_builder_email',
  181. name : name.val(),
  182. subject : subject.val(),
  183. email : email.val(),
  184. phone : phone.val(),
  185. message : message.val(),
  186. terms_checked : termsCheckbox.is(':checked') ? '1' : '0',
  187. post_id : postId,
  188. layout_id : layoutId,
  189. template_id : templateId,
  190. template_node_id : templateNodeId,
  191. node_id : nodeId,
  192. nonce : nonce
  193. }
  194. if ( reCaptchaValue ) {
  195. ajaxData.recaptcha_response = reCaptchaValue;
  196. }
  197. // post the form data
  198. $.post( ajaxurl, ajaxData, $.proxy( this._submitComplete, this ) );
  199. }
  200. },
  201. _submitComplete: function( response )
  202. {
  203. var urlField = $( this.nodeClass + ' .fl-success-url' ),
  204. noMessage = $( this.nodeClass + ' .fl-success-none' );
  205. // On success show the success message
  206. if (typeof response.error !== 'undefined' && response.error === false) {
  207. $( this.nodeClass + ' .fl-send-error' ).fadeOut();
  208. if ( urlField.length > 0 ) {
  209. window.location.href = urlField.val();
  210. }
  211. else if ( noMessage.length > 0 ) {
  212. noMessage.fadeIn();
  213. }
  214. else {
  215. $( this.nodeClass + ' .fl-contact-form' ).hide();
  216. $( this.nodeClass + ' .fl-success-msg' ).fadeIn();
  217. }
  218. }
  219. // On failure show fail message and re-enable the send button
  220. else {
  221. $(this.nodeClass + ' .fl-button').removeClass('fl-disabled');
  222. if ( typeof response.message !== 'undefined' ) {
  223. $(this.nodeClass + ' .fl-send-error').html(response.message);
  224. }
  225. $(this.nodeClass + ' .fl-send-error').fadeIn();
  226. if ( typeof response.errorInfo !== 'undefined' ) {
  227. console.log('Contact Form:',response.errorInfo);
  228. }
  229. return false;
  230. }
  231. }
  232. };
  233. })(jQuery);