You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

527 lines
14 KiB

  1. ( function( $ ) {
  2. 'use strict';
  3. if ( typeof wpcf7 === 'undefined' || wpcf7 === null ) {
  4. return;
  5. }
  6. wpcf7 = $.extend( {
  7. cached: 0,
  8. inputs: []
  9. }, wpcf7 );
  10. $( function() {
  11. wpcf7.supportHtml5 = ( function() {
  12. var features = {};
  13. var input = document.createElement( 'input' );
  14. features.placeholder = 'placeholder' in input;
  15. var inputTypes = [ 'email', 'url', 'tel', 'number', 'range', 'date' ];
  16. $.each( inputTypes, function( index, value ) {
  17. input.setAttribute( 'type', value );
  18. features[ value ] = input.type !== 'text';
  19. } );
  20. return features;
  21. } )();
  22. $( 'div.wpcf7 > form' ).each( function() {
  23. var $form = $( this );
  24. wpcf7.initForm( $form );
  25. if ( wpcf7.cached ) {
  26. wpcf7.refill( $form );
  27. }
  28. } );
  29. } );
  30. wpcf7.getId = function( form ) {
  31. return parseInt( $( 'input[name="_wpcf7"]', form ).val(), 10 );
  32. };
  33. wpcf7.initForm = function( form ) {
  34. var $form = $( form );
  35. wpcf7.setStatus( $form, 'init' );
  36. $form.submit( function( event ) {
  37. if ( ! wpcf7.supportHtml5.placeholder ) {
  38. $( '[placeholder].placeheld', $form ).each( function( i, n ) {
  39. $( n ).val( '' ).removeClass( 'placeheld' );
  40. } );
  41. }
  42. if ( typeof window.FormData === 'function' ) {
  43. wpcf7.submit( $form );
  44. event.preventDefault();
  45. }
  46. } );
  47. $( '.wpcf7-submit', $form ).after( '<span class="ajax-loader"></span>' );
  48. wpcf7.toggleSubmit( $form );
  49. $form.on( 'click', '.wpcf7-acceptance', function() {
  50. wpcf7.toggleSubmit( $form );
  51. } );
  52. // Exclusive Checkbox
  53. $( '.wpcf7-exclusive-checkbox', $form ).on( 'click', 'input:checkbox', function() {
  54. var name = $( this ).attr( 'name' );
  55. $form.find( 'input:checkbox[name="' + name + '"]' ).not( this ).prop( 'checked', false );
  56. } );
  57. // Free Text Option for Checkboxes and Radio Buttons
  58. $( '.wpcf7-list-item.has-free-text', $form ).each( function() {
  59. var $freetext = $( ':input.wpcf7-free-text', this );
  60. var $wrap = $( this ).closest( '.wpcf7-form-control' );
  61. if ( $( ':checkbox, :radio', this ).is( ':checked' ) ) {
  62. $freetext.prop( 'disabled', false );
  63. } else {
  64. $freetext.prop( 'disabled', true );
  65. }
  66. $wrap.on( 'change', ':checkbox, :radio', function() {
  67. var $cb = $( '.has-free-text', $wrap ).find( ':checkbox, :radio' );
  68. if ( $cb.is( ':checked' ) ) {
  69. $freetext.prop( 'disabled', false ).focus();
  70. } else {
  71. $freetext.prop( 'disabled', true );
  72. }
  73. } );
  74. } );
  75. // Placeholder Fallback
  76. if ( ! wpcf7.supportHtml5.placeholder ) {
  77. $( '[placeholder]', $form ).each( function() {
  78. $( this ).val( $( this ).attr( 'placeholder' ) );
  79. $( this ).addClass( 'placeheld' );
  80. $( this ).focus( function() {
  81. if ( $( this ).hasClass( 'placeheld' ) ) {
  82. $( this ).val( '' ).removeClass( 'placeheld' );
  83. }
  84. } );
  85. $( this ).blur( function() {
  86. if ( '' === $( this ).val() ) {
  87. $( this ).val( $( this ).attr( 'placeholder' ) );
  88. $( this ).addClass( 'placeheld' );
  89. }
  90. } );
  91. } );
  92. }
  93. if ( wpcf7.jqueryUi && ! wpcf7.supportHtml5.date ) {
  94. $form.find( 'input.wpcf7-date[type="date"]' ).each( function() {
  95. $( this ).datepicker( {
  96. dateFormat: 'yy-mm-dd',
  97. minDate: new Date( $( this ).attr( 'min' ) ),
  98. maxDate: new Date( $( this ).attr( 'max' ) )
  99. } );
  100. } );
  101. }
  102. if ( wpcf7.jqueryUi && ! wpcf7.supportHtml5.number ) {
  103. $form.find( 'input.wpcf7-number[type="number"]' ).each( function() {
  104. $( this ).spinner( {
  105. min: $( this ).attr( 'min' ),
  106. max: $( this ).attr( 'max' ),
  107. step: $( this ).attr( 'step' )
  108. } );
  109. } );
  110. }
  111. // Character Count
  112. wpcf7.resetCounter( $form );
  113. // URL Input Correction
  114. $form.on( 'change', '.wpcf7-validates-as-url', function() {
  115. var val = $.trim( $( this ).val() );
  116. if ( val
  117. && ! val.match( /^[a-z][a-z0-9.+-]*:/i )
  118. && -1 !== val.indexOf( '.' ) ) {
  119. val = val.replace( /^\/+/, '' );
  120. val = 'http://' + val;
  121. }
  122. $( this ).val( val );
  123. } );
  124. };
  125. wpcf7.submit = function( form ) {
  126. if ( typeof window.FormData !== 'function' ) {
  127. return;
  128. }
  129. var $form = $( form );
  130. $( '.ajax-loader', $form ).addClass( 'is-active' );
  131. wpcf7.clearResponse( $form );
  132. var formData = new FormData( $form.get( 0 ) );
  133. var detail = {
  134. id: $form.closest( 'div.wpcf7' ).attr( 'id' ),
  135. status: 'init',
  136. inputs: [],
  137. formData: formData
  138. };
  139. $.each( $form.serializeArray(), function( i, field ) {
  140. if ( '_wpcf7' == field.name ) {
  141. detail.contactFormId = field.value;
  142. } else if ( '_wpcf7_version' == field.name ) {
  143. detail.pluginVersion = field.value;
  144. } else if ( '_wpcf7_locale' == field.name ) {
  145. detail.contactFormLocale = field.value;
  146. } else if ( '_wpcf7_unit_tag' == field.name ) {
  147. detail.unitTag = field.value;
  148. } else if ( '_wpcf7_container_post' == field.name ) {
  149. detail.containerPostId = field.value;
  150. } else if ( field.name.match( /^_/ ) ) {
  151. // do nothing
  152. } else {
  153. detail.inputs.push( field );
  154. }
  155. } );
  156. wpcf7.triggerEvent( $form.closest( 'div.wpcf7' ), 'beforesubmit', detail );
  157. var ajaxSuccess = function( data, status, xhr, $form ) {
  158. detail.id = $( data.into ).attr( 'id' );
  159. detail.status = data.status;
  160. detail.apiResponse = data;
  161. switch ( data.status ) {
  162. case 'init':
  163. wpcf7.setStatus( $form, 'init' );
  164. break;
  165. case 'validation_failed':
  166. $.each( data.invalid_fields, function( i, n ) {
  167. $( n.into, $form ).each( function() {
  168. wpcf7.notValidTip( this, n.message );
  169. $( '.wpcf7-form-control', this ).addClass( 'wpcf7-not-valid' );
  170. $( '[aria-invalid]', this ).attr( 'aria-invalid', 'true' );
  171. } );
  172. } );
  173. wpcf7.setStatus( $form, 'invalid' );
  174. wpcf7.triggerEvent( data.into, 'invalid', detail );
  175. break;
  176. case 'acceptance_missing':
  177. wpcf7.setStatus( $form, 'unaccepted' );
  178. wpcf7.triggerEvent( data.into, 'unaccepted', detail );
  179. break;
  180. case 'spam':
  181. wpcf7.setStatus( $form, 'spam' );
  182. wpcf7.triggerEvent( data.into, 'spam', detail );
  183. break;
  184. case 'aborted':
  185. wpcf7.setStatus( $form, 'aborted' );
  186. wpcf7.triggerEvent( data.into, 'aborted', detail );
  187. break;
  188. case 'mail_sent':
  189. wpcf7.setStatus( $form, 'sent' );
  190. wpcf7.triggerEvent( data.into, 'mailsent', detail );
  191. break;
  192. case 'mail_failed':
  193. wpcf7.setStatus( $form, 'failed' );
  194. wpcf7.triggerEvent( data.into, 'mailfailed', detail );
  195. break;
  196. default:
  197. wpcf7.setStatus( $form,
  198. 'custom-' + data.status.replace( /[^0-9a-z]+/i, '-' )
  199. );
  200. }
  201. wpcf7.refill( $form, data );
  202. wpcf7.triggerEvent( data.into, 'submit', detail );
  203. if ( 'mail_sent' == data.status ) {
  204. $form.each( function() {
  205. this.reset();
  206. } );
  207. wpcf7.toggleSubmit( $form );
  208. wpcf7.resetCounter( $form );
  209. }
  210. if ( ! wpcf7.supportHtml5.placeholder ) {
  211. $form.find( '[placeholder].placeheld' ).each( function( i, n ) {
  212. $( n ).val( $( n ).attr( 'placeholder' ) );
  213. } );
  214. }
  215. $( '.wpcf7-response-output', $form )
  216. .html( '' ).append( data.message ).slideDown( 'fast' );
  217. $( '.screen-reader-response', $form.closest( '.wpcf7' ) ).each( function() {
  218. var $response = $( this );
  219. $response.html( '' ).append( data.message );
  220. if ( data.invalid_fields ) {
  221. var $invalids = $( '<ul></ul>' );
  222. $.each( data.invalid_fields, function( i, n ) {
  223. if ( n.idref ) {
  224. var $li = $( '<li></li>' ).append( $( '<a></a>' ).attr( 'href', '#' + n.idref ).append( n.message ) );
  225. } else {
  226. var $li = $( '<li></li>' ).append( n.message );
  227. }
  228. $invalids.append( $li );
  229. } );
  230. $response.append( $invalids );
  231. }
  232. $response.focus();
  233. } );
  234. if ( data.posted_data_hash ) {
  235. $form.find( 'input[name="_wpcf7_posted_data_hash"]' ).first()
  236. .val( data.posted_data_hash );
  237. }
  238. };
  239. $.ajax( {
  240. type: 'POST',
  241. url: wpcf7.apiSettings.getRoute(
  242. '/contact-forms/' + wpcf7.getId( $form ) + '/feedback' ),
  243. data: formData,
  244. dataType: 'json',
  245. processData: false,
  246. contentType: false
  247. } ).done( function( data, status, xhr ) {
  248. ajaxSuccess( data, status, xhr, $form );
  249. $( '.ajax-loader', $form ).removeClass( 'is-active' );
  250. } ).fail( function( xhr, status, error ) {
  251. var $e = $( '<div class="ajax-error"></div>' ).text( error.message );
  252. $form.after( $e );
  253. } );
  254. };
  255. wpcf7.triggerEvent = function( target, name, detail ) {
  256. var event = new CustomEvent( 'wpcf7' + name, {
  257. bubbles: true,
  258. detail: detail
  259. } );
  260. $( target ).get( 0 ).dispatchEvent( event );
  261. };
  262. wpcf7.setStatus = function( form, status ) {
  263. var $form = $( form );
  264. var prevStatus = $form.data( 'status' );
  265. $form.data( 'status', status );
  266. $form.addClass( status );
  267. if ( prevStatus && prevStatus !== status ) {
  268. $form.removeClass( prevStatus );
  269. }
  270. }
  271. wpcf7.toggleSubmit = function( form, state ) {
  272. var $form = $( form );
  273. var $submit = $( 'input:submit', $form );
  274. if ( typeof state !== 'undefined' ) {
  275. $submit.prop( 'disabled', ! state );
  276. return;
  277. }
  278. if ( $form.hasClass( 'wpcf7-acceptance-as-validation' ) ) {
  279. return;
  280. }
  281. $submit.prop( 'disabled', false );
  282. $( '.wpcf7-acceptance', $form ).each( function() {
  283. var $span = $( this );
  284. var $input = $( 'input:checkbox', $span );
  285. if ( ! $span.hasClass( 'optional' ) ) {
  286. if ( $span.hasClass( 'invert' ) && $input.is( ':checked' )
  287. || ! $span.hasClass( 'invert' ) && ! $input.is( ':checked' ) ) {
  288. $submit.prop( 'disabled', true );
  289. return false;
  290. }
  291. }
  292. } );
  293. };
  294. wpcf7.resetCounter = function( form ) {
  295. var $form = $( form );
  296. $( '.wpcf7-character-count', $form ).each( function() {
  297. var $count = $( this );
  298. var name = $count.attr( 'data-target-name' );
  299. var down = $count.hasClass( 'down' );
  300. var starting = parseInt( $count.attr( 'data-starting-value' ), 10 );
  301. var maximum = parseInt( $count.attr( 'data-maximum-value' ), 10 );
  302. var minimum = parseInt( $count.attr( 'data-minimum-value' ), 10 );
  303. var updateCount = function( target ) {
  304. var $target = $( target );
  305. var length = $target.val().length;
  306. var count = down ? starting - length : length;
  307. $count.attr( 'data-current-value', count );
  308. $count.text( count );
  309. if ( maximum && maximum < length ) {
  310. $count.addClass( 'too-long' );
  311. } else {
  312. $count.removeClass( 'too-long' );
  313. }
  314. if ( minimum && length < minimum ) {
  315. $count.addClass( 'too-short' );
  316. } else {
  317. $count.removeClass( 'too-short' );
  318. }
  319. };
  320. $( ':input[name="' + name + '"]', $form ).each( function() {
  321. updateCount( this );
  322. $( this ).keyup( function() {
  323. updateCount( this );
  324. } );
  325. } );
  326. } );
  327. };
  328. wpcf7.notValidTip = function( target, message ) {
  329. var $target = $( target );
  330. $( '.wpcf7-not-valid-tip', $target ).remove();
  331. $( '<span></span>' ).attr( {
  332. 'class': 'wpcf7-not-valid-tip',
  333. 'role': 'alert',
  334. 'aria-hidden': 'true',
  335. } ).text( message ).appendTo( $target );
  336. if ( $target.is( '.use-floating-validation-tip *' ) ) {
  337. var fadeOut = function( target ) {
  338. $( target ).not( ':hidden' ).animate( {
  339. opacity: 0
  340. }, 'fast', function() {
  341. $( this ).css( { 'z-index': -100 } );
  342. } );
  343. };
  344. $target.on( 'mouseover', '.wpcf7-not-valid-tip', function() {
  345. fadeOut( this );
  346. } );
  347. $target.on( 'focus', ':input', function() {
  348. fadeOut( $( '.wpcf7-not-valid-tip', $target ) );
  349. } );
  350. }
  351. };
  352. wpcf7.refill = function( form, data ) {
  353. var $form = $( form );
  354. var refillCaptcha = function( $form, items ) {
  355. $.each( items, function( i, n ) {
  356. $form.find( ':input[name="' + i + '"]' ).val( '' );
  357. $form.find( 'img.wpcf7-captcha-' + i ).attr( 'src', n );
  358. var match = /([0-9]+)\.(png|gif|jpeg)$/.exec( n );
  359. $form.find( 'input:hidden[name="_wpcf7_captcha_challenge_' + i + '"]' ).attr( 'value', match[ 1 ] );
  360. } );
  361. };
  362. var refillQuiz = function( $form, items ) {
  363. $.each( items, function( i, n ) {
  364. $form.find( ':input[name="' + i + '"]' ).val( '' );
  365. $form.find( ':input[name="' + i + '"]' ).siblings( 'span.wpcf7-quiz-label' ).text( n[ 0 ] );
  366. $form.find( 'input:hidden[name="_wpcf7_quiz_answer_' + i + '"]' ).attr( 'value', n[ 1 ] );
  367. } );
  368. };
  369. if ( typeof data === 'undefined' ) {
  370. $.ajax( {
  371. type: 'GET',
  372. url: wpcf7.apiSettings.getRoute(
  373. '/contact-forms/' + wpcf7.getId( $form ) + '/refill' ),
  374. beforeSend: function( xhr ) {
  375. var nonce = $form.find( ':input[name="_wpnonce"]' ).val();
  376. if ( nonce ) {
  377. xhr.setRequestHeader( 'X-WP-Nonce', nonce );
  378. }
  379. },
  380. dataType: 'json'
  381. } ).done( function( data, status, xhr ) {
  382. if ( data.captcha ) {
  383. refillCaptcha( $form, data.captcha );
  384. }
  385. if ( data.quiz ) {
  386. refillQuiz( $form, data.quiz );
  387. }
  388. } );
  389. } else {
  390. if ( data.captcha ) {
  391. refillCaptcha( $form, data.captcha );
  392. }
  393. if ( data.quiz ) {
  394. refillQuiz( $form, data.quiz );
  395. }
  396. }
  397. };
  398. wpcf7.clearResponse = function( form ) {
  399. var $form = $( form );
  400. $form.siblings( '.screen-reader-response' ).html( '' );
  401. $( '.wpcf7-not-valid-tip', $form ).remove();
  402. $( '[aria-invalid]', $form ).attr( 'aria-invalid', 'false' );
  403. $( '.wpcf7-form-control', $form ).removeClass( 'wpcf7-not-valid' );
  404. $( '.wpcf7-response-output', $form ).hide().empty();
  405. };
  406. wpcf7.apiSettings.getRoute = function( path ) {
  407. var url = wpcf7.apiSettings.root;
  408. url = url.replace(
  409. wpcf7.apiSettings.namespace,
  410. wpcf7.apiSettings.namespace + path );
  411. return url;
  412. };
  413. } )( jQuery );
  414. /*
  415. * Polyfill for Internet Explorer
  416. * See https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
  417. */
  418. ( function () {
  419. if ( typeof window.CustomEvent === "function" ) return false;
  420. function CustomEvent ( event, params ) {
  421. params = params || { bubbles: false, cancelable: false, detail: undefined };
  422. var evt = document.createEvent( 'CustomEvent' );
  423. evt.initCustomEvent( event,
  424. params.bubbles, params.cancelable, params.detail );
  425. return evt;
  426. }
  427. CustomEvent.prototype = window.Event.prototype;
  428. window.CustomEvent = CustomEvent;
  429. } )();