PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 4.03.07
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v4.03.07
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / js / formidable_admin.js

formidable_admin.js in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 4.03.07, at js/formidable_admin.js

5,717 lines 174.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 var FrmFormsConnect = window.FrmFormsConnect || ( function( document, window, $ ) {
2
3 /*global jQuery:false, frm_admin_js, frmGlobal, ajaxurl */
4
5 var el = {
6 licenseBox: document.getElementById( 'frm_license_top' ),
7 messageBox: document.getElementsByClassName( 'frm_pro_license_msg' )[0],
8 btn: document.getElementById('frm-settings-connect-btn'),
9 reset: document.getElementById( 'frm_reconnect_link' )
10 };
11
12 /**
13 * Public functions and properties.
14 *
15 * @since 4.03
16 *
17 * @type {Object}
18 */
19 var app = {
20
21 /**
22 * Register connect button event.
23 *
24 * @since 4.03
25 */
26 init: function() {
27 $( document.getElementById( 'frm_deauthorize_link' ) ).click( app.deauthorize );
28 $( '.frm_authorize_link' ).click( app.authorize );
29 if ( el.reset !== null ) {
30 $( el.reset ).click( app.reauthorize );
31 }
32
33 $( el.btn ).on( 'click', function(e) {
34 e.preventDefault();
35 app.gotoUpgradeUrl();
36 } );
37
38 window.addEventListener('message', function(msg) {
39 if ( msg.origin.replace(/\/$/, '') !== frmGlobal.app_url.replace(/\/$/, '') ) {
40 return;
41 }
42
43 if ( ! msg.data || 'object' !== typeof msg.data ) {
44 console.error('Messages from "' + frmGlobal.app_url + '" must contain an api key string.');
45 return;
46 }
47
48 app.updateForm(msg.data);
49 });
50 },
51
52 /**
53 * Go to upgrade url.
54 *
55 * @since 4.03
56 */
57 gotoUpgradeUrl: function() {
58 var w = window.open(frmGlobal.app_url + '/api-connect/', '_blank', 'location=no,width=500,height=730,scrollbars=0');
59 w.focus();
60 },
61
62 updateForm: function(response) {
63
64 // Start spinner.
65 var btn = el.btn;
66 btn.classList.add('frm_loading_button');
67
68 if ( response.url !== '' ) {
69 app.showProgress({
70 success:true,
71 message:'Installing...'
72 });
73 var fallback = setTimeout( function() {
74 app.showProgress({
75 success:true,
76 message:'Installing is taking longer than expected. <a class="frm-install-addon button button-primary frm-button-primary" rel="' + response.url + '" aria-label="Install">Install Now</a>'
77 });
78 }, 10000 );
79 $.ajax( {
80 type: 'POST',
81 url: ajaxurl,
82 dataType: 'json',
83 data: {
84 action: 'frm_connect',
85 plugin: response.url,
86 nonce: frmGlobal.nonce
87 },
88 success: function() {
89 clearTimeout( fallback );
90 app.activateKey( response );
91 },
92 error: function(xhr, textStatus, e) {
93 clearTimeout( fallback );
94 btn.classList.remove('frm_loading_button');
95 app.showMessage({
96 success:false,
97 message: e
98 });
99 }
100 });
101 } else if ( response.key !== '' ) {
102 app.activateKey( response );
103 }
104 },
105
106 activateKey: function( response ) {
107 var btn = el.btn;
108 if ( response.key === '' ) {
109 btn.classList.remove('frm_loading_button');
110 } else {
111 app.showProgress({
112 success:true,
113 message:'Activating...'
114 });
115 $.ajax( {
116 type: 'POST',
117 url: ajaxurl,
118 dataType: 'json',
119 data: {
120 action: 'frm_addon_activate',
121 license: response.key,
122 plugin: 'formidable_pro',
123 wpmu: 0,
124 nonce: frmGlobal.nonce
125 },
126 success: function( msg ) {
127 btn.classList.remove('frm_loading_button');
128
129 if ( msg.success === true ) {
130 el.licenseBox.classList.replace( 'frm_unauthorized_box', 'frm_authorized_box' );
131 }
132
133 app.showMessage( msg );
134 },
135 error: function(xhr, textStatus, e) {
136 btn.classList.remove('frm_loading_button');
137 app.showMessage({
138 success:false,
139 message: e
140 });
141 }
142 });
143 }
144 },
145
146 /* Manual license authorization */
147 authorize: function() {
148 /*jshint validthis:true */
149 var button = this;
150 var pluginSlug = this.getAttribute('data-plugin');
151 var input = document.getElementById( 'edd_' + pluginSlug + '_license_key' );
152 var license = input.value;
153 var wpmu = document.getElementById( 'proplug-wpmu' );
154 this.classList.add( 'frm_loading_button' );
155 if ( wpmu === null ) {
156 wpmu = 0;
157 } else if ( wpmu.checked ) {
158 wpmu = 1;
159 } else {
160 wpmu = 0;
161 }
162
163 $.ajax( {
164 type: 'POST', url: ajaxurl, dataType: 'json',
165 data: {
166 action: 'frm_addon_activate',
167 license: license,
168 plugin: pluginSlug,
169 wpmu: wpmu,
170 nonce: frmGlobal.nonce
171 },
172 success: function( msg ) {
173 app.afterAuthorize( msg, input );
174 button.classList.remove( 'frm_loading_button' );
175 }
176 } );
177 },
178
179 afterAuthorize: function( msg, input ) {
180 if ( msg.success === true ) {
181 input.value = '•••••••••••••••••••';
182 }
183
184 app.showMessage( msg );
185 },
186
187 showProgress: function( msg ) {
188 var messageBox = el.messageBox;
189 if ( msg.success === true ) {
190 messageBox.classList.remove( 'frm_error_style' );
191 messageBox.classList.add( 'frm_message', 'frm_updated_message' );
192 } else {
193 messageBox.classList.add( 'frm_error_style' );
194 messageBox.classList.remove( 'frm_message', 'frm_updated_message' );
195 }
196 messageBox.classList.remove( 'frm_hidden' );
197 messageBox.innerHTML = msg.message;
198 },
199
200 showMessage: function( msg ) {
201 var messageBox = el.messageBox;
202
203 if ( msg.success === true ) {
204 var d = el.licenseBox;
205 d.className = d.className.replace( 'frm_unauthorized_box', 'frm_authorized_box' );
206 messageBox.classList.remove( 'frm_error_style' );
207 messageBox.classList.add( 'frm_message', 'frm_updated_message' );
208 } else {
209 messageBox.classList.add( 'frm_error_style' );
210 messageBox.classList.remove( 'frm_message', 'frm_updated_message' );
211 }
212
213 messageBox.classList.remove( 'frm_hidden' );
214 messageBox.innerHTML = msg.message;
215 if ( msg.message !== '' ) {
216 setTimeout( function() {
217 messageBox.innerHTML = '';
218 messageBox.classList.add( 'frm_hidden' );
219 messageBox.classList.remove( 'frm_error_style', 'frm_message', 'frm_updated_message' );
220 }, 10000 );
221 }
222 },
223
224 /* Clear the site license cache */
225 reauthorize: function() {
226 /*jshint validthis:true */
227 this.innerHTML = '<span class="frm-wait frm_spinner" style="visibility:visible;float:none"></span>';
228
229 $.ajax( {
230 type: 'POST',
231 url: ajaxurl,
232 dataType: 'json',
233 data: {
234 action: 'frm_reset_cache',
235 plugin: 'formidable_pro',
236 nonce: frmGlobal.nonce
237 },
238 success: function( msg ) {
239 el.reset.innerHTML = msg.message;
240 if ( el.reset.getAttribute( 'data-refresh' ) === '1' ) {
241 window.location.reload();
242 }
243 }
244 } );
245 return false;
246 },
247
248 deauthorize: function() {
249 /*jshint validthis:true */
250 if ( !confirm( frmGlobal.deauthorize ) ) {
251 return false;
252 }
253 var pluginSlug = this.getAttribute('data-plugin'),
254 input = document.getElementById( 'edd_' + pluginSlug + '_license_key' ),
255 license = input.value,
256 link = this;
257
258 this.innerHTML = '<span class="frm-wait frm_spinner" style="visibility:visible;"></span>';
259
260 $.ajax( {
261 type: 'POST',
262 url: ajaxurl,
263 data: {
264 action: 'frm_addon_deactivate',
265 license: license,
266 plugin: pluginSlug,
267 nonce: frmGlobal.nonce
268 },
269 success: function( msg ) {
270 el.licenseBox.className = el.licenseBox.className.replace( 'frm_authorized_box', 'frm_unauthorized_box' );
271 input.value = '';
272 link.innerHTML = '';
273 }
274 } );
275 return false;
276 }
277 };
278
279 // Provide access to public functions/properties.
280 return app;
281
282 }( document, window, jQuery ) );
283
284 function frmAdminBuildJS() {
285 //'use strict';
286
287 /*global jQuery:false, frm_admin_js, frmGlobal, ajaxurl */
288
289 var $newFields = jQuery( document.getElementById( 'frm-show-fields' ) );
290 var builderForm = document.getElementById( 'new_fields' );
291 var thisForm = document.getElementById( 'form_id' );
292 var cancelSort = false;
293 var copyHelper = false;
294
295 var this_form_id = 0;
296 if ( thisForm !== null ) {
297 this_form_id = thisForm.value;
298 }
299
300 // Global settings
301 var s;
302
303 function showElement( element ) {
304 element[0].style.display = '';
305 }
306
307 function hideElement( element ) {
308 element[0].style.display = 'none';
309 }
310
311 function empty( $obj ) {
312 if ( $obj !== null ) {
313 while ( $obj.firstChild ) {
314 $obj.removeChild( $obj.firstChild );
315 }
316 }
317 }
318
319 function addClass( $obj, className ) {
320 if ( $obj.classList ) {
321 $obj.classList.add( className );
322 } else {
323 $obj.className += ' ' + className;
324 }
325 }
326
327 function confirmClick( e ) {
328 /*jshint validthis:true */
329 e.stopPropagation();
330 e.preventDefault();
331 confirmLinkClick( this );
332 }
333
334 function confirmLinkClick( link ) {
335 var message = link.getAttribute( 'data-frmverify' );
336
337 if ( message === null || link.id === 'frm-confirmed-click' ) {
338 return true;
339 } else {
340 return confirmModal( link );
341 }
342 }
343
344 function confirmModal( link ) {
345 var i, dataAtts,
346 $info = initModal( '#frm_confirm_modal', '400px' ),
347 continueButton = document.getElementById( 'frm-confirmed-click' );
348
349 if ( $info === false ) {
350 return false;
351 }
352
353 var caution = link.getAttribute('data-frmcaution');
354 var cautionHtml = caution ? '<span class="frm-caution">' + caution + '</span> ' : '';
355
356 jQuery('.frm-confirm-msg').html( cautionHtml + link.getAttribute( 'data-frmverify' ) );
357
358 removeAtts = continueButton.dataset;
359 for ( i in dataAtts ) {
360 continueButton.removeAttribute( 'data-' + i );
361 }
362
363 dataAtts = link.dataset;
364 for ( i in dataAtts ) {
365 if ( i !== 'frmverify' ) {
366 continueButton.setAttribute( 'data-' + i, dataAtts[ i ] );
367 }
368 }
369
370 $info.dialog('open');
371 continueButton.setAttribute( 'href', link.getAttribute( 'href' ) );
372 return false;
373 }
374
375 function toggleItem( e ) {
376 /*jshint validthis:true */
377 var toggle = this.getAttribute( 'data-frmtoggle' ),
378 text = this.getAttribute( 'data-toggletext' ),
379 items = jQuery( toggle );
380
381 e.preventDefault();
382
383 if ( items.is( ':visible' ) ) {
384 items.show();
385 } else {
386 items.hide();
387 }
388
389 if ( text !== null && text !== '' ) {
390 this.setAttribute( 'data-toggletext', this.innerHTML );
391 this.innerHTML = text;
392 }
393
394 return false;
395 }
396
397 function hideShowItem( e ) {
398 /*jshint validthis:true */
399 var hide = this.getAttribute( 'data-frmhide' ),
400 show = this.getAttribute( 'data-frmshow' ),
401 toggleClass = this.getAttribute( 'data-toggleclass' );
402
403 e.preventDefault();
404 if ( toggleClass === null ) {
405 toggleClass = 'frm_hidden';
406 }
407
408 if ( hide !== null ) {
409 jQuery( hide ).addClass( toggleClass );
410 }
411
412 if ( show !== null ) {
413 jQuery( show ).removeClass( toggleClass );
414 }
415
416 var current = this.parentNode.querySelectorAll( 'a.current' );
417 if ( current !== null ) {
418 for ( var i = 0; i < current.length; i++ ) {
419 current[ i ].classList.remove( 'current' );
420 }
421 this.classList.add( 'current' );
422 }
423
424 return false;
425 }
426
427 function setupMenuOffset() {
428 window.onscroll = document.documentElement.onscroll = setMenuOffset;
429 setMenuOffset();
430 }
431
432 function setMenuOffset() {
433 var fields = document.getElementById( 'frm_adv_info' );
434 if ( fields === null ) {
435 return;
436 }
437
438 var currentOffset = document.documentElement.scrollTop || document.body.scrollTop; // body for Safari
439 if ( currentOffset === 0 ) {
440 fields.classList.remove( 'frm_fixed' );
441 return;
442 }
443
444 var posEle = document.getElementById( 'frm_position_ele' );
445 if ( posEle === null ) {
446 return;
447 }
448
449 var eleOffset = jQuery( posEle ).offset();
450 var offset = eleOffset.top;
451 var desiredOffset = offset - currentOffset;
452 var menuHeight = 0;
453
454 var menu = document.getElementById( 'wpadminbar' );
455 if ( menu !== null ) {
456 menuHeight = menu.offsetHeight;
457 }
458
459 if ( desiredOffset < menuHeight ) {
460 desiredOffset = menuHeight;
461 }
462
463 if ( desiredOffset > menuHeight ) {
464 fields.classList.remove( 'frm_fixed' );
465 } else {
466 fields.classList.add( 'frm_fixed' );
467 if ( desiredOffset !== 32 ) {
468 fields.style.top = desiredOffset + 'px';
469 }
470 }
471 }
472
473 function loadTooltips() {
474 var wrapClass = jQuery( '.wrap, .frm_wrap' ),
475 confirmModal = document.getElementById( 'frm_confirm_modal' );
476
477 jQuery( confirmModal ).on( 'click', '[data-deletefield]', deleteFieldConfirmed );
478 jQuery( confirmModal ).on( 'click', '[data-removeid]', removeThisTag );
479 jQuery( confirmModal ).on( 'click', '[data-trashtemplate]', trashTemplate );
480
481 wrapClass.on( 'click', '.frm_remove_tag, .frm_remove_form_action', removeThisTag );
482 wrapClass.on( 'click', 'a[data-frmverify]', confirmClick );
483 wrapClass.on( 'click', 'a[data-frmtoggle]', toggleItem );
484 wrapClass.on( 'click', 'a[data-frmhide], a[data-frmshow]', hideShowItem );
485 wrapClass.on( 'click', '.widget-top,a.widget-action', clickWidget );
486
487 wrapClass.on( 'mouseenter.frm', '.frm_bstooltip, .frm_help', function () {
488 jQuery( this ).off( 'mouseenter.frm' );
489
490 jQuery( '.frm_bstooltip, .frm_help' ).tooltip( );
491 jQuery( this ).tooltip( 'show' );
492 } );
493
494 jQuery( '.frm_bstooltip, .frm_help' ).tooltip( );
495 }
496
497 function removeThisTag() {
498 /*jshint validthis:true */
499 var show, hide, id = '', removeMore,
500 deleteButton = jQuery( this ),
501 continueRemove = confirmLinkClick( this );
502
503 if ( continueRemove === false ) {
504 return;
505 } else {
506 id = deleteButton.attr( 'data-removeid' );
507 show = deleteButton.attr( 'data-showlast' );
508 removeMore = deleteButton.attr( 'data-removemore' );
509 if ( typeof show === 'undefined' ) {
510 show = '';
511 }
512 hide = deleteButton.attr( 'data-hidelast' );
513 if ( typeof hide === 'undefined' ) {
514 hide = '';
515 }
516 }
517
518 if ( show !== '' ) {
519 if ( deleteButton.closest( '.frm_add_remove' ).find( '.frm_remove_tag:visible' ).length > 1 ) {
520 show = '';
521 hide = '';
522 }
523 } else if ( id.indexOf( 'frm_postmeta_' ) === 0 ) {
524 if ( jQuery( '#frm_postmeta_rows .frm_postmeta_row' ).length < 2 ) {
525 show = '.frm_add_postmeta_row.button';
526 }
527 if ( jQuery( '.frm_toggle_cf_opts' ).length && jQuery( '#frm_postmeta_rows .frm_postmeta_row:not(#' + id + ')' ).last().length ) {
528 if ( show !== '' ) {
529 show += ',';
530 }
531 show += '#' + jQuery( '#frm_postmeta_rows .frm_postmeta_row:not(#' + id + ')' ).last().attr( 'id' ) + ' .frm_toggle_cf_opts';
532 }
533 }
534
535 var $fadeEle = jQuery( document.getElementById( id ) );
536 $fadeEle.fadeOut( 400, function() {
537 $fadeEle.remove();
538
539 if ( hide !== '' ) {
540 jQuery( hide ).hide();
541 }
542
543 if ( show !== '' ) {
544 jQuery( show + ' a,' + show ).removeClass( 'frm_hidden' ).fadeIn( 'slow' );
545 }
546
547 var action = jQuery( this ).closest( '.frm_form_action_settings' );
548 if ( typeof action !== 'undefined' ) {
549 var type = jQuery( this ).closest( '.frm_form_action_settings' ).find( '.frm_action_name' ).val();
550 checkActiveAction( type );
551 }
552 } );
553
554 if ( typeof removeMore !== 'undefined' ) {
555 removeMore = jQuery( removeMore );
556 removeMore.fadeOut( 400, function() {
557 removeMore.remove();
558 } );
559 }
560
561 if ( show !== '' ) {
562 jQuery( this ).closest( '.frm_logic_rows' ).fadeOut( 'slow' );
563 }
564
565 return false;
566 }
567
568 function clickWidget( event, b ) {
569 /*jshint validthis:true */
570 var target = event.target;
571 if ( typeof b === 'undefined' ) {
572 b = this;
573 }
574
575 popCalcFields( b, false );
576
577 var cont = jQuery( b ).closest( '.frm_form_action_settings' );
578 if ( cont.length && typeof target !== 'undefined' && ( target.parentElement.className.indexOf( 'frm_email_icons' ) > -1 || target.parentElement.className.indexOf( 'frm_toggle' ) > -1 ) ) {
579 // clicking on delete icon shouldn't open it
580 event.stopPropagation();
581 return;
582 }
583
584 var inside = cont.children( '.widget-inside' );
585
586 if ( cont.length && inside.find( 'p, div, table' ).length < 1 ) {
587 var action_id = cont.find( 'input[name$="[ID]"]' ).val();
588 var action_type = cont.find( 'input[name$="[post_excerpt]"]' ).val();
589 if ( action_type ) {
590 inside.html( '<span class="frm-wait frm_spinner"></span>' );
591 cont.find( '.spinner' ).fadeIn( 'slow' );
592 jQuery.ajax( {
593 type: 'POST',
594 url: ajaxurl,
595 data: {
596 action: 'frm_form_action_fill',
597 action_id: action_id,
598 action_type: action_type,
599 nonce: frmGlobal.nonce
600 },
601 success: function( html ) {
602 inside.html( html );
603 initiateMultiselect();
604 showInputIcon( '#' + cont.attr('id') );
605 }
606 } );
607 }
608 }
609
610 jQuery( b ).closest( '.frm_field_box' ).siblings().find( '.widget-inside' ).slideUp( 'fast' );
611 if ( ( typeof b.className !== 'undefined' && b.className.indexOf( 'widget-action' ) !== -1 ) || jQuery( b ).closest( '.start_divider' ).length < 1 ) {
612 return;
613 }
614
615 inside = jQuery( b ).closest( 'div.widget' ).children( '.widget-inside' );
616 if ( inside.is( ':hidden' ) ) {
617 inside.slideDown( 'fast' );
618 } else {
619 inside.slideUp( 'fast' );
620 }
621 }
622
623 function clickNewTab() {
624 /*jshint validthis:true */
625 var t = this.getAttribute( 'href' ),
626 c = t.replace( '#', '.' ),
627 $link = jQuery( this );
628
629 if ( typeof t === 'undefined' ) {
630 return false;
631 }
632
633 $link.closest( 'li' ).addClass( 'frm-tabs active' ).siblings( 'li' ).removeClass( 'frm-tabs active starttab' );
634 $link.closest( 'div' ).children( '.tabs-panel' ).not( t ).not( c ).hide();
635 document.getElementById( t.replace( '#', '' ) ).style.display = 'block';
636
637 if ( this.id === 'frm_insert_fields_tab' ) {
638 clearSettingsBox();
639 }
640 return false;
641 }
642
643 function clickTab( link, auto ) {
644 link = jQuery( link );
645 var t = link.attr( 'href' );
646 if ( typeof t === 'undefined' ) {
647 return;
648 }
649
650 var c = t.replace( '#', '.' );
651 var pro = jQuery( '.frm-category-tabs li' ).length > 2;
652 link.closest( 'li' ).addClass( 'frm-tabs active' ).siblings( 'li' ).removeClass( 'frm-tabs active starttab' );
653 if ( link.closest( 'div' ).find( '.tabs-panel' ).length ) {
654 link.closest( 'div' ).children( '.tabs-panel' ).not( t ).not( c ).hide();
655 } else {
656 if ( document.getElementById( 'form_global_settings' ) !== null ) {
657 /* global settings */
658 var ajax = link.data( 'frmajax' );
659 link.closest( '.frm_wrap' ).find( '.tabs-panel, .hide_with_tabs' ).hide();
660 if ( typeof ajax !== 'undefined' && ajax == '1' ) {
661 loadSettingsTab( t );
662 }
663 } else {
664 /* form settings page */
665 jQuery( '#frm-categorydiv .tabs-panel, .hide_with_tabs' ).hide();
666 }
667 }
668 jQuery( t ).show();
669 jQuery( c ).show();
670
671 hideShortcodes();
672
673 if ( auto !== 'auto' ) {
674 // Hide success message on tab change.
675 jQuery( '.frm_updated_message' ).hide();
676 }
677
678 if ( jQuery( link ).closest( '#frm_adv_info' ).length ) {
679 return;
680 }
681
682 if ( jQuery( '.frm_form_settings' ).length ) {
683 jQuery( '.frm_form_settings' ).attr( 'action', '?page=formidable&frm_action=settings&id=' + jQuery( '.frm_form_settings input[name="id"]' ).val() + '&t=' + t.replace( '#', '' ) );
684 } else {
685 jQuery( '.frm_settings_form' ).attr( 'action', '?page=formidable-settings&t=' + t.replace( '#', '' ) );
686 }
687 }
688
689 /* Form Builder */
690 function setupSortable( sort ) {
691 var startSort = false,
692 container = jQuery( '#post-body-content' );
693
694 var opts = {
695 connectWith: 'ul.frm_sorting',
696 items: '> li.frm_field_box',
697 placeholder: 'sortable-placeholder',
698 axis: 'y',
699 cancel: '.widget,.frm_field_opts_list,input,textarea,select,.edit_field_type_end_divider,.frm_sortable_field_opts,.frm_noallow',
700 accepts: 'field_type_list',
701 forcePlaceholderSize: false,
702 tolerance: 'pointer',
703 handle: '.frm-move',
704 over : function(){
705 this.classList.add( 'drop-me' );
706 },
707 out : function(){
708 this.classList.remove( 'drop-me' );
709 },
710 receive: function( event, ui ) {
711 // Receive event occurs when an item in one sortable list is dragged into another sortable list
712
713 if ( cancelSort ) {
714 ui.item.addClass( 'frm_cancel_sort' );
715 return;
716 }
717
718 if ( typeof ui.item.attr( 'id' ) !== 'undefined' ) {
719 if ( ui.item.attr( 'id' ).indexOf( 'frm_field_id' ) > -1 ) {
720 // An existing field was dragged and dropped into, out of, or between sections
721 updateFieldAfterMovingBetweenSections( ui.item );
722 } else {
723 // A new field was dragged into the form
724 insertNewFieldByDragging( this, ui.item, opts );
725 }
726 }
727 },
728 change: function( event, ui ) {
729 // don't allow some field types inside section
730 if ( allowDrop( ui ) ) {
731 ui.placeholder.addClass( 'sortable-placeholder' ).removeClass( 'no-drop-placeholder' );
732 cancelSort = false;
733 } else {
734 ui.placeholder.addClass( 'no-drop-placeholder' ).removeClass( 'sortable-placeholder' );
735 cancelSort = true;
736 }
737 },
738 start: function( event, ui ) {
739 if ( ui.item[0].offsetHeight > 120 ) {
740 jQuery( sort ).sortable( 'refreshPositions' );
741 }
742 if ( ui.item[0].classList.contains( 'frm-page-collapsed' ) ) {
743 // If a page if collapsed, expand it before dragging since only the page break will move.
744 toggleCollapsePage( jQuery( ui.item[0] ) );
745 }
746 },
747 helper: function( e, li ) {
748 copyHelper = li.clone().insertAfter( li );
749 return li.clone();
750 },
751 beforeStop: function( event, ui ) {
752 // If this was dropped at the beginning of a collpased page, open it.
753 var previous = ui.item[0].previousElementSibling;
754 if ( previous !== null && previous.classList.contains( 'frm-page-collapsed' ) ) {
755 toggleCollapsePage( jQuery( previous ) );
756 }
757 },
758 stop: function( event, ui ) {
759 var moving = jQuery( this );
760 copyHelper && copyHelper.remove();
761 if ( cancelSort ) {
762 moving.sortable( 'cancel' );
763 } else {
764 updateFieldOrder();
765 }
766 moving.children( '.edit_field_type_end_divider' ).appendTo( this );
767 },
768 sort: function( event ) {
769 container.scrollTop( function( i, v ) {
770 if ( startSort === false ) {
771 startSort = event.clientY;
772 return v;
773 }
774
775 var moved = event.clientY - startSort;
776 var h = this.offsetHeight;
777 var relativePos = event.clientY - this.offsetTop;
778 var y = relativePos - h / 2;
779 if ( relativePos > ( h - 50 ) && moved > 5 ) {
780 // scrolling down
781 return v + y * 0.1;
782 } else if ( relativePos < 50 && moved < -5 ) {
783 //scrolling up
784 return v - Math.abs( y * 0.1 );
785 }
786 } );
787 }
788 };
789
790 jQuery( sort ).sortable( opts );
791
792 setupFieldOptionSorting( jQuery( '#frm_builder_page' ) );
793 }
794
795 function setupFieldOptionSorting( sort ) {
796 var opts = {
797 items: '.frm_sortable_field_opts li',
798 axis: 'y',
799 opacity: 0.65,
800 forcePlaceholderSize: false,
801 handle: '.frm-drag',
802 helper: function( e, li ) {
803 copyHelper = li.clone().insertAfter( li );
804 return li.clone();
805 },
806 stop: function( e, ui ) {
807 copyHelper && copyHelper.remove();
808 var fieldId = ui.item.attr( 'id' ).replace( 'frm_delete_field_', '' ).replace( '-' + ui.item.data( 'optkey' ) + '_container', '' );
809 resetDisplayedOpts( fieldId );
810 }
811 };
812
813 jQuery( sort ).sortable( opts );
814 }
815
816 // Get the section where a field is dropped
817 function getSectionForFieldPlacement( currentItem ) {
818 var section = '';
819 if ( typeof currentItem !== 'undefined' ) {
820 section = currentItem.closest( '.edit_field_type_divider' );
821 }
822
823 return section;
824 }
825
826 // Get the form ID where a field is dropped
827 function getFormIdForFieldPlacement( section ) {
828 var form_id = '';
829
830 if ( typeof section[0] !== 'undefined' ) {
831 var sDivide = section.children( '.start_divider' );
832 sDivide.children( '.edit_field_type_end_divider' ).appendTo( sDivide );
833 if ( typeof section.attr( 'data-formid' ) !== 'undefined' ) {
834 var fieldId = section.attr( 'data-fid' );
835 form_id = jQuery( 'input[name="field_options[form_select_' + fieldId + ']"]' ).val();
836 }
837 }
838
839 if ( typeof form_id === 'undefined' || form_id === '' ) {
840 form_id = this_form_id;
841 }
842
843 return form_id;
844 }
845
846 // Get the section ID where a field is dropped
847 function getSectionIdForFieldPlacement( section ) {
848 var sectionId = 0;
849 if ( typeof section[0] !== 'undefined' ) {
850 sectionId = section.attr( 'id' ).replace( 'frm_field_id_', '' );
851 }
852
853 return sectionId;
854 }
855
856 /**
857 * Update a field after it is dragged and dropped into, out of, or between sections
858 *
859 * @param {object} currentItem
860 */
861 function updateFieldAfterMovingBetweenSections( currentItem ) {
862 var fieldId = currentItem.attr( 'id' ).replace( 'frm_field_id_', '' );
863 var section = getSectionForFieldPlacement( currentItem );
864 var formId = getFormIdForFieldPlacement( section );
865 var sectionId = getSectionIdForFieldPlacement( section );
866
867 jQuery.ajax( {
868 type: 'POST', url: ajaxurl,
869 data: {
870 action: 'frm_update_field_after_move',
871 form_id: formId,
872 field: fieldId,
873 section_id: sectionId,
874 nonce: frmGlobal.nonce
875 },
876 success: function() {
877 toggleSectionHolder();
878 updateInSectionValue( fieldId, sectionId );
879 }
880 } );
881 }
882
883 // Update the in_section field value
884 function updateInSectionValue( fieldId, sectionId ) {
885 document.getElementById( 'frm_in_section_' + fieldId ).value = sectionId;
886 }
887
888 /**
889 * Add a new field by dragging and dropping it from the Fields sidebar
890 *
891 * @param {object} selectedItem
892 * @param {object} fieldButton
893 * @param {object} opts
894 */
895 function insertNewFieldByDragging( selectedItem, fieldButton, opts ) {
896 var fieldType = fieldButton.attr( 'id' );
897
898 // We'll optimistically disable the button now. We'll re-enable if AJAX fails
899 if ( 'summary' === fieldType ) {
900 var addBtn = fieldButton.children( '.frm_add_field' );
901 disableSummaryBtnBeforeAJAX( addBtn, fieldButton );
902 }
903
904 var currentItem = jQuery( selectedItem ).data().uiSortable.currentItem;
905 var section = getSectionForFieldPlacement( currentItem );
906 var formId = getFormIdForFieldPlacement( section );
907 var sectionId = getSectionIdForFieldPlacement( section );
908
909 var loadingID = fieldType.replace( '|', '-' );
910 currentItem.replaceWith( '<li class="frm-wait frmbutton_loadingnow" id="' + loadingID + '" ></li>' );
911
912 var hasBreak = 0;
913 if ( 'summary' === fieldType ) {
914 // see if we need to insert a page break before this newly-added summary field. Check for at least 1 page break
915 hasBreak = jQuery( '.frmbutton_loadingnow#' + loadingID ).prevAll( 'li[data-type="break"]:first' ).length > 0 ? 1 : 0;
916 }
917
918 jQuery.ajax( {
919 type: 'POST', url: ajaxurl,
920 data: {
921 action: 'frm_insert_field',
922 form_id: formId,
923 field_type: fieldType,
924 section_id: sectionId,
925 nonce: frmGlobal.nonce,
926 has_break: hasBreak,
927 },
928 success: function( msg ) {
929 document.getElementById( 'frm_form_editor_container' ).classList.add( 'frm-has-fields' );
930 jQuery( '.frmbutton_loadingnow#' + loadingID ).replaceWith( msg );
931 updateFieldOrder();
932
933 afterAddField( msg, false );
934 },
935 error: function( jqXHR, textStatus, errorThrown ) {
936 maybeReenableSummaryBtnAfterAJAX( fieldType, addBtn, fieldButton, errorThrown );
937 },
938 } );
939 }
940
941 // don't allow page break, embed form, captcha, summary, or section inside section field
942 function allowDrop( ui ) {
943 if ( ! ui.placeholder.parent().hasClass( 'start_divider' ) ) {
944 return true;
945 }
946
947 // new field
948 if ( ui.item.hasClass( 'frmbutton' ) ) {
949 if ( ui.item.hasClass( 'frm_tbreak' ) || ui.item.hasClass( 'frm_tform' ) || ui.item.hasClass( 'frm_tdivider' ) || ui.item.hasClass( 'frm_tdivider-repeat' ) ) {
950 return false;
951 }
952 return true;
953 }
954
955 // moving an existing field
956 return ! ( ui.item.hasClass( 'edit_field_type_break' ) || ui.item.hasClass( 'edit_field_type_form' ) ||
957 ui.item.hasClass( 'edit_field_type_divider' ) );
958 }
959
960 function loadFields( field_id ) {
961 var $thisField = jQuery( document.getElementById( field_id ) );
962 var fields;
963 if ( jQuery.isFunction( jQuery.fn.addBack ) ) {
964 fields = $thisField.nextAll( "*:lt(14)" ).addBack();
965 } else {
966 fields = $thisField.nextAll( "*:lt(14)" ).andSelf();
967 }
968 fields.addClass( 'frm_load_now' );
969
970 var h = [];
971 jQuery.each( fields, function( k, v ) {
972 h.push( jQuery( v ).find( '.frm_hidden_fdata' ).html() );
973 } );
974
975 jQuery.ajax( {
976 type: 'POST', url: ajaxurl,
977 data: {action: 'frm_load_field', field: h, form_id: this_form_id, nonce: frmGlobal.nonce},
978 success: function( html ) {
979 html = html.replace( /^\s+|\s+$/g, '' );
980 if ( html.indexOf( '{' ) !== 0 ) {
981 jQuery( '.frm_load_now' ).removeClass( '.frm_load_now' ).html( 'Error' );
982 return;
983 }
984 html = jQuery.parseJSON( html );
985
986 for ( var key in html ) {
987 jQuery( '#frm_field_id_' + key ).replaceWith( html[key] );
988 setupSortable( '#frm_field_id_' + key + '.edit_field_type_divider ul.frm_sorting' );
989 }
990
991 var $nextSet = $thisField.nextAll( '.frm_field_loading:not(.frm_load_now)' );
992 if ( $nextSet.length ) {
993 loadFields( $nextSet.attr( 'id' ) );
994 } else {
995 // go up a level
996 $nextSet = jQuery( document.getElementById( 'frm-show-fields' ) ).find( '.frm_field_loading:not(.frm_load_now)' );
997 if ( $nextSet.length ) {
998 loadFields( $nextSet.attr( 'id' ) );
999 }
1000 }
1001
1002 initiateMultiselect();
1003 renumberPageBreaks();
1004 },
1005 } );
1006 }
1007
1008 function addFieldClick() {
1009 /*jshint validthis:true */
1010 var $thisObj = jQuery( this );
1011 // there is no real way to disable a <a> (with a valid href attribute) in HTML - https://css-tricks.com/how-to-disable-links/
1012 if ( $thisObj.hasClass( 'disabled' ) ) {
1013 return false;
1014 }
1015
1016 var $button = $thisObj.closest( '.frmbutton' );
1017 var fieldType = $button.attr( 'id' );
1018
1019 var hasBreak = 0;
1020 if ( 'summary' === fieldType ) {
1021 // We'll optimistically disable $button now. We'll re-enable if AJAX fails
1022 disableSummaryBtnBeforeAJAX( $thisObj, $button );
1023
1024 hasBreak = $newFields.children( 'li[data-type="break"]' ).length > 0 ? 1 : 0;
1025 }
1026
1027 var form_id = this_form_id;
1028
1029 jQuery.ajax( {
1030 type: 'POST',
1031 url: ajaxurl,
1032 data: {
1033 action: 'frm_insert_field',
1034 form_id: form_id,
1035 field_type: fieldType,
1036 section_id: 0,
1037 nonce: frmGlobal.nonce,
1038 has_break: hasBreak,
1039 },
1040 success: function( msg ) {
1041 document.getElementById( 'frm_form_editor_container' ).classList.add( 'frm-has-fields' );
1042 $newFields.append( msg );
1043 afterAddField( msg, true );
1044 },
1045 error: function( jqXHR, textStatus, errorThrown ) {
1046 maybeReenableSummaryBtnAfterAJAX( fieldType, $thisObj, $button, errorThrown );
1047 },
1048 } );
1049 return false;
1050 }
1051
1052 function disableSummaryBtnBeforeAJAX( addBtn, fieldButton ) {
1053 addBtn.addClass( 'disabled' );
1054 fieldButton.draggable( 'disable' );
1055 }
1056
1057 function reenableAddSummaryBtn() {
1058 var frmBtn = jQuery( 'li#summary' );
1059 var addFieldLink = frmBtn.children( '.frm_add_field' );
1060 frmBtn.draggable( 'enable' );
1061 addFieldLink.removeClass( 'disabled' );
1062 }
1063
1064 function maybeDisableAddSummaryBtn() {
1065 if ( formHasSummaryField() ) {
1066 disableAddSummaryBtn();
1067 }
1068 }
1069
1070 function disableAddSummaryBtn() {
1071 var frmBtn = jQuery( 'li#summary' );
1072 var addFieldLink = frmBtn.children( '.frm_add_field' );
1073 frmBtn.draggable( 'disable' );
1074 addFieldLink.addClass( 'disabled' );
1075 }
1076
1077 function maybeReenableSummaryBtnAfterAJAX( fieldType, addBtn, fieldButton, errorThrown ) {
1078 alert( errorThrown + '. Please try again.' );
1079 if ( 'summary' === fieldType ) {
1080 addBtn.removeClass( 'disabled' );
1081 fieldButton.draggable( 'enable' );
1082 }
1083 }
1084
1085 function formHasSummaryField() {
1086 // .edit_field_type_summary is a better selector here in order to also cover fields loaded by AJAX
1087 return $newFields.children( 'li.edit_field_type_summary' ).length > 0;
1088 }
1089
1090 function duplicateField() {
1091 /*jshint validthis:true */
1092 var thisField = jQuery( this ).closest( 'li' );
1093 var field_id = thisField.data( 'fid' );
1094 var children = fieldsInSection( field_id );
1095
1096 if ( thisField.hasClass( 'frm-section-collapsed' ) || thisField.hasClass( 'frm-page-collapsed' ) ) {
1097 return false;
1098 }
1099
1100 jQuery.ajax( {
1101 type: 'POST', url: ajaxurl,
1102 data: {
1103 action: 'frm_duplicate_field',
1104 field_id: field_id,
1105 form_id: this_form_id,
1106 children: children,
1107 nonce: frmGlobal.nonce,
1108 },
1109 success: function( msg ) {
1110 thisField.after( msg );
1111 updateFieldOrder();
1112 afterAddField( msg, false );
1113 },
1114 } );
1115 return false;
1116 }
1117
1118 function afterAddField( msg, addFocus ) {
1119 var regex = /id="(\S+)"/,
1120 match = regex.exec( msg ),
1121 field = document.getElementById( match[1] ),
1122 section = '#' + match[1] + '.edit_field_type_divider ul.frm_sorting',
1123 $thisSection = jQuery( section ),
1124 toggled = false;
1125
1126 setupSortable( section );
1127
1128 if ( $thisSection.length ) {
1129 $thisSection.parent( '.frm_field_box' ).children( '.frm_no_section_fields' ).addClass( 'frm_block' );
1130 } else {
1131 var $parentSection = jQuery( field ).closest( 'ul.frm_sorting' );
1132 if ( $parentSection.length ) {
1133 toggleOneSectionHolder( $parentSection );
1134 toggled = true;
1135 }
1136 }
1137
1138 if ( msg.indexOf( 'frm-collapse-page' ) !== -1 ) {
1139 renumberPageBreaks();
1140 }
1141
1142 addClass( field, 'frm-newly-added' );
1143 setTimeout( function() {
1144 field.classList.remove( 'frm-newly-added' );
1145 }, 1000 );
1146
1147 if ( addFocus ) {
1148 var bounding = field.getBoundingClientRect(),
1149 container = document.getElementById( 'post-body-content' ),
1150 inView = ( bounding.top >= 0 &&
1151 bounding.left >= 0 &&
1152 bounding.right <= ( window.innerWidth || document.documentElement.clientWidth ) &&
1153 bounding.bottom <= ( window.innerHeight || document.documentElement.clientHeight )
1154 );
1155
1156 if ( ! inView ) {
1157 container.scroll( {
1158 top: container.scrollHeight,
1159 left: 0,
1160 behavior: 'smooth',
1161 } );
1162 }
1163
1164 if ( toggled === false ) {
1165 toggleOneSectionHolder( $thisSection );
1166 }
1167 }
1168
1169 deselectFields();
1170 initiateMultiselect();
1171 }
1172
1173 function clearSettingsBox() {
1174 jQuery( '#new_fields .frm-single-settings' ).addClass( 'frm_hidden' );
1175 jQuery( '#frm-options-panel > .frm-single-settings' ).removeClass( 'frm_hidden' );
1176 deselectFields();
1177 }
1178
1179 function deselectFields() {
1180 jQuery( 'li.ui-state-default.selected' ).removeClass( 'selected' );
1181 }
1182
1183 function scrollToField( field ) {
1184 var newPos = field.getBoundingClientRect().top,
1185 container = document.getElementById( 'post-body-content' ),
1186 pos = container.getBoundingClientRect(),
1187 screenTop = pos.top;
1188
1189 if ( typeof animate === 'undefined' ) {
1190 jQuery( container ).scrollTop(newPos);
1191 } else {
1192 // TODO: smooth scroll
1193 jQuery( container ).animate({scrollTop: newPos}, 500);
1194 }
1195 }
1196
1197 function checkCalculationCreatedByUser() {
1198 var calculation = this.value;
1199 var warningMessage = checkMatchingParens( calculation );
1200 warningMessage += checkShortcodes( calculation, this );
1201
1202 if ( warningMessage !== '' ) {
1203 alert( calculation + "\n\n" + warningMessage );
1204 }
1205 }
1206
1207 /**
1208 * Checks a string for parens, brackets, and curly braces and returns a message if any unmatched are found.
1209 * @param formula
1210 * @returns {string}
1211 */
1212 function checkMatchingParens( formula ) {
1213
1214 var stack = [],
1215 formula_array = formula.split( '' ),
1216 length = formula_array.length,
1217 opening = ["{", "[", "("],
1218 closing = {
1219 "}": "{",
1220 ")": "(",
1221 "]": "[",
1222 },
1223 unmatchedClosing = [],
1224 msg = '',
1225 i, next, top;
1226
1227 for ( i = 0; i < length; i++ ) {
1228 if ( opening.includes( formula_array[i] ) ) {
1229 stack.push( formula_array[i] );
1230 continue;
1231 }
1232 if ( closing.hasOwnProperty( formula_array[i] ) ) {
1233 top = stack.pop();
1234 if ( top !== closing[formula_array[i]] ) {
1235 unmatchedClosing.push( formula_array[i] );
1236 }
1237 }
1238 }
1239
1240 if ( stack.length > 0 || unmatchedClosing.length > 0 ) {
1241 msg = frm_admin_js.unmatched_parens + '\n\n';
1242 return msg;
1243 }
1244
1245 return '';
1246 }
1247
1248 /**
1249 * Checks a calculation for shortcodes that shouldn't be in it and returns a message if found.
1250 * @param calculation
1251 * @param inputElement
1252 * @returns {string}
1253 */
1254 function checkShortcodes( calculation, inputElement ) {
1255 var msg = checkNonNumericShortcodes( calculation, inputElement );
1256 msg += checkNonFormShortcodes( calculation );
1257
1258 return msg;
1259 }
1260
1261 /**
1262 * Checks if a numeric calculation has shortcodes that output non-numeric strings and returns a message if found.
1263 * @param calculation
1264 *
1265 * @param inputElement
1266 * @returns {string}
1267 */
1268 function checkNonNumericShortcodes( calculation, inputElement ) {
1269
1270 var msg = '';
1271
1272 if ( isTextCalculation( inputElement ) ) {
1273 return msg;
1274 }
1275
1276 var nonNumericShortcodes = getNonNumericShortcodes();
1277
1278 if ( nonNumericShortcodes.test( calculation ) ) {
1279 msg = frm_admin_js.text_shortcodes + "\n\n";
1280 }
1281
1282 return msg;
1283 }
1284
1285 /**
1286 * Determines if the calculation input is from a text calculation.
1287 *
1288 * @param inputElement
1289 */
1290 function isTextCalculation( inputElement ) {
1291 return jQuery( inputElement ).siblings( "label[for^='calc_type']" ).children( "input" ).prop( "checked" );
1292 }
1293
1294 /**
1295 * Returns a regular expression of shortcodes that can't be used in numeric calculations.
1296 * @returns {RegExp}
1297 */
1298 function getNonNumericShortcodes() {
1299 return /\[(date|time|email|ip)\]/;
1300 }
1301
1302 /**
1303 * Checks if a string has any shortcodes that do not belong in forms and returns a message if any are found.
1304 * @param formula
1305 * @returns {string}
1306 */
1307 function checkNonFormShortcodes( formula ) {
1308 var nonFormShortcodes = getNonFormShortcodes(),
1309 msg = '';
1310
1311 if ( nonFormShortcodes.test( formula ) ) {
1312 msg += frm_admin_js.view_shortcodes + "\n\n";
1313 }
1314
1315 return msg;
1316 }
1317
1318 /**
1319 * Returns a regular expression of shortcodes that can't be used in forms but can be used in Views, Email
1320 * Notifications, and other Formidable areas.
1321 *
1322 * @returns {RegExp}
1323 */
1324 function getNonFormShortcodes() {
1325 return /\[id\]|\[key\]|\[if\s\w+\]|\[foreach\s\w+\]|\[created-at(\s*)?/g;
1326 }
1327
1328 function isSummaryCalcBox( box ) {
1329 var list = jQuery( box ).find( '.frm_code_list' );
1330 return 1 === list.length && list.hasClass( 'frm_js_summary_list' );
1331 }
1332
1333 function extractExcludedOptions( exclude ) {
1334 var opts = [];
1335 for ( var i = 0; i < exclude.length; i++ ) {
1336 if ( exclude[ i ].startsWith( '[' ) ) {
1337 opts.push( exclude[ i ] );
1338 // remove it
1339 exclude.splice( i, 1 );
1340 // https://love2dev.com/blog/javascript-remove-from-array/#remove-from-array-splice-value
1341 i--;
1342 }
1343 }
1344
1345 return opts;
1346 }
1347
1348 function hasExcludedOption( field, excludedOpts ) {
1349 var hasOption = false;
1350 for ( var i = 0; i < excludedOpts.length; i++ ) {
1351 var inputs = document.getElementsByName( getFieldOptionInputName( excludedOpts[ i ], field.fieldId ) );
1352 // 2nd condition checks that there's at least one non-empty value
1353 if ( inputs.length && jQuery( inputs[0] ).val() ) {
1354 hasOption = true;
1355 break;
1356 }
1357 }
1358 return hasOption;
1359 }
1360
1361 function getFieldOptionInputName( opt, fieldId ) {
1362 var at = opt.indexOf( ']' );
1363 return 'field_options' + opt.substring( 0, at ) + '_' + fieldId + opt.substring( at );
1364 }
1365
1366 function popCalcFields( v, force ) {
1367 var box, exclude, fields, i, list,
1368 p = jQuery( v ).closest( '.frm-single-settings' ),
1369 calc = p.find( '.frm-calc-field' );
1370
1371 if ( ! force && ( ! calc.length || calc.val() === '' || calc.is( ':hidden' ) ) ) {
1372 return;
1373 }
1374
1375 var isSummary = isSummaryCalcBox( v );
1376
1377 var form_id = jQuery( 'input[name="id"]' ).val();
1378 var fieldId = p.find( 'input[name="frm_fields_submitted[]"]' ).val();
1379
1380 if ( force ) {
1381 box = v;
1382 } else {
1383 box = document.getElementById( 'frm-calc-box-' + fieldId );
1384 }
1385
1386 exclude = getExcludeArray( box, isSummary );
1387 var excludedOpts = extractExcludedOptions( exclude );
1388
1389 fields = getFieldList();
1390 list = document.getElementById( 'frm-calc-list-' + fieldId );
1391 list.innerHTML = '';
1392
1393 for ( i = 0; i < fields.length; i++ ) {
1394 if ( exclude.includes( fields[ i ].fieldType ) ||
1395 ( excludedOpts.length && hasExcludedOption( fields[ i ], excludedOpts ) ) ) {
1396 continue;
1397 }
1398
1399 var span = document.createElement( 'span' );
1400 span.appendChild( document.createTextNode( '[' + fields[i].fieldId + ']' ) );
1401
1402 var a = document.createElement( 'a' );
1403 a.setAttribute( 'href', '#' );
1404 a.setAttribute( 'data-code', fields[i].fieldId );
1405 a.classList.add( 'frm_insert_code' );
1406 a.appendChild( span );
1407 a.appendChild( document.createTextNode( fields[i].fieldName ) );
1408
1409 var li = document.createElement( 'li' );
1410 li.classList.add( 'frm-field-list-' + fieldId );
1411 li.classList.add( 'frm-field-list-' + fields[i].fieldType );
1412 li.appendChild( a );
1413 list.appendChild( li );
1414 }
1415 }
1416
1417 function getExcludeArray( calcBox, isSummary ) {
1418 var exclude = JSON.parse( calcBox.getElementsByClassName( 'frm_code_list' )[0].getAttribute( 'data-exclude' ) );
1419
1420 if ( isSummary ) {
1421 // includedExtras are those that are normally excluded from the summary but the form owner can choose to include,
1422 // when they have been chosen to be included, then they can now be manually excluded in the calc box.
1423 var includedExtras = getIncludedExtras();
1424 if ( includedExtras.length ) {
1425 for ( var i = 0; i < exclude.length; i++ ) {
1426 if ( includedExtras.includes( exclude[ i ] ) ) {
1427 // remove it
1428 exclude.splice( i, 1 );
1429 // https://love2dev.com/blog/javascript-remove-from-array/#remove-from-array-splice-value
1430 i--;
1431 }
1432 }
1433 }
1434 }
1435
1436 return exclude;
1437 }
1438
1439 function getIncludedExtras() {
1440 var checked = [];
1441 var checkboxes = document.getElementsByClassName( 'frm_include_extras_field' );
1442
1443 for ( var i = 0; i < checkboxes.length; i++ ) {
1444 if ( checkboxes[i].checked ) {
1445 checked.push( checkboxes[i].value );
1446 }
1447 }
1448
1449 return checked;
1450 }
1451
1452 function rePopCalcFieldsForSummary() {
1453 popCalcFields( jQuery( '.frm-inline-modal.postbox:has(.frm_js_summary_list)' )[0], true );
1454 }
1455
1456 function getFieldList() {
1457 var i, fields = [],
1458 allFields = document.querySelectorAll( 'li.frm_field_box' );
1459
1460 for ( i = 0; i < allFields.length; i++ ) {
1461 var fieldId = allFields[ i ].getAttribute( 'data-fid' );
1462 if ( typeof fieldId !== 'undefined' && fieldId ) {
1463 fields.push( {
1464 'fieldId': fieldId,
1465 'fieldName': getPossibleValue( 'frm_name_' + fieldId ),
1466 'fieldType': getPossibleValue( 'field_options_type_' + fieldId ),
1467 'fieldKey': getPossibleValue( 'field_options_field_key_' + fieldId )
1468 } );
1469 }
1470
1471 if ( i === allFields.length - 1 ) {
1472 return fields;
1473 }
1474 }
1475 }
1476
1477 /**
1478 * If the element doesn't exist, use a blank value.
1479 */
1480 function getPossibleValue( id ) {
1481 field = document.getElementById( id );
1482 if ( field !== null ) {
1483 return field.value;
1484 } else {
1485 return '';
1486 }
1487 }
1488
1489 function liveChanges() {
1490 /*jshint validthis:true */
1491 var option,
1492 newValue = this.value,
1493 changes = document.getElementById( this.getAttribute( 'data-changeme' ) ),
1494 att = this.getAttribute( 'data-changeatt' );
1495
1496 if ( changes === null ) {
1497 return;
1498 }
1499
1500 if ( att !== null ) {
1501 if ( changes.tagName === 'SELECT' && att === 'placeholder' ) {
1502 option = changes.options[0];
1503 if ( option.value === '' ) {
1504 option.innerHTML = newValue;
1505 } else {
1506 // Create a placeholder option if there are no blank values.
1507 addBlankSelectOption( changes, newValue );
1508 }
1509 } else if ( att === 'class' ) {
1510 changeFieldClass( changes, this );
1511 } else {
1512 changes.setAttribute( att, newValue );
1513 }
1514 } else if ( changes.id.indexOf( 'setup-message' ) === 0 ) {
1515 if ( newValue !== '' ) {
1516 changes.innerHTML = '<input type="text" value="" disabled />';
1517 }
1518 } else {
1519 changes.innerHTML = newValue;
1520 }
1521 }
1522
1523 function toggleInvalidMsg() {
1524 /*jshint validthis:true */
1525 var typeDropdown, fieldType,
1526 fieldId = this.id.replace( 'frm_format_', '' ),
1527 hasValue = this.value !== '';
1528
1529 typeDropdown = document.getElementsByName( 'field_options[type_' + fieldId + ']' )[0];
1530 fieldType = typeDropdown.options[typeDropdown.selectedIndex].value;
1531
1532 if ( fieldType === 'text' ) {
1533 toggleValidationBox( hasValue, '.frm_invalid_msg' + fieldId );
1534 }
1535 }
1536
1537 function markRequired() {
1538 /*jshint validthis:true */
1539 var thisid = this.id.replace( 'frm_', '' ),
1540 fieldId = thisid.replace( 'req_field_', '' ),
1541 checked = this.checked,
1542 label = jQuery( '#field_label_' + fieldId + ' .frm_required' );
1543
1544 toggleValidationBox( checked, '.frm_required_details' + fieldId );
1545
1546 if ( checked ) {
1547 var $reqBox = jQuery( 'input[name="field_options[required_indicator_' + fieldId + ']"]' );
1548 if ( $reqBox.val() === '' ) {
1549 $reqBox.val( '*' );
1550 }
1551 label.removeClass( 'frm_hidden' );
1552 } else {
1553 label.addClass( 'frm_hidden' );
1554 }
1555 }
1556
1557 function toggleValidationBox( hasValue, messageClass ) {
1558 $msg = jQuery( messageClass );
1559 if ( hasValue ) {
1560 $msg.fadeIn( 'fast' ).closest( '.frm_validation_msg' ).fadeIn( 'fast' );
1561 } else {
1562 //Fade out validation options
1563 var v = $msg.fadeOut( 'fast' ).closest( '.frm_validation_box' ).children( ':not(' + messageClass + '):visible' ).length;
1564 if ( v === 0 ) {
1565 $msg.closest( '.frm_validation_msg' ).fadeOut( 'fast' );
1566 }
1567 }
1568 }
1569
1570 function markUnique() {
1571 /*jshint validthis:true */
1572 var field_id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
1573 var $thisField = jQuery( '.frm_unique_details' + field_id );
1574 if ( this.checked ) {
1575 $thisField.fadeIn( 'fast' ).closest( '.frm_validation_msg' ).fadeIn( 'fast' );
1576 $unqDetail = jQuery( '.frm_unique_details' + field_id + ' input' );
1577 if ( $unqDetail.val() === '' ) {
1578 $unqDetail.val( frm_admin_js.default_unique );
1579 }
1580 } else {
1581 var v = $thisField.fadeOut( 'fast' ).closest( '.frm_validation_box' ).children( ':not(.frm_unique_details' + field_id + '):visible' ).length;
1582 if ( v === 0 ) {
1583 $thisField.closest( '.frm_validation_msg' ).fadeOut( 'fast' );
1584 }
1585 }
1586 }
1587
1588 //Fade confirmation field and validation option in or out
1589 function addConf() {
1590 /*jshint validthis:true */
1591 var field_id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
1592 var val = jQuery( this ).val();
1593 var $thisField = jQuery( document.getElementById( 'frm_field_id_' + field_id ) );
1594
1595 toggleValidationBox( val !== '', '.frm_conf_details' + field_id );
1596
1597 if ( val !== '' ) {
1598 //Add default validation message if empty
1599 var valMsg = jQuery( '.frm_validation_box .frm_conf_details' + field_id + ' input' );
1600 if ( valMsg.val() === '' ) {
1601 valMsg.val( frm_admin_js.default_conf );
1602 }
1603
1604 setConfirmationFieldDescriptions( field_id );
1605
1606 //Add or remove class for confirmation field styling
1607 if ( val === 'inline' ) {
1608 $thisField.removeClass( 'frm_conf_below' ).addClass( 'frm_conf_inline' );
1609 } else if ( val === 'below' ) {
1610 $thisField.removeClass( 'frm_conf_inline' ).addClass( 'frm_conf_below' );
1611 }
1612 jQuery( '.frm-conf-box-' + field_id ).removeClass( 'frm_hidden' );
1613 } else {
1614 jQuery( '.frm-conf-box-' + field_id ).addClass( 'frm_hidden' );
1615 setTimeout( function() {
1616 $thisField.removeClass( 'frm_conf_inline frm_conf_below' );
1617 }, 200 );
1618 }
1619 }
1620
1621 function setConfirmationFieldDescriptions( field_id ) {
1622 var fieldType = document.getElementsByName( 'field_options[type_' + field_id + ']' )[0].value;
1623
1624 var fieldDescription = document.getElementById( 'field_description_' + field_id );
1625 var hiddenDescName = 'field_options[description_' + field_id + ']';
1626 var newValue = frm_admin_js['enter_' + fieldType];
1627 maybeSetNewDescription( fieldDescription, hiddenDescName, newValue );
1628
1629 var confFieldDescription = document.getElementById( 'conf_field_description_' + field_id );
1630 var hiddenConfName = 'field_options[conf_desc_' + field_id + ']';
1631 var newConfValue = frm_admin_js['confirm_' + fieldType];
1632 maybeSetNewDescription( confFieldDescription, hiddenConfName, newConfValue );
1633 }
1634
1635 function maybeSetNewDescription( descriptionDiv, hiddenName, newValue ) {
1636 if ( descriptionDiv.innerHTML === frm_admin_js.desc ) {
1637
1638 // Set the visible description value and the hidden description value
1639 descriptionDiv.innerHTML = newValue;
1640 document.getElementsByName( hiddenName )[0].value = newValue;
1641 }
1642 }
1643
1644 function initBulkOptionsOverlay() {
1645 /*jshint validthis:true */
1646 var $info = initModal( '#frm-bulk-modal', '700px' );
1647 if ( $info === false ) {
1648 return;
1649 }
1650
1651 jQuery( '.frm-insert-preset' ).click( insertBulkPreset );
1652
1653 jQuery( builderForm ).on( 'click', 'a.frm-bulk-edit-link', function( event ) {
1654 event.preventDefault();
1655 var i, key, label, content = '',
1656 fieldId = jQuery( this ).closest( '[data-fid]' ).data( 'fid' ),
1657 separate = usingSeparateValues( fieldId ),
1658 optList = document.getElementById( 'frm_field_' + fieldId + '_opts' ),
1659 opts = optList.getElementsByTagName( 'li' );
1660
1661 document.getElementById( 'bulk-field-id' ).value = fieldId;
1662
1663 for ( i = 0; i < opts.length; i++ ) {
1664 key = opts[i].getAttribute( 'data-optkey' );
1665 if ( key !== '000' ) {
1666 label = document.getElementsByName( 'field_options[options_' + fieldId + '][' + key + '][label]' )[0];
1667 if ( typeof label !== 'undefined' ) {
1668 content += label.value;
1669 if ( separate ) {
1670 content += '|' + document.getElementsByName( 'field_options[options_' + fieldId + '][' + key + '][value]' )[0].value;
1671 }
1672 content += "\r\n";
1673 }
1674 }
1675
1676 if ( i >= opts.length - 1 ) {
1677 document.getElementById( 'frm_bulk_options' ).value = content;
1678 }
1679 }
1680
1681 $info.dialog('open');
1682
1683 return false;
1684 } );
1685
1686 jQuery( '#frm-update-bulk-opts' ).click( function() {
1687 var fieldId = document.getElementById( 'bulk-field-id' ).value;
1688 this.classList.add( 'frm_loading_button' );
1689 frmAdminBuild.updateOpts( fieldId, document.getElementById( 'frm_bulk_options' ).value, $info );
1690 } );
1691 }
1692
1693 function insertBulkPreset( event ) {
1694 /*jshint validthis:true */
1695 var opts = JSON.parse( this.getAttribute( 'data-opts' ) );
1696 event.preventDefault();
1697 document.getElementById( 'frm_bulk_options' ).value = opts.join( "\n" );
1698 return false;
1699 }
1700
1701 //Add new option or "Other" option to radio/checkbox/dropdown
1702 function addFieldOption() {
1703 /*jshint validthis:true */
1704 var field_id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' ),
1705 newOption = jQuery( '#frm_field_' + field_id + '_opts .frm_option_template' ).prop('outerHTML'),
1706 opt_type = jQuery( this ).data( 'opttype' ),
1707 optKey = 0,
1708 lastKey = 0,
1709 oldKey = '000',
1710 lastOpt = jQuery( '#frm_field_' + field_id + '_opts li:last' );
1711
1712 if ( lastOpt.length ) {
1713 optKey = lastOpt.data( 'optkey');
1714 lastKey = parseInt( optKey );
1715 if ( isNaN( lastKey ) ) {
1716 lastKey = jQuery( '#frm_field_' + field_id + '_opts li' ).length;
1717 if ( document.getElementById( 'frm_delete_field_' + field_id + '-' + ( lastKey + 1 ) + '_container' ) !== null ) {
1718 lastKey = lastKey + 2;
1719 }
1720 }
1721 optKey = lastKey + 1;
1722 }
1723
1724 //Update hidden field
1725 if ( opt_type === 'other' ) {
1726 document.getElementById( 'other_input_' + field_id ).value = 1;
1727
1728 //Hide "Add Other" option now if this is radio field
1729 var ftype = jQuery( this ).data( 'ftype' );
1730 if ( ftype === 'radio' || ftype === 'select' ) {
1731 jQuery( this ).fadeOut( 'slow' );
1732 }
1733
1734 var data = {
1735 action: 'frm_add_field_option', field_id: field_id,
1736 opt_key: optKey,
1737 opt_type: opt_type, nonce: frmGlobal.nonce
1738 };
1739 jQuery.post( ajaxurl, data, function( msg ) {
1740 jQuery( document.getElementById( 'frm_field_' + field_id + '_opts' ) ).append( msg );
1741 resetDisplayedOpts( field_id );
1742 } );
1743 } else {
1744 newOption = newOption.replace( new RegExp( 'optkey="' + oldKey + '"', 'g' ), 'optkey="' + optKey + '"' );
1745 newOption = newOption.replace( new RegExp( '-' + oldKey + '_', 'g' ), '-' + optKey + '_' );
1746 newOption = newOption.replace( new RegExp( '-' + oldKey + '"', 'g' ), '-' + optKey + '"' );
1747 newOption = newOption.replace( new RegExp( '\\[' + oldKey + '\\]', 'g' ), '[' + optKey + ']' );
1748 newOption = newOption.replace( 'frm_hidden frm_option_template', '' );
1749 jQuery( document.getElementById( 'frm_field_' + field_id + '_opts' ) ).append( newOption );
1750 resetDisplayedOpts( field_id );
1751 }
1752 }
1753
1754 function toggleMultSel() {
1755 /*jshint validthis:true */
1756 var field_id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
1757 toggleMultiSelect( field_id, this.value );
1758 }
1759
1760 function toggleMultiSelect( fieldId, value ) {
1761 var setting = jQuery( '.frm_multiple_cont_' + fieldId );
1762 if ( value === 'select' ) {
1763 setting.fadeIn( 'fast' );
1764 } else {
1765 setting.fadeOut( 'fast' );
1766 }
1767 }
1768
1769 function toggleSepValues() {
1770 /*jshint validthis:true */
1771 var field_id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
1772 toggle( jQuery( '.field_' + field_id + '_option_key' ) );
1773 jQuery( '.field_' + field_id + '_option' ).toggleClass( 'frm_with_key' );
1774 }
1775
1776 function toggleMultiselect() {
1777 /*jshint validthis:true */
1778 var dropdown = jQuery( this ).closest( 'li' ).find( '.frm_form_fields select' );
1779 if ( this.checked ) {
1780 dropdown.attr( 'multiple', 'multiple' );
1781 } else {
1782 dropdown.removeAttr( 'multiple' );
1783 }
1784 }
1785
1786 /**
1787 * Allow typing on form switcher click without an extra click to search.
1788 */
1789 function focusSearchBox() {
1790 var searchBox = document.getElementById( 'dropform-search-input' );
1791 if ( searchBox !== null ) {
1792 setTimeout( function() {
1793 searchBox.focus();
1794 }, 100 );
1795 }
1796 }
1797
1798 /**
1799 * If a field is clicked in the builder, prevent inputs from changing.
1800 */
1801 function stopFieldFocus( e ) {
1802 e.preventDefault();
1803 }
1804
1805 function deleteFieldOption() {
1806 /*jshint validthis:true */
1807 var parentLi = this.parentNode;
1808 var parentUl = parentLi.parentNode;
1809 var field_id = this.getAttribute( 'data-fid' );
1810
1811 jQuery( parentLi ).fadeOut( 'slow', function() {
1812 jQuery( parentLi ).remove();
1813
1814 var hasOther = jQuery( parentUl ).find( '.frm_other_option' );
1815 if ( hasOther.length < 1 ) {
1816 document.getElementById( 'other_input_' + field_id ).value = 0;
1817 jQuery( '#other_button_' + field_id ).fadeIn( 'slow' );
1818 }
1819 } );
1820 }
1821
1822 /**
1823 * If a radio button is set as default, allow a click to
1824 * deselect it.
1825 */
1826 function maybeUncheckRadio( e ) {
1827 /*jshint validthis:true */
1828 var $self = jQuery( this );
1829 if ( $self.is( ':checked' ) ) {
1830 var uncheck = function() {
1831 setTimeout( function(){ $self.removeAttr( 'checked' ); },0 );
1832 };
1833 var unbind = function() {
1834 $self.unbind( 'mouseup', up );
1835 };
1836 var up = function() {
1837 uncheck();
1838 unbind();
1839 };
1840 $self.bind( 'mouseup', up );
1841 $self.one( 'mouseout', unbind );
1842 }
1843 }
1844
1845 /**
1846 * If the field option has the default text, clear it out on click.
1847 */
1848 function maybeClearOptText() {
1849 /*jshint validthis:true */
1850 if ( this.value === frm_admin_js.new_option ) {
1851 this.value = '';
1852 }
1853 }
1854
1855 function clickDeleteField() {
1856 /*jshint validthis:true */
1857 var confirm_msg = frm_admin_js.conf_delete,
1858 maybeDivider = this.parentNode.parentNode.parentNode,
1859 li = maybeDivider.parentNode,
1860 field = jQuery( this ).closest( 'li' ),
1861 fieldId = field.data( 'fid' );
1862
1863 if ( li.classList.contains( 'frm-section-collapsed' ) || li.classList.contains( 'frm-page-collapsed' ) ) {
1864 return false;
1865 }
1866
1867 // If deleting a section, use a special message.
1868 if ( maybeDivider.className === 'divider_section_only' ) {
1869 confirm_msg = frm_admin_js.conf_delete_sec;
1870 this.setAttribute('data-frmcaution', frm_admin_js.caution);
1871 }
1872
1873 this.setAttribute( 'data-frmverify', confirm_msg );
1874 this.setAttribute( 'data-deletefield', fieldId );
1875
1876 confirmLinkClick( this );
1877 return false;
1878 }
1879
1880 function deleteFieldConfirmed() {
1881 /*jshint validthis:true */
1882 deleteFields( this.getAttribute( 'data-deletefield' ) );
1883 }
1884
1885 function deleteFields( fieldId ) {
1886 var field = jQuery( '#frm_field_id_' + fieldId );
1887
1888 deleteField( fieldId );
1889
1890 if ( field.hasClass( 'edit_field_type_divider' ) ) {
1891 field.find( 'li.frm_field_box' ).each( function() {
1892 //TODO: maybe delete only end section
1893 //if(n.hasClass('edit_field_type_end_divider')){
1894 deleteField( this.getAttribute( 'data-fid' ) );
1895 //}
1896 } );
1897 }
1898 toggleSectionHolder();
1899 }
1900
1901 function deleteField( field_id ) {
1902 jQuery.ajax( {
1903 type: 'POST',
1904 url: ajaxurl,
1905 data: {action: 'frm_delete_field', field_id: field_id, nonce: frmGlobal.nonce},
1906 success: function( msg ) {
1907 var $thisField = jQuery( document.getElementById( 'frm_field_id_' + field_id ) ),
1908 settings = jQuery( '#frm-single-settings-' + field_id );
1909
1910 // Remove settings from sidebar.
1911 if ( settings.is( ':visible' ) ) {
1912 document.getElementById( 'frm_insert_fields_tab' ).click();
1913 }
1914 settings.remove();
1915
1916 $thisField.fadeOut( 'slow', function() {
1917 var $section = $thisField.closest( '.start_divider' );
1918 $thisField.remove();
1919 if ( $thisField.data( 'type' ) === 'break' ) {
1920 renumberPageBreaks();
1921 }
1922 if ( $thisField.data( 'type' ) === 'summary' ) {
1923 reenableAddSummaryBtn();
1924 }
1925 if ( jQuery( '#frm-show-fields li' ).length === 0 ) {
1926 document.getElementById( 'frm_form_editor_container' ).classList.remove( 'frm-has-fields' );
1927 } else if ( $section.length ) {
1928 toggleOneSectionHolder( $section );
1929 }
1930 } );
1931 }
1932 } );
1933 }
1934
1935 function addFieldLogicRow() {
1936 /*jshint validthis:true */
1937 var id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' ),
1938 form_id = this_form_id,
1939 meta_name = 0;
1940
1941 if ( jQuery( '#frm_logic_row_' + id + ' .frm_logic_row' ).length > 0 ) {
1942 meta_name = 1 + parseInt( jQuery( '#frm_logic_row_' + id + ' .frm_logic_row:last' ).attr( 'id' ).replace( 'frm_logic_' + id + '_', '' ) );
1943 }
1944 jQuery.ajax( {
1945 type: 'POST', url: ajaxurl,
1946 data: {
1947 action: 'frm_add_logic_row',
1948 form_id: form_id,
1949 field_id: id,
1950 nonce: frmGlobal.nonce,
1951 meta_name: meta_name,
1952 fields: getFieldList()
1953 },
1954 success: function( html ) {
1955 jQuery( document.getElementById( 'logic_' + id ) ).fadeOut( 'slow', function() {
1956 var logicRow = jQuery( document.getElementById( 'frm_logic_row_' + id ) );
1957 logicRow.append( html );
1958 logicRow.closest( '.frm_logic_rows' ).fadeIn( 'slow' );
1959 } );
1960 }
1961 } );
1962 return false;
1963 }
1964
1965 function addWatchLookupRow() {
1966 /*jshint validthis:true */
1967 var id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
1968 var form_id = this_form_id;
1969 var row_key = 0;
1970 var lookupBlockRows = document.getElementById( 'frm_watch_lookup_block_' + id ).children;
1971 if ( lookupBlockRows.length > 0 ) {
1972 var lastRowId = lookupBlockRows[lookupBlockRows.length - 1].id;
1973 row_key = 1 + parseInt( lastRowId.replace( 'frm_watch_lookup_' + id + '_', '' ) );
1974 }
1975
1976 jQuery.ajax( {
1977 type: 'POST', url: ajaxurl,
1978 data: {
1979 action: 'frm_add_watch_lookup_row',
1980 form_id: form_id,
1981 field_id: id,
1982 row_key: row_key,
1983 nonce: frmGlobal.nonce
1984 },
1985 success: function( newRow ) {
1986 var watchRowBlock = jQuery( document.getElementById( 'frm_watch_lookup_block_' + id ) );
1987 watchRowBlock.append( newRow );
1988 watchRowBlock.fadeIn( 'slow' );
1989 }
1990 } );
1991 return false;
1992 }
1993
1994 function updateGetValueFieldSelection() {
1995 /*jshint validthis:true */
1996 var fieldID = this.id.replace( 'get_values_form_', '' );
1997 var fieldSelect = document.getElementById( 'get_values_field_' + fieldID );
1998 var fieldType = this.getAttribute( 'data-fieldtype' );
1999
2000 if ( this.value === '' ) {
2001 fieldSelect.options.length = 1;
2002 } else {
2003 var formID = this.value;
2004 jQuery.ajax( {
2005 type: 'POST', url: ajaxurl,
2006 data: {
2007 action: 'frm_get_options_for_get_values_field',
2008 form_id: formID,
2009 field_type: fieldType,
2010 nonce: frmGlobal.nonce
2011 },
2012 success: function( fields ) {
2013 fieldSelect.innerHTML = fields;
2014 }
2015 } );
2016 }
2017 }
2018
2019 // Clear the Watch Fields option when Lookup field switches to "Text" option
2020 function maybeClearWatchFields() {
2021 /*jshint validthis:true */
2022 var link, lookupBlock,
2023 fieldID = this.name.replace( 'field_options[data_type_', '' ).replace( ']', '' );
2024
2025 if ( this.value === 'text' ) {
2026 lookupBlock = document.getElementById( 'frm_watch_lookup_block_' + fieldID );
2027 if ( lookupBlock !== null ) {
2028 // Clear the Watch Fields option
2029 lookupBlock.innerHTML = '';
2030
2031 // Hide the Watch Fields row
2032 link = document.getElementById( 'frm_add_watch_lookup_link_' + fieldID ).parentNode;
2033 link.style.display = 'none';
2034 link.previousElementSibling.style.display = 'none';
2035 link.previousElementSibling.previousElementSibling.style.display = 'none';
2036 link.previousElementSibling.previousElementSibling.previousElementSibling.style.display = 'none';
2037 }
2038 }
2039
2040 toggleMultiSelect( fieldID, this.value );
2041 }
2042
2043 // Number the pages and hide/show the first page as needed.
2044 function renumberPageBreaks() {
2045 var i, containerClass,
2046 pages = document.getElementsByClassName( 'frm-page-num' );
2047
2048 if ( pages.length > 1 ) {
2049 document.getElementById( 'frm-fake-page' ).style.display = 'block';
2050 for ( i = 0; i < pages.length; i++ ) {
2051 containerClass = pages[i].parentNode.parentNode.parentNode.classList;
2052 if ( i === 1 ) {
2053 // Hide previous button on page 1
2054 containerClass.add( 'frm-first-page' );
2055 } else {
2056 containerClass.remove( 'frm-first-page' );
2057 }
2058 pages[i].innerHTML = ( i + 1 );
2059 }
2060 } else {
2061 document.getElementById( 'frm-fake-page' ).style.display = 'none';
2062 }
2063 }
2064
2065 // The fake field works differently than real fields.
2066 function maybeCollapsePage() {
2067 /*jshint validthis:true */
2068 var field = jQuery( this ).closest( '.frm_field_box[data-ftype=break]' );
2069 if ( field.length ) {
2070 toggleCollapsePage( field );
2071 } else {
2072 toggleCollapseFakePage();
2073 }
2074 }
2075
2076 // Find all fields in a page and hide/show them
2077 function toggleCollapsePage( field ) {
2078 var toCollapse = field.nextUntil( '.frm_field_box[data-ftype=break]' );
2079 togglePage( field, toCollapse );
2080 }
2081
2082 function toggleCollapseFakePage() {
2083 var topLevel = document.getElementById( 'frm-fake-page' ),
2084 firstField = document.getElementById( 'frm-show-fields' ).firstElementChild,
2085 toCollapse = jQuery( firstField ).nextUntil( '.frm_field_box[data-ftype=break]' ).andSelf();
2086
2087 if ( firstField.getAttribute( 'data-ftype' ) === 'break' ) {
2088 // Don't collapse if the first field is a page break.
2089 return;
2090 }
2091
2092 togglePage( jQuery( topLevel ), toCollapse );
2093 }
2094
2095 function togglePage( field, toCollapse ) {
2096 var i,
2097 fieldCount = toCollapse.length,
2098 slide = Math.min( fieldCount, 3 );
2099
2100 if ( field.hasClass( 'frm-page-collapsed' ) ) {
2101 field.removeClass( 'frm-page-collapsed' );
2102 toCollapse.removeClass( 'frm-is-collapsed' );
2103 for ( i = 0; i < slide; i++ ) {
2104 if ( i == slide - 1 ) {
2105 jQuery( toCollapse[ i ] ).slideDown( 150, function() {
2106 toCollapse.show();
2107 } );
2108 } else {
2109 jQuery( toCollapse[ i ] ).slideDown( 150 );
2110 }
2111 }
2112 } else {
2113 field.addClass( 'frm-page-collapsed' );
2114 toCollapse.addClass( 'frm-is-collapsed' );
2115 for ( i = 0; i < slide; i++ ) {
2116 if ( i == slide - 1 ) {
2117 jQuery( toCollapse[ i ] ).slideUp( 150, function() {
2118 toCollapse.css( 'cssText', 'display:none !important;' );
2119 } );
2120 } else {
2121 jQuery( toCollapse[ i ] ).slideUp( 150 );
2122 }
2123 }
2124 }
2125 }
2126
2127 function maybeCollapseSection() {
2128 /*jshint validthis:true */
2129 var parentCont = this.parentNode.parentNode.parentNode.parentNode;
2130
2131 parentCont.classList.toggle( 'frm-section-collapsed' );
2132 }
2133
2134 function maybeCollapseSettings() {
2135 /*jshint validthis:true */
2136 this.classList.toggle( 'frm-collapsed' );
2137 }
2138
2139 function clickLabel() {
2140 /*jshint validthis:true */
2141 var setting = document.querySelectorAll( '[data-changeme="' + this.id + '"]' )[0],
2142 fieldId = this.id.replace( 'field_label_', '' ),
2143 fieldType = document.getElementById( 'field_options_type_' + fieldId ),
2144 fieldTypeName = fieldType.value;
2145
2146 if ( typeof setting !== 'undefined' ) {
2147 if ( fieldType.tagName === 'SELECT' ) {
2148 fieldTypeName = fieldType.options[ fieldType.selectedIndex ].text.toLowerCase();
2149 } else {
2150 fieldTypeName = fieldTypeName.replace( '_', ' ' );
2151 }
2152
2153 fieldTypeName = normalizeFieldName( fieldTypeName );
2154
2155 setTimeout( function() {
2156 if ( setting.value.toLowerCase() === fieldTypeName ) {
2157 setting.select();
2158 } else {
2159 setting.focus();
2160 }
2161 }, 50 );
2162 }
2163 }
2164
2165 function clickDescription() {
2166 /*jshint validthis:true */
2167 var setting = document.querySelectorAll( '[data-changeme="' + this.id + '"]' )[0];
2168 if ( typeof setting !== 'undefined' ) {
2169 setTimeout( function() {
2170 setting.focus();
2171 autoExpandSettings( setting );
2172 }, 50 );
2173 }
2174 }
2175
2176 function autoExpandSettings( setting ) {
2177 var inSection = setting.closest( '.frm-collapse-me' );
2178 if ( inSection !== null ) {
2179 inSection.previousElementSibling.classList.remove( 'frm-collapsed' );
2180 }
2181 }
2182
2183 function normalizeFieldName( fieldTypeName ) {
2184 if ( fieldTypeName === 'divider' ) {
2185 fieldTypeName = 'section';
2186 } else if ( fieldTypeName === 'range' ) {
2187 fieldTypeName = 'slider';
2188 } else if ( fieldTypeName === 'data' ) {
2189 fieldTypeName = 'dynamic';
2190 } else if ( fieldTypeName === 'form' ) {
2191 fieldTypeName = 'embed form';
2192 }
2193 return fieldTypeName;
2194 }
2195
2196 function clickVis( e ) {
2197 /*jshint validthis:true */
2198 var currentClass = e.target.classList;
2199 if ( currentClass.contains( 'frm-collapse-page' ) || currentClass.contains( 'frm-sub-label' ) ) {
2200 return;
2201 }
2202
2203 if ( this.closest( '.start_divider' ) !== null ) {
2204 e.stopPropagation();
2205 }
2206 clickAction( this );
2207 }
2208
2209 /**
2210 * Open Advanced settings on double click.
2211 */
2212 function openAdvanced() {
2213 var fieldId = this.getAttribute( 'data-fid' );
2214 autoExpandSettings( document.getElementById( 'field_options_field_key_' + fieldId ) );
2215 }
2216
2217 function toggleRepeatButtons() {
2218 /*jshint validthis:true */
2219 var $thisField = jQuery( this ).closest( '.frm_field_box' );
2220 $thisField.find( '.repeat_icon_links' ).removeClass( 'repeat_format repeat_formatboth repeat_formattext' ).addClass( 'repeat_format' + this.value );
2221 if ( this.value === 'text' || this.value === 'both' ) {
2222 $thisField.find( '.frm_repeat_text' ).show();
2223 $thisField.find( '.repeat_icon_links a' ).addClass( 'frm_button' );
2224 } else {
2225 $thisField.find( '.frm_repeat_text' ).hide();
2226 $thisField.find( '.repeat_icon_links a' ).removeClass( 'frm_button' );
2227 }
2228 }
2229
2230 function checkRepeatLimit() {
2231 /*jshint validthis:true */
2232 var val = this.value;
2233 if ( val !== '' && ( val < 2 || val > 200 ) ) {
2234 alert( frm_admin_js.repeat_limit_min );
2235 this.value = '';
2236 }
2237 }
2238
2239 function checkCheckboxSelectionsLimit() {
2240 /*jshint validthis:true */
2241 var val = this.value;
2242 if ( val !== '' && ( val < 1 || val > 200 ) ) {
2243 alert( frm_admin_js.checkbox_limit );
2244 this.value = '';
2245 }
2246 }
2247
2248 function updateRepeatText( obj, addRemove ) {
2249 var $thisField = jQuery( obj ).closest( '.frm_field_box' );
2250 $thisField.find( '.frm_' + addRemove + '_form_row .frm_repeat_label' ).text( obj.value );
2251 }
2252
2253 function fieldsInSection( id ) {
2254 var children = [];
2255 jQuery( document.getElementById( 'frm_field_id_' + id ) ).find( 'li.frm_field_box:not(.no_repeat_section .edit_field_type_end_divider)' ).each( function() {
2256 children.push( jQuery( this ).data( 'fid' ) );
2257 } );
2258 return children;
2259 }
2260
2261 function toggleFormTax() {
2262 /*jshint validthis:true */
2263 var id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
2264 var val = this.value;
2265 var $showFields = document.getElementById( 'frm_show_selected_fields_' + id );
2266 var $showForms = document.getElementById( 'frm_show_selected_forms_' + id );
2267
2268 jQuery( $showForms ).find( 'select' ).val( '' );
2269 if ( val === 'form' ) {
2270 $showForms.style.display = 'inline';
2271 empty( $showFields );
2272 } else {
2273 $showFields.style.display = 'none';
2274 $showForms.style.display = 'none';
2275 getTaxOrFieldSelection( val, id );
2276 }
2277
2278 }
2279
2280 function resetOptOnChange() {
2281 /*jshint validthis:true */
2282 var field = getFieldKeyFromOpt( this ),
2283 thisOpt = jQuery( this ).closest( '.frm_single_option' );
2284
2285 resetSingleOpt( field.fieldId, field.fieldKey, thisOpt );
2286 }
2287
2288 function getFieldKeyFromOpt( object ) {
2289 var allOpts = jQuery( object ).closest( '.frm_sortable_field_opts' ),
2290 fieldId = allOpts.attr( 'id' ).replace( 'frm_field_', '' ).replace( '_opts', '' ),
2291 fieldKey = allOpts.data( 'key' );
2292
2293 return {
2294 fieldId: fieldId,
2295 fieldKey: fieldKey
2296 };
2297 }
2298
2299 function resetSingleOpt( fieldId, fieldKey, thisOpt ) {
2300 var saved, text, defaultVal, previewInput,
2301 optKey = thisOpt.data( 'optkey' ),
2302 separateValues = usingSeparateValues( fieldId ),
2303 single = jQuery( 'label[for="field_' + fieldKey + '-' + optKey + '"]' ),
2304 baseName = 'field_options[options_' + fieldId + '][' + optKey + ']';
2305 label = jQuery( 'input[name="' + baseName + '[label]"]' );
2306
2307 if ( single.length < 1 ) {
2308 resetDisplayedOpts( fieldId );
2309
2310 // Set the default value.
2311 defaultVal = thisOpt.find( 'input[name^="default_value_"]' );
2312 if ( defaultVal.is( ':checked' ) && label.length > 0 ) {
2313 jQuery( 'select[name^="item_meta[' + fieldId + ']"]' ).val( label.val() );
2314 }
2315 return;
2316 }
2317
2318 previewInput = single.children( 'input' );
2319
2320 if ( label.length < 1 ) {
2321 // Check for other label.
2322 label = jQuery( 'input[name="' + baseName + '"]' );
2323 saved = label.val();
2324 } else if ( separateValues ) {
2325 saved = jQuery( 'input[name="' + baseName + '[value]"]' ).val();
2326 } else {
2327 saved = label.val();
2328 }
2329
2330 if ( label.length ) {
2331 // Set the displayed value.
2332 text = single[0].childNodes;
2333 text[ text.length - 1 ].nodeValue = ' ' + label.val();
2334
2335 // Set saved value.
2336 previewInput.val( saved );
2337
2338 // Set the default value.
2339 defaultVal = thisOpt.find( 'input[name^="default_value_"]' );
2340 previewInput.prop( 'checked', defaultVal.is( ':checked' ) ? true : false );
2341 }
2342 }
2343
2344 function resetDisplayedOpts( fieldId ) {
2345 var i, opt, opts, type, placeholder, fieldInfo,
2346 input = jQuery( '[name^="item_meta[' + fieldId + ']"]' );
2347
2348 if ( input.length < 1 ) {
2349 return;
2350 }
2351
2352 if ( input.is( 'select' ) ) {
2353 placeholder = document.getElementById( 'frm_placeholder_' + fieldId );
2354 if ( placeholder !== null && placeholder.value === '' ) {
2355 fillDropdownOpts( input[0], { sourceID: fieldId } );
2356 } else {
2357 fillDropdownOpts( input[0], {
2358 sourceID: fieldId,
2359 placeholder: placeholder.value
2360 } );
2361 }
2362 } else {
2363 opts = getMultipleOpts( fieldId );
2364 type = input.attr( 'type' );
2365 jQuery( '#field_' + fieldId + '_inner_container > .frm_form_fields' ).html( '' );
2366 fieldInfo = getFieldKeyFromOpt( jQuery( '#frm_delete_field_' + fieldId + '-000_container' ) );
2367
2368 for ( i = 0; i < opts.length; i++ ) {
2369 addRadioCheckboxOpt( type, opts[ i ], fieldId, fieldInfo.fieldKey );
2370 }
2371 }
2372 }
2373
2374 function addRadioCheckboxOpt( type, opt, fieldId, fieldKey ) {
2375 var other, single,
2376 isOther = opt.key.indexOf( 'other' ) !== -1,
2377 id = 'field_' + fieldKey + '-' + opt.key,
2378 container = jQuery( '#field_' + fieldId + '_inner_container > .frm_form_fields' );
2379
2380 other = '<input type="text" id="field_' + fieldKey + '-' + opt.key + '-otext" class="frm_other_input frm_pos_none" name="item_meta[other][' + fieldId + '][' + opt.key + ']" value="" />';
2381
2382 single = '<div class="frm_' + type + ' ' + type + '" id="frm_' + type + '_' + fieldId + '-' + opt.key + '"><label for="' + id +
2383 '"><input type="' + type +
2384 '" name="item_meta[' + fieldId + ']' + ( type === 'checkbox' ? '[]' : '' ) +
2385 '" value="' + opt.saved + '" id="' + id + '"> ' + opt.label + '</label>' +
2386 ( isOther ? other : '' ) +
2387 '</div>';
2388
2389 container.append( single );
2390 }
2391
2392 function fillDropdownOpts( field, atts ) {
2393 if ( field === null ) {
2394 return;
2395 }
2396 var sourceID = atts.sourceID,
2397 placeholder = atts.placeholder,
2398 showOther = atts.other;
2399
2400 removeDropdownOpts( field );
2401 var opts = getMultipleOpts( sourceID ),
2402 hasPlaceholder = ( typeof placeholder !== 'undefined' );
2403
2404 for ( var i = 0; i < opts.length; i++ ) {
2405 var label = opts[ i ].label,
2406 isOther = opts[ i ].key.indexOf( 'other' ) !== -1;
2407
2408 if ( hasPlaceholder && label !== '' ) {
2409 addBlankSelectOption( field, placeholder );
2410 } else if ( hasPlaceholder ) {
2411 label = placeholder;
2412 }
2413 hasPlaceholder = false;
2414
2415 if ( ! isOther || showOther ) {
2416 var opt = document.createElement( 'option' );
2417 opt.value = opts[ i ].saved;
2418 opt.innerHTML = label;
2419 field.appendChild( opt );
2420 }
2421 }
2422 }
2423
2424 function addBlankSelectOption( field, placeholder ) {
2425 var opt = document.createElement( 'option' ),
2426 firstChild = field.firstChild;
2427
2428 opt.value = '';
2429 opt.innerHTML = placeholder;
2430 if ( firstChild !== null ) {
2431 field.insertBefore( opt, firstChild );
2432 field.selectedIndex = 0;
2433 } else {
2434 field.appendChild( opt );
2435 }
2436 }
2437
2438 function getMultipleOpts( fieldId ) {
2439 var i, saved, labelName, label, key, opts = [],
2440 optVals = jQuery( 'input[name^="field_options[options_' + fieldId + ']"]' ),
2441 separateValues = usingSeparateValues( fieldId );
2442
2443 for ( i = 0; i < optVals.length; i++ ) {
2444 if ( optVals[ i ].name.indexOf( '[000]' ) > 0 || optVals[ i ].name.indexOf( '[value]' ) > 0 ) {
2445 continue;
2446 }
2447 saved = optVals[ i ].value;
2448 label = saved;
2449 key = optVals[ i ].name.replace( 'field_options[options_' + fieldId + '][', '' ).replace( '[label]', '' ).replace( ']', '' );
2450
2451 if ( separateValues ) {
2452 labelName = optVals[ i ].name.replace( '[label]', '[value]' );
2453 saved = jQuery( 'input[name="' + labelName + '"]' ).val();
2454 }
2455
2456 opts.push( {
2457 saved: saved,
2458 label: label,
2459 key: key
2460 } );
2461 }
2462
2463 return opts;
2464 }
2465
2466 function removeDropdownOpts( field ) {
2467 var i;
2468 if ( typeof field.options === 'undefined' ) {
2469 return;
2470 }
2471
2472 for ( i = field.options.length - 1; i >= 0; i-- ) {
2473 field.remove( i );
2474 }
2475 }
2476
2477 /**
2478 * Is the box checked to use separate values?
2479 */
2480 function usingSeparateValues( fieldId ) {
2481 var field = document.getElementById( 'separate_value_' + fieldId );
2482 if ( field === null ) {
2483 return false;
2484 } else {
2485 return field.checked;
2486 }
2487 }
2488
2489 /* TODO: Is this still used? */
2490 function checkUniqueOpt( id, text ) {
2491 if ( id.indexOf( 'field_key_' ) === 0 ) {
2492 var a = id.split( '-' );
2493 jQuery.each( jQuery( 'label[id^="' + a[0] + '"]' ), function( k, v ) {
2494 var c = false;
2495 if ( !c && jQuery( v ).attr( 'id' ) != id && jQuery( v ).html() == text ) {
2496 c = true;
2497 alert( 'Saved values cannot be identical.' );
2498 }
2499 } );
2500 }
2501 }
2502
2503 function setStarValues() {
2504 /*jshint validthis:true */
2505 var fieldID = this.id.replace( 'radio_maxnum_', '' );
2506 var container = jQuery( '#field_' + fieldID + '_inner_container .frm-star-group' );
2507 var fieldKey = document.getElementsByName( 'field_options[field_key_' + fieldID + ']' )[0].value;
2508 container.html( '' );
2509
2510 var min = 1;
2511 var max = this.value;
2512 if ( min > max ) {
2513 max = min;
2514 }
2515
2516 for ( var i = min; i <= max; i++ ) {
2517 container.append( '<input type="hidden" name="field_options[options_' + fieldID + '][' + i + ']" value="' + i + '"><input type="radio" name="item_meta[' + fieldID + ']" id="field_' + fieldKey + '-' + i + '" value="' + i + '" /><label for="field_' + fieldKey + '-' + i + '" class="star-rating"></label>' );
2518 }
2519 }
2520
2521 function setScaleValues() {
2522 /*jshint validthis:true */
2523 var isMin = this.id.indexOf( 'minnum' ) !== -1;
2524 var fieldID = this.id.replace( 'scale_maxnum_', '' ).replace( 'scale_minnum_', '' );
2525 var min = this.value;
2526 var max = this.value;
2527 if ( isMin ) {
2528 max = document.getElementById( 'scale_maxnum_' + fieldID ).value;
2529 } else {
2530 min = document.getElementById( 'scale_minnum_' + fieldID ).value;
2531 }
2532
2533 updateScaleValues( parseInt( min ), parseInt( max ), fieldID );
2534 }
2535
2536 function updateScaleValues( min, max, fieldID ) {
2537 var container = jQuery( '#field_' + fieldID + '_inner_container .frm_form_fields' );
2538 container.html( '' );
2539
2540 if ( min >= max ) {
2541 max = min + 1;
2542 }
2543
2544 for ( var i = min; i <= max; i++ ) {
2545 container.append( '<div class="frm_scale"><label><input type="hidden" name="field_options[options_' + fieldID + '][' + i + ']" value="' + i + '"> <input type="radio" name="item_meta[' + fieldID + ']" value="' + i + '"> ' + i + ' </label></div>' );
2546 }
2547 container.append( '<div class="clear"></div>' );
2548 }
2549
2550 function getFieldValues() {
2551 /*jshint validthis:true */
2552 var is_taxonomy,
2553 val = this.value;
2554
2555 if ( val ) {
2556 var parentIDs = this.parentNode.id.replace( 'frm_logic_', '' ).split( '_' );
2557 var fieldID = parentIDs[0];
2558 var metaKey = parentIDs[1];
2559 var valueField = document.getElementById( 'frm_field_id_' + val );
2560 var valueFieldType = valueField.getAttribute( 'data-ftype' );
2561 var fill = document.getElementById( 'frm_show_selected_values_' + fieldID + '_' + metaKey );
2562 var optionName = 'field_options[hide_opt_' + fieldID + '][]';
2563 var optionID = 'frm_field_logic_opt_' + fieldID;
2564 var input = false;
2565 var showSelect = (valueFieldType == 'select' || valueFieldType == 'checkbox' || valueFieldType == 'radio' );
2566 var showText = ( valueFieldType == 'text' || valueFieldType == 'email' || valueFieldType == 'phone' || valueFieldType == 'url' || valueFieldType == 'number' );
2567
2568 if ( showSelect ) {
2569 is_taxonomy = document.getElementById( 'frm_has_hidden_options_' + val );
2570 if ( is_taxonomy !== null ) {
2571 // get the category options with ajax
2572 showSelect = false;
2573 }
2574 }
2575
2576 if ( showSelect || showText ) {
2577 fill.innerHTML = '';
2578 if ( showSelect ) {
2579 input = document.createElement( 'select' );
2580 } else {
2581 input = document.createElement( 'input' );
2582 input.type = 'text';
2583 }
2584 input.name = optionName;
2585 input.id = optionID + '_' + metaKey;
2586 fill.appendChild( input );
2587
2588 if ( showSelect ) {
2589 var fillField = document.getElementById( input.id );
2590 fillDropdownOpts( fillField, {
2591 sourceID: val,
2592 placeholder: '',
2593 other: true
2594 } );
2595 }
2596 } else {
2597 var thisType = this.getAttribute( 'data-type' );
2598 frmGetFieldValues( val, fieldID, metaKey, thisType );
2599 }
2600 }
2601 }
2602
2603 function getFieldSelection() {
2604 /*jshint validthis:true */
2605 var form_id = this.value;
2606 if ( form_id ) {
2607 var field_id = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
2608 getTaxOrFieldSelection( form_id, field_id );
2609 }
2610 }
2611
2612 function getTaxOrFieldSelection( form_id, field_id ) {
2613 if ( form_id ) {
2614 jQuery.ajax( {
2615 type: 'POST', url: ajaxurl,
2616 data: {action: 'frm_get_field_selection', field_id: field_id, form_id: form_id, nonce: frmGlobal.nonce},
2617 success: function( msg ) {
2618 jQuery( "#frm_show_selected_fields_" + field_id ).html( msg ).show();
2619 }
2620 } );
2621 }
2622 }
2623
2624 function updateFieldOrder() {
2625 var i;
2626 renumberPageBreaks();
2627 jQuery( '#frm-show-fields' ).each( function( i ) {
2628 var fields = jQuery( 'li.frm_field_box', this );
2629 for ( i = 0; i < fields.length; i ++ ) {
2630 var fieldId = fields[ i ].getAttribute( 'data-fid' ),
2631 field = jQuery( 'input[name="field_options[field_order_' + fieldId + ']"]' ),
2632 currentOrder = field.val(),
2633 newOrder = ( i + 1 );
2634
2635 if ( currentOrder != newOrder ) {
2636 field.val( newOrder );
2637 singleField = document.getElementById( 'frm-single-settings-' + fieldId );
2638
2639 moveFieldSettings( singleField );
2640 }
2641 }
2642 } );
2643 }
2644
2645 function toggleSectionHolder() {
2646 jQuery( '.start_divider' ).each( function() {
2647 toggleOneSectionHolder( jQuery( this ) );
2648 } );
2649 }
2650
2651 function toggleOneSectionHolder( $section ) {
2652 if ( $section.length === 0 ) {
2653 return;
2654 }
2655
2656 var sectionFields = $section.parent( '.frm_field_box' ).children( '.frm_no_section_fields' );
2657 if ( $section.children( 'li' ).length < 2 ) {
2658 sectionFields.addClass( 'frm_block' );
2659 } else {
2660 sectionFields.removeClass( 'frm_block' );
2661 }
2662 }
2663
2664 function slideDown() {
2665 /*jshint validthis:true */
2666 var id = jQuery( this ).data( 'slidedown' );
2667 var $thisId = jQuery( document.getElementById( id ) );
2668 if ( $thisId.is( ":hidden" ) ) {
2669 $thisId.slideDown( 'fast' );
2670 this.style.display = 'none';
2671 }
2672 return false;
2673 }
2674
2675 function slideUp() {
2676 /*jshint validthis:true */
2677 var id = jQuery( this ).data( 'slideup' );
2678 var $thisId = jQuery( document.getElementById( id ) );
2679 $thisId.slideUp( 'fast' );
2680 $thisId.siblings( 'a' ).show();
2681 return false;
2682 }
2683
2684 /**
2685 * Get rid of empty container that inserts extra space.
2686 */
2687 function hideEmptyEle() {
2688 jQuery( '.frm-hide-empty' ).each( function() {
2689 if ( jQuery( this ).text().trim().length == 0 ) {
2690 jQuery( this ).remove();
2691 }
2692 });
2693 }
2694
2695 /* Change the classes in the builder */
2696 function changeFieldClass( field, setting ) {
2697 var classes, replace, alignField,
2698 replaceWith = ' ' + setting.value,
2699 fieldId = field.getAttribute( 'data-fid' );
2700
2701 // Include classes from multiple settings.
2702 if ( typeof fieldId !== 'undefined' ) {
2703 if ( setting.classList.contains( 'field_options_align' ) ) {
2704 replaceWith += ' ' + document.getElementById( 'frm_classes_' + fieldId ).value;
2705 } else if ( setting.classList.contains( 'frm_classes' ) ) {
2706 alignField = document.getElementById( 'field_options_align_' + fieldId );
2707 if ( alignField !== null ) {
2708 replaceWith += ' ' + alignField.value;
2709 }
2710 }
2711 }
2712 replaceWith += ' ';
2713
2714 // Allow for the column number dropdown.
2715 replaceWith = replaceWith.replace( ' block ', ' ' ).replace( ' inline ', ' horizontal_radio ' ).replace( ' frm_alignright ', ' ' );
2716
2717 classes = field.className.split( ' frmstart ' )[1].split( ' frmend ' )[0];
2718 if ( classes.trim() === '' ) {
2719 replace = ' frmstart frmend ';
2720 replaceWith = ' frmstart ' + replaceWith.trim() + ' frmend ';
2721 } else {
2722 replace = classes.trim();
2723 replaceWith = replaceWith.trim();
2724 }
2725 field.className = field.className.replace( replace, replaceWith );
2726 }
2727
2728 function maybeShowInlineModal( e ) {
2729 /*jshint validthis:true */
2730 e.preventDefault();
2731 showInlineModal( this );
2732 }
2733
2734 function showInlineModal( icon, input ) {
2735 var box = document.getElementById( icon.getAttribute( 'data-open' ) ),
2736 container = jQuery( icon ).closest( 'p' ),
2737 pos = icon.getBoundingClientRect(),
2738 parentPos = box.parentNode.getBoundingClientRect(),
2739 inputTrigger = ( typeof input !== 'undefined' );
2740
2741 if ( container.hasClass( 'frm-open' ) ) {
2742 container.removeClass( 'frm-open' );
2743 box.classList.add( 'frm_hidden' );
2744 } else {
2745 if ( ! inputTrigger ) {
2746 input = getInputForIcon( icon );
2747 }
2748 if ( input !== null ) {
2749 if ( ! inputTrigger ) {
2750 input.focus();
2751 }
2752 container.after( box );
2753 box.setAttribute( 'data-fills', input.id );
2754
2755 if ( box.id.indexOf( 'frm-calc-box' ) === 0 ) {
2756 popCalcFields( box, true );
2757 }
2758 }
2759
2760 container.addClass( 'frm-open' );
2761 box.classList.remove( 'frm_hidden' );
2762 }
2763 }
2764
2765 function dismissInlineModal( e ) {
2766 /*jshint validthis:true */
2767 e.preventDefault();
2768 this.parentNode.classList.add( 'frm_hidden' );
2769 jQuery('.frm-open [data-open="' + this.parentNode.id + '"]').closest( '.frm-open' ).removeClass( 'frm-open' );
2770 }
2771
2772 function changeInputtedValue() {
2773 /*jshint validthis:true */
2774 var action = this.getAttribute( 'data-frmchange' );
2775 this.value = this.value[ action ]();
2776 }
2777
2778 function submitBuild() {
2779 /*jshint validthis:true */
2780 var $thisEle = jQuery( this );
2781 var p = $thisEle.html();
2782
2783 preFormSave( this );
2784
2785 var $form = jQuery( builderForm );
2786 var v = JSON.stringify( $form.serializeArray() );
2787
2788 jQuery( document.getElementById( 'frm_compact_fields' ) ).val( v );
2789 jQuery.ajax( {
2790 type: 'POST',
2791 url: ajaxurl,
2792 data: {action: 'frm_save_form', 'frm_compact_fields': v, nonce: frmGlobal.nonce},
2793 success: function( msg ) {
2794 afterFormSave( $thisEle, p );
2795
2796 var $postStuff = document.getElementById( 'post-body-content' );
2797 var $html = document.createElement( 'div' );
2798 $html.setAttribute( 'class', 'frm_updated_message' );
2799 $html.innerHTML = msg;
2800 $postStuff.insertBefore( $html, $postStuff.firstChild );
2801 },
2802 error: function( html ) {
2803 jQuery( document.getElementById( 'frm_js_build_form' ) ).submit();
2804 }
2805 } );
2806 }
2807
2808 function submitNoAjax() {
2809 /*jshint validthis:true */
2810 preFormSave( this );
2811
2812 var form = jQuery( builderForm );
2813 jQuery( document.getElementById( 'frm_compact_fields' ) ).val( JSON.stringify( form.serializeArray() ) );
2814 jQuery( document.getElementById( 'frm_js_build_form' ) ).submit();
2815 }
2816
2817 function preFormSave( b ) {
2818 removeWPUnload();
2819 if ( jQuery( 'form.inplace_form' ).length ) {
2820 jQuery( '.inplace_save, .postbox' ).click();
2821 }
2822
2823 $button = jQuery( b );
2824
2825 if ( $button.hasClass( 'frm_button_submit' ) ) {
2826 $button.addClass( 'frm_loading_form' );
2827 $button.html( frm_admin_js.saving );
2828 } else {
2829 $button.addClass( 'frm_loading_button' );
2830 $button.val( frm_admin_js.saving );
2831 }
2832 }
2833
2834 function afterFormSave( $button, buttonVal ) {
2835 $button.removeClass( 'frm_loading_form' ).removeClass( 'frm_loading_button' );
2836 $button.html( frm_admin_js.saved );
2837
2838 setTimeout( function() {
2839 jQuery( '.frm_updated_message' ).fadeOut( 'slow', function() {
2840 this.parentNode.removeChild( this );
2841 } );
2842 $button.fadeOut( 'slow', function() {
2843 $button.html( buttonVal );
2844 $button.show();
2845 } );
2846 }, 5000 );
2847 }
2848
2849 function initUpgradeModal() {
2850 var $info = initModal( '#frm_upgrade_modal' );
2851 if ( $info === false ) {
2852 return;
2853 }
2854
2855 jQuery( document ).on( 'click', '[data-upgrade]', function( event ) {
2856 event.preventDefault();
2857 jQuery( '#frm_upgrade_modal .frm_lock_icon' ).removeClass( 'frm_lock_open_icon' );
2858 jQuery( '#frm_upgrade_modal .frm_lock_icon use' ).attr( 'xlink:href', '#frm_lock_icon' );
2859
2860 var requires = this.getAttribute( 'data-requires' );
2861 if ( typeof requires === 'undefined' || requires === null || requires === '' ) {
2862 requires = 'Pro';
2863 }
2864 jQuery( '.license-level' ).html( requires );
2865
2866 // If one click upgrade, hide other content
2867 addOneClickModal( this );
2868
2869 jQuery('.frm_feature_label').html( this.getAttribute( 'data-upgrade' ) );
2870 jQuery( '#frm_upgrade_modal h2' ).show();
2871
2872 $info.dialog('open');
2873
2874 // set the utm medium
2875 var button = $info.find('.button-primary:not(#frm-oneclick-button)');
2876 var link = button.attr('href').replace( /(medium=)[a-z_-]+/ig, '$1' + this.getAttribute( 'data-medium' ) );
2877 var content = this.getAttribute( 'data-content' );
2878 if ( content === undefined ) {
2879 content = '';
2880 }
2881 link = link.replace( /(content=)[a-z_-]+/ig, '$1' + content );
2882 button.attr( 'href', link );
2883 return false;
2884 } );
2885 }
2886
2887 /**
2888 * Allow addons to be installed from the upgrade modal.
2889 */
2890 function addOneClickModal( link ) {
2891 var oneclickMessage = document.getElementById( 'frm-oneclick' ),
2892 oneclick = link.getAttribute( 'data-oneclick' ),
2893 customLink = link.getAttribute( 'data-link' ),
2894 showLink = document.getElementById( 'frm-upgrade-modal-link' ),
2895 upgradeMessage = document.getElementById( 'frm-upgrade-message' ),
2896 newMessage = link.getAttribute('data-message'),
2897 button = document.getElementById( 'frm-oneclick-button' ),
2898 showIt = 'block',
2899 hideIt = 'none';
2900
2901 // If one click upgrade, hide other content.
2902 if ( oneclickMessage !== null && typeof oneclick !== 'undefined' && oneclick ) {
2903 showIt = 'none';
2904 hideIt = 'block';
2905 oneclick = JSON.parse( oneclick );
2906
2907 button.className = button.className.replace( ' frm-install-addon', '' ).replace( ' frm-activate-addon', '' );
2908 button.className = button.className + ' ' + oneclick.class;
2909 button.rel = oneclick.url;
2910 }
2911
2912 // Use a custom message in the modal.
2913 if ( newMessage === null || typeof newMessage === 'undefined' || newMessage === '' ) {
2914 newMessage = upgradeMessage.getAttribute('data-default');
2915 }
2916 upgradeMessage.innerHTML = newMessage;
2917
2918 // Either set the link or use the default.
2919 if ( customLink === null || typeof customLink === 'undefined' || customLink === '' ) {
2920 customLink = showLink.getAttribute('data-default');
2921 }
2922 showLink.href = customLink;
2923
2924 document.getElementById( 'frm-addon-status' ).style.display = 'none';
2925 oneclickMessage.style.display = hideIt;
2926 button.style.display = hideIt == 'block' ? 'inline-block' : hideIt;
2927 upgradeMessage.style.display = showIt;
2928 showLink.style.display = showIt == 'block' ? 'inline-block' : showIt;
2929 }
2930
2931 /* Form settings */
2932
2933 function showInputIcon( parentClass ) {
2934 if ( typeof parentClass === 'undefined' ) {
2935 parentClass = '';
2936 }
2937 maybeAddFieldSelection( parentClass );
2938 jQuery( parentClass + ' .frm_has_shortcodes:not(.frm-with-right-icon) input,' + parentClass + ' .frm_has_shortcodes:not(.frm-with-right-icon) textarea' ).wrap( '<span class="frm-with-right-icon"></span>' ).before( '<svg class="frmsvg frm-show-box"><use xlink:href="#frm_more_horiz_solid_icon"/></svg>' );
2939 }
2940
2941 /**
2942 * For reverse compatibility. Check for fields that were
2943 * using the old sidebar.
2944 */
2945 function maybeAddFieldSelection( parentClass ) {
2946 var i, missingClass = jQuery( parentClass + ' :not(.frm_has_shortcodes) .frm_not_email_message, ' + parentClass + ' :not(.frm_has_shortcodes) .frm_not_email_to, ' + parentClass + ' :not(.frm_has_shortcodes) .frm_not_email_subject' );
2947 for ( i = 0; i < missingClass.length; i ++ ) {
2948 missingClass[i].parentNode.classList.add( 'frm_has_shortcodes' );
2949 }
2950 }
2951
2952 function showSuccessOpt() {
2953 /*jshint validthis:true */
2954 var c = 'success';
2955 if ( this.name === 'options[edit_action]' ) {
2956 c = 'edit';
2957 }
2958 var v = jQuery( this ).val();
2959 jQuery( '.' + c + '_action_box' ).hide();
2960 if ( v === 'redirect' ) {
2961 jQuery( '.' + c + '_action_redirect_box.' + c + '_action_box' ).fadeIn( 'slow' );
2962 } else if ( v === 'page' ) {
2963 jQuery( '.' + c + '_action_page_box.' + c + '_action_box' ).fadeIn( 'slow' );
2964 } else {
2965 jQuery( '.' + c + '_action_message_box.' + c + '_action_box' ).fadeIn( 'slow' );
2966 }
2967 }
2968
2969 function copyFormAction() {
2970 /*jshint validthis:true */
2971 var action = jQuery( this ).closest( '.frm_form_action_settings' ).clone();
2972 var currentID = action.attr( 'id' ).replace( 'frm_form_action_', '' );
2973 var newID = newActionId( currentID );
2974 action.find( '.frm_action_id, .frm-btn-group' ).remove();
2975 action.find( 'input[name$="[' + currentID + '][ID]"]' ).val( '' );
2976 action.find( '.widget-inside' ).hide();
2977
2978 // the .html() gets original values, so they need to be set
2979 action.find( 'input[type=text], textarea, input[type=number]' ).prop( 'defaultValue', function() {
2980 return this.value;
2981 } );
2982
2983 action.find( 'input[type=checkbox], input[type=radio]' ).prop( 'defaultChecked', function() {
2984 return this.checked;
2985 } );
2986
2987 var rename = new RegExp( '\\[' + currentID + '\\]', 'g' );
2988 var reid = new RegExp( '_' + currentID + '"', 'g' );
2989 var reclass = new RegExp( '-' + currentID + '"', 'g' );
2990 var revalue = new RegExp( '"' + currentID + '"', 'g' ); // if a field id matches, this could cause trouble
2991
2992 var html = action.html().replace( rename, '[' + newID + ']' ).replace( reid, '_' + newID + '"' );
2993 html = html.replace( reclass, '-' + newID + '"' ).replace( revalue, '"' + newID + '"' );
2994 var div = '<div id="frm_form_action_' + newID + '" class="widget frm_form_action_settings frm_single_email_settings" data-actionkey="' + newID + '">';
2995
2996 jQuery( '#frm_notification_settings' ).append( div + html + '</div>' );
2997 initiateMultiselect();
2998 }
2999
3000 function newActionId( currentID ) {
3001 var newID = parseInt( currentID ) + 11;
3002 var exists = document.getElementById( 'frm_form_action_' + newID );
3003 if ( exists !== null ) {
3004 newID++;
3005 newID = newActionId( newID );
3006 }
3007 return newID;
3008 }
3009
3010 function addFormAction() {
3011 /*jshint validthis:true */
3012 var actionId = getNewActionId();
3013 var type = jQuery( this ).data( 'actiontype' );
3014 var formId = this_form_id;
3015
3016 jQuery.ajax( {
3017 type: 'POST', url: ajaxurl,
3018 data: {
3019 action: 'frm_add_form_action',
3020 type: type,
3021 list_id: actionId,
3022 form_id: formId,
3023 nonce: frmGlobal.nonce
3024 },
3025 success: function( html ) {
3026 // Close any open actions first.
3027 jQuery( '.frm_form_action_settings.open' ).removeClass( 'open' );
3028
3029 jQuery( '#frm_notification_settings' ).append( html );
3030 jQuery( '.frm_form_action_settings' ).fadeIn( 'slow' );
3031
3032 var newAction = document.getElementById( 'frm_form_action_' + actionId );
3033
3034 newAction.classList.add( 'open' );
3035 document.getElementById( 'post-body-content' ).scroll( {
3036 top: newAction.offsetTop + 10,
3037 left: 0,
3038 behavior: 'smooth'
3039 } );
3040
3041 //check if icon should be active
3042 checkActiveAction( type );
3043 initiateMultiselect();
3044 showInputIcon( '#frm_form_action_' + actionId );
3045 }
3046 } );
3047 }
3048
3049 function toggleActionGroups() {
3050 /*jshint validthis:true */
3051 var actions = document.getElementById( 'frm_email_addon_menu' ).classList,
3052 search = document.getElementById( 'actions-search-input' );
3053
3054 if ( actions.contains( 'frm-all-actions' ) ) {
3055 actions.remove( 'frm-all-actions' );
3056 actions.add( 'frm-limited-actions' );
3057 } else {
3058 actions.add( 'frm-all-actions' );
3059 actions.remove( 'frm-limited-actions' );
3060 }
3061
3062 // Reset search.
3063 search.value = '';
3064 triggerEvent( search, 'input' );
3065 }
3066
3067 function getNewActionId() {
3068 var len = 0;
3069 if ( jQuery( '.frm_form_action_settings:last' ).length ) {
3070 //Get number of previous action
3071 len = jQuery( '.frm_form_action_settings:last' ).attr( 'id' ).replace( 'frm_form_action_', '' );
3072 }
3073 len = parseInt( len ) + 1;
3074 if ( typeof document.getElementById( 'frm_form_action_' + len ) !== 'undefined' ) {
3075 len = len + 100;
3076 }
3077 return len;
3078 }
3079
3080 function clickAction( obj ) {
3081 var $thisobj = jQuery( obj );
3082
3083 if ( obj.className.indexOf( 'selected' ) !== -1 ) {
3084 return;
3085 }
3086 if ( obj.className.indexOf( 'edit_field_type_end_divider' ) !== -1 && $thisobj.closest( '.edit_field_type_divider' ).hasClass( 'no_repeat_section' ) ) {
3087 return;
3088 }
3089
3090 deselectFields();
3091 $thisobj.addClass( 'selected' );
3092
3093 showFieldOptions( obj );
3094 }
3095
3096 /**
3097 * When a field is selected, show the field settings in the sidebar.
3098 */
3099 function showFieldOptions( obj ) {
3100 var i, singleField,
3101 fieldId = obj.getAttribute( 'data-fid' ),
3102 allFieldSettings = document.querySelectorAll( '.frm-single-settings:not(.frm_hidden)' );
3103
3104 for ( i = 0; i < allFieldSettings.length; i++ ) {
3105 allFieldSettings[i].classList.add( 'frm_hidden' );
3106 }
3107
3108 singleField = document.getElementById( 'frm-single-settings-' + fieldId );
3109 moveFieldSettings( singleField );
3110
3111 singleField.classList.remove( 'frm_hidden' );
3112 document.getElementById( 'frm-options-panel-tab' ).click();
3113 }
3114
3115 /**
3116 * Move the settings to the sidebar the first time they are changed or selected.
3117 * Keep the end marker at the end of the form.
3118 */
3119 function moveFieldSettings( singleField ) {
3120 if ( singleField === null ) {
3121 // The field may have not been loaded yet via ajax.
3122 return;
3123 }
3124
3125 var classes = singleField.parentElement.classList;
3126 if ( classes.contains( 'frm_field_box' ) || classes.contains( 'divider_section_only' ) ) {
3127 var endMarker = document.getElementById( 'frm-end-form-marker' );
3128 builderForm.insertBefore( singleField, endMarker );
3129 }
3130 }
3131
3132 function showEmailRow() {
3133 /*jshint validthis:true */
3134 var actionKey = jQuery( this ).closest( '.frm_form_action_settings' ).data( 'actionkey' );
3135 var rowType = this.getAttribute( 'data-emailrow' );
3136
3137 jQuery( '#frm_form_action_' + actionKey + ' .frm_' + rowType + '_row' ).fadeIn( 'slow' );
3138 jQuery( this ).fadeOut( 'slow' );
3139 }
3140
3141 function hideEmailRow() {
3142 /*jshint validthis:true */
3143 var action_box = jQuery( this ).closest( '.frm_form_action_settings' );
3144 var rowType = this.getAttribute( 'data-emailrow' );
3145
3146 var emailRowSelector = '.frm_' + rowType + '_row';
3147 var emailButtonSelector = '.frm_' + rowType + '_button';
3148
3149 jQuery( action_box ).find( emailButtonSelector ).fadeIn( 'slow' );
3150 jQuery( action_box ).find( emailRowSelector ).fadeOut( 'slow', function() {
3151 jQuery( action_box ).find( emailRowSelector + ' input' ).val( '' );
3152 } );
3153 }
3154
3155 function checkActiveAction( type ) {
3156 var limit = parseInt( jQuery( '.frm_' + type + '_action' ).data( 'limit' ) );
3157 var len = jQuery( '.frm_single_' + type + '_settings' ).length;
3158 if ( len >= limit ) {
3159 jQuery( '.frm_' + type + '_action' ).removeClass( 'frm_active_action' ).addClass( 'frm_inactive_action' );
3160 } else {
3161 jQuery( '.frm_' + type + '_action' ).removeClass( 'frm_inactive_action' ).addClass( 'frm_active_action' );
3162 }
3163 }
3164
3165 function addFormLogicRow() {
3166 /*jshint validthis:true */
3167 var id = jQuery( this ).data( 'emailkey' );
3168 var type = jQuery( this ).closest( '.frm_form_action_settings' ).find( '.frm_action_name' ).val();
3169 var meta_name = 0;
3170 var form_id = document.getElementById( 'form_id' ).value;
3171 if ( jQuery( '#frm_form_action_' + id + ' .frm_logic_row' ).length ) {
3172 meta_name = 1 + parseInt( jQuery( '#frm_form_action_' + id + ' .frm_logic_row:last' ).attr( 'id' ).replace( 'frm_logic_' + id + '_', '' ) );
3173 }
3174 jQuery.ajax( {
3175 type: 'POST', url: ajaxurl,
3176 data: {
3177 action: 'frm_add_form_logic_row',
3178 email_id: id,
3179 form_id: form_id,
3180 meta_name: meta_name,
3181 type: type,
3182 nonce: frmGlobal.nonce
3183 },
3184 success: function( html ) {
3185 jQuery( document.getElementById( 'logic_link_' + id ) ).fadeOut( 'slow', function() {
3186 var $logicRow = jQuery( document.getElementById( 'frm_logic_row_' + id ) );
3187 $logicRow.append( html );
3188 $logicRow.parent( '.frm_logic_rows' ).fadeIn( 'slow' );
3189 } );
3190 }
3191 } );
3192 return false;
3193 }
3194
3195 function toggleSubmitLogic() {
3196 /*jshint validthis:true */
3197 if ( this.checked ) {
3198 addSubmitLogic();
3199 } else {
3200 jQuery( '.frm_logic_row_submit' ).remove();
3201 document.getElementById( 'frm_submit_logic_rows' ).style.display = 'none';
3202 }
3203 }
3204
3205 /**
3206 * Adds submit button Conditional Logic row and reveals submit button Conditional Logic
3207 *
3208 * @returns {boolean}
3209 */
3210 function addSubmitLogic() {
3211 /*jshint validthis:true */
3212 var form_id = this_form_id;
3213 var meta_name = 0;
3214 if ( jQuery( '#frm_submit_logic_row .frm_logic_row' ).length > 0 ) {
3215 var last = jQuery( '#frm_submit_logic_row .frm_logic_row:last' );
3216 var submitRowID = last.attr( 'id' );
3217 var idFromSubmitRow = submitRowID.replace( 'frm_logic_submit_', '' );
3218
3219 meta_name = 1 + parseInt( last.attr( 'id' ).replace( 'frm_logic_submit_', '' ) );
3220 }
3221 jQuery.ajax( {
3222 type: 'POST',
3223 url: ajaxurl,
3224 data: {
3225 action: 'frm_add_submit_logic_row',
3226 form_id: form_id,
3227 meta_name: meta_name,
3228 nonce: frmGlobal.nonce
3229 },
3230 success: function( html ) {
3231 var $logicRow = jQuery( document.getElementById( 'frm_submit_logic_row' ) );
3232 $logicRow.append( html );
3233 $logicRow.parent( '.frm_submit_logic_rows' ).fadeIn( 'slow' );
3234 }
3235 } );
3236 return false;
3237 }
3238
3239 /**
3240 * When the user selects a field for a submit condition, update corresponding options field accordingly.
3241 */
3242 function addSubmitLogicOpts() {
3243 var fieldOpt = jQuery( this );
3244 var field_id = fieldOpt.find( ':selected' ).val();
3245
3246 if ( field_id ) {
3247 var row = fieldOpt.data( 'row' );
3248 frmGetFieldValues( field_id, 'submit', row, '', 'options[submit_conditions][hide_opt][]' );
3249 }
3250 }
3251
3252 function formatEmailSetting() {
3253 /*jshint validthis:true */
3254 var val = jQuery( this ).val();
3255 var email = val.match( /(\s[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi );
3256 /*if(email !== null && email.length) {
3257 //has email
3258 //TODO: add < > if they aren't there
3259 }*/
3260 }
3261
3262 function maybeShowFormMessages() {
3263 var header = document.getElementById( 'frm_messages_header' );
3264 if ( showFormMessages() ) {
3265 header.style.display = 'block';
3266 } else {
3267 header.style.display = 'none';
3268 }
3269 }
3270
3271 function showFormMessages() {
3272 var action = document.getElementById( 'success_action' );
3273 var selectedAction = action.options[action.selectedIndex].value;
3274 if ( selectedAction === 'message' ) {
3275 return true;
3276 }
3277
3278 var show = false;
3279 var editable = document.getElementById( 'editable' );
3280 if ( editable !== null ) {
3281 show = editable.checked && jQuery( document.getElementById( 'edit_action' ) ).val() === 'message';
3282 if ( !show ) {
3283 show = document.getElementById( 'save_draft' ).checked;
3284 }
3285 }
3286 return show;
3287 }
3288
3289 function checkDupPost() {
3290 /*jshint validthis:true */
3291 var postField = jQuery( 'select.frm_single_post_field' );
3292 postField.css( 'border-color', '' );
3293 var $t = this;
3294 var v = jQuery( $t ).val();
3295 if ( v === '' || v === 'checkbox' ) {
3296 return false;
3297 }
3298 postField.each( function() {
3299 if ( jQuery( this ).val() === v && this.name !== $t.name ) {
3300 this.style.borderColor = 'red';
3301 jQuery( $t ).val( '' );
3302 alert( 'Oops. You have already used that field.' );
3303 return false;
3304 }
3305 } );
3306 }
3307
3308 function togglePostContent() {
3309 /*jshint validthis:true */
3310 var v = jQuery( this ).val();
3311 if ( '' === v ) {
3312 jQuery( '.frm_post_content_opt, select.frm_dyncontent_opt' ).hide().val( '' );
3313 jQuery( '.frm_dyncontent_opt' ).hide();
3314 } else if ( 'post_content' === v ) {
3315 jQuery( '.frm_post_content_opt' ).show();
3316 jQuery( '.frm_dyncontent_opt' ).hide();
3317 jQuery( 'select.frm_dyncontent_opt' ).val( '' );
3318 } else {
3319 jQuery( '.frm_post_content_opt' ).hide().val( '' );
3320 jQuery( 'select.frm_dyncontent_opt, .frm_form_field.frm_dyncontent_opt' ).show();
3321 }
3322 }
3323
3324 function fillDyncontent() {
3325 /*jshint validthis:true */
3326 var v = jQuery( this ).val();
3327 var $dyn = jQuery( document.getElementById( 'frm_dyncontent' ) );
3328 if ( '' === v || 'new' === v ) {
3329 $dyn.val( '' );
3330 jQuery( '.frm_dyncontent_opt' ).show();
3331 } else {
3332 jQuery.ajax( {
3333 type: 'POST', url: ajaxurl,
3334 data: {action: 'frm_display_get_content', id: v, nonce: frmGlobal.nonce},
3335 success: function( val ) {
3336 $dyn.val( val );
3337 jQuery( '.frm_dyncontent_opt' ).show();
3338 }
3339 } );
3340 }
3341 }
3342
3343 function switchPostType() {
3344 /*jshint validthis:true */
3345 // update all rows of categories/taxonomies
3346 var cat_rows = document.getElementById( 'frm_posttax_rows' ).childNodes;
3347 var post_type = this.value;
3348 var cur_select;
3349 var new_select;
3350
3351 // Get new category/taxonomy options
3352 jQuery.ajax( {
3353 type: 'POST', url: ajaxurl,
3354 data: {action: 'frm_replace_posttax_options', post_type: post_type, nonce: frmGlobal.nonce},
3355 success: function( html ) {
3356
3357 // Loop through each category row, and replace the first dropdown
3358 for ( i = 0; i < cat_rows.length; i++ ) {
3359 // Check if current element is a div
3360 if ( cat_rows[i].tagName != 'DIV' ) {
3361 continue;
3362 }
3363
3364 // Get current category select
3365 cur_select = cat_rows[i].getElementsByTagName( 'select' )[0];
3366
3367 // Set up new select
3368 new_select = document.createElement( "select" );
3369 new_select.innerHTML = html;
3370 new_select.className = cur_select.className;
3371 new_select.name = cur_select.name;
3372
3373 // Replace the old select with the new select
3374 cat_rows[i].replaceChild( new_select, cur_select );
3375 }
3376 }
3377 } );
3378 }
3379
3380 function addPosttaxRow() {
3381 /*jshint validthis:true */
3382 addPostRow( 'tax', this );
3383 }
3384
3385 function addPostmetaRow() {
3386 /*jshint validthis:true */
3387 addPostRow( 'meta', this );
3388 }
3389
3390 function addPostRow( type, button ) {
3391 var id = jQuery( 'input[name="id"]' ).val();
3392 var settings = jQuery( button ).closest( '.frm_form_action_settings' );
3393 var key = settings.data( 'actionkey' );
3394 var post_type = settings.find( '.frm_post_type' ).val();
3395
3396 var meta_name = 0;
3397 if ( jQuery( '.frm_post' + type + '_row' ).length ) {
3398 var name = jQuery( '.frm_post' + type + '_row:last' ).attr( 'id' ).replace( 'frm_post' + type + '_', '' );
3399 if ( jQuery.isNumeric( name ) ) {
3400 meta_name = 1 + parseInt( name );
3401 } else {
3402 meta_name = 1;
3403 }
3404 }
3405 jQuery.ajax( {
3406 type: 'POST', url: ajaxurl,
3407 data: {
3408 action: 'frm_add_post' + type + '_row', form_id: id,
3409 meta_name: meta_name, tax_key: meta_name,
3410 post_type: post_type, action_key: key, nonce: frmGlobal.nonce
3411 },
3412 success: function( html ) {
3413 jQuery( document.getElementById( 'frm_post' + type + '_rows' ) ).append( html );
3414 jQuery( '.frm_add_post' + type + '_row.button' ).hide();
3415
3416 if ( type === 'meta' ) {
3417 jQuery( '.frm_name_value' ).show();
3418 jQuery( '.frm_toggle_cf_opts' ).not( ':last' ).hide();
3419 } else if ( type === 'tax' ) {
3420 jQuery( '.frm_posttax_labels' ).show();
3421 }
3422 }
3423 } );
3424 }
3425
3426 function getMetaValue( id, meta_name ) {
3427 var new_meta = meta_name;
3428 if ( jQuery( document.getElementById( id + meta_name ) ).length > 0 ) {
3429 new_meta = getMetaValue( id, meta_name + 1 );
3430 }
3431 return new_meta;
3432 }
3433
3434 function changePosttaxRow() {
3435 /*jshint validthis:true */
3436 if ( !jQuery( this ).closest( '.frm_posttax_row' ).find( '.frm_posttax_opt_list' ).length ) {
3437 return;
3438 }
3439
3440 jQuery( this ).closest( '.frm_posttax_row' ).find( '.frm_posttax_opt_list' ).html( '<div class="spinner frm_spinner" style="display:block"></div>' );
3441
3442 var post_type = jQuery( this ).closest( '.frm_form_action_settings' ).find( 'select[name$="[post_content][post_type]"]' ).val();
3443 var action_key = jQuery( this ).closest( '.frm_form_action_settings' ).data( 'actionkey' );
3444 var tax_key = jQuery( this ).closest( '.frm_posttax_row' ).attr( 'id' ).replace( 'frm_posttax_', '' );
3445 var meta_name = jQuery( this ).val();
3446 var show_exclude = jQuery( document.getElementById( tax_key + '_show_exclude' ) ).is( ':checked' ) ? 1 : 0;
3447 var field_id = jQuery( 'select[name$="[post_category][' + tax_key + '][field_id]"]' ).val();
3448 var id = jQuery( 'input[name="id"]' ).val();
3449
3450 jQuery.ajax( {
3451 type: 'POST', url: ajaxurl,
3452 data: {
3453 action: 'frm_add_posttax_row',
3454 form_id: id,
3455 post_type: post_type,
3456 tax_key: tax_key,
3457 action_key: action_key,
3458 meta_name: meta_name,
3459 field_id: field_id,
3460 show_exclude: show_exclude,
3461 nonce: frmGlobal.nonce
3462 },
3463 success: function( html ) {
3464 var $tax = jQuery( document.getElementById( 'frm_posttax_' + tax_key ) );
3465 $tax.replaceWith( html );
3466 }
3467 } );
3468 }
3469
3470 function toggleCfOpts() {
3471 /*jshint validthis:true */
3472 var row = jQuery( this ).closest( '.frm_postmeta_row' );
3473 var cancel = row.find( '.frm_cancelnew' );
3474 var select = row.find( '.frm_enternew' );
3475 if ( row.find( 'select.frm_cancelnew' ).is( ':visible' ) ) {
3476 cancel.hide();
3477 select.show();
3478 } else {
3479 cancel.show();
3480 select.hide();
3481 }
3482
3483 row.find( 'input.frm_enternew, select.frm_cancelnew' ).val( '' );
3484 return false;
3485 }
3486
3487 function toggleFormOpts() {
3488 /*jshint validthis:true */
3489 var changedOpt = jQuery( this );
3490 var val = changedOpt.val();
3491 if ( changedOpt.attr( 'type' ) === 'checkbox' ) {
3492 if ( this.checked === false ) {
3493 val = '';
3494 }
3495 }
3496
3497 var toggleClass = changedOpt.data( 'toggleclass' );
3498 if ( val === '' ) {
3499 jQuery( '.' + toggleClass ).hide();
3500 } else {
3501 jQuery( '.' + toggleClass ).show();
3502 jQuery( '.hide_' + toggleClass + '_' + val ).hide();
3503 }
3504 }
3505
3506 function submitSettings() {
3507 /*jshint validthis:true */
3508 preFormSave( this );
3509 jQuery( '.frm_form_settings' ).submit();
3510 }
3511
3512 /* View Functions */
3513 function showCount() {
3514 /*jshint validthis:true */
3515 var value = jQuery( this ).val();
3516
3517 var $cont = document.getElementById( 'date_select_container' );
3518 var tab = document.getElementById( 'frm_listing_tab' );
3519 var label = tab.getAttribute( 'data-label' );
3520 if ( value === 'calendar' ) {
3521 jQuery( '.hide_dyncontent, .hide_single_content' ).removeClass( 'frm_hidden' );
3522 jQuery( '.limit_container' ).addClass( 'frm_hidden' );
3523 $cont.style.display = 'block';
3524 } else if ( value === 'dynamic' ) {
3525 jQuery( '.hide_dyncontent, .limit_container, .hide_single_content' ).removeClass( 'frm_hidden' );
3526 } else if ( value === 'one' ) {
3527 label = tab.getAttribute( 'data-one' );
3528 jQuery( '.hide_dyncontent, .limit_container, .hide_single_content' ).addClass( 'frm_hidden' );
3529 } else {
3530 jQuery( '.hide_dyncontent' ).addClass( 'frm_hidden' );
3531 jQuery( '.limit_container, .hide_single_content' ).removeClass( 'frm_hidden' );
3532 }
3533
3534 if ( value !== 'calendar' ) {
3535 $cont.style.display = 'none';
3536 }
3537 tab.innerHTML = label;
3538 }
3539
3540 function displayFormSelected() {
3541 /*jshint validthis:true */
3542 var form_id = jQuery( this ).val();
3543 this_form_id = form_id; // set the global form id
3544 if ( form_id === '' ) {
3545 return;
3546 }
3547
3548 jQuery.ajax( {
3549 type: 'POST', url: ajaxurl,
3550 data: {action: 'frm_get_cd_tags_box', form_id: form_id, nonce: frmGlobal.nonce},
3551 success: function( html ) {
3552 jQuery( '#frm_adv_info .categorydiv' ).html( html );
3553 }
3554 } );
3555
3556 jQuery.ajax( {
3557 type: 'POST', url: ajaxurl,
3558 data: {action: 'frm_get_date_field_select', form_id: form_id, nonce: frmGlobal.nonce},
3559 success: function( html ) {
3560 jQuery( document.getElementById( 'date_select_container' ) ).html( html );
3561 }
3562 } );
3563 }
3564
3565 function clickTabsAfterAjax() {
3566 /*jshint validthis:true */
3567 var t = jQuery( this ).attr( 'href' );
3568 jQuery( this ).parent().addClass( 'tabs' ).siblings( 'li' ).removeClass( 'tabs' );
3569 jQuery( t ).show().siblings( '.tabs-panel' ).hide();
3570 return false;
3571 }
3572
3573 function clickContentTab() {
3574 /*jshint validthis:true */
3575 link = jQuery( this );
3576 var t = link.attr( 'href' );
3577 if ( typeof t === 'undefined' ) {
3578 return false;
3579 }
3580
3581 var c = t.replace( '#', '.' );
3582 link.closest( '.nav-tab-wrapper' ).find( 'a' ).removeClass( 'nav-tab-active' );
3583 link.addClass( 'nav-tab-active' );
3584 jQuery( '.nav-menu-content' ).not( t ).not( c ).hide();
3585 jQuery( t + ',' + c ).show();
3586
3587 return false;
3588 }
3589
3590 function addOrderRow() {
3591 var l = 0;
3592 if ( jQuery( '#frm_order_options .frm_logic_rows div:last' ).length > 0 ) {
3593 l = jQuery( '#frm_order_options .frm_logic_rows div:last' ).attr( 'id' ).replace( 'frm_order_field_', '' );
3594 }
3595 jQuery.ajax( {
3596 type: 'POST', url: ajaxurl,
3597 data: {
3598 action: 'frm_add_order_row',
3599 form_id: this_form_id,
3600 order_key: (parseInt( l ) + 1),
3601 nonce: frmGlobal.nonce
3602 },
3603 success: function( html ) {
3604 jQuery( '#frm_order_options .frm_logic_rows' ).append( html ).show().prev( '.frm_add_order_row' ).hide();
3605 }
3606 } );
3607 }
3608
3609 function addWhereRow() {
3610 var l = 0;
3611 if ( jQuery( '#frm_where_options .frm_logic_rows div:last' ).length ) {
3612 l = jQuery( '#frm_where_options .frm_logic_rows div:last' ).attr( 'id' ).replace( 'frm_where_field_', '' );
3613 }
3614 jQuery.ajax( {
3615 type: 'POST', url: ajaxurl,
3616 data: {
3617 action: 'frm_add_where_row',
3618 form_id: this_form_id,
3619 where_key: (parseInt( l ) + 1),
3620 nonce: frmGlobal.nonce
3621 },
3622 success: function( html ) {
3623 jQuery( '#frm_where_options .frm_logic_rows' ).append( html ).show().prev( '.frm_add_where_row' ).hide();
3624 }
3625 } );
3626 }
3627
3628 function insertWhereOptions() {
3629 /*jshint validthis:true */
3630 var value = this.value;
3631 var where_key = jQuery( this ).closest( '.frm_where_row' ).attr( 'id' ).replace( 'frm_where_field_', '' );
3632 jQuery.ajax( {
3633 type: 'POST', url: ajaxurl,
3634 data: {action: 'frm_add_where_options', where_key: where_key, field_id: value, nonce: frmGlobal.nonce},
3635 success: function( html ) {
3636 jQuery( document.getElementById( 'where_field_options_' + where_key ) ).html( html );
3637 }
3638 } );
3639 }
3640
3641 function hideWhereOptions() {
3642 /*jshint validthis:true */
3643 var value = this.value;
3644 var where_key = jQuery( this ).closest( '.frm_where_row' ).attr( 'id' ).replace( 'frm_where_field_', '' );
3645 if ( value === 'group_by' || value === 'group_by_newest' ) {
3646 document.getElementById( 'where_field_options_' + where_key ).style.display = 'none';
3647 } else {
3648 document.getElementById( 'where_field_options_' + where_key ).style.display = 'inline-block';
3649 }
3650 }
3651
3652 function setDefaultPostStatus() {
3653 var urlQuery = window.location.search.substring( 1 );
3654 if ( urlQuery.indexOf( 'action=edit' ) === -1 ) {
3655 document.getElementById( 'post-visibility-display' ).innerHTML = frm_admin_js.private;
3656 document.getElementById( 'hidden-post-visibility' ).value = 'private';
3657 document.getElementById( 'visibility-radio-private' ).checked = true;
3658 }
3659 }
3660
3661 /* Customization Panel */
3662 function insertCode( e ) {
3663 /*jshint validthis:true */
3664 e.preventDefault();
3665 insertFieldCode( jQuery( this ), this.getAttribute( 'data-code' ) );
3666 return false;
3667 }
3668
3669 function insertFieldCode( element, variable ) {
3670 var rich = false,
3671 element_id = element;
3672 if ( typeof element === 'object' ) {
3673 if ( element.hasClass( 'frm_noallow' ) ) {
3674 return;
3675 }
3676
3677 element_id = jQuery( element ).closest( '[data-fills]' ).attr( 'data-fills' );
3678 if ( typeof element_id === 'undefined' ) {
3679 element_id = element.closest( 'div' ).attr( 'class' );
3680 if ( typeof element_id !== 'undefined' ) {
3681 element_id = element_id.split( ' ' )[1];
3682 }
3683 }
3684 }
3685
3686 if ( typeof element_id === 'undefined' ) {
3687 var active = document.activeElement;
3688 if ( active.type === 'search' ) {
3689 // If the search field has focus, find the correct field.
3690 element_id = active.id.replace( '-search-input', '' );
3691 if ( element_id.match( /\d/gi ) === null ) {
3692 active = jQuery( '.frm-single-settings:visible .' + element_id );
3693 element_id = active.attr( 'id' );
3694 }
3695 } else {
3696 element_id = active.id;
3697 }
3698 }
3699
3700 if ( element_id ) {
3701 rich = jQuery( '#wp-' + element_id + '-wrap.wp-editor-wrap' ).length > 0;
3702 }
3703
3704 var content_box = jQuery( document.getElementById( element_id ) );
3705 if ( typeof element.attr('data-shortcode') === 'undefined' && ( ! content_box.length || typeof content_box.attr('data-shortcode') === 'undefined' ) ) {
3706 // this helps to exclude those that don't want shortcode-like inserted content e.g. frm-pro's summary field
3707 var doShortcode = element.parents( 'ul.frm_code_list' ).attr( 'data-shortcode' );
3708 if ( doShortcode === 'undefined' || doShortcode !== 'no' ) {
3709 variable = '[' + variable + ']';
3710 }
3711 }
3712
3713 if ( rich ) {
3714 wpActiveEditor = element_id;
3715 send_to_editor( variable );
3716 return;
3717 }
3718
3719 if ( ! content_box.length ) {
3720 return false;
3721 }
3722
3723 if ( variable === '[default-html]' || variable === '[default-plain]' ) {
3724 var p = 0;
3725 if ( variable === '[default-plain]' ) {
3726 p = 1;
3727 }
3728 jQuery.ajax( {
3729 type: 'POST', url: ajaxurl,
3730 data: {
3731 action: 'frm_get_default_html',
3732 form_id: jQuery( 'input[name="id"]' ).val(),
3733 plain_text: p,
3734 nonce: frmGlobal.nonce
3735 },
3736 success: function( msg ) {
3737 insertContent( content_box, msg );
3738 }
3739 } );
3740 } else {
3741 insertContent( content_box, variable );
3742 }
3743 return false;
3744 }
3745
3746 function insertContent( content_box, variable ) {
3747 if ( document.selection ) {
3748 content_box[0].focus();
3749 document.selection.createRange().text = variable;
3750 } else {
3751 obj = content_box[0];
3752 var e = obj.selectionEnd;
3753
3754 variable = maybeFormatInsertedContent( content_box, variable, obj.selectionStart, e );
3755
3756 obj.value = obj.value.substr( 0, obj.selectionStart ) + variable + obj.value.substr( obj.selectionEnd, obj.value.length );
3757 var s = e + variable.length;
3758 obj.focus();
3759 obj.setSelectionRange( s, s );
3760 }
3761 content_box.change(); //trigger change
3762 }
3763
3764 function maybeFormatInsertedContent( input, textToInsert, selectionStart, selectionEnd ) {
3765 var separator = input.data( 'sep' );
3766 if ( undefined === separator ) {
3767 return textToInsert;
3768 }
3769
3770 var value = input.val();
3771
3772 if ( ! value.trim().length ) {
3773 return textToInsert;
3774 }
3775
3776 var startPattern = new RegExp( separator + "\\s*$" );
3777 var endPattern = new RegExp( "^\\s*" + separator );
3778
3779 if ( value.substr( 0, selectionStart ).trim().length && false === startPattern.test( value.substr( 0, selectionStart ) ) ) {
3780 textToInsert = separator + textToInsert;
3781 }
3782
3783 if ( value.substr( selectionEnd, value.length ).trim().length && false === endPattern.test( value.substr( selectionEnd, value.length ) ) ) {
3784 textToInsert += separator;
3785 }
3786
3787 return textToInsert;
3788 }
3789
3790 function resetLogicBuilder() {
3791 /*jshint validthis:true */
3792 var id = document.getElementById( 'frm-id-condition' ),
3793 key = document.getElementById( 'frm-key-condition' );
3794
3795 if ( this.checked ) {
3796 id.classList.remove( 'frm_hidden' );
3797 key.classList.add( 'frm_hidden' );
3798 triggerEvent( key, 'change' );
3799 } else {
3800 id.classList.add( 'frm_hidden' );
3801 key.classList.remove( 'frm_hidden' );
3802 triggerEvent( id, 'change' );
3803 }
3804 }
3805
3806 function setLogicExample() {
3807 var field, code,
3808 idKey = document.getElementById( 'frm-id-key-condition' ).checked ? 'frm-id-condition' : 'frm-key-condition',
3809 is = document.getElementById( 'frm-is-condition' ).value,
3810 text = document.getElementById( 'frm-text-condition' ).value,
3811 result = document.getElementById( 'frm-insert-condition' );
3812
3813 idKey = document.getElementById( idKey );
3814 field = idKey.options[idKey.selectedIndex].value;
3815 code = 'if ' + field + ' ' + is + '="' + text + '"]';
3816 result.setAttribute( 'data-code', code + frm_admin_js.conditional_text + '[/if ' + field );
3817 result.innerHTML = '[' + code + '[/if ' + field + ']';
3818 }
3819
3820 function showBuilderModal( e ) {
3821 /*jshint validthis:true */
3822 var moreIcon = getIconForInput( this );
3823 showInlineModal( moreIcon, this );
3824 }
3825
3826 function maybeShowModal( input ) {
3827 var moreIcon;
3828 if ( input.parentNode.parentNode.classList.contains( 'frm_has_shortcodes' ) ) {
3829 hideShortcodes();
3830 moreIcon = getIconForInput( input );
3831 if ( moreIcon.tagName === 'use' ) {
3832 moreIcon = moreIcon.firstElementChild;
3833 if ( moreIcon.getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ).indexOf( 'frm_close_icon' ) === -1 ) {
3834 showShortcodeBox( moreIcon, 'nofocus' );
3835 }
3836 } else if ( ! moreIcon.classList.contains( 'frm_close_icon' ) ) {
3837 showShortcodeBox( moreIcon, 'nofocus' );
3838 }
3839 }
3840 }
3841
3842 function showShortcodes( e ) {
3843 /*jshint validthis:true */
3844 e.preventDefault();
3845 e.stopPropagation();
3846
3847 showShortcodeBox( this );
3848 }
3849
3850 function showShortcodeBox( moreIcon, shouldFocus ) {
3851 var pos = moreIcon.getBoundingClientRect(),
3852 input = getInputForIcon( moreIcon ),
3853 box = document.getElementById( 'frm_adv_info' ),
3854 classes = moreIcon.className,
3855 parentPos = box.parentElement.getBoundingClientRect();
3856
3857 if ( moreIcon.tagName === 'svg' ) {
3858 moreIcon = moreIcon.firstElementChild;
3859 }
3860 if ( moreIcon.tagName === 'use' ) {
3861 classes = moreIcon.getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' );
3862 }
3863
3864 if ( classes.indexOf( 'frm_close_icon' ) !== -1 ) {
3865 hideShortcodes( box );
3866 } else {
3867 box.style.top = ( pos.top - parentPos.top + 32 ) + 'px';
3868 box.style.left = ( pos.left - parentPos.left - 257 ) + 'px';
3869
3870 jQuery( '.frm_code_list a' ).removeClass( 'frm_noallow' );
3871 if ( input.classList.contains( 'frm_not_email_to' ) ) {
3872 jQuery( '#frm-insert-fields-box .frm_code_list li:not(.show_frm_not_email_to) a' ).addClass( 'frm_noallow' );
3873 } else if ( input.classList.contains( 'frm_not_email_subject' ) ) {
3874 jQuery( '.frm_code_list li.hide_frm_not_email_subject a' ).addClass( 'frm_noallow' );
3875 }
3876
3877 box.setAttribute( 'data-fills', input.id );
3878 box.style.display = 'block';
3879
3880 if ( moreIcon.tagName === 'use' ) {
3881 moreIcon.setAttributeNS( 'http://www.w3.org/1999/xlink', 'href', '#frm_close_icon' );
3882 } else {
3883 moreIcon.className = classes.replace( 'frm_more_horiz_solid_icon', 'frm_close_icon' );
3884 }
3885
3886 if ( shouldFocus !== 'nofocus' ) {
3887 input.focus();
3888 }
3889 }
3890 }
3891
3892 /**
3893 * Get the input box for the selected ... icon.
3894 */
3895 function getInputForIcon( moreIcon ) {
3896 var input = moreIcon.nextElementSibling;
3897 if ( input !== null && input.tagName !== 'INPUT' && input.tagName !== 'TEXTAREA' ) {
3898 // Workaround for 1Password.
3899 input = input.nextElementSibling;
3900 }
3901 return input;
3902 }
3903
3904 /**
3905 * Get the ... icon for the selected input box.
3906 */
3907 function getIconForInput( input ) {
3908 var moreIcon = input.previousElementSibling;
3909 if ( moreIcon !== null && moreIcon.tagName !== 'I' && moreIcon.tagName !== 'svg' ) {
3910 moreIcon = moreIcon.previousElementSibling;
3911 }
3912 return moreIcon;
3913 }
3914
3915 function hideShortcodes( box ) {
3916 var i, u, closeIcons, closeSvg;
3917 if ( typeof box === 'undefined' ) {
3918 box = document.getElementById( 'frm_adv_info' );
3919 if ( box === null ) {
3920 return;
3921 }
3922 }
3923
3924 if ( document.getElementById( 'frm_dyncontent' ) !== null ) {
3925 // Don't run when in the sidebar.
3926 return;
3927 }
3928
3929 box.style.display = 'none';
3930
3931 closeIcons = document.querySelectorAll( '.frm-show-box.frm_close_icon' );
3932 for ( i = 0; i < closeIcons.length; i++ ) {
3933 closeIcons[i].classList.remove( 'frm_close_icon' );
3934 closeIcons[i].classList.add( 'frm_more_horiz_solid_icon' );
3935 }
3936
3937 closeSvg = document.querySelectorAll( '.frm_has_shortcodes use' );
3938 for ( u = 0; u < closeSvg.length; u++ ) {
3939 if ( closeSvg[u].getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ) === '#frm_close_icon' ) {
3940 closeSvg[u].setAttributeNS( 'http://www.w3.org/1999/xlink', 'href', '#frm_more_horiz_solid_icon' );
3941 }
3942 }
3943 }
3944
3945 function initToggleShortcodes() {
3946 if ( typeof tinymce !== 'object' ) {
3947 return;
3948 }
3949
3950 DOM = tinymce.DOM;
3951 if ( typeof(DOM.events) !== 'undefined' && typeof(DOM.events.add) !== 'undefined' ) {
3952 DOM.events.add( DOM.select( '.wp-editor-wrap' ), 'mouseover', function( e ) {
3953 if ( jQuery( '*:focus' ).length > 0 ) {
3954 return;
3955 }
3956 if ( this.id ) {
3957 toggleAllowedShortcodes( this.id.slice( 3, -5 ), 'focusin' );
3958 }
3959 } );
3960 DOM.events.add( DOM.select( '.wp-editor-wrap' ), 'mouseout', function( e ) {
3961 if ( jQuery( '*:focus' ).length > 0 ) {
3962 return;
3963 }
3964 if ( this.id ) {
3965 toggleAllowedShortcodes( this.id.slice( 3, -5 ), 'focusin' );
3966 }
3967 } );
3968 } else {
3969 jQuery( '#frm_dyncontent' ).on( 'mouseover mouseout', '.wp-editor-wrap', function( e ) {
3970 if ( jQuery( '*:focus' ).length > 0 ) {
3971 return;
3972 }
3973 if ( this.id ) {
3974 toggleAllowedShortcodes( this.id.slice( 3, -5 ), 'focusin' );
3975 }
3976 } );
3977 }
3978 }
3979
3980 function toggleAllowedShortcodes( id, f ) {
3981 var c, clickedID;
3982 if ( typeof(id) === 'undefined' ) {
3983 id = '';
3984 }
3985 c = id;
3986
3987 if ( id.indexOf( '-search-input' ) !== -1 ) {
3988 return;
3989 }
3990
3991 if ( id !== '' ) {
3992 var $ele = jQuery( document.getElementById( id ) );
3993 if ( $ele.attr( 'class' ) && id !== 'wpbody-content' && id !== 'content' && id !== 'dyncontent' && id !== 'success_msg' ) {
3994 var d = $ele.attr( 'class' ).split( ' ' )[0];
3995 if ( d === 'frm_long_input' || d === 'frm_98_width' || typeof d === 'undefined' ) {
3996 d = '';
3997 } else {
3998 id = jQuery.trim( d );
3999 }
4000 c = c + ' ' + d;
4001 c = c.replace( 'widefat', '' ).replace( 'frm_with_left_label', '' );
4002 }
4003 }
4004
4005 jQuery( '#frm-insert-fields-box,#frm-conditionals,#frm-adv-info-tab,#frm-dynamic-values' ).attr( 'data-fills', jQuery.trim( c ) );
4006 var a = [
4007 'content', 'wpbody-content', 'dyncontent', 'success_url',
4008 'success_msg', 'edit_msg', 'frm_dyncontent', 'frm_not_email_message',
4009 'frm_not_email_subject'
4010 ];
4011 var b = [
4012 'before_content', 'after_content', 'frm_not_email_to',
4013 'dyn_default_value',
4014 ];
4015
4016 if ( jQuery.inArray( id, a ) >= 0 ) {
4017 jQuery( '.frm_code_list a' ).removeClass( 'frm_noallow' ).addClass( 'frm_allow' );
4018 jQuery( '.frm_code_list a.hide_' + id ).addClass( 'frm_noallow' ).removeClass( 'frm_allow' );
4019 } else if ( jQuery.inArray( id, b ) >= 0 ) {
4020 jQuery( '.frm_code_list:not(.frm-dropdown-menu) a:not(.show_' + id + ')' ).addClass( 'frm_noallow' ).removeClass( 'frm_allow' );
4021 jQuery( '.frm_code_list a.show_' + id ).removeClass('frm_noallow').addClass( 'frm_allow' );
4022 } else {
4023 jQuery( '.frm_code_list:not(.frm-dropdown-menu) a' ).addClass( 'frm_noallow' ).removeClass( 'frm_allow' );
4024 }
4025
4026 // Automatically select a tab.
4027 if ( id === 'dyn_default_value' ) {
4028 clickedID = 'frm_dynamic_values';
4029 jQuery( document.getElementById( clickedID + '_tab' ) ).click();
4030 jQuery( '#' + clickedID.replace( /_/g, '-' ) + ' .frm_show_inactive' ).addClass( 'frm_hidden' );
4031 jQuery( '#' + clickedID.replace( /_/g, '-' ) + ' .frm_show_active' ).removeClass( 'frm_hidden' );
4032 }
4033 }
4034
4035 function toggleAllowedHTML( input, f ) {
4036 var b, id = input.id;
4037 if ( typeof id === 'undefined' || id.indexOf( '-search-input' ) !== -1 ) {
4038 return;
4039 }
4040
4041 jQuery( '#frm-adv-info-tab' ).attr( 'data-fills', jQuery.trim( id ) );
4042 if ( input.classList.contains( 'field_custom_html' ) ) {
4043 id = 'field_custom_html';
4044 }
4045
4046 b = [ 'after_html', 'before_html', 'submit_html', 'field_custom_html' ];
4047 if ( jQuery.inArray( id, b ) >= 0 ) {
4048 jQuery( '.frm_code_list li:not(.show_' + id + ')' ).addClass( 'frm_hidden' );
4049 jQuery( '.frm_code_list li.show_' + id ).removeClass( 'frm_hidden' );
4050 }
4051 }
4052
4053 function toggleKeyID( switch_to, e ) {
4054 e.stopPropagation();
4055 jQuery( '.frm_code_list .frmids, .frm_code_list .frmkeys' ).addClass( 'frm_hidden' );
4056 jQuery( '.frm_code_list .' + switch_to ).removeClass( 'frm_hidden' );
4057 jQuery( '.frmids, .frmkeys' ).removeClass( 'current' );
4058 jQuery( '.' + switch_to ).addClass( 'current' );
4059 }
4060
4061 /* Styling */
4062
4063 //function to append a new theme stylesheet with the new style changes
4064 function updateUICSS( locStr ) {
4065 if ( locStr == -1 ) {
4066 jQuery( 'link.ui-theme' ).remove();
4067 return false;
4068 }
4069 var cssLink = jQuery( '<link href="' + locStr + '" type="text/css" rel="Stylesheet" class="ui-theme" />' );
4070 jQuery( 'head' ).append( cssLink );
4071
4072 if ( jQuery( 'link.ui-theme' ).length > 1 ) {
4073 jQuery( 'link.ui-theme:first' ).remove();
4074 }
4075 }
4076
4077 function setPosClass() {
4078 /*jshint validthis:true */
4079 var value = this.value;
4080 if ( value === 'none' ) {
4081 value = 'top';
4082 } else if ( value === 'no_label' ) {
4083 value = 'none';
4084 }
4085 jQuery( '.frm_pos_container' ).removeClass( 'frm_top_container frm_left_container frm_right_container frm_none_container frm_inside_container' ).addClass( 'frm_' + value + '_container' );
4086 }
4087
4088 function collapseAllSections() {
4089 jQuery( '.control-section.accordion-section.open' ).removeClass( 'open' );
4090 }
4091
4092 function textSquishCheck() {
4093 var size = document.getElementById( 'frm_field_font_size' ).value.replace( /\D/g, '' );
4094 var height = document.getElementById( 'frm_field_height' ).value.replace( /\D/g, '' );
4095 var paddingEntered = document.getElementById( 'frm_field_pad' ).value.split( ' ' );
4096 var paddingCount = paddingEntered.length;
4097
4098 // If too many or too few padding entries, leave now
4099 if ( paddingCount === 0 || paddingCount > 4 || height === '' ) {
4100 return;
4101 }
4102
4103 // Get the top and bottom padding from entered values
4104 var paddingTop = paddingEntered[0].replace( /\D/g, '' );
4105 var paddingBottom = paddingTop;
4106 if ( paddingCount >= 3 ) {
4107 paddingBottom = paddingEntered[2].replace( /\D/g, '' );
4108 }
4109
4110 // Check if there is enough space for text
4111 var textSpace = height - size - paddingTop - paddingBottom - 3;
4112 if ( textSpace < 0 ) {
4113 alert( frm_admin_js.css_invalid_size );
4114 }
4115 }
4116
4117 /* Global settings page */
4118 function loadSettingsTab( anchor ) {
4119 var holder = anchor.replace( '#', '' );
4120 var holderContainer = jQuery( '.frm_' + holder + '_ajax' );
4121 if ( holderContainer.length ) {
4122 jQuery.ajax( {
4123 type: 'POST', url: ajaxurl,
4124 data: {
4125 'action': 'frm_settings_tab',
4126 'tab': holder.replace( '_settings', '' ),
4127 'nonce': frmGlobal.nonce
4128 },
4129 success: function( html ) {
4130 holderContainer.replaceWith( html );
4131 }
4132 } );
4133 }
4134 }
4135
4136 function uninstallNow() {
4137 /*jshint validthis:true */
4138 if ( confirmLinkClick( this ) === true ) {
4139 jQuery( '.frm_uninstall .frm-wait' ).css( 'visibility', 'visible' );
4140 jQuery.ajax( {
4141 type: 'POST',
4142 url: ajaxurl,
4143 data: 'action=frm_uninstall&nonce=' + frmGlobal.nonce,
4144 success: function( msg ) {
4145 jQuery( '.frm_uninstall' ).fadeOut( 'slow' );
4146 window.location = msg;
4147 }
4148 } );
4149 }
4150 return false;
4151 }
4152
4153 function saveAddonLicense() {
4154 /*jshint validthis:true */
4155 var button = jQuery( this );
4156 var buttonName = this.name;
4157 var pluginSlug = this.getAttribute( 'data-plugin' );
4158 var action = buttonName.replace( 'edd_' + pluginSlug + '_license_', '' );
4159 var license = document.getElementById( 'edd_' + pluginSlug + '_license_key' ).value;
4160 jQuery.ajax( {
4161 type: 'POST', url: ajaxurl, dataType: 'json',
4162 data: {action: 'frm_addon_' + action, license: license, plugin: pluginSlug, nonce: frmGlobal.nonce},
4163 success: function( msg ) {
4164 var thisRow = button.closest( '.edd_frm_license_row' );
4165 if ( action === 'deactivate' ) {
4166 license = '';
4167 document.getElementById( 'edd_' + pluginSlug + '_license_key' ).value = '';
4168 }
4169 thisRow.find( '.edd_frm_license' ).html( license );
4170 if ( msg.success === true ) {
4171 thisRow.find( '.frm_icon_font' ).removeClass( 'frm_hidden' );
4172 thisRow.find( 'div.alignleft' ).toggleClass( 'frm_hidden', 1000 );
4173 }
4174
4175 var messageBox = thisRow.find( '.frm_license_msg' );
4176 messageBox.html( msg.message );
4177 if ( msg.message !== '' ) {
4178 setTimeout( function() {
4179 messageBox.html( '' );
4180 }, 15000 );
4181 }
4182 }
4183 } );
4184 }
4185
4186 /* Import/Export page */
4187
4188 function startFormMigration( event ) {
4189 event.preventDefault();
4190
4191 var checkedBoxes = jQuery( '#frm_form_importer input:checked' );
4192 if ( checkedBoxes.length ) {
4193
4194 var ids = [];
4195 checkedBoxes.each( function( i ) {
4196 ids[i] = this.value;
4197 } );
4198
4199 // Begin the import process.
4200 importForms( ids );
4201 }
4202 }
4203
4204 /**
4205 * Begins the process of importing the forms.
4206 */
4207 function importForms( forms ) {
4208
4209 var $processSettings = jQuery( '#frm-importer-process' );
4210
4211 // Display total number of forms we have to import.
4212 $processSettings.find( '.form-total' ).text( forms.length );
4213 $processSettings.find( '.form-current' ).text( '1' );
4214
4215 // Hide the form select section.
4216 jQuery( '#frm_form_importer' ).hide();
4217
4218 // Show processing status.
4219 $processSettings.show();
4220 $processSettings.find( '.process-completed' ).hide();
4221
4222 // Create global import queue.
4223 s.importQueue = forms;
4224 s.imported = 0;
4225
4226 // Import the first form in the queue.
4227 importForm();
4228 }
4229
4230 /**
4231 * Imports a single form from the import queue.
4232 */
4233 function importForm() {
4234 var $processSettings = jQuery( '#frm-importer-process' ),
4235 formID = s.importQueue[0],
4236 provider = jQuery( 'input[name="slug"]' ).val(),
4237 data = {
4238 action: 'frm_import_' + provider,
4239 form_id: formID,
4240 nonce: frmGlobal.nonce
4241 };
4242
4243 // Trigger AJAX import for this form.
4244 jQuery.post( ajaxurl, data, function( res ) {
4245
4246 if ( res.success ) {
4247 var statusUpdate;
4248
4249 if ( res.data.error ) {
4250 statusUpdate = '<p>' + res.data.name + ': ' + res.data.msg + '</p>';
4251 } else {
4252 statusUpdate = '<p>Imported <a href="' + res.data.link + '" target="_blank">' + res.data.name + '</a></p>';
4253 }
4254
4255 $processSettings.find( '.status' ).prepend( statusUpdate );
4256 $processSettings.find( '.status' ).show();
4257
4258 // Remove this form ID from the queue.
4259 s.importQueue = jQuery.grep( s.importQueue, function( value ) {
4260 return value != formID;
4261 } );
4262 s.imported++;
4263
4264 if ( s.importQueue.length === 0 ) {
4265 $processSettings.find( '.process-count' ).hide();
4266 $processSettings.find( '.forms-completed' ).text( s.imported );
4267 $processSettings.find( '.process-completed' ).show();
4268 } else {
4269 // Import next form in the queue.
4270 $processSettings.find( '.form-current' ).text( s.imported + 1 );
4271 importForm();
4272 }
4273 }
4274 } );
4275 }
4276
4277 function validateExport( e ) {
4278 /*jshint validthis:true */
4279 e.preventDefault();
4280
4281 var s = false;
4282 var $exportForms = jQuery( 'input[name="frm_export_forms[]"]' );
4283
4284 if ( ! jQuery( 'input[name="frm_export_forms[]"]:checked' ).val() ) {
4285 $exportForms.closest( '.frm-table-box' ).addClass( 'frm_blank_field' );
4286 s = 'stop';
4287 }
4288
4289 var $exportType = jQuery( 'input[name="type[]"]' );
4290 if ( ! jQuery( 'input[name="type[]"]:checked' ).val() && $exportType.attr( 'type' ) === 'checkbox' ) {
4291 $exportType.closest( 'p' ).addClass( 'frm_blank_field' );
4292 s = 'stop';
4293 }
4294
4295 if ( s === 'stop' ) {
4296 return false;
4297 }
4298
4299 e.stopPropagation();
4300 this.submit();
4301 }
4302
4303 function removeExportError() {
4304 /*jshint validthis:true */
4305 var t = jQuery( this ).closest( '.frm_blank_field' );
4306 if ( typeof(t) === 'undefined' ) {
4307 return;
4308 }
4309
4310 var $thisName = this.name;
4311 if ( $thisName === 'type[]' && jQuery( 'input[name="type[]"]:checked' ).val() ) {
4312 t.removeClass( 'frm_blank_field' );
4313 } else if ( $thisName === 'frm_export_forms[]' && jQuery( this ).val() ) {
4314 t.removeClass( 'frm_blank_field' );
4315 }
4316
4317 }
4318
4319 function checkCSVExtension() {
4320 /*jshint validthis:true */
4321 var f = jQuery( this ).val();
4322 var re = /\.csv$/i;
4323 if ( f.match( re ) !== null ) {
4324 jQuery( '.show_csv' ).fadeIn();
4325 } else {
4326 jQuery( '.show_csv' ).fadeOut();
4327 }
4328 }
4329
4330 function checkExportTypes() {
4331 /*jshint validthis:true */
4332 var $dropdown = jQuery( this );
4333 var $selected = $dropdown.find( ':selected' );
4334 var s = $selected.data( 'support' );
4335
4336 var multiple = s.indexOf( '|' );
4337 jQuery( 'input[name="type[]"]' ).each( function() {
4338 this.checked = false;
4339 if ( s.indexOf( this.value ) >= 0 ) {
4340 this.disabled = false;
4341 if ( multiple == -1 ) {
4342 this.checked = true;
4343 }
4344 } else {
4345 this.disabled = true;
4346 }
4347 } );
4348
4349 if ( $dropdown.val() === 'csv' ) {
4350 jQuery( '.csv_opts' ).show();
4351 jQuery( '.xml_opts' ).hide();
4352 } else {
4353 jQuery( '.csv_opts' ).hide();
4354 jQuery( '.xml_opts' ).show();
4355 }
4356
4357 var c = $selected.data( 'count' );
4358 var exportField = jQuery( 'input[name="frm_export_forms[]"]' );
4359 if ( c === 'single' ) {
4360 exportField.prop( 'multiple', false );
4361 exportField.removeAttr( 'checked' );
4362 } else {
4363 exportField.prop( 'multiple', true );
4364 exportField.removeAttr( 'disabled' );
4365 }
4366 }
4367
4368 function preventMultipleExport() {
4369 var type = jQuery( 'select[name=format]' ),
4370 selected = type.find( ':selected' ),
4371 count = selected.data( 'count' ),
4372 exportField = jQuery( 'input[name="frm_export_forms[]"]' );
4373
4374 if ( count === 'single' ) {
4375 // Disable all other fields to prevent multiple selections.
4376 if ( this.checked ) {
4377 exportField.attr( 'disabled', true );
4378 this.removeAttribute( 'disabled' );
4379 } else {
4380 exportField.removeAttr( 'disabled' );
4381 }
4382 } else {
4383 exportField.removeAttr( 'disabled' );
4384 }
4385 }
4386
4387 function initiateMultiselect() {
4388 jQuery( '.frm_multiselect' ).multiselect( {
4389 templates: {ul: '<ul class="multiselect-container frm-dropdown-menu"></ul>'},
4390 buttonContainer: '<div class="btn-group frm-btn-group dropdown" />',
4391 nonSelectedText: frm_admin_js['default'],
4392 onDropdownShown: function( event ) {
4393 var action = jQuery( event.currentTarget.closest( '.frm_form_action_settings, #frm-show-fields' ) );
4394 if ( action.length ) {
4395 jQuery( '#wpcontent' ).click( function() {
4396 if ( jQuery( '.multiselect-container.frm-dropdown-menu' ).is( ':visible' ) ) {
4397 jQuery( event.currentTarget ).removeClass( 'open' );
4398 }
4399 } );
4400 }
4401 }
4402 } );
4403 }
4404
4405 /* Addons page */
4406 function activateAddon( e ) {
4407 e.preventDefault();
4408 installOrActivate( this, 'frm_activate_addon' );
4409 }
4410
4411 function installAddon( e ) {
4412 e.preventDefault();
4413 installOrActivate( this, 'frm_install_addon' );
4414 }
4415
4416 function installOrActivate( clicked, action ) {
4417 // Remove any leftover error messages, output an icon and get the plugin basename that needs to be activated.
4418 jQuery( '.frm-addon-error' ).remove();
4419 var button = jQuery( clicked );
4420 var plugin = button.attr( 'rel' );
4421 var el = button.parent();
4422 var message = el.parent().find( '.addon-status-label' );
4423
4424 button.addClass('frm_loading_button');
4425
4426 // Process the Ajax to perform the activation.
4427 jQuery.ajax( {
4428 url: ajaxurl,
4429 type: 'POST',
4430 async: true,
4431 cache: false,
4432 dataType: 'json',
4433 data: {
4434 action: action,
4435 nonce: frmGlobal.nonce,
4436 plugin: plugin
4437 },
4438 success: function( response ) {
4439 // If there is a WP Error instance, output it here and quit the script.
4440 if ( response.error ) {
4441 addonError( response, el, button );
4442 return;
4443 }
4444
4445 // If we need more credentials, output the form sent back to us.
4446 if ( response.form ) {
4447 // Display the form to gather the users credentials.
4448
4449 button.append( '<div class="frm-addon-error frm_error_style">' + response.form + '</div>' );
4450 loader.hide();
4451
4452 // Add a disabled attribute the install button if the creds are needed.
4453 button.attr( 'disabled', true );
4454
4455 el.on( 'click', '#upgrade', 'installAddonWithCreds' );
4456
4457 // No need to move further if we need to enter our creds.
4458 return;
4459 }
4460
4461 afterAddonInstall( response, button, message, el );
4462 },
4463 error: function(xhr, textStatus, e) {
4464 button.removeClass('frm_loading_button');
4465 }
4466 } );
4467 }
4468
4469 function installAddonWithCreds( e ) {
4470 // Prevent the default action, let the user know we are attempting to install again and go with it.
4471 e.preventDefault();
4472
4473 // Now let's make another Ajax request once the user has submitted their credentials.
4474 var proceed = jQuery( this );
4475 var el = proceed.parent().parent();
4476
4477 proceed.addClass( 'frm_loading_button' );
4478
4479 jQuery.ajax( {
4480 url: ajaxurl,
4481 type: 'POST',
4482 async: true,
4483 cache: false,
4484 dataType: 'json',
4485 data: {
4486 action: 'frm_install_addon',
4487 nonce: frm_admin_js.nonce,
4488 plugin: plugin,
4489 hostname: el.find( '#hostname' ).val(),
4490 username: el.find( '#username' ).val(),
4491 password: el.find( '#password' ).val()
4492 },
4493 success: function( response ) {
4494 // If there is a WP Error instance, output it here and quit the script.
4495 if ( response.error ) {
4496 addonError( response, el, button );
4497 return;
4498 }
4499
4500 if ( response.form ) {
4501 loader.hide();
4502 jQuery( '.frm-inline-error' ).remove();
4503 //proceed.val(monsterinsights_admin.proceed);
4504 //proceed.after('<span class="frm-inline-error">' + monsterinsights_admin.connect_error + '</span>');
4505 return;
4506 }
4507
4508 afterAddonInstall( response, proceed, message, el );
4509 },
4510 error: function(xhr, textStatus ,e) {
4511 proceed.removeClass( 'frm_loading_button' );
4512 }
4513 } );
4514 }
4515
4516 function afterAddonInstall( response, button, message, el ) {
4517 // The Ajax request was successful, so let's update the output.
4518 button.css({ 'opacity': '0' });
4519 message.text( frm_admin_js.active );
4520 jQuery( '#frm-oneclick' ).hide();
4521 jQuery( '#frm-addon-status' ).text( response ).show();
4522 jQuery( '#frm_upgrade_modal h2' ).hide();
4523 jQuery( '#frm_upgrade_modal .frm_lock_icon' ).addClass( 'frm_lock_open_icon' );
4524 jQuery( '#frm_upgrade_modal .frm_lock_icon use' ).attr( 'xlink:href', '#frm_lock_open_icon' );
4525
4526 // Proceed with CSS changes
4527 el.parent().removeClass('frm-addon-not-installed frm-addon-installed').addClass('frm-addon-active');
4528 button.removeClass('frm_loading_button');
4529 }
4530
4531 function addonError( response, el, button ) {
4532 el.append( '<div class="frm-addon-error frm_error_style"><p><strong>' + response.error + '</strong></p></div>' );
4533 button.removeClass( 'frm_loading_button' );
4534 jQuery( '.frm-addon-error' ).delay( 4000 ).fadeOut();
4535 }
4536
4537 /* Templates */
4538
4539 function initNewFormModal() {
4540 var $info = initModal( '#frm_form_modal', '650px' );
4541 if ( $info === false ) {
4542 return;
4543 }
4544
4545 jQuery( '.frm-new-form-button' ).click( function( event ) {
4546 event.preventDefault();
4547 $info.dialog( 'open' );
4548 } );
4549
4550 jQuery( document ).on( 'submit', '#frm-new-form', installTemplate );
4551 }
4552
4553 function initTemplateModal() {
4554 var $preview = initModal( '#frm_preview_template_modal', '700px' );
4555 if ( $preview !== false ) {
4556 jQuery( '.frm-preview-template' ).click( function( event ) {
4557 event.preventDefault();
4558 var link = this.attributes.rel.value,
4559 cont = document.getElementById( 'frm-preview-block' );
4560
4561 if ( link.indexOf( ajaxurl ) > -1 ) {
4562 var iframe = document.createElement( 'iframe' );
4563 iframe.src = link;
4564 iframe.height = '400';
4565 iframe.width = '100%';
4566 cont.innerHTML = '';
4567 cont.appendChild( iframe );
4568 } else {
4569 frmApiPreview( cont, link );
4570 }
4571 $preview.dialog( 'open' );
4572 } );
4573 }
4574
4575 var $info = initModal( '#frm_template_modal', '650px' );
4576 if ( $info === false ) {
4577 return;
4578 }
4579
4580 jQuery( '.frm-install-template' ).click( function( event ) {
4581 event.preventDefault();
4582 var oldName = jQuery( this ).closest( 'li, td' ).find( 'h3' ).html(),
4583 nameLabel = document.getElementById( 'frm_new_name' ),
4584 descLabel = document.getElementById( 'frm_new_desc' );
4585
4586 document.getElementById( 'frm_template_name' ).value = oldName;
4587 document.getElementById( 'frm_link' ).value = this.attributes.rel.value;
4588 document.getElementById( 'frm_action_type' ).value = 'frm_install_template';
4589 nameLabel.innerHTML = nameLabel.getAttribute( 'data-form' );
4590 descLabel.innerHTML = descLabel.getAttribute( 'data-form' );
4591 $info.dialog( 'open' );
4592 } );
4593
4594 jQuery( '.frm-build-template' ).click( function( event ) {
4595 event.preventDefault();
4596 var nameLabel = document.getElementById( 'frm_new_name' ),
4597 descLabel = document.getElementById( 'frm_new_desc' );
4598
4599 nameLabel.innerHTML = nameLabel.getAttribute( 'data-template' );
4600 descLabel.innerHTML = descLabel.getAttribute( 'data-template' );
4601 document.getElementById( 'frm_template_name' ).value = this.getAttribute( 'data-fullname' );
4602 document.getElementById( 'frm_link' ).value = this.getAttribute( 'data-formid' );
4603 document.getElementById( 'frm_action_type' ).value = 'frm_build_template';
4604 $info.dialog( 'open' );
4605 } );
4606
4607 jQuery( '.frm-new-form-button' ).click( function( event ) {
4608 event.preventDefault();
4609 var nameLabel = document.getElementById( 'frm_new_name' ),
4610 descLabel = document.getElementById( 'frm_new_desc' );
4611
4612 nameLabel.innerHTML = nameLabel.getAttribute( 'data-form' );
4613 descLabel.innerHTML = descLabel.getAttribute( 'data-form' );
4614 document.getElementById( 'frm_template_name' ).value = '';
4615 document.getElementById( 'frm_link' ).value = '';
4616 document.getElementById( 'frm_action_type' ).value = 'frm_install_form';
4617 $info.dialog( 'open' );
4618 } );
4619
4620 jQuery( document ).on( 'submit', '#frm-new-template', installTemplate );
4621 }
4622
4623 function initSelectionAutocomplete() {
4624 if ( jQuery.fn.autocomplete ) {
4625 initAutocomplete( 'page' );
4626 initAutocomplete( 'user' );
4627 }
4628 }
4629
4630 function initAutocomplete( type ) {
4631 if ( jQuery( '.frm-' + type + '-search' ).length < 1 ) {
4632 return;
4633 }
4634
4635 jQuery( '.frm-' + type + '-search' ).autocomplete( {
4636 delay: 100,
4637 minLength: 0,
4638 source: ajaxurl + '?action=frm_' + type + '_search&nonce=' + frmGlobal.nonce,
4639 select: autoCompleteSelectFromResults,
4640 focus: autoCompleteFocus,
4641 position: {
4642 my: 'left top',
4643 at: 'left bottom',
4644 collision: 'flip'
4645 },
4646 response: function( event, ui ) {
4647 if ( !ui.content.length ) {
4648 var noResult = { value: '', label: frm_admin_js.no_items_found };
4649 ui.content.push( noResult );
4650 }
4651 },
4652 create: function( event, ui ) {
4653 var $container = jQuery( this ).parent();
4654
4655 if ( $container.length == 0 ) {
4656 $container = 'body';
4657 }
4658
4659 jQuery( this ).autocomplete( 'option', 'appendTo', $container );
4660 }
4661 } )
4662 .focus( function(){
4663 // Show options on click to make it work more like a dropdown.
4664 if ( this.value === '' || this.nextElementSibling.value < 1 ) {
4665 jQuery( this ).autocomplete( 'search', this.value );
4666 }
4667 } );
4668 }
4669
4670 /**
4671 * Prevent the value from changing when using keyboard to scroll.
4672 */
4673 function autoCompleteFocus( e, ui ) {
4674 return false;
4675 }
4676
4677 function autoCompleteSelectFromResults( e, ui ) {
4678 e.preventDefault();
4679
4680 if ( ui.item.value === '' ) {
4681 this.value = '';
4682 } else {
4683 this.value = ui.item.label;
4684 }
4685
4686 this.nextElementSibling.value = ui.item.value;
4687 }
4688
4689 function frmApiPreview( cont, link ) {
4690 cont.innerHTML = '<div class="frm-wait"></div>';
4691 jQuery.ajax( {
4692 dataType: 'json',
4693 url: link,
4694 success: function( json ) {
4695 var form = json.renderedHtml;
4696 form = form.replace( /<script\b[^<]*(js\/jquery\/jquery)[^<]*><\/script>/gi, '' );
4697 form = form.replace( /<link\b[^>]*(jquery-ui.min.css)[^>]*>/gi, '' );
4698 form = form.replace( ' frm_logic_form ', ' ' );
4699 form = form.replace( '<form ', '<form onsubmit="event.preventDefault();" ' );
4700 cont.innerHTML = '<div class="frm-wait" id="frm-remove-me"></div><div class="frm-fade" id="frm-show-me">' +
4701 form + '</div>';
4702 setTimeout( function(){
4703 document.getElementById( 'frm-remove-me' ).style.display = 'none';
4704 document.getElementById( 'frm-show-me' ).style.opacity = '1';
4705 }, 300 );
4706 }
4707 } );
4708 }
4709
4710 function installTemplate( e ) {
4711 /*jshint validthis:true */
4712 var action = this.elements['type'].value,
4713 button = this.querySelector( 'button' );
4714 e.preventDefault();
4715 button.classList.add( 'frm_loading_button' );
4716 installNewForm( this, action );
4717 }
4718
4719 function installNewForm( form, action ) {
4720 var data,
4721 formName = form.elements['template_name'].value,
4722 formDesc = form.elements['template_desc'].value,
4723 link = form.elements['link'].value;
4724
4725 data = {
4726 action: action,
4727 xml: link,
4728 name: formName,
4729 desc: formDesc,
4730 nonce: frmGlobal.nonce
4731 };
4732 postAjax( data, function( response ) {
4733 if ( typeof response.redirect !== 'undefined' ) {
4734 window.location = response.redirect;
4735 } else {
4736 jQuery( '.spinner' ).css( 'visibility', 'hidden' );
4737 // TODO: show response.message
4738 }
4739 } );
4740 }
4741
4742 function trashTemplate( e ) {
4743 /*jshint validthis:true */
4744 var id = this.getAttribute( 'data-id' );
4745 e.preventDefault();
4746
4747 data = {
4748 action: 'frm_forms_trash',
4749 id: id,
4750 nonce: frmGlobal.nonce
4751 };
4752 postAjax( data, function() {
4753 var card = document.getElementById( 'frm-template-custom-' + id );
4754 fadeOut( card, function() {
4755 card.parentNode.removeChild( card );
4756 } );
4757 } );
4758 }
4759
4760 function searchContent() {
4761 /*jshint validthis:true */
4762 var i,
4763 regEx = false,
4764 searchText = this.value.toLowerCase(),
4765 toSearch = this.getAttribute( 'data-tosearch' ),
4766 items = document.getElementsByClassName( toSearch );
4767
4768 if ( this.tagName === 'SELECT' ) {
4769 searchText = selectedOptions( this );
4770 searchText = searchText.join('|').toLowerCase();
4771 regEx = true;
4772 }
4773
4774 if ( toSearch === 'frm-action' && searchText !== '' ) {
4775 var addons = document.getElementById( 'frm_email_addon_menu' ).classList;
4776 addons.remove( 'frm-all-actions' );
4777 addons.add( 'frm-limited-actions' );
4778 }
4779
4780 for ( i = 0; i < items.length; i++ ) {
4781 var innerText = items[i].innerText.toLowerCase();
4782 if ( searchText === '' ) {
4783 items[i].classList.remove( 'frm_hidden' );
4784 items[i].classList.remove( 'frm-search-result' );
4785 } else if ( ( regEx && new RegExp( searchText ).test( innerText ) ) || innerText.indexOf( searchText ) >= 0 ) {
4786 items[i].classList.remove( 'frm_hidden' );
4787 items[i].classList.add( 'frm-search-result' );
4788 } else {
4789 items[i].classList.add( 'frm_hidden' );
4790 items[i].classList.remove( 'frm-search-result' );
4791 }
4792 }
4793 }
4794
4795 function stopPropagation( e ) {
4796 e.stopPropagation();
4797 }
4798
4799 /* Helpers */
4800
4801 function selectedOptions( select ) {
4802 var opt,
4803 result = [],
4804 options = select && select.options;
4805
4806 for ( var i = 0, iLen = options.length; i < iLen; i++ ) {
4807 opt = options[i];
4808
4809 if ( opt.selected ) {
4810 result.push( opt.value );
4811 }
4812 }
4813 return result;
4814 }
4815
4816 function triggerEvent( element, event ) {
4817 var evt = document.createEvent( 'HTMLEvents' );
4818 evt.initEvent( event, false, true );
4819 element.dispatchEvent( evt );
4820 }
4821
4822 function postAjax( data, success ) {
4823 var xmlHttp = new XMLHttpRequest();
4824 var params = typeof data == 'string' ? data : Object.keys( data ).map(
4825 function( k ) {
4826 return encodeURIComponent( k ) + '=' + encodeURIComponent( data[k] );
4827 }
4828 ).join( '&' );
4829
4830 xmlHttp.open( 'post', ajaxurl, true );
4831 xmlHttp.onreadystatechange = function() {
4832 if ( xmlHttp.readyState > 3 && xmlHttp.status == 200 ) {
4833 var response = xmlHttp.responseText;
4834 if ( response !== '' ) {
4835 response = JSON.parse( response );
4836 }
4837 success( response );
4838 }
4839 };
4840 xmlHttp.setRequestHeader( 'X-Requested-With', 'XMLHttpRequest' );
4841 xmlHttp.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );
4842 xmlHttp.send( params );
4843 return xmlHttp;
4844 }
4845
4846 function fadeOut( element, success ) {
4847 element.classList.add( 'frm-fade' );
4848 setTimeout( success, 1000 );
4849 }
4850
4851 function initModal( id, width ) {
4852 var $info = jQuery( id );
4853 if ( $info.length < 1 ) {
4854 return false;
4855 }
4856
4857 if ( typeof width === 'undefined' ) {
4858 width = '550px';
4859 }
4860 $info.dialog( {
4861 dialogClass: 'frm-dialog',
4862 modal: true,
4863 autoOpen: false,
4864 closeOnEscape: true,
4865 width: width,
4866 resizable: false,
4867 draggable: false,
4868 open: function( event ) {
4869 jQuery( '.ui-dialog-titlebar' ).addClass( 'frm_hidden' ).removeClass( 'ui-helper-clearfix' );
4870 jQuery( '#wpwrap' ).addClass( 'frm_overlay' );
4871 jQuery( '.frm-dialog' ).removeClass( 'ui-widget ui-widget-content ui-corner-all' );
4872 jQuery( id ).removeClass( 'ui-dialog-content ui-widget-content' );
4873
4874 // close dialog by clicking the overlay behind it
4875 jQuery( '.ui-widget-overlay, a.dismiss' ).bind( 'click', function() {
4876 $info.dialog( 'close' );
4877 } );
4878 },
4879 close: function() {
4880 jQuery( '#wpwrap' ).removeClass( 'frm_overlay' );
4881 jQuery( '.spinner' ).css( 'visibility', 'hidden' );
4882 }
4883 } );
4884
4885 return $info;
4886 }
4887
4888 function toggle( cname, id ) {
4889 if ( id === '#' ) {
4890 var cont = document.getElementById( cname );
4891 var hidden = cont.style.display;
4892 if ( hidden === 'none' ) {
4893 cont.style.display = 'block';
4894 } else {
4895 cont.style.display = 'none';
4896 }
4897 } else {
4898 var vis = cname.is( ':visible' );
4899 if ( vis ) {
4900 cname.hide();
4901 } else {
4902 cname.show();
4903 }
4904 }
4905 }
4906
4907 function removeWPUnload() {
4908 window.onbeforeunload = null;
4909 var w = jQuery( window );
4910 w.off( 'beforeunload.widgets' );
4911 w.off( 'beforeunload.edit-post' );
4912 }
4913
4914 function maybeChangeEmbedFormMsg() {
4915 var fieldId = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
4916 var fieldItem = document.getElementById( 'frm_field_id_' + fieldId );
4917 if ( null === fieldItem || 'form' !== fieldItem.dataset['type'] ) {
4918 return;
4919 }
4920
4921 fieldItem = jQuery( fieldItem );
4922
4923 if ( this.options[ this.selectedIndex ].value ) {
4924 fieldItem.find( '.frm-not-set' )[0].classList.add( 'frm_hidden' );
4925 var embedMsg = fieldItem.find( '.frm-embed-message' );
4926 embedMsg.html( embedMsg.data( 'embedmsg' ) + this.options[ this.selectedIndex ].text );
4927 fieldItem.find( '.frm-embed-field-placeholder' )[0].classList.remove( 'frm_hidden' );
4928 } else {
4929 fieldItem.find( '.frm-not-set' )[0].classList.remove( 'frm_hidden' );
4930 fieldItem.find( '.frm-embed-field-placeholder' )[0].classList.add( 'frm_hidden' );
4931 }
4932 }
4933
4934 return {
4935 init: function() {
4936 s = {};
4937
4938 // Bootstrap dropdown button
4939 jQuery( '.wp-admin' ).click( function( e ) {
4940 var t = jQuery( e.target );
4941 var $openDrop = jQuery( '.dropdown.open' );
4942 if ( $openDrop.length && ! t.hasClass( 'dropdown' ) && !t.closest( '.dropdown' ).length ) {
4943 $openDrop.removeClass( 'open' );
4944 }
4945 } );
4946 jQuery( '#frm_bs_dropdown:not(.open) a' ).click( focusSearchBox );
4947
4948 if ( typeof this_form_id === 'undefined' ) {
4949 this_form_id = jQuery( document.getElementById( 'form_id' ) ).val();
4950 }
4951
4952 if ( $newFields.length > 0 ) {
4953 // only load this on the form builder page
4954 frmAdminBuild.buildInit();
4955 } else if ( document.getElementById( 'frm_notification_settings' ) !== null ) {
4956 // only load on form settings page
4957 frmAdminBuild.settingsInit();
4958 } else if ( document.getElementById( 'frm_styling_form' ) !== null ) {
4959 // load styling settings js
4960 frmAdminBuild.styleInit();
4961 } else if ( document.getElementById( 'frm_custom_css_box' ) !== null ) {
4962 // load styling settings js
4963 frmAdminBuild.customCSSInit();
4964 } else if ( document.getElementById( 'form_global_settings' ) !== null ) {
4965 // global settings page
4966 frmAdminBuild.globalSettingsInit();
4967 } else if ( document.getElementById( 'frm_export_xml' ) !== null ) {
4968 // import/export page
4969 frmAdminBuild.exportInit();
4970 } else if ( document.getElementById( 'frm-templates-page' ) !== null ) {
4971 frmAdminBuild.templateInit();
4972 } else if ( document.getElementById( 'frm_dyncontent' ) !== null ) {
4973 // only load on views settings page
4974 frmAdminBuild.viewInit();
4975 } else {
4976 // New form selection page
4977 initNewFormModal();
4978 initSelectionAutocomplete();
4979
4980 jQuery( '[data-frmprint]' ).click( function() {
4981 window.print();
4982 return false;
4983 } );
4984 }
4985
4986 var $advInfo = jQuery( document.getElementById( 'frm_adv_info' ) );
4987 if ( $advInfo.length > 0 || jQuery( '.frm_field_list' ).length > 0 ) {
4988 // only load on the form, form settings, and view settings pages
4989 frmAdminBuild.panelInit();
4990 }
4991
4992 loadTooltips();
4993 initUpgradeModal();
4994
4995 // used on build, form settings, and view settings
4996 var $shortCodeDiv = jQuery( document.getElementById( 'frm_shortcodediv' ) );
4997 if ( $shortCodeDiv.length > 0 ) {
4998 jQuery( 'a.edit-frm_shortcode' ).click( function() {
4999 if ( $shortCodeDiv.is( ':hidden' ) ) {
5000 $shortCodeDiv.slideDown( 'fast' );
5001 this.style.display = 'none';
5002 }
5003 return false;
5004 } );
5005
5006 jQuery( '.cancel-frm_shortcode', '#frm_shortcodediv' ).click( function() {
5007 $shortCodeDiv.slideUp( 'fast' );
5008 $shortCodeDiv.siblings( 'a.edit-frm_shortcode' ).show();
5009 return false;
5010 } );
5011 }
5012
5013 // tabs
5014 jQuery( document ).on( 'click', '#frm-nav-tabs a', clickNewTab );
5015 jQuery( '.post-type-frm_display .frm-nav-tabs a, .frm-category-tabs a, #frm-templates-page .frm-nav-tabs a' ).click( function() {
5016 if ( ! this.classList.contains( 'frm_noallow' ) ) {
5017 clickTab( this );
5018 return false;
5019 }
5020 } );
5021 clickTab( jQuery( '.starttab a' ), 'auto' );
5022
5023 // submit the search form with dropdown
5024 jQuery( '#frm-fid-search-menu a' ).click( function() {
5025 var val = this.id.replace( 'fid-', '' );
5026 jQuery( 'select[name="fid"]' ).val( val );
5027 jQuery( document.getElementById( 'posts-filter' ) ).submit();
5028 return false;
5029 } );
5030
5031 jQuery( '.frm_select_box' ).on( 'click focus', function() {
5032 this.select();
5033 } );
5034
5035 jQuery( document ).on( 'input search change', '.frm-auto-search', searchContent );
5036 jQuery( document ).on( 'focusin click', '.frm-auto-search', stopPropagation );
5037 var autoSearch = jQuery( '.frm-auto-search' );
5038 if ( autoSearch.val() !== '' ) {
5039 autoSearch.keyup();
5040 }
5041
5042 // Initialize Formidable Connection.
5043 FrmFormsConnect.init();
5044
5045 jQuery( document ).on( 'click', '.frm-install-addon', installAddon );
5046 jQuery( document ).on( 'click', '.frm-activate-addon', activateAddon );
5047
5048 // prevent annoying confirmation message from WordPress
5049 jQuery( 'button, input[type=submit]' ).on( 'click', removeWPUnload );
5050 },
5051
5052 buildInit: function() {
5053 if ( jQuery( '.frm_field_loading' ).length ) {
5054 var load_field_id = jQuery( '.frm_field_loading' ).first().attr( 'id' );
5055 loadFields( load_field_id );
5056 }
5057
5058 setupSortable( 'ul.frm_sorting' );
5059
5060 // Show message if section has no fields inside
5061 var frm_sorting = jQuery( '.start_divider.frm_sorting' );
5062 for ( i = 0; i < frm_sorting.length; i++ ) {
5063 if ( frm_sorting[i].children.length < 2 ) {
5064 jQuery( frm_sorting[i] ).parent().children( '.frm_no_section_fields' ).addClass( 'frm_block' );
5065 }
5066 }
5067
5068 jQuery( '.field_type_list > li:not(.frm_noallow)' ).draggable( {
5069 connectToSortable: '#frm-show-fields',
5070 helper: 'clone',
5071 revert: 'invalid',
5072 delay: 10,
5073 cancel: '.frm-dropdown-menu'
5074 } );
5075 jQuery( 'ul.field_type_list, .field_type_list li, ul.frm_code_list, .frm_code_list li, .frm_code_list li a, #frm_adv_info #category-tabs li, #frm_adv_info #category-tabs li a' ).disableSelection();
5076
5077 jQuery( '.frm_submit_ajax' ).click( submitBuild );
5078 jQuery( '.frm_submit_no_ajax' ).click( submitNoAjax );
5079
5080 jQuery( 'a.edit-form-status' ).click( slideDown );
5081 jQuery( '.cancel-form-status' ).click( slideUp );
5082 jQuery( '.save-form-status' ).click( function() {
5083 var newStatus = jQuery( document.getElementById( 'form_change_status' ) ).val();
5084 jQuery( 'input[name="new_status"]' ).val( newStatus );
5085 jQuery( document.getElementById( 'form-status-display' ) ).html( newStatus );
5086 jQuery( '.cancel-form-status' ).click();
5087 return false;
5088 } );
5089
5090 jQuery( '.frm_form_builder form:first' ).submit( function() {
5091 jQuery( '.inplace_field' ).blur();
5092 } );
5093
5094 initiateMultiselect();
5095 renumberPageBreaks();
5096
5097 var $builderForm = jQuery( builderForm );
5098 var builderArea = document.getElementById( 'frm_form_editor_container' );
5099 $builderForm.on( 'click', '.frm_add_logic_row', addFieldLogicRow );
5100 $builderForm.on( 'click', '.frm_add_watch_lookup_row', addWatchLookupRow );
5101 $builderForm.on( 'change', '.frm_get_values_form', updateGetValueFieldSelection );
5102 $builderForm.on( 'change', '.frm_logic_field_opts', getFieldValues );
5103 $builderForm.on( 'change', '.scale_maxnum, .scale_minnum', setScaleValues );
5104 $builderForm.on( 'change', '.radio_maxnum', setStarValues );
5105
5106 jQuery( document.getElementById( 'frm-insert-fields' ) ).on( 'click', '.frm_add_field', addFieldClick );
5107 $newFields.on( 'click', '.frm_clone_field', duplicateField );
5108 $builderForm.on( 'blur', 'input[id^="frm_calc"]', checkCalculationCreatedByUser );
5109 $builderForm.on( 'change', 'input.frm_format_opt', toggleInvalidMsg );
5110 $builderForm.on( 'change click', '[data-changeme]', liveChanges );
5111 $builderForm.on( 'click', 'input.frm_req_field', markRequired );
5112 $builderForm.on( 'click', '.frm_mark_unique', markUnique );
5113
5114 $builderForm.on( 'change', '.frm_repeat_format', toggleRepeatButtons );
5115 $builderForm.on( 'change', '.frm_repeat_limit', checkRepeatLimit );
5116 $builderForm.on( 'change', '.frm_js_checkbox_limit', checkCheckboxSelectionsLimit );
5117 $builderForm.on( 'input', 'input[name^="field_options[add_label_"]', function() {
5118 updateRepeatText( this, 'add' );
5119 } );
5120 $builderForm.on( 'input', 'input[name^="field_options[remove_label_"]', function() {
5121 updateRepeatText( this, 'remove' );
5122 } );
5123 $builderForm.on( 'change', 'select[name^="field_options[data_type_"]', maybeClearWatchFields );
5124 jQuery( builderArea ).on( 'click', '.frm-collapse-page', maybeCollapsePage );
5125 jQuery( builderArea ).on( 'click', '.frm-collapse-section', maybeCollapseSection );
5126 $builderForm.on( 'click', '.frm-single-settings h3', maybeCollapseSettings );
5127
5128 $builderForm.on( 'click', '.frm_toggle_sep_values', toggleSepValues );
5129 $builderForm.on( 'click', '.frm_multiselect_opt', toggleMultiselect );
5130 $newFields.on( 'mousedown', 'input, textarea, select', stopFieldFocus );
5131 $newFields.on( 'click', 'input[type=radio], input[type=checkbox]', stopFieldFocus );
5132 $newFields.on( 'click', '.frm_delete_field', clickDeleteField );
5133 $builderForm.on( 'click', '.frm_single_option a[data-removeid]', deleteFieldOption );
5134 $builderForm.on( 'mousedown', '.frm_single_option input[type=radio]', maybeUncheckRadio );
5135 $builderForm.on( 'focusin', '.frm_single_option input[type=text]', maybeClearOptText );
5136 $builderForm.on( 'click', '.frm_add_opt', addFieldOption );
5137 $builderForm.on( 'change', '.frm_single_option input', resetOptOnChange );
5138 $builderForm.on( 'change', '.frm_toggle_mult_sel', toggleMultSel );
5139 $builderForm.on( 'focusin', '.frm_classes', showBuilderModal );
5140
5141 $newFields.on( 'click', '.frm_primary_label', clickLabel );
5142 $newFields.on( 'click', '.frm_description', clickDescription );
5143 $newFields.on( 'click', 'li.ui-state-default', clickVis );
5144 $newFields.on( 'dblclick', 'li.ui-state-default', openAdvanced );
5145 $builderForm.on( 'change', '.frm_tax_form_select', toggleFormTax );
5146 $builderForm.on( 'change', 'select.conf_field', addConf );
5147
5148 $builderForm.on( 'change', '.frm_get_field_selection', getFieldSelection );
5149
5150 $builderForm.on( 'click', '.frm-show-inline-modal', maybeShowInlineModal );
5151
5152 $builderForm.on( 'click', '.frm-inline-modal .dismiss', dismissInlineModal );
5153 jQuery( document ).on( 'change', '[data-frmchange]', changeInputtedValue );
5154
5155 $builderForm.on( 'change', '.frm_include_extras_field', rePopCalcFieldsForSummary );
5156 $builderForm.on( 'change', 'select[name^="field_options[form_select_"]', maybeChangeEmbedFormMsg );
5157
5158 initBulkOptionsOverlay();
5159 hideEmptyEle();
5160 maybeDisableAddSummaryBtn();
5161 },
5162
5163 settingsInit: function() {
5164 var $formActions = jQuery( document.getElementById( 'frm_notification_settings' ) );
5165 //BCC, CC, and Reply To button functionality
5166 $formActions.on( 'click', '.frm_email_buttons', showEmailRow );
5167 $formActions.on( 'click', '.frm_remove_field', hideEmailRow );
5168 $formActions.on( 'change', '.frm_tax_selector', changePosttaxRow );
5169 $formActions.on( 'change', 'select.frm_single_post_field', checkDupPost );
5170 $formActions.on( 'change', 'select.frm_toggle_post_content', togglePostContent );
5171 $formActions.on( 'change', 'select.frm_dyncontent_opt', fillDyncontent );
5172 $formActions.on( 'change', '.frm_post_type', switchPostType );
5173 $formActions.on( 'click', '.frm_add_postmeta_row', addPostmetaRow );
5174 $formActions.on( 'click', '.frm_add_posttax_row', addPosttaxRow );
5175 $formActions.on( 'click', '.frm_toggle_cf_opts', toggleCfOpts );
5176 $formActions.on( 'click', '.frm_duplicate_form_action', copyFormAction );
5177 jQuery( 'select[data-toggleclass], input[data-toggleclass]' ).change( toggleFormOpts );
5178 jQuery( '.frm_actions_list' ).on( 'click', '.frm_active_action', addFormAction );
5179 jQuery( '#frm-show-groups, #frm-hide-groups').click( toggleActionGroups );
5180 initiateMultiselect();
5181
5182 //set actions icons to inactive
5183 jQuery( 'ul.frm_actions_list li' ).each( function() {
5184 checkActiveAction( jQuery( this ).children( 'a' ).data( 'actiontype' ) );
5185
5186 // If the icon is a background image, don't add BG color.
5187 var icon = jQuery( this ).find( 'i' );
5188 if ( icon.css('background-image') !== 'none' ) {
5189 icon.addClass( 'frm-inverse' );
5190 }
5191 } );
5192
5193 jQuery( '.frm_submit_settings_btn' ).click( submitSettings );
5194
5195 var formSettings = jQuery( '.frm_form_settings' );
5196 formSettings.on( 'click', '.frm_add_form_logic', addFormLogicRow );
5197 formSettings.on( 'blur', '.frm_email_blur', formatEmailSetting );
5198
5199 formSettings.on( 'change', '#logic_link_submit', toggleSubmitLogic );
5200 formSettings.on( 'click', '.frm_add_submit_logic', addSubmitLogic );
5201 formSettings.on( 'change', '.frm_submit_logic_field_opts', addSubmitLogicOpts );
5202
5203
5204 // Close shortcode modal on click.
5205 formSettings.on( 'mouseup', '*:not(.frm-show-box)', function( e ) {
5206 e.stopPropagation();
5207 if ( e.target.classList.contains( 'frm-show-box' ) ) {
5208 return;
5209 }
5210 var sidebar = document.getElementById( 'frm_adv_info' ),
5211 isChild = jQuery( e.target ).closest( '#frm_adv_info' ).length > 0;
5212
5213 if ( sidebar.getAttribute( 'data-fills' ) === e.target.id && typeof e.target.id !== 'undefined' ) {
5214 return;
5215 }
5216
5217 if ( sidebar !== null && ! isChild && sidebar.display !== 'none' ) {
5218 hideShortcodes( sidebar );
5219 }
5220 } );
5221
5222 //Warning when user selects "Do not store entries ..."
5223 jQuery( document.getElementById( 'no_save' ) ).change( function() {
5224 if ( this.checked ) {
5225 if ( confirm( frm_admin_js.no_save_warning ) !== true ) {
5226 // Uncheck box if user hits "Cancel"
5227 jQuery( this ).attr( 'checked', false );
5228 }
5229 }
5230 } );
5231
5232 //Show/hide Messages header
5233 jQuery( '#editable, #edit_action, #save_draft, #success_action' ).change( function() {
5234 maybeShowFormMessages();
5235 } );
5236 jQuery( "select[name='options[success_action]'], select[name='options[edit_action]']" ).change( showSuccessOpt );
5237
5238 var $loggedIn = document.getElementById( 'logged_in' );
5239 jQuery( $loggedIn ).change( function() {
5240 if ( this.checked ) {
5241 frmFrontForm.visible( '.hide_logged_in' );
5242 } else {
5243 frmFrontForm.invisible( '.hide_logged_in' );
5244 }
5245 } );
5246
5247 var $cookieExp = jQuery( document.getElementById( 'frm_cookie_expiration' ) );
5248 jQuery( document.getElementById( 'frm_single_entry_type' ) ).change( function() {
5249 if ( this.value === 'cookie' ) {
5250 $cookieExp.fadeIn( 'slow' );
5251 } else {
5252 $cookieExp.fadeOut( 'slow' );
5253 }
5254 } );
5255
5256 var $singleEntry = document.getElementById( 'single_entry' );
5257 jQuery( $singleEntry ).change( function() {
5258 if ( this.checked ) {
5259 frmFrontForm.visible( '.hide_single_entry' );
5260 } else {
5261 frmFrontForm.invisible( '.hide_single_entry' );
5262 }
5263
5264 if ( this.checked && jQuery( document.getElementById( 'frm_single_entry_type' ) ).val() === 'cookie' ) {
5265 $cookieExp.fadeIn( 'slow' );
5266 } else {
5267 $cookieExp.fadeOut( 'slow' );
5268 }
5269 } );
5270
5271 jQuery( '.hide_save_draft' ).hide();
5272
5273 var $saveDraft = jQuery( document.getElementById( 'save_draft' ) );
5274 $saveDraft.change( function() {
5275 if ( this.checked ) {
5276 jQuery( '.hide_save_draft' ).fadeIn( 'slow' );
5277 } else {
5278 jQuery( '.hide_save_draft' ).fadeOut( 'slow' );
5279 }
5280 } );
5281 $saveDraft.change();
5282
5283 //If Allow editing is checked/unchecked
5284 var $editable = document.getElementById( 'editable' );
5285 jQuery( $editable ).change( function() {
5286 if ( this.checked ) {
5287 jQuery( '.hide_editable' ).fadeIn( 'slow' );
5288 jQuery( '#edit_action' ).change();
5289 } else {
5290 jQuery( '.hide_editable' ).fadeOut( 'slow' );
5291 jQuery( '.edit_action_message_box' ).fadeOut( 'slow' );//Hide On Update message box
5292 }
5293 } );
5294
5295 // Page Selection Autocomplete
5296 initSelectionAutocomplete();
5297 },
5298
5299 panelInit: function() {
5300 jQuery( '.frm_wrap, #postbox-container-1' ).on( 'click', '.frm_insert_code', insertCode );
5301 jQuery( document ).on( 'change', '.frm_insert_val', function() {
5302 insertFieldCode( jQuery( this ).data( 'target' ), jQuery( this ).val() );
5303 jQuery( this ).val( '' );
5304 } );
5305
5306 jQuery( document ).on( 'click change', '#frm-id-key-condition', resetLogicBuilder );
5307 jQuery( document ).on( 'keyup change', '.frm-build-logic', setLogicExample );
5308
5309 showInputIcon();
5310 jQuery( document ).on( 'frmElementAdded', function( event, parentEle ) {
5311 /* This is here for add-ons to trigger */
5312 showInputIcon( parentEle );
5313 });
5314 jQuery( document ).on( 'mousedown', '.frm-show-box', showShortcodes );
5315
5316 var settingsPage = document.getElementById( 'form_settings_page' ),
5317 viewPage = document.body.classList.contains( 'post-type-frm_display' ),
5318 htmlTab = document.getElementById( 'frm_html_tags_tab' ),
5319 insertFieldsTab = document.getElementById( 'frm_insert_fields_tab' );
5320
5321 if ( settingsPage !== null || viewPage ) {
5322 jQuery( document ).on( 'focusin', 'form input, form textarea', function( e ) {
5323 e.stopPropagation();
5324 maybeShowModal( this );
5325
5326 if ( jQuery( this ).is( ':not(:submit, input[type=button], .frm-search-input, input[type=checkbox])' ) ) {
5327 if ( jQuery( e.target ).closest( '#frm_adv_info' ).length ) {
5328 // Don't trigger for fields inside of the modal.
5329 return;
5330 }
5331
5332 if ( settingsPage !== null ) {
5333 /* form settings page */
5334 var htmlTab = jQuery( '#frm_html_tab' );
5335 if ( jQuery( this ).closest( '#html_settings' ).length > 0 ) {
5336 htmlTab.show();
5337 htmlTab.siblings().hide();
5338 jQuery( '#frm_html_tab a' ).click();
5339 toggleAllowedHTML( this, e.type );
5340 } else {
5341 showElement( jQuery( '.frm-category-tabs li' ) );
5342 insertFieldsTab.click();
5343 htmlTab.hide();
5344 htmlTab.siblings().show();
5345 }
5346 } else if ( viewPage ) {
5347 // Run on view page.
5348 toggleAllowedShortcodes( this.id, e.type );
5349 }
5350 }
5351 } );
5352 }
5353
5354 jQuery( '.frm_wrap, #postbox-container-1' ).on( 'mousedown', '#frm_adv_info a, .frm_field_list a', function( e ) {
5355 e.preventDefault();
5356 } );
5357
5358 var customPanel = jQuery( '#frm_adv_info' );
5359 customPanel.on( 'click', '.subsubsub a.frmids', function( e ) {
5360 toggleKeyID( 'frmids', e );
5361 } );
5362 customPanel.on( 'click', '.subsubsub a.frmkeys', function( e ) {
5363 toggleKeyID( 'frmkeys', e );
5364 } );
5365 },
5366
5367 templateInit: function() {
5368 initTemplateModal();
5369 initiateMultiselect();
5370 },
5371
5372 viewInit: function() {
5373 var $advInfo = jQuery( document.getElementById( 'frm_adv_info' ) );
5374 $advInfo.before( '<div id="frm_position_ele"></div>' );
5375 setupMenuOffset();
5376
5377 // Show loading indicator.
5378 jQuery( '#publish' ).mousedown( function() {
5379 this.classList.add( 'frm_loading_button' );
5380 });
5381
5382 // move content tabs
5383 jQuery( '#frm_dyncontent .handlediv' ).before( jQuery( '#frm_dyncontent .nav-menus-php' ) );
5384
5385 // click content tabs
5386 jQuery( '.nav-tab-wrapper a' ).click( clickContentTab );
5387
5388 // click tabs after panel is replaced with ajax
5389 jQuery( '#side-sortables' ).on( 'click', '.frm_doing_ajax.categorydiv .category-tabs a', clickTabsAfterAjax );
5390
5391 initToggleShortcodes();
5392 jQuery( '.frm_code_list:not(.frm-dropdown-menu) a' ).addClass( 'frm_noallow' );
5393
5394 jQuery( 'input[name="show_count"]' ).change( showCount );
5395
5396 jQuery( document.getElementById( 'form_id' ) ).change( displayFormSelected );
5397
5398 var $addRemove = jQuery( '.frm_repeat_rows' );
5399 $addRemove.on( 'click', '.frm_add_order_row', addOrderRow );
5400 $addRemove.on( 'click', '.frm_add_where_row', addWhereRow );
5401 $addRemove.on( 'change', '.frm_insert_where_options', insertWhereOptions );
5402 $addRemove.on( 'change', '.frm_where_is_options', hideWhereOptions );
5403
5404 setDefaultPostStatus();
5405 },
5406
5407 styleInit: function() {
5408 collapseAllSections();
5409
5410 document.getElementById( 'frm_field_height' ).addEventListener( 'change', textSquishCheck );
5411 document.getElementById( 'frm_field_font_size' ).addEventListener( 'change', textSquishCheck );
5412 document.getElementById( 'frm_field_pad' ).addEventListener( 'change', textSquishCheck );
5413
5414 jQuery( 'input.hex' ).wpColorPicker( {
5415 change: function( event, ui ) {
5416 var hexcolor = jQuery( this ).wpColorPicker( 'color' );
5417 jQuery( event.target ).val( hexcolor ).change();
5418 }
5419 } );
5420 jQuery( '.wp-color-result-text' ).text( function( i, oldText ) {
5421 return oldText === 'Select Color' ? 'Select' : oldText;
5422 } );
5423
5424 // update styling on change
5425 jQuery( '#frm_styling_form .styling_settings' ).change( function() {
5426 var locStr = jQuery( 'input[name^="frm_style_setting[post_content]"], select[name^="frm_style_setting[post_content]"], textarea[name^="frm_style_setting[post_content]"], input[name="style_name"]' ).serializeArray();
5427 locStr = JSON.stringify( locStr );
5428 jQuery.ajax( {
5429 type: 'POST', url: ajaxurl,
5430 data: {
5431 action: 'frm_change_styling',
5432 nonce: frmGlobal.nonce,
5433 frm_style_setting: locStr,
5434 },
5435 success: function( css ) {
5436 document.getElementById( 'this_css' ).innerHTML = css;
5437 }
5438 } );
5439 } );
5440
5441 // menu tabs
5442 jQuery( '#menu-settings-column' ).bind( 'click', function( e ) {
5443 var selectAreaMatch, panelId, wrapper, items,
5444 target = jQuery( e.target );
5445
5446 if ( e.target.className.indexOf( 'nav-tab-link' ) !== -1 ) {
5447
5448 panelId = target.data( 'type' );
5449
5450 wrapper = target.parents( '.accordion-section-content' ).first();
5451
5452
5453 jQuery( '.tabs-panel-active', wrapper ).removeClass( 'tabs-panel-active' ).addClass( 'tabs-panel-inactive' );
5454 jQuery( '#' + panelId, wrapper ).removeClass( 'tabs-panel-inactive' ).addClass( 'tabs-panel-active' );
5455
5456 jQuery( '.tabs', wrapper ).removeClass( 'tabs' );
5457 target.parent().addClass( 'tabs' );
5458
5459 // select the search bar
5460 jQuery( '.quick-search', wrapper ).focus();
5461
5462 e.preventDefault();
5463 }
5464 } );
5465
5466 jQuery( '.multiselect-container.frm-dropdown-menu li a' ).click( function() {
5467 var radio = this.children[0].children[0];
5468 var btnGrp = jQuery( this ).closest( '.btn-group' );
5469 var btnId = btnGrp.attr( 'id' );
5470 document.getElementById( btnId.replace( '_select', '' ) ).value = radio.value;
5471 btnGrp.children( 'button' ).html( radio.nextElementSibling.innerHTML + ' <b class="caret"></b>' );
5472
5473 // set active class
5474 btnGrp.find( 'li.active' ).removeClass( 'active' );
5475 jQuery( this ).closest( 'li' ).addClass( 'active' );
5476 } );
5477
5478 jQuery( '#frm_confirm_modal' ).on( 'click', '[data-resetstyle]', function( e ) {
5479 var button = document.getElementById( 'frm_reset_style' );
5480
5481 button.classList.add( 'frm_loading_button' );
5482 e.stopPropagation();
5483
5484 jQuery.ajax( {
5485 type: 'POST', url: ajaxurl,
5486 data: {action: 'frm_settings_reset', nonce: frmGlobal.nonce},
5487 success: function( errObj ) {
5488 errObj = errObj.replace( /^\s+|\s+$/g, '' );
5489 if ( errObj.indexOf( '{' ) === 0 ) {
5490 errObj = jQuery.parseJSON( errObj );
5491 }
5492 for ( var key in errObj ) {
5493 jQuery( 'input[name$="[' + key + ']"], select[name$="[' + key + ']"]' ).val( errObj[key] );
5494 }
5495 jQuery( '#frm_submit_style, #frm_auto_width' ).prop( 'checked', false );
5496 jQuery( document.getElementById( 'frm_fieldset' ) ).change();
5497 button.classList.remove( 'frm_loading_button' );
5498 }
5499 } );
5500 } );
5501
5502 jQuery( '.frm_pro_form #datepicker_sample' ).datepicker( {changeMonth: true, changeYear: true} );
5503
5504 jQuery( document.getElementById( 'frm_position' ) ).change( setPosClass );
5505
5506 jQuery( 'select[name$="[theme_selector]"]' ).change( function() {
5507 var themeVal = jQuery( this ).val();
5508 var themeName = themeVal;
5509 var css = themeVal;
5510 if ( themeVal !== -1 ) {
5511 if ( themeVal === 'ui-lightness' && frm_admin_js.pro_url !== '' ) {
5512 css = frm_admin_js.pro_url + '/css/ui-lightness/jquery-ui.css';
5513 jQuery( '.frm_date_color' ).show();
5514 } else {
5515 css = frm_admin_js.jquery_ui_url + '/themes/' + themeVal + '/jquery-ui.css';
5516 jQuery( '.frm_date_color' ).hide();
5517 }
5518 }
5519
5520 updateUICSS( css );
5521 document.getElementById( 'frm_theme_css' ).value = themeVal;
5522 return false;
5523 } ).change();
5524 },
5525
5526 customCSSInit: function() {
5527 /* deprecated since WP 4.9 */
5528 var customCSS = document.getElementById( 'frm_custom_css_box' );
5529 if ( customCSS !== null ) {
5530 var editor = CodeMirror.fromTextArea( customCSS, {
5531 lineNumbers: true
5532 } );
5533 }
5534 },
5535
5536 globalSettingsInit: function() {
5537 jQuery( document).on( 'click', '[data-frmuninstall]', uninstallNow );
5538
5539 initiateMultiselect();
5540
5541 // activate addon licenses
5542 var licenseTab = document.getElementById( 'licenses_settings' );
5543 if ( licenseTab !== null ) {
5544 jQuery( licenseTab ).on( 'click', '.edd_frm_save_license', saveAddonLicense );
5545 }
5546
5547 jQuery( '#frm-dismissable-cta .dismiss' ).click( function( event ) {
5548 event.preventDefault();
5549 jQuery.post( ajaxurl, {
5550 action: 'frm_lite_settings_upgrade'
5551 } );
5552 jQuery( '.settings-lite-cta' ).remove();
5553 } );
5554 },
5555
5556 exportInit: function() {
5557 jQuery( '#frm_form_importer' ).submit( startFormMigration );
5558 jQuery( document.getElementById( 'frm_export_xml' ) ).submit( validateExport );
5559 jQuery( '#frm_export_xml input, #frm_export_xml select' ).change( removeExportError );
5560 jQuery( 'input[name="frm_import_file"]' ).change( checkCSVExtension );
5561 jQuery( 'select[name="format"]' ).change( checkExportTypes ).change();
5562 jQuery( 'input[name="frm_export_forms[]"]' ).click( preventMultipleExport );
5563 initiateMultiselect();
5564 },
5565
5566 updateOpts: function( field_id, opts, modal ) {
5567 var separate = usingSeparateValues( field_id );
5568 $fieldOpts = document.getElementById( 'frm_field_' + field_id + '_opts' );
5569 empty( $fieldOpts );
5570 jQuery.ajax( {
5571 type: 'POST',
5572 url: ajaxurl,
5573 data: {
5574 action: 'frm_import_options',
5575 field_id: field_id,
5576 opts: opts,
5577 separate: separate,
5578 nonce: frmGlobal.nonce
5579 },
5580 success: function( html ) {
5581 document.getElementById( 'frm_field_' + field_id + '_opts' ).innerHTML = html;
5582 resetDisplayedOpts( field_id );
5583
5584 if ( typeof modal !== 'undefined' ) {
5585 modal.dialog( 'close' );
5586 document.getElementById( 'frm-update-bulk-opts' ).classList.remove( 'frm_loading_button' );
5587 }
5588 }
5589 } );
5590 },
5591
5592 /* remove conditional logic if the field doesn't exist */
5593 triggerRemoveLogic: function( fieldID, metaName ) {
5594 jQuery( '#frm_logic_' + fieldID + '_' + metaName + ' .frm_remove_tag' ).click();
5595 },
5596
5597 downloadXML: function( controller, ids, isTemplate ) {
5598 var url = ajaxurl + '?action=frm_' + controller + '_xml&ids=' + ids;
5599 if ( isTemplate !== null ) {
5600 url = url + '&is_template=' + isTemplate;
5601 }
5602 location.href = url;
5603 }
5604 };
5605 }
5606
5607 var frmAdminBuild = frmAdminBuildJS();
5608
5609 jQuery( document ).ready( function( $ ) {
5610 frmAdminBuild.init();
5611 } );
5612
5613 function frm_remove_tag( html_tag ) {
5614 console.warn( 'DEPRECATED: function frm_remove_tag in v2.0' );
5615 jQuery( html_tag ).remove();
5616 }
5617
5618 function frm_show_div( div, value, show_if, class_id ) {
5619 if ( value == show_if ) {
5620 jQuery( class_id + div ).fadeIn( 'slow' ).css( 'visibility', 'visible' );
5621 } else {
5622 jQuery( class_id + div ).fadeOut( 'slow' );
5623 }
5624 }
5625
5626 function frmCheckAll( checked, n ) {
5627 if ( checked ) {
5628 jQuery( "input[name^='" + n + "']" ).attr( 'checked', 'checked' );
5629 } else {
5630 jQuery( "input[name^='" + n + "']" ).removeAttr( 'checked' );
5631 }
5632 }
5633
5634 function frmCheckAllLevel( checked, n, level ) {
5635 var $kids = jQuery( ".frm_catlevel_" + level ).children( ".frm_checkbox" ).children( 'label' );
5636 if ( checked ) {
5637 $kids.children( "input[name^='" + n + "']" ).attr( "checked", "checked" );
5638 } else {
5639 $kids.children( "input[name^='" + n + "']" ).removeAttr( "checked" );
5640 }
5641 }
5642
5643 function frm_add_logic_row( id, form_id ) {
5644 console.warn( 'DEPRECATED: function frm_add_logic_row in v2.0' );
5645 jQuery.ajax( {
5646 type: "POST", url: ajaxurl,
5647 data: {
5648 action: 'frm_add_logic_row',
5649 form_id: form_id,
5650 field_id: id,
5651 meta_name: jQuery( '#frm_logic_row_' + id + ' > div' ).size(),
5652 nonce: frmGlobal.nonce
5653 },
5654 success: function( html ) {
5655 jQuery( '#frm_logic_row_' + id ).append( html );
5656 }
5657 } );
5658 return false;
5659 }
5660
5661 function frmGetFieldValues( field_id, cur, row_number, field_type, html_name ) {
5662
5663 if ( field_id ) {
5664 jQuery.ajax( {
5665 type: 'POST', url: ajaxurl,
5666 data: 'action=frm_get_field_values&current_field=' + cur + '&field_id=' + field_id + '&name=' + html_name + '&t=' + field_type + '&form_action=' + jQuery( 'input[name="frm_action"]' ).val() + '&nonce=' + frmGlobal.nonce,
5667 success: function( msg ) {
5668 document.getElementById( 'frm_show_selected_values_' + cur + '_' + row_number ).innerHTML = msg;
5669 }
5670 } );
5671 }
5672 }
5673
5674 function frmImportCsv( formID ) {
5675 var urlVars = '';
5676 if ( typeof __FRMURLVARS != 'undefined' ) {
5677 urlVars = __FRMURLVARS;
5678 }
5679
5680 jQuery.ajax( {
5681 type: "POST", url: ajaxurl,
5682 data: 'action=frm_import_csv&nonce=' + frmGlobal.nonce + '&frm_skip_cookie=1' + urlVars,
5683 success: function( count ) {
5684 var max = jQuery( '.frm_admin_progress_bar' ).attr( 'aria-valuemax' );
5685 var imported = max - count;
5686 var percent = (imported / max) * 100;
5687 jQuery( '.frm_admin_progress_bar' ).css( 'width', percent + '%' ).attr( 'aria-valuenow', imported );
5688
5689 if ( parseInt( count ) > 0 ) {
5690 jQuery( '.frm_csv_remaining' ).html( count );
5691 frmImportCsv( formID );
5692 } else {
5693 jQuery( document.getElementById( 'frm_import_message' ) ).html( frm_admin_js.import_complete );
5694 setTimeout( function() {
5695 location.href = '?page=formidable-entries&frm_action=list&form=' + formID + '&import-message=1';
5696 }, 2000 );
5697 }
5698 }
5699 } );
5700 }
5701
5702 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
5703 if ( ! String.prototype.trim ) {
5704 String.prototype.trim = function () {
5705 return this.replace( /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '' );
5706 };
5707 }
5708 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill
5709 if (!String.prototype.startsWith) {
5710 Object.defineProperty(String.prototype, 'startsWith', {
5711 value: function(search, pos) {
5712 pos = !pos || pos < 0 ? 0 : +pos;
5713 return this.substring(pos, pos + search.length) === search;
5714 }
5715 });
5716 }
5717