PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
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 +73 -114 6.25 → trunk View file →
@@ -2,9 +2,9 @@
2 2 /** globals frmGlobal */
3 3
4 4 let __;
5 5
6 - if ( 'undefined' === typeof wp || 'undefined' === typeof wp.i18n || 'function' !== typeof wp.i18n.__ ) {
6 + if ( 'undefined' === typeof wp || wp.i18n === undefined || 'function' !== typeof wp.i18n.__ ) {
7 7 __ = text => text;
8 8 } else {
9 9 __ = wp.i18n.__;
10 10 }
@@ -9,9 +9,9 @@
9 9 __ = wp.i18n.__;
10 10 }
11 11
12 12 const modal = {
13 - maybeCreateModal: ( id, { title, content, footer, width } = {} ) => {
13 + maybeCreateModal: ( id, { title, content, footer, width, dialogClass } = {} ) => {
14 14 let modal = document.getElementById( id );
15 15
16 16 if ( ! modal ) {
17 17 modal = createEmptyModal( id );
@@ -32,9 +32,9 @@
32 32 }
33 33 );
34 34 const postbox = modal.querySelector( '.postbox' );
35 35
36 - postbox.appendChild(
36 + postbox.append(
37 37 div( {
38 38 className: 'frm_modal_top',
39 39 children: [
40 40 titleElement,
@@ -41,14 +41,14 @@
41 41 div( { child: a } )
42 42 ]
43 43 } )
44 44 );
45 - postbox.appendChild(
45 + postbox.append(
46 46 div( { className: 'frm_modal_content' } )
47 47 );
48 48
49 49 if ( footer ) {
50 - postbox.appendChild(
50 + postbox.append(
51 51 div( { className: 'frm_modal_footer' } )
52 52 );
53 53 }
54 54 } else if ( 'string' === typeof title ) {
@@ -56,9 +56,9 @@
56 56 titleElement.textContent = title;
57 57 }
58 58
59 59 if ( ! content && ! footer ) {
60 - makeModalIntoADialogAndOpen( modal, { width } );
60 + makeModalIntoADialogAndOpen( modal, { width, dialogClass } );
61 61 return modal;
62 62 }
63 63
64 64 const postbox = modal.querySelector( '.postbox' );
@@ -71,9 +71,9 @@
71 71 if ( footer ) {
72 72 modalHelper( footer, 'frm_modal_footer' );
73 73 }
74 74
75 - makeModalIntoADialogAndOpen( modal );
75 + makeModalIntoADialogAndOpen( modal, { width, dialogClass } );
76 76 return modal;
77 77 },
78 78 footerButton: args => {
79 79 const output = a( args );
@@ -81,9 +81,9 @@
81 81 output.setAttribute( 'tabindex', 0 );
82 82 if ( args.buttonType ) {
83 83 output.classList.add( 'button' );
84 84
85 - if ( ! args.noDismiss && -1 !== [ 'red', 'primary' ].indexOf( args.buttonType ) ) {
85 + if ( ! args.noDismiss && [ 'red', 'primary' ].includes( args.buttonType ) ) {
86 86 // Primary and red buttons close modals by default on click.
87 87 // To disable this default behaviour you can use the noDismiss: 1 arg.
88 88 output.classList.add( 'dismiss' );
89 89 }
@@ -108,12 +108,12 @@
108 108 }
109 109 };
110 110
111 111 const ajax = {
112 - doJsonFetch: async function( action ) {
113 - let targetUrl = ajaxurl + '?action=frm_' + action;
114 - if ( -1 === targetUrl.indexOf( 'nonce=' ) ) {
115 - targetUrl += '&nonce=' + frmGlobal.nonce;
112 + async doJsonFetch( action ) {
113 + let targetUrl = `${ ajaxurl }?action=frm_${ action }`;
114 + if ( ! targetUrl.includes( 'nonce=' ) ) {
115 + targetUrl += `&nonce=${ frmGlobal.nonce }`;
116 116 }
117 117 const response = await fetch( targetUrl );
118 118 const json = await response.json();
119 119 if ( ! json.success ) {
@@ -120,9 +120,9 @@
120 120 return Promise.reject( json.data || 'JSON result is not successful' );
121 121 }
122 122 return Promise.resolve( json.data );
123 123 },
124 - doJsonPost: async function( action, formData, { signal } = {} ) {
124 + async doJsonPost( action, formData, { signal } = {} ) {
125 125 formData.append( 'nonce', frmGlobal.nonce );
126 126 const init = {
127 127 method: 'POST',
128 128 body: formData
@@ -129,32 +129,30 @@
129 129 };
130 130 if ( signal ) {
131 131 init.signal = signal;
132 132 }
133 - const response = await fetch( ajaxurl + '?action=frm_' + action, init );
133 + const response = await fetch( `${ ajaxurl }?action=frm_${ action }`, init );
134 134 const json = await response.json();
135 135 if ( ! json.success ) {
136 136 return Promise.reject( json.data || 'JSON result is not successful' );
137 137 }
138 - return Promise.resolve( 'undefined' !== typeof json.data ? json.data : json );
138 + return Promise.resolve( json.data !== undefined ? json.data : json );
139 139 }
140 140 };
141 141
142 142 const multiselect = {
143 - init: function() {
143 + init() {
144 144 const $select = jQuery( this );
145 145 const id = $select.is( '[id]' ) ? $select.attr( 'id' ).replace( '[]', '' ) : false;
146 146
147 - let labelledBy = id ? jQuery( '#for_' + id ) : false;
148 - labelledBy = id && labelledBy.length ? 'aria-labelledby="' + labelledBy.attr( 'id' ) + '"' : '';
147 + let labelledBy = id ? jQuery( `#for_${ id }` ) : false;
148 + labelledBy = id && labelledBy.length ? `aria-labelledby="${ labelledBy.attr( 'id' ) }"` : '';
149 149
150 - // Set empty title attributes so that none of the dropdown options include title attributes.
151 - $select.find( 'option' ).attr( 'title', ' ' );
152 150 $select.multiselect( {
153 151 templates: {
154 - popupContainer: '<div class="multiselect-container frm-dropdown-menu"></div>',
152 + popupContainer: '<div class="multiselect-container frm-dropdown-menu dropdown-menu"></div>',
155 153 option: '<button type="button" class="multiselect-option dropdown-item frm_no_style_button"></button>',
156 - button: '<button type="button" class="multiselect dropdown-toggle btn" data-toggle="dropdown" ' + labelledBy + '><span class="multiselect-selected-text"></span> <b class="caret"></b></button>'
154 + button: `<button type="button" class="multiselect dropdown-toggle btn" data-bs-toggle="dropdown" ${ labelledBy }><span class="multiselect-selected-text"></span> <b class="caret"></b></button>`
157 155 },
158 156 buttonContainer: '<div class="btn-group frm-btn-group dropdown" />',
159 157 nonSelectedText: __( '— Select —', 'formidable' ),
160 158 // Prevent the dropdown from showing "All Selected" when every option is checked.
@@ -160,12 +158,12 @@
160 158 // Prevent the dropdown from showing "All Selected" when every option is checked.
161 159 allSelectedText: '',
162 160 // This is 3 by default. We want to show more options before it starts showing a count.
163 161 numberDisplayed: 8,
164 - onInitialized: function( _, $container ) {
165 - $container.find( '.multiselect.dropdown-toggle' ).removeAttr( 'title' );
162 + onInitialized( _, $container ) {
163 + $container.find( '.multiselect.dropdown-toggle,.multiselect-option.dropdown-item' ).removeAttr( 'title' );
166 164 },
167 - onDropdownShown: function( event ) {
165 + onDropdownShown( event ) {
168 166 const action = jQuery( event.currentTarget.closest( '.frm_form_action_settings, #frm-show-fields' ) );
169 167 if ( action.length ) {
170 168 jQuery( '#wpcontent' ).on( 'click', function() {
171 169 if ( jQuery( '.multiselect-container.frm-dropdown-menu' ).is( ':visible' ) ) {
@@ -185,14 +183,14 @@
185 183 }
186 184 }
187 185 );
188 186 },
189 - onChange: function( $option, checked ) {
187 + onChange( $option, checked ) {
190 188 $select.trigger( 'frm-multiselect-changed', $option, checked );
191 189
192 190 const $dropdown = $select.next( '.frm-btn-group.dropdown' );
193 191 const optionValue = $option.val();
194 - const $dropdownItem = $dropdown.find( 'input[value="' + optionValue + '"]' ).closest( 'button.dropdown-item' );
192 + const $dropdownItem = $dropdown.find( `input[value="${ optionValue }"]` ).closest( 'button.dropdown-item' );
195 193 if ( $dropdownItem.length ) {
196 194 $dropdownItem.attr( 'aria-checked', checked ? 'true' : 'false' );
197 195
198 196 // Delay a focus event so the screen reader reads the option value again.
@@ -204,53 +202,17 @@
204 202 }
205 203 };
206 204
207 205 const bootstrap = {
208 - setupBootstrapDropdowns( callback ) {
209 - if ( ! window.bootstrap || ! window.bootstrap.Dropdown ) {
210 - return;
211 - }
212 -
213 - window.bootstrap.Dropdown._getParentFromElement = getParentFromElement;
214 - window.bootstrap.Dropdown.prototype._getParentFromElement = getParentFromElement;
215 -
216 - function getParentFromElement( element ) {
217 - let parent;
218 - const selector = window.bootstrap.Util.getSelectorFromElement( element );
219 -
220 - if ( selector ) {
221 - parent = document.querySelector( selector );
222 - }
223 -
224 - const result = parent || element.parentNode;
225 - const frmDropdownMenu = result.querySelector( '.frm-dropdown-menu' );
226 -
227 - if ( ! frmDropdownMenu ) {
228 - // Not a formidable dropdown, treat like Bootstrap does normally.
229 - return result;
230 - }
231 -
232 - // Temporarily add dropdown-menu class so bootstrap can initialize.
233 - frmDropdownMenu.classList.add( 'dropdown-menu' );
234 - setTimeout(
235 - function() {
236 - frmDropdownMenu.classList.remove( 'dropdown-menu' );
237 - },
238 - 0
239 - );
240 -
241 - if ( 'function' === typeof callback ) {
242 - callback( frmDropdownMenu );
243 - }
244 -
245 - return result;
246 - }
206 + setupBootstrapDropdowns() {
207 + // This function is no longer necessary.
208 + // It's call in Pro though, so keep it to avoid any errors for now.
247 209 },
248 210 multiselect
249 211 };
250 212
251 213 const autocomplete = {
252 - initSelectionAutocomplete: function( container ) {
214 + initSelectionAutocomplete( container ) {
253 215 if ( jQuery.fn.autocomplete ) {
254 216 autocomplete.initAutocomplete( 'page', container );
255 217 autocomplete.initAutocomplete( 'user', container );
256 218 autocomplete.initAutocomplete( 'custom', container );
@@ -263,11 +225,11 @@
263 225 *
264 226 * @param {string} type Type of data. Accepts `page` or `user`.
265 227 * @param {string|Object} container Container class or element. Default is null.
266 228 */
267 - initAutocomplete: function( type, container ) {
268 - const basedUrlParams = '?action=frm_' + type + '_search&nonce=' + frmGlobal.nonce;
269 - const elements = ! container ? jQuery( '.frm-' + type + '-search' ) : jQuery( container ).find( '.frm-' + type + '-search' );
229 + initAutocomplete( type, container ) {
230 + const basedUrlParams = `?action=frm_${ type }_search&nonce=${ frmGlobal.nonce }`;
231 + const elements = ! container ? jQuery( `.frm-${ type }-search` ) : jQuery( container ).find( `.frm-${ type }-search` );
270 232
271 233 elements.each( initAutocompleteForElement );
272 234
273 235 function initAutocompleteForElement() {
@@ -275,9 +237,9 @@
275 237 const element = jQuery( this );
276 238
277 239 // Check if a custom post type is specific.
278 240 if ( element.attr( 'data-post-type' ) ) {
279 - urlParams += '&post_type=' + element.attr( 'data-post-type' );
241 + urlParams += `&post_type=${ element.attr( 'data-post-type' ) }`;
280 242 }
281 243
282 244 let source = ajaxurl + urlParams;
283 245
@@ -290,9 +252,9 @@
290 252
291 253 element.autocomplete( {
292 254 delay: 100,
293 255 minLength: 0,
294 - source: source,
256 + source,
295 257 change: autocomplete.selectBlank,
296 258 select: autocomplete.completeSelectFromResults,
297 259 focus: () => false,
298 260 position: {
@@ -299,9 +261,9 @@
299 261 my: 'left top',
300 262 at: 'left bottom',
301 263 collision: 'flip'
302 264 },
303 - response: function( event, ui ) {
265 + response( event, ui ) {
304 266 if ( ! ui.content.length ) {
305 267 const noResult = {
306 268 value: '',
307 269 label: frm_admin_js.no_items_found
@@ -308,9 +270,9 @@
308 270 };
309 271 ui.content.push( noResult );
310 272 }
311 273 },
312 - create: function() {
274 + create() {
313 275 let $container = jQuery( this ).parent();
314 276
315 277 if ( $container.length === 0 ) {
316 278 $container = 'body';
@@ -333,9 +295,9 @@
333 295 };
334 296 }
335 297 },
336 298
337 - selectBlank: function( e, ui ) {
299 + selectBlank( e, ui ) {
338 300 if ( ui.item === null ) {
339 301 this.nextElementSibling.value = '';
340 302
341 303 /**
@@ -346,9 +308,9 @@
346 308 wp.hooks.doAction( 'frm_autocomplete_clear_value', e, ui, this );
347 309 }
348 310 },
349 311
350 - completeSelectFromResults: function( e, ui ) {
312 + completeSelectFromResults( e, ui ) {
351 313 e.preventDefault();
352 314 this.value = ui.item.value === '' ? '' : ui.item.label;
353 315 this.nextElementSibling.value = ui.item.value;
354 316
@@ -426,9 +388,9 @@
426 388 itemText = item.innerText.toLowerCase();
427 389 item.setAttribute( 'frm-search-text', itemText );
428 390 }
429 391
430 - const hide = notEmptySearchText && -1 === itemText.indexOf( searchText );
392 + const hide = notEmptySearchText && ! itemText.includes( searchText );
431 393 item.classList.toggle( 'frm_hidden', hide );
432 394
433 395 const isSearchResult = ! hide && notEmptySearchText;
434 396 if ( isSearchResult ) {
@@ -469,9 +431,9 @@
469 431 * @param {Function} handler Handler.
470 432 * @param {boolean|Object} options Options to be added to `addEventListener()` method. Default is `false`.
471 433 */
472 434 documentOn: ( event, selector, handler, options ) => {
473 - if ( 'undefined' === typeof options ) {
435 + if ( options === undefined ) {
474 436 options = false;
475 437 }
476 438
477 439 document.addEventListener( event, function( e ) {
@@ -478,9 +440,9 @@
478 440 let target;
479 441
480 442 // loop parent nodes from the target to the delegation node.
481 443 for ( target = e.target; target && target != this; target = target.parentNode ) {
482 - if ( target && target.matches && target.matches( selector ) ) {
444 + if ( target.matches && target.matches( selector ) ) {
483 445 handler.call( target, e );
484 446 break;
485 447 }
486 448 }
@@ -527,19 +489,19 @@
527 489 setUpTinyMceVisualButtonListener();
528 490 setUpTinyMceHtmlButtonListener();
529 491
530 492 function initQuickTagsButtons() {
531 - if ( 'function' !== typeof window.quicktags || typeof window.QTags.instances[ editor.id ] !== 'undefined' ) {
493 + if ( 'function' !== typeof window.quicktags || window.QTags.instances[ editor.id ] !== undefined ) {
532 494 return;
533 495 }
534 496
535 - const id = editor.id;
497 + const { id } = editor;
536 498 window.quicktags( {
537 - name: 'qt_' + id,
538 - id: id,
499 + name: `qt_${ id }`,
500 + id,
539 501 canvas: editor,
540 502 settings: { id },
541 - toolbar: document.getElementById( 'qt_' + id + '_toolbar' ),
503 + toolbar: document.getElementById( `qt_${ id }_toolbar` ),
542 504 theButtons: {}
543 505 } );
544 506 }
545 507
@@ -550,9 +512,9 @@
550 512 const settings = Object.assign(
551 513 {},
552 514 orgSettings,
553 515 {
554 - selector: '#' + editor.id,
516 + selector: `#${ editor.id }`,
555 517 body_class: orgSettings.body_class.replace( key, editor.id )
556 518 }
557 519 );
558 520
@@ -590,16 +552,16 @@
590 552 initRichText();
591 553 }
592 554
593 555 function isTinyMceActive() {
594 - const id = editor.id;
595 - const wrapper = document.getElementById( 'wp-' + id + '-wrap' );
596 - return null !== wrapper && wrapper.classList.contains( 'tmce-active' );
556 + const { id } = editor;
557 + const wrapper = document.getElementById( `wp-${ id }-wrap` );
558 + return wrapper && wrapper.classList.contains( 'tmce-active' );
597 559 }
598 560
599 561 function setUpTinyMceVisualButtonListener() {
600 562 jQuery( document ).on(
601 - 'click', '#' + editor.id + '-html',
563 + 'click', `#${ editor.id }-html`,
602 564 function() {
603 565 editor.style.visibility = 'visible';
604 566 initQuickTagsButtons();
605 567 }
@@ -606,9 +568,9 @@
606 568 );
607 569 }
608 570
609 571 function setUpTinyMceHtmlButtonListener() {
610 - jQuery( '#' + editor.id + '-tmce' ).on( 'click', handleTinyMceHtmlButtonClick );
572 + jQuery( `#${ editor.id }-tmce` ).on( 'click', handleTinyMceHtmlButtonClick );
611 573 }
612 574
613 575 function handleTinyMceHtmlButtonClick() {
614 576 if ( isTinyMceActive() ) {
@@ -616,9 +578,9 @@
616 578 } else {
617 579 initRichText();
618 580 }
619 581
620 - const wrap = document.getElementById( 'wp-' + editor.id + '-wrap' );
582 + const wrap = document.getElementById( `wp-${ editor.id }-wrap` );
621 583 wrap.classList.add( 'tmce-active' );
622 584 wrap.classList.remove( 'html-active' );
623 585 }
624 586 }
@@ -625,15 +587,15 @@
625 587 };
626 588
627 589 function getModalHelper( modal, appendTo ) {
628 590 return function( child, uniqueClassName ) {
629 - let element = modal.querySelector( '.' + uniqueClassName );
591 + let element = modal.querySelector( `.${ uniqueClassName }` );
630 592 if ( null === element ) {
631 593 element = div( {
632 - child: child,
594 + child,
633 595 className: uniqueClassName
634 596 } );
635 - appendTo.appendChild( element );
597 + appendTo.append( element );
636 598 } else {
637 599 redraw( element, child );
638 600 }
639 601 };
@@ -642,20 +604,20 @@
642 604 function createEmptyModal( id ) {
643 605 const modal = div( { id, className: 'frm-modal' } );
644 606 const postbox = div( { className: 'postbox' } );
645 607 const metaboxHolder = div( { className: 'metabox-holder', child: postbox } );
646 - modal.appendChild( metaboxHolder );
647 - document.body.appendChild( modal );
608 + modal.append( metaboxHolder );
609 + document.body.append( modal );
648 610 return modal;
649 611 }
650 612
651 - function makeModalIntoADialogAndOpen( modal, { width } = {} ) {
613 + function makeModalIntoADialogAndOpen( modal, { width, dialogClass = '' } = {} ) {
652 614 const bodyWithModalClassName = 'frm-body-with-open-modal';
653 615
654 616 const $modal = jQuery( modal );
655 617 if ( ! $modal.hasClass( 'frm-dialog' ) ) {
656 618 $modal.dialog( {
657 - dialogClass: 'frm-dialog',
619 + dialogClass: `frm-dialog ${ dialogClass }`,
658 620 modal: true,
659 621 autoOpen: false,
660 622 closeOnEscape: true,
661 623 width: width || '550px',
@@ -660,9 +622,9 @@
660 622 closeOnEscape: true,
661 623 width: width || '550px',
662 624 resizable: false,
663 625 draggable: false,
664 - open: function() {
626 + open() {
665 627 jQuery( '.ui-dialog-titlebar' ).addClass( 'frm_hidden' ).removeClass( 'ui-helper-clearfix' );
666 628 jQuery( '#wpwrap' ).addClass( 'frm_overlay' );
667 629 jQuery( '.frm-dialog' ).removeClass( 'ui-widget ui-widget-content ui-corner-all' );
668 630
@@ -683,9 +645,9 @@
683 645 }
684 646 );
685 647 }
686 648 },
687 - close: function() {
649 + close() {
688 650 document.body.classList.remove( bodyWithModalClassName );
689 651 jQuery( '#wpwrap' ).removeClass( 'frm_overlay' );
690 652 jQuery( '.spinner' ).css( 'visibility', 'hidden' );
691 653 }
@@ -781,21 +743,21 @@
781 743 }
782 744 if ( children ) {
783 745 children.forEach( child => {
784 746 if ( 'string' === typeof child ) {
785 - output.appendChild( document.createTextNode( child ) );
747 + output.append( document.createTextNode( child ) );
786 748 } else {
787 - output.appendChild( child );
749 + output.append( child );
788 750 }
789 751 } );
790 752 } else if ( child ) {
791 - output.appendChild( child );
753 + output.append( child );
792 754 } else if ( text ) {
793 755 output.textContent = text;
794 756 }
795 757 if ( data ) {
796 758 Object.keys( data ).forEach( function( dataKey ) {
797 - output.setAttribute( 'data-' + dataKey, data[ dataKey ] );
759 + output.setAttribute( `data-${ dataKey }`, data[ dataKey ] );
798 760 } );
799 761 }
800 762 return output;
801 763 }
@@ -809,9 +771,9 @@
809 771
810 772 if ( href ) {
811 773 const use = document.createElementNS( namespace, 'use' );
812 774 use.setAttribute( 'href', href );
813 - output.appendChild( use );
775 + output.append( use );
814 776 output.classList.add( 'frmsvg' );
815 777 }
816 778 return output;
817 779 }
@@ -831,9 +793,9 @@
831 793 className: 'frm-satisfied',
832 794 child: 'string' === typeof content ? document.createTextNode( content ) : content
833 795 } )
834 796 } );
835 - container.appendChild( notice );
797 + container.append( notice );
836 798
837 799 setTimeout(
838 800 () => jQuery( notice ).fadeOut( () => notice.remove() ),
839 801 2000
@@ -847,9 +809,9 @@
847 809 }
848 810
849 811 function redraw( element, child ) {
850 812 element.innerHTML = '';
851 - element.appendChild( child );
813 + element.append( child );
852 814 }
853 815
854 816 const allowedHtml = {
855 817 b: [],
@@ -863,9 +825,9 @@
863 825 a: [ 'href', 'class' ]
864 826 };
865 827
866 828 function cleanNode( node ) {
867 - if ( 'undefined' === typeof node.tagName ) {
829 + if ( node.tagName === undefined ) {
868 830 if ( '#text' === node.nodeName ) {
869 831 return document.createTextNode( node.textContent );
870 832 }
871 833 return document.createTextNode( '' );
@@ -878,17 +840,14 @@
878 840 classList: Array.from( node.classList )
879 841 };
880 842 const use = node.querySelector( 'use' );
881 843 if ( use ) {
882 - svgArgs.href = use.getAttribute( 'xlink:href' );
883 - if ( ! svgArgs.href ) {
884 - svgArgs.href = use.getAttribute( 'href' );
885 - }
844 + svgArgs.href = use.getAttribute( 'href' ) || use.getAttribute( 'xlink:href' );
886 845 }
887 846 return svg( svgArgs );
888 847 }
889 848
890 - if ( 'undefined' === typeof allowedHtml[ tagType ] ) {
849 + if ( allowedHtml[ tagType ] === undefined ) {
891 850 // Tag type is not allowed.
892 851 return document.createTextNode( '' );
893 852 }
894 853
@@ -901,9 +860,9 @@
901 860 }
902 861 }
903 862 );
904 863
905 - node.childNodes.forEach( child => newNode.appendChild( cleanNode( child ) ) );
864 + node.childNodes.forEach( child => newNode.append( cleanNode( child ) ) );
906 865 return newNode;
907 866 }
908 867
909 868 window.frmDom = { tag, div, span, a, img, labelledTextInput, svg, setAttributes, success, modal, ajax, bootstrap, autocomplete, search, util, wysiwyg, cleanNode };