-1 ) { const peeParts = pee.split( '
' + tinkle.replace( /^(?:\s+|\s+)$/g, '' ) + '
\s*<\/p>/gmi, '' ); // Under certain strange conditions, it could create a P of entire whitespace. pee = pee.replace( /
([^<]+)<\/(div|address|form)>/gmi, '
$1
\s*(?' + allBlocks + '[^>]*>)\s*
(
]*)>/gmi, '' ); pee = pee.replace( /<\/blockquote><\/p>/gmi, '' ); pee = pee.replace( new RegExp( '\s*(?' + allBlocks + '[^>]*>)', 'gmi' ), '$1' ); pee = pee.replace( new RegExp( '(?' + allBlocks + '[^>]*>)\s*', 'gmi' ), '$1' ); if ( br ) { pee = pee.replace( /<(script|style)(?:.|\n)*?<\/\\1>/gmi, _autopNewlinePreservationHelper ); // /s modifier from php PCRE regexp replaced with (?:.|\n). pee = pee.replace( /()?((?=(\s*))\2)\n/gmi, '\n' ); // optionally make line breaks. pee = pee.replace( '', '\n' ); } pee = pee.replace( new RegExp( '(?' + allBlocks + '[^>]*>)\s*', 'gmi' ), '$1' ); pee = pee.replace( /(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)/gmi, '$1' ); pee = pee.replace( /\n<\/p>$/gmi, '' ); /* eslint-enable */ if ( Object.keys( preTags ).length ) { pee = pee.replace( new RegExp( Object.keys( preTags ).join( '|' ), 'gi' ), function( matched ) { return preTags[ matched ]; } ); } return pee; }, /** * Init Media Library. * * @since 1.8.6 * * @param {Object} args List of arguments. * * @return {wp.media.view.MediaFrame} A media workflow. */ initMediaLibrary( args ) { const mediaFrame = wp.media.frames.wpforms_media_frame = wp.media( { className: 'media-frame wpforms-media-frame', multiple: false, title: args.title, library: { type: args.extensions }, button: { text: args.buttonText, }, } ); mediaFrame.on( 'uploader:ready', function() { const accept = args.extensions.join( ',' ); jQuery( '.wpforms-media-frame .moxie-shim-html5 input[type="file"]' ) .attr( 'accept', accept ); } ).on( 'library:selection:add', function() { const attachment = mediaFrame.state().get( 'selection' ).first().toJSON(); if ( ! args.extensions.includes( attachment.file.type ) ) { // eslint-disable-next-line no-alert alert( args.extensionsError ); mediaFrame.state().get( 'selection' ).reset(); } } ); return mediaFrame; }, /** * Determine whether an element is visible in the viewport. * * @since 1.8.8 * * @param {jQuery} $element DOM element. * * @return {boolean} true if an element is visible in the viewport. */ isInViewport( $element ) { const rect = $element[ 0 ].getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= ( window.innerHeight || document.documentElement.clientHeight ) && rect.right <= ( window.innerWidth || document.documentElement.clientWidth ) ); }, /** * Copy the target element to the clipboard. * * @since 1.9.5 * * @param {Object} event Event object. * @param {jQuery} $copyButton Copy button. * @param {jQuery} targetElement Target element. */ copyValueToClipboard( event, $copyButton, targetElement ) { event.preventDefault(); // Use Clipboard API for modern browsers and HTTPS connections, in other cases use the old-fashioned way. if ( navigator.clipboard ) { navigator.clipboard.writeText( targetElement.val() ).then( function() { $copyButton.find( 'span' ).removeClass( 'dashicons-admin-page' ).addClass( 'dashicons-yes-alt' ); } ); return; } targetElement.attr( 'disabled', false ).focus().select(); document.execCommand( 'copy' ); $copyButton.find( 'span' ).removeClass( 'dashicons-admin-page' ).addClass( 'dashicons-yes-alt' ); targetElement.attr( 'disabled', true ); }, /** * Utility for tracking the repeated execution. * * @since 1.9.5 * * @param {string} context Context key. * @param {number} timeout Debounce timeout. * * @return {boolean} It returns `false` when called the first time, `true` - * if called repeatedly (with the same `context` argument) until the timeout is over. */ isRepeatedCall( context, timeout = 500 ) { wpf.isRepeatedCallData = wpf.isRepeatedCallData || {}; if ( wpf.isRepeatedCallData[ context ] ) { return true; } wpf.isRepeatedCallData[ context ] = true; setTimeout( () => wpf.isRepeatedCallData[ context ] = false, timeout ); return false; }, /** * Receive current form settings in the key=>value format. * * @since 1.9.6 * * @internal * * @return {Object} Object with all field names and their values. */ _getCurrentFormState() { // eslint-disable-line complexity const currentState = Object.fromEntries( new FormData( document.getElementById( 'wpforms-builder-form' ) ).entries() ); // noinspection JSUnusedLocalSymbols // eslint-disable-next-line no-unused-vars for ( const [ key ] of Object.entries( currentState ) ) { // The lock option is used to keep AJAX requests up to date. if ( key.includes( '[__lock__]' ) ) { delete currentState[ key ]; } } // Textarea created by tinyMCE updates only before form saving. // We should determine if these fields where updated and update the form state separately. if ( typeof tinyMCE !== 'undefined' && tinyMCE.editors ) { for ( const key in tinyMCE.editors ) { const editor = tinyMCE.editors[ key ]; const editorName = editor.targetElm.getAttribute( 'name' ); if ( ! editorName ) { continue; } if ( editor.isDirty() ) { currentState[ editorName ] = editor.getContent(); } } } currentState.fieldsOrder = wpf.orders.fields.toString(); // Keyword filter stores separately and doesn't have a name attribute. const $keywordFilter = jQuery( '.wpforms-panel-field-keyword-keywords textarea' ); if ( $keywordFilter.length ) { currentState.keywordFilter = $keywordFilter.val(); } return currentState; }, /** * Update form state. * For internal usage only. * * @since 1.9.6 */ _updateFormState() { wpf.savedFormState = wpf._getCurrentFormState(); }, }; wpf.init();
' ); pee = pee.replace( /<\/blockquote><\/p>/gmi, '
\s*(?' + allBlocks + '[^>]*>)', 'gmi' ), '$1' ); pee = pee.replace( new RegExp( '(?' + allBlocks + '[^>]*>)\s*