PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.5
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.5
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
← All changes | js/admin/dom.js +25 -234 6.5 → 5.5 View file →
@@ -44,14 +44,11 @@
44 44 );
45 45 postbox.appendChild(
46 46 div({ className: 'frm_modal_content' })
47 47 );
48 -
49 - if ( footer ) {
50 - postbox.appendChild(
51 - div({ className: 'frm_modal_footer' })
52 - );
53 - }
48 + postbox.appendChild(
49 + div({ className: 'frm_modal_footer' })
50 + );
54 51 } else if ( 'string' === typeof title ) {
55 52 const titleElement = modal.querySelector( '.frm-modal-title' );
56 53 titleElement.textContent = title;
57 54 }
@@ -80,21 +77,14 @@
80 77 output.setAttribute( 'role', 'button' );
81 78 output.setAttribute( 'tabindex', 0 );
82 79 if ( args.buttonType ) {
83 80 output.classList.add( 'button' );
84 -
85 - if ( ! args.noDismiss && -1 !== [ 'red', 'primary' ].indexOf( args.buttonType ) ) {
86 - // Primary and red buttons close modals by default on click.
87 - // To disable this default behaviour you can use the noDismiss: 1 arg.
88 - output.classList.add( 'dismiss' );
89 - }
90 -
91 81 switch ( args.buttonType ) {
92 - case 'red':
93 - output.classList.add( 'frm-button-red', 'frm-button-primary' );
94 - break;
95 82 case 'primary':
96 83 output.classList.add( 'button-primary', 'frm-button-primary' );
84 + if ( ! args.noDismiss ) {
85 + output.classList.add( 'dismiss' );
86 + }
97 87 break;
98 88 case 'secondary':
99 89 output.classList.add( 'button-secondary', 'frm-button-secondary' );
100 90 output.style.marginRight = '10px';
@@ -109,13 +99,9 @@
109 99 };
110 100
111 101 const ajax = {
112 102 doJsonFetch: async function( action ) {
113 - let targetUrl = ajaxurl + '?action=frm_' + action;
114 - if ( -1 === targetUrl.indexOf( 'nonce=' ) ) {
115 - targetUrl += '&nonce=' + frmGlobal.nonce;
116 - }
117 - const response = await fetch( targetUrl );
103 + const response = await fetch( ajaxurl + '?action=frm_' + action );
118 104 const json = await response.json();
119 105 if ( ! json.success ) {
120 106 return Promise.reject( json.data || 'JSON result is not successful' );
121 107 }
@@ -120,19 +106,16 @@
120 106 return Promise.reject( json.data || 'JSON result is not successful' );
121 107 }
122 108 return Promise.resolve( json.data );
123 109 },
124 - doJsonPost: async function( action, formData, { signal } = {}) {
110 + doJsonPost: async function( action, formData ) {
125 111 formData.append( 'nonce', frmGlobal.nonce );
126 112 const init = {
127 113 method: 'POST',
128 114 body: formData
129 115 };
130 - if ( signal ) {
131 - init.signal = signal;
132 - }
133 116 const response = await fetch( ajaxurl + '?action=frm_' + action, init );
134 - const json = await response.json();
117 + const json = await response.json();
135 118 if ( ! json.success ) {
136 119 return Promise.reject( json.data || 'JSON result is not successful' );
137 120 }
138 121 return Promise.resolve( 'undefined' !== typeof json.data ? json.data : json );
@@ -140,13 +123,14 @@
140 123 };
141 124
142 125 const multiselect = {
143 126 init: function() {
144 - const $select = jQuery( this );
145 - const id = $select.is( '[id]' ) ? $select.attr( 'id' ).replace( '[]', '' ) : false;
127 + let $select, id, labelledBy;
146 128
147 - let labelledBy = id ? jQuery( '#for_' + id ) : false;
148 - labelledBy = id && labelledBy.length ? 'aria-labelledby="' + labelledBy.attr( 'id' ) + '"' : '';
129 + $select = jQuery( this );
130 + id = $select.is( '[id]' ) ? $select.attr( 'id' ).replace( '[]', '' ) : false;
131 + labelledBy = id ? jQuery( '#for_' + id ) : false;
132 + labelledBy = id && labelledBy.length ? 'aria-labelledby="' + labelledBy.attr( 'id' ) + '"' : '';
149 133
150 134 $select.multiselect({
151 135 templates: {
152 136 popupContainer: '<div class="multiselect-container frm-dropdown-menu"></div>',
@@ -163,34 +147,11 @@
163 147 jQuery( event.currentTarget ).removeClass( 'open' );
164 148 }
165 149 });
166 150 }
167 -
168 - const $dropdown = $select.next( '.frm-btn-group.dropdown' );
169 - $dropdown.find( '.dropdown-item' ).each(
170 - function() {
171 - const option = this;
172 - const dropdownInput = option.querySelector( 'input[type="checkbox"], input[type="radio"]' );
173 - if ( dropdownInput ) {
174 - option.setAttribute( 'role', 'checkbox' );
175 - option.setAttribute( 'aria-checked', dropdownInput.checked ? 'true' : 'false' );
176 - }
177 - }
178 - );
179 151 },
180 - onChange: function( $option, checked ) {
181 - $select.trigger( 'frm-multiselect-changed', $option, checked );
182 -
183 - const $dropdown = $select.next( '.frm-btn-group.dropdown' );
184 - const optionValue = $option.val();
185 - const $dropdownItem = $dropdown.find( 'input[value="' + optionValue + '"]' ).closest( 'button.dropdown-item' );
186 - if ( $dropdownItem.length ) {
187 - $dropdownItem.attr( 'aria-checked', checked ? 'true' : 'false' );
188 -
189 - // Delay a focus event so the screen reader reads the option value again.
190 - // Without this, and without the setTimeout, it only reads "checked" or "unchecked".
191 - setTimeout( () => $dropdownItem.get( 0 ).focus(), 0 );
192 - }
152 + onChange: function( element, option ) {
153 + $select.trigger( 'frm-multiselect-changed', element, option );
193 154 }
194 155 });
195 156 }
196 157 };
@@ -355,9 +316,9 @@
355 316 const wrappedSearch = search.wrapInput( input, placeholder );
356 317 search.init( input, targetClassName, args );
357 318
358 319 function getAutoSearchInput( id, placeholder ) {
359 - const className = 'frm-search-input frm-auto-search frm-w-full';
320 + const className = 'frm-search-input frm-auto-search';
360 321 const inputArgs = { id, className };
361 322 const input = tag( 'input', inputArgs );
362 323 input.setAttribute( 'placeholder', placeholder );
363 324 return input;
@@ -423,41 +384,13 @@
423 384 event.preventDefault();
424 385 callback( event );
425 386 };
426 387 element.addEventListener( 'click', listener );
427 - },
428 -
429 - /**
430 - * Does the same as jQuery( document ).on( 'event', 'selector', handler ).
431 - *
432 - * @since 6.0
433 - *
434 - * @param {String} event Event name.
435 - * @param {String} selector Selector.
436 - * @param {Function} handler Handler.
437 - * @param {Boolean|Object} options Options to be added to `addEventListener()` method. Default is `false`.
438 - */
439 - documentOn: ( event, selector, handler, options ) => {
440 - if ( 'undefined' === typeof options ) {
441 - options = false;
442 - }
443 -
444 - document.addEventListener( event, function( e ) {
445 - let target;
446 -
447 - // loop parent nodes from the target to the delegation node.
448 - for ( target = e.target; target && target != this; target = target.parentNode ) {
449 - if ( target && target.matches && target.matches( selector ) ) {
450 - handler.call( target, e );
451 - break;
452 - }
453 - }
454 - }, options );
455 388 }
456 389 };
457 390
458 391 const wysiwyg = {
459 - init( editor, { setupCallback, height, addFocusEvents } = {}) {
392 + init( editor, { setupCallback } = {}) {
460 393 if ( isTinyMceActive() ) {
461 394 setTimeout( resetTinyMce, 0 );
462 395 } else {
463 396 initQuickTagsButtons();
@@ -494,28 +427,10 @@
494 427 body_class: orgSettings.body_class.replace( key, editor.id )
495 428 }
496 429 );
497 430
498 - settings.setup = editor => {
499 - if ( addFocusEvents ) {
500 - function focusInCallback() {
501 - jQuery( editor.targetElm ).trigger( 'focusin' );
502 - editor.off( 'focusin', '**' );
503 - }
504 -
505 - editor.on( 'focusin', focusInCallback );
506 -
507 - editor.on( 'focusout', function() {
508 - editor.on( 'focusin', focusInCallback );
509 - });
510 - }
511 - if ( setupCallback ) {
512 - setupCallback( editor );
513 - }
514 - };
515 -
516 - if ( height ) {
517 - settings.height = height;
431 + if ( setupCallback ) {
432 + settings.setup = setupCallback;
518 433 }
519 434
520 435 tinymce.init( settings );
521 436 }
@@ -587,10 +502,8 @@
587 502 return modal;
588 503 }
589 504
590 505 function makeModalIntoADialogAndOpen( modal, { width } = {}) {
591 - const bodyWithModalClassName = 'frm-body-with-open-modal';
592 -
593 506 const $modal = jQuery( modal );
594 507 if ( ! $modal.hasClass( 'frm-dialog' ) ) {
595 508 $modal.dialog({
596 509 dialogClass: 'frm-dialog',
@@ -623,9 +536,9 @@
623 536 );
624 537 }
625 538 },
626 539 close: function() {
627 - document.body.classList.remove( bodyWithModalClassName );
540 + document.body.style.overflowY = 'initial';
628 541 jQuery( '#wpwrap' ).removeClass( 'frm_overlay' );
629 542 jQuery( '.spinner' ).css( 'visibility', 'hidden' );
630 543 }
631 544 });
@@ -630,10 +543,9 @@
630 543 }
631 544 });
632 545 }
633 546
634 - document.body.classList.add( bodyWithModalClassName );
635 -
547 + document.body.style.overflowY = 'hidden';
636 548 $modal.dialog( 'open' );
637 549 return $modal;
638 550 }
639 551
@@ -658,50 +570,11 @@
658 570 const output = tag( 'img', args );
659 571 if ( 'string' === typeof args.src ) {
660 572 output.setAttribute( 'src', args.src );
661 573 }
662 - if ( 'string' === typeof args.alt ) {
663 - output.setAttribute( 'alt', args.alt );
664 - }
665 574 return output;
666 575 }
667 576
668 - /**
669 - * Get a labelled text input and a matching label.
670 - *
671 - * @since 6.0
672 - *
673 - * @param {String} inputId
674 - * @param {String} labelText
675 - * @param {String} inputName
676 - * @returns {Element}
677 - */
678 - function labelledTextInput( inputId, labelText, inputName ) {
679 - const label = tag( 'label', labelText );
680 - label.setAttribute( 'for', inputId );
681 -
682 - const input = tag(
683 - 'input',
684 - {
685 - id: inputId,
686 - className: 'frm_long_input'
687 - }
688 - );
689 - input.type = 'text';
690 - input.setAttribute( 'name', inputName );
691 -
692 - return div({ children: [ label, input ] });
693 - }
694 -
695 - /**
696 - * Build an element.
697 - *
698 - * @since 6.4.1 Accept a string as one of `children` to append a text node inside the element.
699 - *
700 - * @param {String} type Element tag name.
701 - * @param {Object} args The args.
702 - * @return {Object}
703 - */
704 577 function tag( type, args = {}) {
705 578 const output = document.createElement( type );
706 579
707 580 if ( 'string' === typeof args ) {
@@ -709,9 +582,9 @@
709 582 output.textContent = args;
710 583 return output;
711 584 }
712 585
713 - const { id, className, children, child, text, data } = args;
586 + const { id, className, children, child, text } = args;
714 587
715 588 if ( id ) {
716 589 output.id = id;
717 590 }
@@ -718,25 +591,14 @@
718 591 if ( className ) {
719 592 output.className = className;
720 593 }
721 594 if ( children ) {
722 - children.forEach( child => {
723 - if ( 'string' === typeof child ) {
724 - output.appendChild( document.createTextNode( child ) );
725 - } else {
726 - output.appendChild( child )
727 - }
728 - } );
595 + children.forEach( child => output.appendChild( child ) );
729 596 } else if ( child ) {
730 597 output.appendChild( child );
731 598 } else if ( text ) {
732 599 output.textContent = text;
733 600 }
734 - if ( data ) {
735 - Object.keys( data ).forEach( function( dataKey ) {
736 - output.setAttribute( 'data-' + dataKey, data[dataKey] );
737 - });
738 - }
739 601 return output;
740 602 }
741 603
742 604 function svg({ href, classList } = {}) {
@@ -754,32 +616,8 @@
754 616 }
755 617 return output;
756 618 }
757 619
758 - /**
759 - * Pop up a success message in the lower right corner.
760 - * It then fades out and gets deleted automatically.
761 - *
762 - * @param {HTMLElement|String} content
763 - * @returns {void}
764 - */
765 - function success( content ) {
766 - const container = document.getElementById( 'wpbody' );
767 - const notice = div({
768 - className: 'notice notice-info frm-review-notice frm_updated_message frm-floating-success-message',
769 - child: div({
770 - className: 'frm-satisfied',
771 - child: 'string' === typeof content ? document.createTextNode( content ) : content
772 - })
773 - });
774 - container.appendChild( notice );
775 -
776 - setTimeout(
777 - () => jQuery( notice ).fadeOut( () => notice.remove() ),
778 - 2000
779 - );
780 - }
781 -
782 620 function setAttributes( element, attrs ) {
783 621 Object.entries( attrs ).forEach(
784 622 ([ key, value ]) => element.setAttribute( key, value )
785 623 );
@@ -789,53 +627,6 @@
789 627 element.innerHTML = '';
790 628 element.appendChild( child );
791 629 }
792 630
793 - const allowedHtml = {
794 - b: [],
795 - div: [ 'class' ],
796 - img: [ 'src', 'alt' ],
797 - p: [],
798 - span: [ 'class' ],
799 - strong: [],
800 - svg: [ 'class' ],
801 - use: []
802 - };
803 -
804 - function cleanNode( node ) {
805 - if ( 'undefined' === typeof node.tagName ) {
806 - if ( '#text' === node.nodeName ) {
807 - return document.createTextNode( node.textContent );
808 - }
809 - return document.createTextNode( '' );
810 - }
811 -
812 - const tagType = node.tagName.toLowerCase();
813 -
814 - if ( 'svg' === tagType ) {
815 - return svg({
816 - href: node.querySelector( 'use' ).getAttribute( 'xlink:href' ),
817 - classList: Array.from( node.classList )
818 - });
819 - }
820 -
821 - const newNode = document.createElement( tagType );
822 -
823 - if ( 'undefined' === typeof allowedHtml[ tagType ]) {
824 - // Tag type is not allowed.
825 - return document.createTextNode( '' );
826 - }
827 -
828 - allowedHtml[ tagType ].forEach(
829 - allowedTag => {
830 - if ( node.hasAttribute( allowedTag ) ) {
831 - newNode.setAttribute( allowedTag, node.getAttribute( allowedTag ) );
832 - }
833 - }
834 - );
835 -
836 - node.childNodes.forEach( child => newNode.appendChild( cleanNode( child ) ) );
837 - return newNode;
838 - }
839 -
840 - window.frmDom = { tag, div, span, a, img, labelledTextInput, svg, setAttributes, success, modal, ajax, bootstrap, autocomplete, search, util, wysiwyg, cleanNode };
631 + window.frmDom = { tag, div, span, a, img, svg, setAttributes, modal, ajax, bootstrap, autocomplete, search, util, wysiwyg };
841 632 }() );