scripts.js 14 KB

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