grunion.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. /* jshint onevar: false, devel: true, smarttabs: true */
  2. /* global GrunionFB_i18n: true, FB, ajax_nonce_shortcode, ajax_nonce_json, ajaxurl, postId */
  3. if ( ! window.FB ) {
  4. window.FB = {};
  5. }
  6. GrunionFB_i18n = jQuery.extend( {
  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: 'Oops, there was a problem generating your form. You\'ll likely need to try again.',
  16. moveInstructions: 'Drag up or down\nto re-arrange',
  17. moveLabel: 'move',
  18. editLabel: 'edit',
  19. savedMessage: 'Saved successfully',
  20. requiredLabel: '(required)',
  21. exitConfirmMessage: 'Are you sure you want to exit the form editor without saving? Any changes you have made will be lost.',
  22. maxNewFields: 5,
  23. invalidEmail: ' is an invalid email address.'
  24. }, GrunionFB_i18n );
  25. GrunionFB_i18n.moveInstructions = GrunionFB_i18n.moveInstructions.replace( '\n', '<br />' );
  26. FB.span = jQuery( '<span>' );
  27. FB.esc_html = function( string ) {
  28. return FB.span.text( string ).html();
  29. };
  30. FB.esc_attr = function( string ) {
  31. string = FB.esc_html( string );
  32. return string.replace( '"', '&quot;' ).replace( '\'', '&#039;' );
  33. };
  34. FB.ContactForm = (function() {
  35. var fbForm = { // Main object that generated shortcode via AJAX call
  36. 'action' : 'grunion_shortcode',
  37. '_ajax_nonce' : ajax_nonce_shortcode,
  38. 'to' : '',
  39. 'subject' : '',
  40. 'fields' : {}
  41. };
  42. var defaultFields = {
  43. 'name': {
  44. 'label' : GrunionFB_i18n.nameLabel,
  45. 'type' : 'name',
  46. 'required' : true,
  47. 'options' : [],
  48. 'order' : '1'
  49. },
  50. 'email': {
  51. 'label' : GrunionFB_i18n.emailLabel,
  52. 'type' : 'email',
  53. 'required' : true,
  54. 'options' : [],
  55. 'order' : '2'
  56. },
  57. 'url': {
  58. 'label' : GrunionFB_i18n.urlLabel,
  59. 'type' : 'url',
  60. 'required' : false,
  61. 'options' : [],
  62. 'order' : '3'
  63. },
  64. 'comment': {
  65. 'label' : GrunionFB_i18n.commentLabel,
  66. 'type' : 'textarea',
  67. 'required' : true,
  68. 'options' : [],
  69. 'order' : '4'
  70. }
  71. };
  72. var debug = false; // will print errors to log if true
  73. var grunionNewCount = 0; // increment for new fields
  74. var maxNewFields = GrunionFB_i18n.maxNewFields; // See filter in ../grunion-form-view.php
  75. var optionsCache = {};
  76. var optionsCount = 0; // increment for options
  77. var shortcode;
  78. function addField () {
  79. try {
  80. grunionNewCount++;
  81. if (grunionNewCount <= maxNewFields) {
  82. // Add to preview
  83. jQuery('#fb-extra-fields').append('<div id="fb-new-field' + grunionNewCount + '" fieldid="' + grunionNewCount + '" class="fb-new-fields"><div class="fb-fields"><div id="' + grunionNewCount + '" class="fb-remove"></div><label fieldid="' + grunionNewCount + '" for="fb-field' + grunionNewCount + '"><span class="label-text">' + GrunionFB_i18n.newLabel + '</span> </label><input type="text" id="fb-field' + grunionNewCount + '" disabled="disabled" /></div></div>');
  84. // Add to form object
  85. fbForm.fields[grunionNewCount] = {
  86. 'label' : GrunionFB_i18n.newLabel,
  87. 'type' : 'text',
  88. 'required' : false,
  89. 'options' : [],
  90. 'order' : '5'
  91. };
  92. if (grunionNewCount === maxNewFields) {
  93. jQuery('#fb-new-field').hide();
  94. }
  95. // Reset form for this new field
  96. optionsCount = 0;
  97. optionsCache = {};
  98. jQuery('#fb-new-options').html('<label for="fb-option0">' + GrunionFB_i18n.optionsLabel + '</label><input type="text" id="fb-option0" optionid="0" value="' + GrunionFB_i18n.firstOptionLabel + '" class="fb-options" />');
  99. jQuery('#fb-options').hide();
  100. jQuery('#fb-new-label').val( GrunionFB_i18n.newLabel );
  101. jQuery('#fb-new-type').val('text');
  102. jQuery('#fb-field-id').val(grunionNewCount);
  103. setTimeout(function () { jQuery('#fb-new-label').focus().select(); }, 100);
  104. } else {
  105. jQuery('#fb-new-field').hide();
  106. }
  107. } catch(e) {
  108. if (debug) {
  109. console.log('addField(): ' + e);
  110. }
  111. }
  112. }
  113. function addOption () {
  114. try {
  115. optionsCount = jQuery( '#fb-new-options .fb-options' ).length;
  116. var thisId = jQuery('#fb-field-id').val();
  117. var thisType = jQuery('#fb-new-type').val();
  118. if (thisType === 'radio') {
  119. // Add to right col
  120. jQuery('#fb-new-options').append('<div id="fb-option-box-' + optionsCount + '" class="fb-new-fields"><span optionid="' + optionsCount + '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' + optionsCount + '" optionid="' + optionsCount + '" value="' + GrunionFB_i18n.optionLabel + '" class="fb-options" /><div>');
  121. // Add to preview
  122. jQuery('#fb-new-field' + thisId + ' .fb-fields').append('<div id="fb-radio-' + thisId + '-' + optionsCount + '"><input type="radio" disabled="disabled" id="fb-field' + thisId + '" name="radio-' + thisId + '" /><span>' + GrunionFB_i18n.optionLabel + '</span><div class="clear"></div></div>');
  123. } else if ( 'checkbox-multiple' === thisType ) {
  124. // Add to right col
  125. jQuery('#fb-new-options').append('<div id="fb-option-box-' + optionsCount + '" class="fb-new-fields"><span optionid="' + optionsCount + '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' + optionsCount + '" optionid="' + optionsCount + '" value="' + GrunionFB_i18n.optionLabel + '" class="fb-options" /><div>');
  126. // Add to preview
  127. jQuery('#fb-new-field' + thisId + ' .fb-fields').append('<div id="fb-checkbox-multiple-' + thisId + '-' + optionsCount + '"><input type="checkbox" disabled="disabled" id="fb-field' + thisId + '" name="checkbox-multiple-' + thisId + '" /><span>' + GrunionFB_i18n.optionLabel + '</span><div class="clear"></div></div>');
  128. } else {
  129. // Add to right col
  130. jQuery('#fb-new-options').append('<div id="fb-option-box-' + optionsCount + '" class="fb-new-fields"><span optionid="' + optionsCount + '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' + optionsCount + '" optionid="' + optionsCount + '" value="" class="fb-options" /><div>');
  131. // Add to preview
  132. jQuery('#fb-field'+ thisId).append('<option id="fb-' + thisId + '-' + optionsCount + '" value="' + thisId + '-' + optionsCount + '"></option>');
  133. }
  134. // Add to fbForm object
  135. fbForm.fields[thisId].options[optionsCount] = '';
  136. // Add focus to new field
  137. jQuery('#fb-option' + optionsCount).focus().select();
  138. } catch(e) {
  139. if (debug) {
  140. console.log('addOption(): ' + e);
  141. }
  142. }
  143. }
  144. function buildPreview () {
  145. try {
  146. if (fbForm.to) { jQuery('#fb-field-my-email').val(fbForm.to); }
  147. if (fbForm.subject) { jQuery('#fb-field-subject').val(fbForm.subject); }
  148. // Loop over and add fields
  149. jQuery.each(fbForm.fields, function(index, value) {
  150. jQuery('#fb-extra-fields').before('<div class="fb-new-fields ui-state-default" fieldid="' + index + '" id="fb-new-field' + index + '"><div class="fb-fields"></div></div>');
  151. jQuery('#fb-field-id').val(index);
  152. optionsCache[index] = {};
  153. optionsCache[index].options = [];
  154. if ( 'radio' === value.type || 'select' === value.type || 'checkbox-multiple' === value.type ) {
  155. jQuery.each(value.options, function(i, value) {
  156. optionsCache[index].options[i] = value;
  157. });
  158. }
  159. updateType(value.type, value.label, value.required);
  160. });
  161. } catch(e) {
  162. if (debug) {
  163. console.log('buildPreview(): ' + e);
  164. }
  165. }
  166. }
  167. function customOptions (id, thisType) {
  168. try {
  169. var thisOptions = '';
  170. for (var i=0; i<optionsCache[id].options.length; i++) {
  171. if (optionsCache[id].options[i] !== undefined) {
  172. if (thisType === 'radio') {
  173. thisOptions = thisOptions + '<div id="fb-radio-' + id + '-' + i + '"><input type="radio" id="fb-field' + id + '" name="radio-' + id + '" /><span>' + FB.esc_html( optionsCache[id].options[i] ) + '</span><div class="clear"></div></div>';
  174. } else if ( 'checkbox-multiple' === thisType ) {
  175. thisOptions = thisOptions + '<div id="fb-checkbox-multiple-' + id + '-' + i + '"><input type="checkbox" id="fb-field' + id + '" name="checkbox-multiple-' + id + '" /><span>' + FB.esc_html( optionsCache[id].options[i] ) + '</span><div class="clear"></div></div>';
  176. } else {
  177. thisOptions = thisOptions + '<option id="fb-' + id + '-' + i + '" value="' + id + '-' + i + '">' + FB.esc_html( optionsCache[id].options[i] ) + '</option>';
  178. }
  179. }
  180. }
  181. return thisOptions;
  182. } catch(e) {
  183. if (debug) {
  184. console.log('customOptions(): ' + e);
  185. }
  186. }
  187. }
  188. function deleteField (that) {
  189. try {
  190. grunionNewCount--;
  191. var thisId = that.attr('id');
  192. delete fbForm.fields[thisId];
  193. jQuery('#' + thisId).parent().parent().remove();
  194. if (grunionNewCount <= maxNewFields) {
  195. jQuery('#fb-new-field').show();
  196. }
  197. } catch(e) {
  198. if (debug) {
  199. console.log('deleteField(): ' + e);
  200. }
  201. }
  202. }
  203. function editField (that) {
  204. try {
  205. scroll(0,0);
  206. setTimeout(function () { jQuery('#fb-new-label').focus().select(); }, 100);
  207. var thisId = that.parent().attr('fieldid');
  208. loadFieldEditor(thisId);
  209. } catch(e) {
  210. if (debug) {
  211. console.log('editField(): ' + e);
  212. }
  213. }
  214. }
  215. function grabShortcode () {
  216. try {
  217. // Takes fbForm object and returns shortcode syntax
  218. jQuery.post(ajaxurl, fbForm, function(response) {
  219. shortcode = response;
  220. });
  221. } catch(e) {
  222. alert( GrunionFB_i18n.problemGeneratingForm );
  223. if (debug) {
  224. console.log('grabShortcode(): ' + e);
  225. }
  226. }
  227. }
  228. function hideDesc () {
  229. jQuery('#fb-desc').hide();
  230. jQuery('#fb-add-field').show();
  231. }
  232. function hidePopup () {
  233. try {
  234. // copied from wp-includes/js/thickbox/thickbox.js
  235. jQuery('#TB_imageOff', window.parent.document).unbind('click');
  236. jQuery('#TB_closeWindowButton', window.parent.document).unbind('click');
  237. jQuery('#TB_window', window.parent.document).fadeOut('fast');
  238. jQuery('body', window.parent.document).removeClass('modal-open');
  239. jQuery('#TB_window,#TB_overlay,#TB_HideSelect', window.parent.document).trigger('unload').unbind().remove();
  240. jQuery('#TB_load', window.parent.document).remove();
  241. if (typeof window.parent.document.body.style.maxHeight === 'undefined') {//if IE 6
  242. jQuery('body', 'html', window.parent.document).css({height: 'auto', width: 'auto'});
  243. jQuery('html', window.parent.document).css('overflow', '');
  244. }
  245. window.parent.document.onkeydown = '';
  246. window.parent.document.onkeyup = '';
  247. return false;
  248. } catch(e) {
  249. if (debug) {
  250. console.log('hidePopup(): ' + e);
  251. }
  252. }
  253. }
  254. function hideShowEditLink (whichType, that) {
  255. try {
  256. if (whichType === 'show') {
  257. // Prevents showing links twice
  258. if (jQuery('.fb-edit-field').is(':visible')) {
  259. jQuery('.fb-edit-field').remove();
  260. }
  261. that.find('label').prepend('<span class="right fb-edit-field" style="font-weight: normal;"><a href="" class="fb-reorder"><div style="display: none;">' + GrunionFB_i18n.moveInstructions + '</div>' + GrunionFB_i18n.moveLabel + '</a>&nbsp;&nbsp;<span style="color: #C7D8DE;">|</span>&nbsp;&nbsp;<a href="" class="fb-edit">' + GrunionFB_i18n.editLabel + '</a></span>');
  262. } else {
  263. jQuery('.fb-edit-field').remove();
  264. }
  265. } catch(e) {
  266. if (debug) {
  267. console.log('hideShowEditLink(): ' + e);
  268. }
  269. }
  270. }
  271. function loadFieldEditor (id) {
  272. try {
  273. var thisType = fbForm.fields[id].type;
  274. jQuery('#fb-options').hide();
  275. // Reset hidden field ID
  276. jQuery('#fb-field-id').val(id);
  277. // Load label
  278. jQuery('#fb-new-label').val(fbForm.fields[id].label);
  279. // Load type
  280. jQuery('#fb-new-type').val(fbForm.fields[id].type);
  281. // Load required
  282. if (fbForm.fields[id].required) {
  283. jQuery('#fb-new-required').prop('checked', true);
  284. } else {
  285. jQuery('#fb-new-required').prop('checked', false);
  286. }
  287. // Load options if there are any
  288. if ( 'select' === thisType || 'radio' === thisType || 'checkbox-multiple' === thisType ) {
  289. var thisOptions = fbForm.fields[id].options;
  290. jQuery('#fb-options').show();
  291. jQuery('#fb-new-options').html(''); // Clear it all out
  292. for (var i=0; i<thisOptions.length; i++) {
  293. if (thisOptions[i] !== undefined) {
  294. if (thisType === 'radio') {
  295. jQuery('#fb-new-options').append('<div id="fb-option-box-' + i + '" class="fb-new-fields"><span optionid="' + i + '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' + i + '" optionid="' + i + '" value="' + FB.esc_attr( fbForm.fields[id].options[i] ) + '" class="fb-options" /><div>');
  296. } else {
  297. jQuery('#fb-new-options').append('<div id="fb-option-box-' + i + '" class="fb-new-fields"><span optionid="' + i + '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' + i + '" optionid="' + i + '" value="' + FB.esc_attr( fbForm.fields[id].options[i] ) + '" class="fb-options" /><div>');
  298. }
  299. }
  300. }
  301. }
  302. // Load editor & hide description
  303. hideDesc();
  304. } catch(e) {
  305. if (debug) {
  306. console.log('loadFieldEditor(): ' + e);
  307. }
  308. }
  309. }
  310. function parseShortcode (data) {
  311. try {
  312. // Clean up fields by resetting them
  313. fbForm.fields = {};
  314. // Add new fields
  315. if (!data) {
  316. fbForm.fields = defaultFields;
  317. } else {
  318. jQuery.each(data.fields, function(index, value) {
  319. if ( 1 === parseInt(value.required, 10) ) {
  320. value.required = 'true';
  321. }
  322. fbForm.fields[index] = value;
  323. });
  324. fbForm.to = data.to;
  325. fbForm.subject = data.subject;
  326. }
  327. } catch(e) {
  328. if (debug) {
  329. console.log('parseShortcode(): ' + e);
  330. }
  331. }
  332. }
  333. function removeOption (optionId) {
  334. try {
  335. var thisId = jQuery('#fb-field-id').val();
  336. var thisVal = jQuery('#fb-option' + optionId).val();
  337. var thisType = jQuery('#fb-new-type').val();
  338. // Remove from right
  339. jQuery('#fb-option-box-' + optionId).remove();
  340. // Remove from preview
  341. if (thisType === 'radio') {
  342. jQuery('#fb-radio-' + thisId + '-' + optionId).remove();
  343. } else if ( 'checkbox-multiple' === thisType ) {
  344. jQuery('#fb-checkbox-multiple-' + thisId + '-' + optionId).remove();
  345. } else {
  346. jQuery('#fb-' + thisId + '-' + optionId).remove();
  347. }
  348. // Remove from fbForm object
  349. var idx = fbForm.fields[thisId].options.indexOf(thisVal);
  350. if (idx !== -1) { fbForm.fields[thisId].options.splice(idx, 1); }
  351. } catch(e) {
  352. if (debug) {
  353. console.log('removeOption(): ' + e);
  354. }
  355. }
  356. }
  357. function removeOptions () {
  358. try {
  359. var thisId = jQuery('#fb-field-id').val();
  360. jQuery('#fb-options').hide();
  361. if (optionsCache[thisId] === undefined) { optionsCache[thisId] = {}; }
  362. optionsCache[thisId].options = fbForm.fields[thisId].options; // Save options in case they change their mind
  363. fbForm.fields[thisId].options = []; // Removes all options
  364. } catch(e) {
  365. if (debug) {
  366. console.log('removeOptions(): ' + e);
  367. }
  368. }
  369. }
  370. function sendShortcodeToEditor () {
  371. try {
  372. // Serialize fields
  373. jQuery('div#sortable div.fb-new-fields').each(function(index) {
  374. var thisId = jQuery(this).attr('fieldid');
  375. fbForm.fields[thisId].order = index;
  376. });
  377. // Export to WYSIWYG editor
  378. jQuery.post(ajaxurl, fbForm, function(response) {
  379. var isVisual = jQuery('#edButtonPreview', window.parent.document).hasClass('active');
  380. /* WP 3.3+ */
  381. if ( !isVisual ) {
  382. isVisual = jQuery( '#wp-content-wrap', window.parent.document ).hasClass( 'tmce-active' );
  383. }
  384. var win = window.dialogArguments || opener || parent || top;
  385. var currentCode;
  386. if (isVisual) {
  387. currentCode = win.tinyMCE.activeEditor.getContent();
  388. } else {
  389. currentCode = jQuery('#editorcontainer textarea', window.parent.document).val();
  390. /* WP 3.3+ */
  391. if ( typeof currentCode !== 'string' ) {
  392. currentCode = jQuery( '.wp-editor-area', window.parent.document ).val();
  393. }
  394. }
  395. var regexp = new RegExp('\\[contact-form\\b.*?\\/?\\](?:[\\s\\S]+?\\[\\/contact-form\\])?');
  396. // Remove new lines that cause BR tags to show up
  397. response = response.replace(/\n/g,' ');
  398. // Convert characters to comma
  399. response = response.replace( /%26#x002c;/g , ',' );
  400. // Add new shortcode
  401. if (currentCode.match(regexp)) {
  402. if (isVisual) {
  403. win.tinyMCE.activeEditor.execCommand('mceSetContent', false, currentCode.replace(regexp, response));
  404. } else {
  405. // looks like the visual editor is disabled,
  406. // update the contents of the post directly
  407. jQuery( '#content', window.parent.document ).val( currentCode.replace( regexp, response ) );
  408. }
  409. } else {
  410. try {
  411. win.send_to_editor( response );
  412. } catch ( e ) {
  413. if (isVisual) {
  414. win.tinyMCE.activeEditor.execCommand('mceInsertContent', false, response);
  415. } else {
  416. // looks like the visual editor is disabled,
  417. // update the contents of the post directly
  418. jQuery( '#content', window.parent.document ).val( currentCode + response );
  419. }
  420. }
  421. }
  422. hidePopup();
  423. });
  424. } catch(e) {
  425. if (debug) {
  426. console.log('sendShortcodeToEditor(): ' + e);
  427. }
  428. }
  429. }
  430. function showDesc () {
  431. jQuery('#fb-desc').show();
  432. jQuery('#fb-add-field').hide();
  433. }
  434. function showAndHideMessage (message) {
  435. try {
  436. var newMessage = (!message) ? GrunionFB_i18n.savedMessage : message;
  437. jQuery('#fb-success').text(newMessage);
  438. jQuery('#fb-success').slideDown('fast');
  439. setTimeout(function () {
  440. jQuery('#fb-success').slideUp('fast');
  441. }, 2500);
  442. } catch(e) {
  443. if (debug) {
  444. console.log('showAndHideMessage(): ' + e);
  445. }
  446. }
  447. }
  448. function switchTabs (whichType) {
  449. try {
  450. if (whichType === 'preview') {
  451. if ( ! validateEmails( jQuery( '#fb-field-my-email' ).val() ) ) {
  452. return;
  453. }
  454. jQuery('#tab-preview a').addClass('current');
  455. jQuery('#tab-settings a').removeClass('current');
  456. jQuery('#fb-preview-form, #fb-desc').show();
  457. jQuery('#fb-email-settings, #fb-email-desc').hide();
  458. showAndHideMessage( GrunionFB_i18n.savedMessage );
  459. } else {
  460. jQuery('#tab-preview a').removeClass('current');
  461. jQuery('#tab-settings a').addClass('current');
  462. jQuery('#fb-preview-form, #fb-desc, #fb-add-field').hide();
  463. jQuery('#fb-email-settings, #fb-email-desc').show();
  464. jQuery('#fb-field-my-email').focus().select();
  465. }
  466. } catch(e) {
  467. if (debug) {
  468. console.log('switchTabs(): ' + e);
  469. }
  470. }
  471. }
  472. function validateEmails( emails ) {
  473. // Field is allowed to be empty :)
  474. if ( 0 === emails.length ) {
  475. return true;
  476. }
  477. var $e, emailList = emails.split( ',' );
  478. for ( $e = 0 ; $e < emailList.length ; $e++ ) {
  479. if ( false === validateEmail( emailList[ $e ] ) ) {
  480. alert( emailList[ $e ] + GrunionFB_i18n.invalidEmail );
  481. return false;
  482. }
  483. }
  484. return true;
  485. }
  486. /* Uses The Official Standard: RFC 5322 -- http://www.regular-expressions.info/email.html */
  487. function validateEmail( email ) {
  488. var re = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/i;
  489. return re.test( email );
  490. }
  491. function updateLabel () {
  492. try {
  493. var thisId = jQuery('#fb-field-id').val();
  494. var thisLabel = jQuery('#fb-new-label').val();
  495. // Update preview
  496. if (thisLabel.length === 0) {
  497. jQuery('#fb-new-field' + thisId + ' label .label-text').text( GrunionFB_i18n.newLabel );
  498. } else {
  499. jQuery('#fb-new-field' + thisId + ' label .label-text').text( thisLabel );
  500. }
  501. // Update fbForm object
  502. fbForm.fields[thisId].label = thisLabel;
  503. } catch(e) {
  504. if (debug) {
  505. console.log('updateLabel(): ' + e);
  506. }
  507. }
  508. }
  509. function updateMyEmail () {
  510. try {
  511. var thisEmail = jQuery('#fb-field-my-email').val();
  512. fbForm.to = thisEmail;
  513. } catch(e) {
  514. if (debug) {
  515. console.log('updateMyEmail(): ' + e);
  516. }
  517. }
  518. }
  519. function updateOption (that) {
  520. try {
  521. var thisId = jQuery('#fb-field-id').val();
  522. var thisOptionid = that.attr('optionid');
  523. var thisOptionValue = that.val();
  524. var thisType = jQuery('#fb-new-type').val();
  525. // Update preview
  526. if (thisType === 'radio') {
  527. jQuery('#fb-radio-' + thisId + '-' + thisOptionid + ' span').text(thisOptionValue);
  528. } else if ( 'checkbox-multiple' === thisType ) {
  529. jQuery('#fb-checkbox-multiple-' + thisId + '-' + thisOptionid + ' span').text(thisOptionValue);
  530. } else {
  531. jQuery('#fb-' + thisId + '-' + thisOptionid).text(thisOptionValue);
  532. }
  533. // Update fbForm object
  534. fbForm.fields[thisId].options[thisOptionid] = thisOptionValue;
  535. } catch(e) {
  536. if (debug) {
  537. console.log('updateOption(): ' + e);
  538. }
  539. }
  540. }
  541. function updateRequired () {
  542. try {
  543. var thisId = jQuery('#fb-field-id').val();
  544. var thisChecked = jQuery('#fb-new-required').is(':checked');
  545. // Update object and preview
  546. if (thisChecked) {
  547. fbForm.fields[thisId].required = true;
  548. jQuery('#fb-new-field' + thisId + ' label').append('<span class="label-required">' + GrunionFB_i18n.requiredLabel + '</span>');
  549. } else {
  550. fbForm.fields[thisId].required = false;
  551. jQuery('#fb-new-field' + thisId + ' label .label-required').remove();
  552. }
  553. } catch(e) {
  554. if (debug) {
  555. console.log('updateRequired(): ' + e);
  556. }
  557. }
  558. }
  559. function updateSubject () {
  560. try {
  561. var thisSubject = jQuery('#fb-field-subject').val();
  562. fbForm.subject = thisSubject;
  563. } catch(e) {
  564. if (debug) {
  565. console.log('updateSubject(): ' + e);
  566. }
  567. }
  568. }
  569. function updateType(thisType, thisLabelText, thisRequired) {
  570. try {
  571. var thisId = jQuery('#fb-field-id').val();
  572. if (!thisType) { thisType = jQuery('#fb-new-type').val(); }
  573. if (!thisLabelText) { thisLabelText = jQuery('#fb-new-field' + thisId + ' .label-text').text(); }
  574. var isRequired = (thisRequired) ? '<span class="label-required">' + GrunionFB_i18n.requiredLabel + '</span>' : '';
  575. var thisLabel = '<label fieldid="' + thisId + '" for="fb-field' + thisId + '"><span class="label-text">' + FB.esc_html( thisLabelText ) + '</span>' + isRequired + '</label>';
  576. var thisRadio = '<input type="radio" name="radio-' + thisId + '" id="fb-field' + thisId + ' "disabled="disabled" />';
  577. var thisRadioLabel = '<label fieldid="' + thisId + '" for="fb-field' + thisId + '" class="fb-radio-label"><span class="label-text">' + FB.esc_html( thisLabelText ) + '</span>' + isRequired + '</label>';
  578. var thisRadioRemove = '<div class="fb-remove fb-remove-small" id="' + thisId + '"></div>';
  579. var thisRemove = '<div class="fb-remove" id="' + thisId + '"></div>';
  580. var thisCheckbox = '<input type="checkbox" id="fb-field' + thisId + '" "disabled="disabled" />';
  581. var thisCheckboxMultiple = '<input type="checkbox" id="fb-field' + thisId + '" "disabled="disabled" />';
  582. var thisCheckboxMultipleRemove = '<div class="fb-remove fb-remove-small" id="' + thisId + '"></div>';
  583. var thisText = '<input type="text" id="fb-field' + thisId + '" "disabled="disabled" />';
  584. var thisTextarea = '<textarea id="fb-field' + thisId + '" "disabled="disabled"></textarea>';
  585. var thisClear = '<div class="clear"></div>';
  586. var thisSelect = '<select id="fb-field' + thisId + '" fieldid="' + thisId + '"><option id="fb-' + thisId + '-' + optionsCount + '" value="' + thisId + '-' + optionsCount + '">' + GrunionFB_i18n.firstOptionLabel + '</option></select>';
  587. switch (thisType) {
  588. case 'checkbox':
  589. removeOptions();
  590. jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRadioRemove + thisCheckbox + thisRadioLabel + thisClear);
  591. break;
  592. case 'checkbox-multiple':
  593. jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisLabel + thisCheckboxMultipleRemove + '<div fieldid="' + thisId + '" id="fb-custom-checkbox-multiple' + thisId + '"></div>');
  594. if (optionsCache[thisId] !== undefined && optionsCache[thisId].options.length !== 0) {
  595. fbForm.fields[thisId].options = optionsCache[thisId].options;
  596. jQuery('#fb-custom-checkbox-multiple' + thisId).append(customOptions(thisId, thisType));
  597. } else {
  598. jQuery('#fb-new-options').html('<label for="fb-option0">' + GrunionFB_i18n.optionsLabel + '</label><input type="text" id="fb-option0" optionid="0" value="' + GrunionFB_i18n.firstOptionLabel + '" class="fb-options" />');
  599. jQuery('#fb-custom-checkbox-multiple' + thisId).append('<div id="fb-checkbox-multiple-' + thisId + '-0">' + thisCheckboxMultiple + '<span>' + GrunionFB_i18n.firstOptionLabel + '</span>' + thisClear + '</div>');
  600. fbForm.fields[thisId].options[optionsCount] = GrunionFB_i18n.firstOptionLabel;
  601. }
  602. jQuery('#fb-options').show();
  603. setTimeout(function () { jQuery('#fb-option0').focus().select(); }, 100);
  604. break;
  605. case 'email':
  606. removeOptions();
  607. jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
  608. break;
  609. case 'name':
  610. removeOptions();
  611. jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
  612. break;
  613. case 'radio':
  614. jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisLabel + thisRadioRemove + '<div fieldid="' + thisId + '" id="fb-custom-radio' + thisId + '"></div>');
  615. if (optionsCache[thisId] !== undefined && optionsCache[thisId].options.length !== 0) {
  616. fbForm.fields[thisId].options = optionsCache[thisId].options;
  617. jQuery('#fb-custom-radio' + thisId).append(customOptions(thisId, thisType));
  618. } else {
  619. jQuery('#fb-new-options').html('<label for="fb-option0">' + GrunionFB_i18n.optionsLabel + '</label><input type="text" id="fb-option0" optionid="0" value="' + GrunionFB_i18n.firstOptionLabel + '" class="fb-options" />');
  620. jQuery('#fb-custom-radio' + thisId).append('<div id="fb-radio-' + thisId + '-0">' + thisRadio + '<span>' + GrunionFB_i18n.firstOptionLabel + '</span>' + thisClear + '</div>');
  621. fbForm.fields[thisId].options[optionsCount] = GrunionFB_i18n.firstOptionLabel;
  622. }
  623. jQuery('#fb-options').show();
  624. setTimeout(function () { jQuery('#fb-option0').focus().select(); }, 100);
  625. break;
  626. case 'select':
  627. jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisSelect);
  628. if (optionsCache[thisId] !== undefined && optionsCache[thisId].options.length !== 0) {
  629. fbForm.fields[thisId].options = optionsCache[thisId].options;
  630. jQuery('#fb-field' + thisId).html(customOptions(thisId, thisType));
  631. } else {
  632. jQuery('#fb-new-options').html('<label for="fb-option0">' + GrunionFB_i18n.optionsLabel + '</label><input type="text" id="fb-option0" optionid="0" value="' + GrunionFB_i18n.firstOptionLabel + '" class="fb-options" />');
  633. fbForm.fields[thisId].options[optionsCount] = GrunionFB_i18n.firstOptionLabel;
  634. }
  635. jQuery('#fb-options').show();
  636. setTimeout(function () { jQuery('#fb-option0').focus().select(); }, 100);
  637. break;
  638. case 'text':
  639. removeOptions();
  640. jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
  641. break;
  642. case 'textarea':
  643. removeOptions();
  644. jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisTextarea);
  645. break;
  646. case 'url':
  647. removeOptions();
  648. jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
  649. break;
  650. }
  651. // update object
  652. fbForm.fields[thisId].type = thisType;
  653. } catch(e) {
  654. if (debug) {
  655. console.log('updateType(): ' + e);
  656. }
  657. }
  658. }
  659. return {
  660. resizePop: function () {
  661. try {
  662. //Thickbox won't resize for some reason, we are manually doing it here
  663. var totalWidth = jQuery('body', window.parent.document).width();
  664. var totalHeight = jQuery('body', window.parent.document).height();
  665. var isIE6 = typeof document.body.style.maxHeight === 'undefined';
  666. jQuery('#TB_window, #TB_iframeContent', window.parent.document).css('width', '768px');
  667. jQuery('#TB_window', window.parent.document).css({ left: (totalWidth-768)/2 + 'px', top: '23px', position: 'absolute', marginLeft: '0' });
  668. if ( ! isIE6 ) { // take away IE6
  669. jQuery('#TB_window, #TB_iframeContent', window.parent.document).css('height', (totalHeight-73) + 'px');
  670. }
  671. } catch(e) {
  672. if (debug) {
  673. console.log('resizePop(): ' + e);
  674. }
  675. }
  676. },
  677. init: function () {
  678. // Scroll to top of page
  679. window.parent.scroll(0,0);
  680. //Check for existing form data
  681. var contentSource;
  682. if (jQuery('#edButtonPreview', window.parent.document).hasClass('active') || jQuery( '#wp-content-wrap', window.parent.document ).hasClass( 'tmce-active' ) ) {
  683. var win = window.dialogArguments || opener || parent || top;
  684. contentSource = win.tinyMCE.activeEditor.getContent();
  685. } else {
  686. contentSource = jQuery('#content', window.parent.document).val();
  687. }
  688. var data = {
  689. action: 'grunion_shortcode_to_json',
  690. '_ajax_nonce' : ajax_nonce_json,
  691. post_id: postId,
  692. content: contentSource
  693. };
  694. var $doc = jQuery(document);
  695. jQuery.post(ajaxurl, data, function(response) {
  696. // Setup fbForm
  697. parseShortcode(jQuery.parseJSON(response));
  698. // Now build out the preview form
  699. buildPreview();
  700. });
  701. // actions
  702. jQuery('.fb-add-field').click(function () {
  703. addField();
  704. hideDesc();
  705. return false;
  706. });
  707. jQuery('#fb-new-label').keyup(function () {
  708. updateLabel();
  709. });
  710. jQuery('#fb-new-type').change(function () {
  711. updateType();
  712. });
  713. jQuery('#fb-new-required').click(function () {
  714. updateRequired();
  715. });
  716. $doc.on('click', '.fb-remove', function () {
  717. showDesc();
  718. deleteField(jQuery(this));
  719. grabShortcode();
  720. });
  721. jQuery('#fb-preview').submit(function () {
  722. sendShortcodeToEditor();
  723. return false;
  724. });
  725. jQuery('#TB_overlay, #TB_closeWindowButton', window.parent.document).mousedown(function () {
  726. if(confirm( GrunionFB_i18n.exitConfirmMessage )) {
  727. hidePopup();
  728. }
  729. });
  730. $doc.on('click', '#fb-another-option', function () {
  731. addOption();
  732. });
  733. $doc.on('keyup', '.fb-options', function () {
  734. updateOption(jQuery(this));
  735. });
  736. $doc.on('click', '.fb-remove-option', function () {
  737. removeOption(jQuery(this).attr('optionid'));
  738. });
  739. jQuery('#tab-preview a').click(function () {
  740. switchTabs('preview');
  741. return false;
  742. });
  743. jQuery('#fb-prev-form').click(function () {
  744. switchTabs('preview');
  745. return false;
  746. });
  747. jQuery('#tab-settings a').click(function () {
  748. switchTabs();
  749. return false;
  750. });
  751. jQuery('#fb-field-my-email').blur(function () {
  752. updateMyEmail();
  753. });
  754. jQuery('#fb-field-subject').blur(function () {
  755. updateSubject();
  756. });
  757. $doc.on('mouseenter', '.fb-form-case .fb-new-fields', function () {
  758. hideShowEditLink('show', jQuery(this));
  759. });
  760. $doc.on('mouseleave', '.fb-form-case .fb-new-fields', function () {
  761. hideShowEditLink('hide');
  762. return false;
  763. });
  764. $doc.on('click', '.fb-edit-field', function () {
  765. editField(jQuery(this));
  766. return false;
  767. });
  768. $doc.on('click', '.fb-edit-field .fb-reorder', function () {
  769. return false;
  770. });
  771. $doc.on('click', '#fb-save-field', function () {
  772. showDesc();
  773. showAndHideMessage();
  774. return false;
  775. });
  776. jQuery('#fb-feedback').click(function () {
  777. var thisHref = jQuery(this).attr('href');
  778. window.parent.location = thisHref;
  779. return false;
  780. });
  781. jQuery('#sortable').sortable({
  782. axis: 'y',
  783. handle: '.fb-reorder',
  784. revert: true,
  785. start: function() { jQuery('.fb-edit-field').hide(); }
  786. });
  787. jQuery('#draggable').draggable({
  788. axis: 'y',
  789. handle: '.fb-reorder',
  790. connectToSortable: '#sortable',
  791. helper: 'clone',
  792. revert: 'invalid'
  793. });
  794. }
  795. };
  796. })();