Нет описания

grunion.js 34KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  1. /* global GrunionFB_i18n: true, FB, ajax_nonce_shortcode, ajax_nonce_json, ajaxurl, postId */
  2. if ( ! window.FB ) {
  3. window.FB = {};
  4. }
  5. GrunionFB_i18n = jQuery.extend(
  6. {
  7. nameLabel: 'Name',
  8. emailLabel: 'Email',
  9. urlLabel: 'Website',
  10. commentLabel: 'Comment',
  11. newLabel: 'New Field',
  12. optionsLabel: 'Options',
  13. optionLabel: 'Option',
  14. firstOptionLabel: 'First option',
  15. problemGeneratingForm:
  16. "Oops, there was a problem generating your form. You'll likely need to try again.",
  17. moveInstructions: 'Drag up or down\nto re-arrange',
  18. moveLabel: 'move',
  19. editLabel: 'edit',
  20. savedMessage: 'Saved successfully',
  21. requiredLabel: '(required)',
  22. exitConfirmMessage:
  23. 'Are you sure you want to exit the form editor without saving? Any changes you have made will be lost.',
  24. maxNewFields: 5,
  25. invalidEmail: ' is an invalid email address.',
  26. },
  27. GrunionFB_i18n
  28. );
  29. GrunionFB_i18n.moveInstructions = GrunionFB_i18n.moveInstructions.replace( '\n', '<br />' );
  30. FB.span = jQuery( '<span>' );
  31. FB.esc_html = function ( string ) {
  32. return FB.span.text( string ).html();
  33. };
  34. FB.esc_attr = function ( string ) {
  35. string = FB.esc_html( string );
  36. return string.replace( '"', '&quot;' ).replace( "'", '&#039;' );
  37. };
  38. FB.ContactForm = ( function () {
  39. var fbForm = {
  40. // Main object that generated shortcode via AJAX call
  41. action: 'grunion_shortcode',
  42. _ajax_nonce: ajax_nonce_shortcode,
  43. to: '',
  44. subject: '',
  45. fields: {},
  46. };
  47. var defaultFields = {
  48. name: {
  49. label: GrunionFB_i18n.nameLabel,
  50. type: 'name',
  51. required: true,
  52. options: [],
  53. order: '1',
  54. },
  55. email: {
  56. label: GrunionFB_i18n.emailLabel,
  57. type: 'email',
  58. required: true,
  59. options: [],
  60. order: '2',
  61. },
  62. url: {
  63. label: GrunionFB_i18n.urlLabel,
  64. type: 'url',
  65. required: false,
  66. options: [],
  67. order: '3',
  68. },
  69. comment: {
  70. label: GrunionFB_i18n.commentLabel,
  71. type: 'textarea',
  72. required: true,
  73. options: [],
  74. order: '4',
  75. },
  76. };
  77. var debug = false; // will print errors to log if true
  78. var grunionNewCount = 0; // increment for new fields
  79. var maxNewFields = GrunionFB_i18n.maxNewFields; // See filter in ../grunion-form-view.php
  80. var optionsCache = {};
  81. var optionsCount = 0; // increment for options
  82. var shortcode;
  83. function addField() {
  84. try {
  85. grunionNewCount++;
  86. if ( grunionNewCount <= maxNewFields ) {
  87. // Add to preview
  88. jQuery( '#fb-extra-fields' ).append(
  89. '<div id="fb-new-field' +
  90. grunionNewCount +
  91. '" fieldid="' +
  92. grunionNewCount +
  93. '" class="fb-new-fields"><div class="fb-fields"><div id="' +
  94. grunionNewCount +
  95. '" class="fb-remove"></div><label fieldid="' +
  96. grunionNewCount +
  97. '" for="fb-field' +
  98. grunionNewCount +
  99. '"><span class="label-text">' +
  100. GrunionFB_i18n.newLabel +
  101. '</span> </label><input type="text" id="fb-field' +
  102. grunionNewCount +
  103. '" disabled="disabled" /></div></div>'
  104. );
  105. // Add to form object
  106. fbForm.fields[ grunionNewCount ] = {
  107. label: GrunionFB_i18n.newLabel,
  108. type: 'text',
  109. required: false,
  110. options: [],
  111. order: '5',
  112. };
  113. if ( grunionNewCount === maxNewFields ) {
  114. jQuery( '#fb-new-field' ).hide();
  115. }
  116. // Reset form for this new field
  117. optionsCount = 0;
  118. optionsCache = {};
  119. jQuery( '#fb-new-options' ).html(
  120. '<label for="fb-option0">' +
  121. GrunionFB_i18n.optionsLabel +
  122. '</label><input type="text" id="fb-option0" optionid="0" value="' +
  123. GrunionFB_i18n.firstOptionLabel +
  124. '" class="fb-options" />'
  125. );
  126. jQuery( '#fb-options' ).hide();
  127. jQuery( '#fb-new-label' ).val( GrunionFB_i18n.newLabel );
  128. jQuery( '#fb-new-type' ).val( 'text' );
  129. jQuery( '#fb-field-id' ).val( grunionNewCount );
  130. setTimeout( function () {
  131. jQuery( '#fb-new-label' ).focus().select();
  132. }, 100 );
  133. } else {
  134. jQuery( '#fb-new-field' ).hide();
  135. }
  136. } catch ( e ) {
  137. if ( debug ) {
  138. console.log( 'addField(): ' + e );
  139. }
  140. }
  141. }
  142. function addOption() {
  143. try {
  144. optionsCount = jQuery( '#fb-new-options .fb-options' ).length;
  145. var thisId = jQuery( '#fb-field-id' ).val();
  146. var thisType = jQuery( '#fb-new-type' ).val();
  147. if ( thisType === 'radio' ) {
  148. // Add to right col
  149. jQuery( '#fb-new-options' ).append(
  150. '<div id="fb-option-box-' +
  151. optionsCount +
  152. '" class="fb-new-fields"><span optionid="' +
  153. optionsCount +
  154. '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' +
  155. optionsCount +
  156. '" optionid="' +
  157. optionsCount +
  158. '" value="' +
  159. GrunionFB_i18n.optionLabel +
  160. '" class="fb-options" /><div>'
  161. );
  162. // Add to preview
  163. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).append(
  164. '<div id="fb-radio-' +
  165. thisId +
  166. '-' +
  167. optionsCount +
  168. '"><input type="radio" disabled="disabled" id="fb-field' +
  169. thisId +
  170. '" name="radio-' +
  171. thisId +
  172. '" /><span>' +
  173. GrunionFB_i18n.optionLabel +
  174. '</span><div class="clear"></div></div>'
  175. );
  176. } else if ( 'checkbox-multiple' === thisType ) {
  177. // Add to right col
  178. jQuery( '#fb-new-options' ).append(
  179. '<div id="fb-option-box-' +
  180. optionsCount +
  181. '" class="fb-new-fields"><span optionid="' +
  182. optionsCount +
  183. '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' +
  184. optionsCount +
  185. '" optionid="' +
  186. optionsCount +
  187. '" value="' +
  188. GrunionFB_i18n.optionLabel +
  189. '" class="fb-options" /><div>'
  190. );
  191. // Add to preview
  192. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).append(
  193. '<div id="fb-checkbox-multiple-' +
  194. thisId +
  195. '-' +
  196. optionsCount +
  197. '"><input type="checkbox" disabled="disabled" id="fb-field' +
  198. thisId +
  199. '" name="checkbox-multiple-' +
  200. thisId +
  201. '" /><span>' +
  202. GrunionFB_i18n.optionLabel +
  203. '</span><div class="clear"></div></div>'
  204. );
  205. } else {
  206. // Add to right col
  207. jQuery( '#fb-new-options' ).append(
  208. '<div id="fb-option-box-' +
  209. optionsCount +
  210. '" class="fb-new-fields"><span optionid="' +
  211. optionsCount +
  212. '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' +
  213. optionsCount +
  214. '" optionid="' +
  215. optionsCount +
  216. '" value="" class="fb-options" /><div>'
  217. );
  218. // Add to preview
  219. jQuery( '#fb-field' + thisId ).append(
  220. '<option id="fb-' +
  221. thisId +
  222. '-' +
  223. optionsCount +
  224. '" value="' +
  225. thisId +
  226. '-' +
  227. optionsCount +
  228. '"></option>'
  229. );
  230. }
  231. // Add to fbForm object
  232. fbForm.fields[ thisId ].options[ optionsCount ] = '';
  233. // Add focus to new field
  234. jQuery( '#fb-option' + optionsCount )
  235. .focus()
  236. .select();
  237. } catch ( e ) {
  238. if ( debug ) {
  239. console.log( 'addOption(): ' + e );
  240. }
  241. }
  242. }
  243. function buildPreview() {
  244. try {
  245. if ( fbForm.to ) {
  246. jQuery( '#fb-field-my-email' ).val( fbForm.to );
  247. }
  248. if ( fbForm.subject ) {
  249. jQuery( '#fb-field-subject' ).val( fbForm.subject );
  250. }
  251. // Loop over and add fields
  252. jQuery.each( fbForm.fields, function ( index, value ) {
  253. jQuery( '#fb-extra-fields' ).before(
  254. '<div class="fb-new-fields ui-state-default" fieldid="' +
  255. index +
  256. '" id="fb-new-field' +
  257. index +
  258. '"><div class="fb-fields"></div></div>'
  259. );
  260. jQuery( '#fb-field-id' ).val( index );
  261. optionsCache[ index ] = {};
  262. optionsCache[ index ].options = [];
  263. if (
  264. 'radio' === value.type ||
  265. 'select' === value.type ||
  266. 'checkbox-multiple' === value.type
  267. ) {
  268. jQuery.each( value.options, function ( i, value ) {
  269. optionsCache[ index ].options[ i ] = value;
  270. } );
  271. }
  272. updateType( value.type, value.label, value.required );
  273. } );
  274. } catch ( e ) {
  275. if ( debug ) {
  276. console.log( 'buildPreview(): ' + e );
  277. }
  278. }
  279. }
  280. function customOptions( id, thisType ) {
  281. try {
  282. var thisOptions = '';
  283. for ( var i = 0; i < optionsCache[ id ].options.length; i++ ) {
  284. if ( optionsCache[ id ].options[ i ] !== undefined ) {
  285. if ( thisType === 'radio' ) {
  286. thisOptions =
  287. thisOptions +
  288. '<div id="fb-radio-' +
  289. id +
  290. '-' +
  291. i +
  292. '"><input type="radio" id="fb-field' +
  293. id +
  294. '" name="radio-' +
  295. id +
  296. '" /><span>' +
  297. FB.esc_html( optionsCache[ id ].options[ i ] ) +
  298. '</span><div class="clear"></div></div>';
  299. } else if ( 'checkbox-multiple' === thisType ) {
  300. thisOptions =
  301. thisOptions +
  302. '<div id="fb-checkbox-multiple-' +
  303. id +
  304. '-' +
  305. i +
  306. '"><input type="checkbox" id="fb-field' +
  307. id +
  308. '" name="checkbox-multiple-' +
  309. id +
  310. '" /><span>' +
  311. FB.esc_html( optionsCache[ id ].options[ i ] ) +
  312. '</span><div class="clear"></div></div>';
  313. } else {
  314. thisOptions =
  315. thisOptions +
  316. '<option id="fb-' +
  317. id +
  318. '-' +
  319. i +
  320. '" value="' +
  321. id +
  322. '-' +
  323. i +
  324. '">' +
  325. FB.esc_html( optionsCache[ id ].options[ i ] ) +
  326. '</option>';
  327. }
  328. }
  329. }
  330. return thisOptions;
  331. } catch ( e ) {
  332. if ( debug ) {
  333. console.log( 'customOptions(): ' + e );
  334. }
  335. }
  336. }
  337. function deleteField( that ) {
  338. try {
  339. grunionNewCount--;
  340. var thisId = that.attr( 'id' );
  341. delete fbForm.fields[ thisId ];
  342. jQuery( '#' + thisId )
  343. .parent()
  344. .parent()
  345. .remove();
  346. if ( grunionNewCount <= maxNewFields ) {
  347. jQuery( '#fb-new-field' ).show();
  348. }
  349. } catch ( e ) {
  350. if ( debug ) {
  351. console.log( 'deleteField(): ' + e );
  352. }
  353. }
  354. }
  355. function editField( that ) {
  356. try {
  357. scroll( 0, 0 );
  358. setTimeout( function () {
  359. jQuery( '#fb-new-label' ).focus().select();
  360. }, 100 );
  361. var thisId = that.parent().attr( 'fieldid' );
  362. loadFieldEditor( thisId );
  363. } catch ( e ) {
  364. if ( debug ) {
  365. console.log( 'editField(): ' + e );
  366. }
  367. }
  368. }
  369. function grabShortcode() {
  370. try {
  371. // Takes fbForm object and returns shortcode syntax
  372. jQuery.post( ajaxurl, fbForm, function ( response ) {
  373. shortcode = response;
  374. } );
  375. } catch ( e ) {
  376. alert( GrunionFB_i18n.problemGeneratingForm );
  377. if ( debug ) {
  378. console.log( 'grabShortcode(): ' + e );
  379. }
  380. }
  381. }
  382. function hideDesc() {
  383. jQuery( '#fb-desc' ).hide();
  384. jQuery( '#fb-add-field' ).show();
  385. }
  386. function hidePopup() {
  387. try {
  388. // copied from wp-includes/js/thickbox/thickbox.js
  389. jQuery( '#TB_imageOff', window.parent.document ).unbind( 'click' );
  390. jQuery( '#TB_closeWindowButton', window.parent.document ).unbind( 'click' );
  391. jQuery( '#TB_window', window.parent.document ).fadeOut( 'fast' );
  392. jQuery( 'body', window.parent.document ).removeClass( 'modal-open' );
  393. jQuery( '#TB_window,#TB_overlay,#TB_HideSelect', window.parent.document )
  394. .trigger( 'unload' )
  395. .unbind()
  396. .remove();
  397. jQuery( '#TB_load', window.parent.document ).remove();
  398. if ( typeof window.parent.document.body.style.maxHeight === 'undefined' ) {
  399. //if IE 6
  400. jQuery( 'body', 'html', window.parent.document ).css( { height: 'auto', width: 'auto' } );
  401. jQuery( 'html', window.parent.document ).css( 'overflow', '' );
  402. }
  403. window.parent.document.onkeydown = '';
  404. window.parent.document.onkeyup = '';
  405. return false;
  406. } catch ( e ) {
  407. if ( debug ) {
  408. console.log( 'hidePopup(): ' + e );
  409. }
  410. }
  411. }
  412. function hideShowEditLink( whichType, that ) {
  413. try {
  414. if ( whichType === 'show' ) {
  415. // Prevents showing links twice
  416. if ( jQuery( '.fb-edit-field' ).is( ':visible' ) ) {
  417. jQuery( '.fb-edit-field' ).remove();
  418. }
  419. that
  420. .find( 'label' )
  421. .prepend(
  422. '<span class="right fb-edit-field" style="font-weight: normal;"><a href="" class="fb-reorder"><div style="display: none;">' +
  423. GrunionFB_i18n.moveInstructions +
  424. '</div>' +
  425. GrunionFB_i18n.moveLabel +
  426. '</a>&nbsp;&nbsp;<span style="color: #C7D8DE;">|</span>&nbsp;&nbsp;<a href="" class="fb-edit">' +
  427. GrunionFB_i18n.editLabel +
  428. '</a></span>'
  429. );
  430. } else {
  431. jQuery( '.fb-edit-field' ).remove();
  432. }
  433. } catch ( e ) {
  434. if ( debug ) {
  435. console.log( 'hideShowEditLink(): ' + e );
  436. }
  437. }
  438. }
  439. function loadFieldEditor( id ) {
  440. try {
  441. var thisType = fbForm.fields[ id ].type;
  442. jQuery( '#fb-options' ).hide();
  443. // Reset hidden field ID
  444. jQuery( '#fb-field-id' ).val( id );
  445. // Load label
  446. jQuery( '#fb-new-label' ).val( fbForm.fields[ id ].label );
  447. // Load type
  448. jQuery( '#fb-new-type' ).val( fbForm.fields[ id ].type );
  449. // Load required
  450. if ( fbForm.fields[ id ].required ) {
  451. jQuery( '#fb-new-required' ).prop( 'checked', true );
  452. } else {
  453. jQuery( '#fb-new-required' ).prop( 'checked', false );
  454. }
  455. // Load options if there are any
  456. if ( 'select' === thisType || 'radio' === thisType || 'checkbox-multiple' === thisType ) {
  457. var thisOptions = fbForm.fields[ id ].options;
  458. jQuery( '#fb-options' ).show();
  459. jQuery( '#fb-new-options' ).html( '' ); // Clear it all out
  460. for ( var i = 0; i < thisOptions.length; i++ ) {
  461. if ( thisOptions[ i ] !== undefined ) {
  462. if ( thisType === 'radio' ) {
  463. jQuery( '#fb-new-options' ).append(
  464. '<div id="fb-option-box-' +
  465. i +
  466. '" class="fb-new-fields"><span optionid="' +
  467. i +
  468. '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' +
  469. i +
  470. '" optionid="' +
  471. i +
  472. '" value="' +
  473. FB.esc_attr( fbForm.fields[ id ].options[ i ] ) +
  474. '" class="fb-options" /><div>'
  475. );
  476. } else {
  477. jQuery( '#fb-new-options' ).append(
  478. '<div id="fb-option-box-' +
  479. i +
  480. '" class="fb-new-fields"><span optionid="' +
  481. i +
  482. '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' +
  483. i +
  484. '" optionid="' +
  485. i +
  486. '" value="' +
  487. FB.esc_attr( fbForm.fields[ id ].options[ i ] ) +
  488. '" class="fb-options" /><div>'
  489. );
  490. }
  491. }
  492. }
  493. }
  494. // Load editor & hide description
  495. hideDesc();
  496. } catch ( e ) {
  497. if ( debug ) {
  498. console.log( 'loadFieldEditor(): ' + e );
  499. }
  500. }
  501. }
  502. function parseShortcode( data ) {
  503. try {
  504. // Clean up fields by resetting them
  505. fbForm.fields = {};
  506. // Add new fields
  507. if ( ! data ) {
  508. fbForm.fields = defaultFields;
  509. } else {
  510. jQuery.each( data.fields, function ( index, value ) {
  511. if ( 1 === parseInt( value.required, 10 ) ) {
  512. value.required = 'true';
  513. }
  514. fbForm.fields[ index ] = value;
  515. } );
  516. fbForm.to = data.to;
  517. fbForm.subject = data.subject;
  518. }
  519. } catch ( e ) {
  520. if ( debug ) {
  521. console.log( 'parseShortcode(): ' + e );
  522. }
  523. }
  524. }
  525. function removeOption( optionId ) {
  526. try {
  527. var thisId = jQuery( '#fb-field-id' ).val();
  528. var thisVal = jQuery( '#fb-option' + optionId ).val();
  529. var thisType = jQuery( '#fb-new-type' ).val();
  530. // Remove from right
  531. jQuery( '#fb-option-box-' + optionId ).remove();
  532. // Remove from preview
  533. if ( thisType === 'radio' ) {
  534. jQuery( '#fb-radio-' + thisId + '-' + optionId ).remove();
  535. } else if ( 'checkbox-multiple' === thisType ) {
  536. jQuery( '#fb-checkbox-multiple-' + thisId + '-' + optionId ).remove();
  537. } else {
  538. jQuery( '#fb-' + thisId + '-' + optionId ).remove();
  539. }
  540. // Remove from fbForm object
  541. var idx = fbForm.fields[ thisId ].options.indexOf( thisVal );
  542. if ( idx !== -1 ) {
  543. fbForm.fields[ thisId ].options.splice( idx, 1 );
  544. }
  545. } catch ( e ) {
  546. if ( debug ) {
  547. console.log( 'removeOption(): ' + e );
  548. }
  549. }
  550. }
  551. function removeOptions() {
  552. try {
  553. var thisId = jQuery( '#fb-field-id' ).val();
  554. jQuery( '#fb-options' ).hide();
  555. if ( optionsCache[ thisId ] === undefined ) {
  556. optionsCache[ thisId ] = {};
  557. }
  558. optionsCache[ thisId ].options = fbForm.fields[ thisId ].options; // Save options in case they change their mind
  559. fbForm.fields[ thisId ].options = []; // Removes all options
  560. } catch ( e ) {
  561. if ( debug ) {
  562. console.log( 'removeOptions(): ' + e );
  563. }
  564. }
  565. }
  566. function sendShortcodeToEditor() {
  567. try {
  568. // Serialize fields
  569. jQuery( 'div#sortable div.fb-new-fields' ).each( function ( index ) {
  570. var thisId = jQuery( this ).attr( 'fieldid' );
  571. fbForm.fields[ thisId ].order = index;
  572. } );
  573. // Export to WYSIWYG editor
  574. jQuery.post( ajaxurl, fbForm, function ( response ) {
  575. var isVisual = jQuery( '#edButtonPreview', window.parent.document ).hasClass( 'active' );
  576. /* WP 3.3+ */
  577. if ( ! isVisual ) {
  578. isVisual = jQuery( '#wp-content-wrap', window.parent.document ).hasClass( 'tmce-active' );
  579. }
  580. var win = window.dialogArguments || opener || parent || top;
  581. var currentCode;
  582. if ( isVisual ) {
  583. currentCode = win.tinyMCE.activeEditor.getContent();
  584. } else {
  585. currentCode = jQuery( '#editorcontainer textarea', window.parent.document ).val();
  586. /* WP 3.3+ */
  587. if ( typeof currentCode !== 'string' ) {
  588. currentCode = jQuery( '.wp-editor-area', window.parent.document ).val();
  589. }
  590. }
  591. var regexp = new RegExp(
  592. '\\[contact-form\\b.*?\\/?\\](?:[\\s\\S]+?\\[\\/contact-form\\])?'
  593. );
  594. // Remove new lines that cause BR tags to show up
  595. response = response.replace( /\n/g, ' ' );
  596. // Convert characters to comma
  597. response = response.replace( /%26#x002c;/g, ',' );
  598. // Add new shortcode
  599. if ( currentCode.match( regexp ) ) {
  600. if ( isVisual ) {
  601. win.tinyMCE.activeEditor.execCommand(
  602. 'mceSetContent',
  603. false,
  604. currentCode.replace( regexp, response )
  605. );
  606. } else {
  607. // looks like the visual editor is disabled,
  608. // update the contents of the post directly
  609. jQuery( '#content', window.parent.document ).val(
  610. currentCode.replace( regexp, response )
  611. );
  612. }
  613. } else {
  614. try {
  615. win.send_to_editor( response );
  616. } catch ( e ) {
  617. if ( isVisual ) {
  618. win.tinyMCE.activeEditor.execCommand( 'mceInsertContent', false, response );
  619. } else {
  620. // looks like the visual editor is disabled,
  621. // update the contents of the post directly
  622. jQuery( '#content', window.parent.document ).val( currentCode + response );
  623. }
  624. }
  625. }
  626. hidePopup();
  627. } );
  628. } catch ( e ) {
  629. if ( debug ) {
  630. console.log( 'sendShortcodeToEditor(): ' + e );
  631. }
  632. }
  633. }
  634. function showDesc() {
  635. jQuery( '#fb-desc' ).show();
  636. jQuery( '#fb-add-field' ).hide();
  637. }
  638. function showAndHideMessage( message ) {
  639. try {
  640. var newMessage = ! message ? GrunionFB_i18n.savedMessage : message;
  641. jQuery( '#fb-success' ).text( newMessage );
  642. jQuery( '#fb-success' ).slideDown( 'fast' );
  643. setTimeout( function () {
  644. jQuery( '#fb-success' ).slideUp( 'fast' );
  645. }, 2500 );
  646. } catch ( e ) {
  647. if ( debug ) {
  648. console.log( 'showAndHideMessage(): ' + e );
  649. }
  650. }
  651. }
  652. function switchTabs( whichType ) {
  653. try {
  654. if ( whichType === 'preview' ) {
  655. if ( ! validateEmails( jQuery( '#fb-field-my-email' ).val() ) ) {
  656. return;
  657. }
  658. jQuery( '#tab-preview a' ).addClass( 'current' );
  659. jQuery( '#tab-settings a' ).removeClass( 'current' );
  660. jQuery( '#fb-preview-form, #fb-desc' ).show();
  661. jQuery( '#fb-email-settings, #fb-email-desc' ).hide();
  662. showAndHideMessage( GrunionFB_i18n.savedMessage );
  663. } else {
  664. jQuery( '#tab-preview a' ).removeClass( 'current' );
  665. jQuery( '#tab-settings a' ).addClass( 'current' );
  666. jQuery( '#fb-preview-form, #fb-desc, #fb-add-field' ).hide();
  667. jQuery( '#fb-email-settings, #fb-email-desc' ).show();
  668. jQuery( '#fb-field-my-email' ).focus().select();
  669. }
  670. } catch ( e ) {
  671. if ( debug ) {
  672. console.log( 'switchTabs(): ' + e );
  673. }
  674. }
  675. }
  676. function validateEmails( emails ) {
  677. // Field is allowed to be empty :)
  678. if ( 0 === emails.length ) {
  679. return true;
  680. }
  681. var $e,
  682. emailList = emails.split( ',' );
  683. for ( $e = 0; $e < emailList.length; $e++ ) {
  684. if ( false === validateEmail( emailList[ $e ] ) ) {
  685. alert( emailList[ $e ] + GrunionFB_i18n.invalidEmail );
  686. return false;
  687. }
  688. }
  689. return true;
  690. }
  691. /* Uses The Official Standard: RFC 5322 -- http://www.regular-expressions.info/email.html */
  692. function validateEmail( email ) {
  693. var re = /^(?=[a-z0-9@.!#$%&'*+/=?^_`{|}~-]{6,254}$)(?=[a-z0-9.!#$%&'*+/=?^_`{|}~-]{1,64}@)[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:(?=[a-z0-9-]{1,63}\.)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?=[a-z0-9-]{1,63}$)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i;
  694. return re.test( email );
  695. }
  696. function updateLabel() {
  697. try {
  698. var thisId = jQuery( '#fb-field-id' ).val();
  699. var thisLabel = jQuery( '#fb-new-label' ).val();
  700. // Update preview
  701. if ( thisLabel.length === 0 ) {
  702. jQuery( '#fb-new-field' + thisId + ' label .label-text' ).text( GrunionFB_i18n.newLabel );
  703. } else {
  704. jQuery( '#fb-new-field' + thisId + ' label .label-text' ).text( thisLabel );
  705. }
  706. // Update fbForm object
  707. fbForm.fields[ thisId ].label = thisLabel;
  708. } catch ( e ) {
  709. if ( debug ) {
  710. console.log( 'updateLabel(): ' + e );
  711. }
  712. }
  713. }
  714. function updateMyEmail() {
  715. try {
  716. var thisEmail = jQuery( '#fb-field-my-email' ).val();
  717. fbForm.to = thisEmail;
  718. } catch ( e ) {
  719. if ( debug ) {
  720. console.log( 'updateMyEmail(): ' + e );
  721. }
  722. }
  723. }
  724. function updateOption( that ) {
  725. try {
  726. var thisId = jQuery( '#fb-field-id' ).val();
  727. var thisOptionid = that.attr( 'optionid' );
  728. var thisOptionValue = that.val();
  729. var thisType = jQuery( '#fb-new-type' ).val();
  730. // Update preview
  731. if ( thisType === 'radio' ) {
  732. jQuery( '#fb-radio-' + thisId + '-' + thisOptionid + ' span' ).text( thisOptionValue );
  733. } else if ( 'checkbox-multiple' === thisType ) {
  734. jQuery( '#fb-checkbox-multiple-' + thisId + '-' + thisOptionid + ' span' ).text(
  735. thisOptionValue
  736. );
  737. } else {
  738. jQuery( '#fb-' + thisId + '-' + thisOptionid ).text( thisOptionValue );
  739. }
  740. // Update fbForm object
  741. fbForm.fields[ thisId ].options[ thisOptionid ] = thisOptionValue;
  742. } catch ( e ) {
  743. if ( debug ) {
  744. console.log( 'updateOption(): ' + e );
  745. }
  746. }
  747. }
  748. function updateRequired() {
  749. try {
  750. var thisId = jQuery( '#fb-field-id' ).val();
  751. var thisChecked = jQuery( '#fb-new-required' ).is( ':checked' );
  752. // Update object and preview
  753. if ( thisChecked ) {
  754. fbForm.fields[ thisId ].required = true;
  755. jQuery( '#fb-new-field' + thisId + ' label' ).append(
  756. '<span class="label-required">' + GrunionFB_i18n.requiredLabel + '</span>'
  757. );
  758. } else {
  759. fbForm.fields[ thisId ].required = false;
  760. jQuery( '#fb-new-field' + thisId + ' label .label-required' ).remove();
  761. }
  762. } catch ( e ) {
  763. if ( debug ) {
  764. console.log( 'updateRequired(): ' + e );
  765. }
  766. }
  767. }
  768. function updateSubject() {
  769. try {
  770. var thisSubject = jQuery( '#fb-field-subject' ).val();
  771. fbForm.subject = thisSubject;
  772. } catch ( e ) {
  773. if ( debug ) {
  774. console.log( 'updateSubject(): ' + e );
  775. }
  776. }
  777. }
  778. function updateType( thisType, thisLabelText, thisRequired ) {
  779. try {
  780. var thisId = jQuery( '#fb-field-id' ).val();
  781. if ( ! thisType ) {
  782. thisType = jQuery( '#fb-new-type' ).val();
  783. }
  784. if ( ! thisLabelText ) {
  785. thisLabelText = jQuery( '#fb-new-field' + thisId + ' .label-text' ).text();
  786. }
  787. var isRequired = thisRequired
  788. ? '<span class="label-required">' + GrunionFB_i18n.requiredLabel + '</span>'
  789. : '';
  790. var thisLabel =
  791. '<label fieldid="' +
  792. thisId +
  793. '" for="fb-field' +
  794. thisId +
  795. '"><span class="label-text">' +
  796. FB.esc_html( thisLabelText ) +
  797. '</span>' +
  798. isRequired +
  799. '</label>';
  800. var thisRadio =
  801. '<input type="radio" name="radio-' +
  802. thisId +
  803. '" id="fb-field' +
  804. thisId +
  805. ' "disabled="disabled" />';
  806. var thisRadioLabel =
  807. '<label fieldid="' +
  808. thisId +
  809. '" for="fb-field' +
  810. thisId +
  811. '" class="fb-radio-label"><span class="label-text">' +
  812. FB.esc_html( thisLabelText ) +
  813. '</span>' +
  814. isRequired +
  815. '</label>';
  816. var thisRadioRemove = '<div class="fb-remove fb-remove-small" id="' + thisId + '"></div>';
  817. var thisRemove = '<div class="fb-remove" id="' + thisId + '"></div>';
  818. var thisCheckbox =
  819. '<input type="checkbox" id="fb-field' + thisId + '" "disabled="disabled" />';
  820. var thisCheckboxMultiple =
  821. '<input type="checkbox" id="fb-field' + thisId + '" "disabled="disabled" />';
  822. var thisCheckboxMultipleRemove =
  823. '<div class="fb-remove fb-remove-small" id="' + thisId + '"></div>';
  824. var thisText = '<input type="text" id="fb-field' + thisId + '" "disabled="disabled" />';
  825. var thisTextarea = '<textarea id="fb-field' + thisId + '" "disabled="disabled"></textarea>';
  826. var thisClear = '<div class="clear"></div>';
  827. var thisSelect =
  828. '<select id="fb-field' +
  829. thisId +
  830. '" fieldid="' +
  831. thisId +
  832. '"><option id="fb-' +
  833. thisId +
  834. '-' +
  835. optionsCount +
  836. '" value="' +
  837. thisId +
  838. '-' +
  839. optionsCount +
  840. '">' +
  841. GrunionFB_i18n.firstOptionLabel +
  842. '</option></select>';
  843. switch ( thisType ) {
  844. case 'checkbox':
  845. removeOptions();
  846. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).html(
  847. thisRadioRemove + thisCheckbox + thisRadioLabel + thisClear
  848. );
  849. break;
  850. case 'checkbox-multiple':
  851. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).html(
  852. thisLabel +
  853. thisCheckboxMultipleRemove +
  854. '<div fieldid="' +
  855. thisId +
  856. '" id="fb-custom-checkbox-multiple' +
  857. thisId +
  858. '"></div>'
  859. );
  860. if (
  861. optionsCache[ thisId ] !== undefined &&
  862. optionsCache[ thisId ].options.length !== 0
  863. ) {
  864. fbForm.fields[ thisId ].options = optionsCache[ thisId ].options;
  865. jQuery( '#fb-custom-checkbox-multiple' + thisId ).append(
  866. customOptions( thisId, thisType )
  867. );
  868. } else {
  869. jQuery( '#fb-new-options' ).html(
  870. '<label for="fb-option0">' +
  871. GrunionFB_i18n.optionsLabel +
  872. '</label><input type="text" id="fb-option0" optionid="0" value="' +
  873. GrunionFB_i18n.firstOptionLabel +
  874. '" class="fb-options" />'
  875. );
  876. jQuery( '#fb-custom-checkbox-multiple' + thisId ).append(
  877. '<div id="fb-checkbox-multiple-' +
  878. thisId +
  879. '-0">' +
  880. thisCheckboxMultiple +
  881. '<span>' +
  882. GrunionFB_i18n.firstOptionLabel +
  883. '</span>' +
  884. thisClear +
  885. '</div>'
  886. );
  887. fbForm.fields[ thisId ].options[ optionsCount ] = GrunionFB_i18n.firstOptionLabel;
  888. }
  889. jQuery( '#fb-options' ).show();
  890. setTimeout( function () {
  891. jQuery( '#fb-option0' ).focus().select();
  892. }, 100 );
  893. break;
  894. case 'email':
  895. removeOptions();
  896. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).html(
  897. thisRemove + thisLabel + thisText
  898. );
  899. break;
  900. case 'name':
  901. removeOptions();
  902. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).html(
  903. thisRemove + thisLabel + thisText
  904. );
  905. break;
  906. case 'radio':
  907. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).html(
  908. thisLabel +
  909. thisRadioRemove +
  910. '<div fieldid="' +
  911. thisId +
  912. '" id="fb-custom-radio' +
  913. thisId +
  914. '"></div>'
  915. );
  916. if (
  917. optionsCache[ thisId ] !== undefined &&
  918. optionsCache[ thisId ].options.length !== 0
  919. ) {
  920. fbForm.fields[ thisId ].options = optionsCache[ thisId ].options;
  921. jQuery( '#fb-custom-radio' + thisId ).append( customOptions( thisId, thisType ) );
  922. } else {
  923. jQuery( '#fb-new-options' ).html(
  924. '<label for="fb-option0">' +
  925. GrunionFB_i18n.optionsLabel +
  926. '</label><input type="text" id="fb-option0" optionid="0" value="' +
  927. GrunionFB_i18n.firstOptionLabel +
  928. '" class="fb-options" />'
  929. );
  930. jQuery( '#fb-custom-radio' + thisId ).append(
  931. '<div id="fb-radio-' +
  932. thisId +
  933. '-0">' +
  934. thisRadio +
  935. '<span>' +
  936. GrunionFB_i18n.firstOptionLabel +
  937. '</span>' +
  938. thisClear +
  939. '</div>'
  940. );
  941. fbForm.fields[ thisId ].options[ optionsCount ] = GrunionFB_i18n.firstOptionLabel;
  942. }
  943. jQuery( '#fb-options' ).show();
  944. setTimeout( function () {
  945. jQuery( '#fb-option0' ).focus().select();
  946. }, 100 );
  947. break;
  948. case 'select':
  949. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).html(
  950. thisRemove + thisLabel + thisSelect
  951. );
  952. if (
  953. optionsCache[ thisId ] !== undefined &&
  954. optionsCache[ thisId ].options.length !== 0
  955. ) {
  956. fbForm.fields[ thisId ].options = optionsCache[ thisId ].options;
  957. jQuery( '#fb-field' + thisId ).html( customOptions( thisId, thisType ) );
  958. } else {
  959. jQuery( '#fb-new-options' ).html(
  960. '<label for="fb-option0">' +
  961. GrunionFB_i18n.optionsLabel +
  962. '</label><input type="text" id="fb-option0" optionid="0" value="' +
  963. GrunionFB_i18n.firstOptionLabel +
  964. '" class="fb-options" />'
  965. );
  966. fbForm.fields[ thisId ].options[ optionsCount ] = GrunionFB_i18n.firstOptionLabel;
  967. }
  968. jQuery( '#fb-options' ).show();
  969. setTimeout( function () {
  970. jQuery( '#fb-option0' ).focus().select();
  971. }, 100 );
  972. break;
  973. case 'text':
  974. removeOptions();
  975. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).html(
  976. thisRemove + thisLabel + thisText
  977. );
  978. break;
  979. case 'textarea':
  980. removeOptions();
  981. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).html(
  982. thisRemove + thisLabel + thisTextarea
  983. );
  984. break;
  985. case 'url':
  986. removeOptions();
  987. jQuery( '#fb-new-field' + thisId + ' .fb-fields' ).html(
  988. thisRemove + thisLabel + thisText
  989. );
  990. break;
  991. }
  992. // update object
  993. fbForm.fields[ thisId ].type = thisType;
  994. } catch ( e ) {
  995. if ( debug ) {
  996. console.log( 'updateType(): ' + e );
  997. }
  998. }
  999. }
  1000. return {
  1001. resizePop: function () {
  1002. try {
  1003. //Thickbox won't resize for some reason, we are manually doing it here
  1004. var totalWidth = jQuery( 'body', window.parent.document ).width();
  1005. var totalHeight = jQuery( 'body', window.parent.document ).height();
  1006. var isIE6 = typeof document.body.style.maxHeight === 'undefined';
  1007. jQuery( '#TB_window, #TB_iframeContent', window.parent.document ).css( 'width', '768px' );
  1008. jQuery( '#TB_window', window.parent.document ).css( {
  1009. left: ( totalWidth - 768 ) / 2 + 'px',
  1010. top: '23px',
  1011. position: 'absolute',
  1012. marginLeft: '0',
  1013. } );
  1014. if ( ! isIE6 ) {
  1015. // take away IE6
  1016. jQuery( '#TB_window, #TB_iframeContent', window.parent.document ).css(
  1017. 'height',
  1018. totalHeight - 73 + 'px'
  1019. );
  1020. }
  1021. } catch ( e ) {
  1022. if ( debug ) {
  1023. console.log( 'resizePop(): ' + e );
  1024. }
  1025. }
  1026. },
  1027. init: function () {
  1028. // Scroll to top of page
  1029. window.parent.scroll( 0, 0 );
  1030. //Check for existing form data
  1031. var contentSource;
  1032. if (
  1033. jQuery( '#edButtonPreview', window.parent.document ).hasClass( 'active' ) ||
  1034. jQuery( '#wp-content-wrap', window.parent.document ).hasClass( 'tmce-active' )
  1035. ) {
  1036. var win = window.dialogArguments || opener || parent || top;
  1037. contentSource = win.tinyMCE.activeEditor.getContent();
  1038. } else {
  1039. contentSource = jQuery( '#content', window.parent.document ).val();
  1040. }
  1041. var data = {
  1042. action: 'grunion_shortcode_to_json',
  1043. _ajax_nonce: ajax_nonce_json,
  1044. post_id: postId,
  1045. content: contentSource,
  1046. };
  1047. var $doc = jQuery( document );
  1048. jQuery.post( ajaxurl, data, function ( response ) {
  1049. // Setup fbForm
  1050. parseShortcode( jQuery.parseJSON( response ) );
  1051. // Now build out the preview form
  1052. buildPreview();
  1053. } );
  1054. // actions
  1055. jQuery( '.fb-add-field' ).click( function () {
  1056. addField();
  1057. hideDesc();
  1058. return false;
  1059. } );
  1060. jQuery( '#fb-new-label' ).keyup( function () {
  1061. updateLabel();
  1062. } );
  1063. jQuery( '#fb-new-type' ).change( function () {
  1064. updateType();
  1065. } );
  1066. jQuery( '#fb-new-required' ).click( function () {
  1067. updateRequired();
  1068. } );
  1069. $doc.on( 'click', '.fb-remove', function () {
  1070. showDesc();
  1071. deleteField( jQuery( this ) );
  1072. grabShortcode();
  1073. } );
  1074. jQuery( '#fb-preview' ).submit( function () {
  1075. sendShortcodeToEditor();
  1076. return false;
  1077. } );
  1078. jQuery( '#TB_overlay, #TB_closeWindowButton', window.parent.document ).mousedown(
  1079. function () {
  1080. if ( confirm( GrunionFB_i18n.exitConfirmMessage ) ) {
  1081. hidePopup();
  1082. }
  1083. }
  1084. );
  1085. $doc.on( 'click', '#fb-another-option', function () {
  1086. addOption();
  1087. } );
  1088. $doc.on( 'keyup', '.fb-options', function () {
  1089. updateOption( jQuery( this ) );
  1090. } );
  1091. $doc.on( 'click', '.fb-remove-option', function () {
  1092. removeOption( jQuery( this ).attr( 'optionid' ) );
  1093. } );
  1094. jQuery( '#tab-preview a' ).click( function () {
  1095. switchTabs( 'preview' );
  1096. return false;
  1097. } );
  1098. jQuery( '#fb-prev-form' ).click( function () {
  1099. switchTabs( 'preview' );
  1100. return false;
  1101. } );
  1102. jQuery( '#tab-settings a' ).click( function () {
  1103. switchTabs();
  1104. return false;
  1105. } );
  1106. jQuery( '#fb-field-my-email' ).blur( function () {
  1107. updateMyEmail();
  1108. } );
  1109. jQuery( '#fb-field-subject' ).blur( function () {
  1110. updateSubject();
  1111. } );
  1112. $doc.on( 'mouseenter', '.fb-form-case .fb-new-fields', function () {
  1113. hideShowEditLink( 'show', jQuery( this ) );
  1114. } );
  1115. $doc.on( 'mouseleave', '.fb-form-case .fb-new-fields', function () {
  1116. hideShowEditLink( 'hide' );
  1117. return false;
  1118. } );
  1119. $doc.on( 'click', '.fb-edit-field', function () {
  1120. editField( jQuery( this ) );
  1121. return false;
  1122. } );
  1123. $doc.on( 'click', '.fb-edit-field .fb-reorder', function () {
  1124. return false;
  1125. } );
  1126. $doc.on( 'click', '#fb-save-field', function () {
  1127. showDesc();
  1128. showAndHideMessage();
  1129. return false;
  1130. } );
  1131. jQuery( '#fb-feedback' ).click( function () {
  1132. var thisHref = jQuery( this ).attr( 'href' );
  1133. window.parent.location = thisHref;
  1134. return false;
  1135. } );
  1136. jQuery( '#sortable' ).sortable( {
  1137. axis: 'y',
  1138. handle: '.fb-reorder',
  1139. revert: true,
  1140. start: function () {
  1141. jQuery( '.fb-edit-field' ).hide();
  1142. },
  1143. } );
  1144. jQuery( '#draggable' ).draggable( {
  1145. axis: 'y',
  1146. handle: '.fb-reorder',
  1147. connectToSortable: '#sortable',
  1148. helper: 'clone',
  1149. revert: 'invalid',
  1150. } );
  1151. },
  1152. };
  1153. } )();