/* global wpforms_admin, wpforms_forms_locator, wpforms_admin_forms_overview, Choices, wpf */
/**
* WPForms Forms Overview.
*
* @since 1.7.3
*/
'use strict';
var WPFormsForms = window.WPFormsForms || {};
WPFormsForms.Overview = WPFormsForms.Overview || ( function( document, window, $ ) {
/**
* Elements.
*
* @since 1.7.5
*
* @type {object}
*/
var el = {};
/**
* Runtime variables.
*
* @since 1.7.5
*
* @type {object}
*/
var vars = {};
/**
* Public functions and properties.
*
* @since 1.7.3
*
* @type {object}
*/
var app = {
/**
* Start the engine.
*
* @since 1.7.3
*/
init: function() {
$( app.ready );
},
/**
* Document ready.
*
* @since 1.7.3
*/
ready() {
app.initElements();
app.initTableColumns();
app.initTagsFilter();
app.adjustBulkEditTagsForm();
app.initEditTagsBulkActionItem();
app.events();
},
/**
* Init elements.
*
* @since 1.7.5
*/
initElements() {
el.$overview = $( '#wpforms-overview' );
el.$tagsFilterSelect = $( '.wpforms-tags-filter select' );
el.$tagsFilterButton = $( '.wpforms-tags-filter button' );
el.$listTableRows = $( '#wpforms-overview #the-list' );
el.$bulkEditTagsRows = $( '.wpforms-bulk-edit-tags' );
el.$bulkEditTagsForms = $( '.wpforms-bulk-edit-tags .wpforms-edit-forms select' );
el.$bulkEditTagsTags = $( '.wpforms-bulk-edit-tags .wpforms-edit-tags select' );
el.$bulkEditTagsMessage = $( '.wpforms-bulk-edit-tags .wpforms-message' );
},
/**
* Init table columns.
*
* @since 1.8.6
*/
initTableColumns() {
const $table = el.$overview.find( '.wp-list-table' );
// Set the Name column as primary.
$table.find( '.column-primary' ).removeClass( 'column-primary' );
$table.find( '.column-name' ).addClass( 'column-primary' );
},
/**
* Register JS events.
*
* @since 1.7.3
*/
events: function() {
el.$overview
.on( 'click', '.wp-list-table .delete a, .wp-list-table .duplicate a', app.confirmSingleAction )
.on( 'click', '.button.delete-all', app.confirmSingleAction )
.on( 'click', '.bulkactions #doaction', app.confirmBulkAction )
.on( 'click', '#wpforms-reset-filter .reset', app.resetSearch )
.on( 'click', '.wp-list-table .wpforms-locations-count, .wp-list-table .row-actions .locations, .wp-list-table .wpforms-locations-close', app.formsLocator )
.on( 'click', '#the-list .wpforms-column-tags-edit', app.editTagsClick )
.on( 'click', '#the-list .wpforms-column-tags-edit-cancel', app.cancelEditTagsClick )
.on( 'click', '#the-list .wpforms-column-tags-edit-save', app.saveEditTagsClick )
.on( 'click', '#the-list .wpforms-bulk-edit-tags-cancel', app.cancelBulkEditTagsClick )
.on( 'click', '#the-list .wpforms-bulk-edit-tags-save', app.saveBulkEditTagsClick )
.on( 'click', '.wpforms-tags-filter .button', app.tagsFilterClick )
.on( 'click', '.wpforms-manage-tags', app.manageTagsClick )
.on( 'keydown', '.wpforms-column-tags-form input, .wpforms-bulk-edit-tags input', app.addCustomItemInput )
.on( 'removeItem', '.choices select', app.editTagsRemoveItem );
el.$bulkEditTagsForms
.on( 'removeItem', app.bulkEditTagsFormRemoveItem );
$( '#adv-settings' )
.on( 'change', 'input.hide-column-tog', app.adjustBulkEditTagsForm )
.on( 'change', '#tags-hide', app.toggleTagsColumn );
$( window )
.on( 'resize', _.debounce( app.adjustBulkEditTagsForm, 200 ) );
$( document )
.on( 'change', '.wpforms-manage-tags-items input', app.manageTagsItemChange )
.on( 'htmx:afterSwap', app.initTableNav );
},
/**
* Re-init table after swapping the content.
*
* @since 1.9.3
*/
htmxAfterSettle() {
app.initElements();
app.initTableColumns();
app.initTagsFilter();
app.adjustBulkEditTagsForm();
app.initEditTagsBulkActionItem();
},
/**
* Confirm forms deletion and duplications.
*
* @since 1.7.3
*
* @param {object} event Event object.
*/
confirmSingleAction: function( event ) {
event.preventDefault();
var $link = $( this ),
url = $link.attr( 'href' ),
msg = $link.hasClass( 'delete-all' ) ? wpforms_admin.form_delete_all_confirm : '',
type = $link.data( 'type' ) ?? '';
if ( msg === '' ) {
const duplicateMsg = type === 'template' ? wpforms_admin.template_duplicate_confirm : wpforms_admin.form_duplicate_confirm;
const deleteMsg = type === 'template' ? wpforms_admin.template_delete_confirm : wpforms_admin.form_delete_confirm;
msg = $link.parent().hasClass( 'delete' ) ? deleteMsg : duplicateMsg;
}
app.confirmModal( msg, { url } );
},
/**
* Confirm forms bulk deletion.
*
* @since 1.7.3
*
* @param {object} event Event object.
*/
confirmBulkAction: function( event ) {
var $button = $( this ),
$form = $button.closest( 'form' ),
action = $form.find( '#bulk-action-selector-top' ).val();
if ( action === 'edit_tags' ) {
event.preventDefault();
app.openBulkEditTags();
return;
}
if ( action !== 'delete' ) {
return;
}
event.preventDefault();
app.confirmModal( wpforms_admin.form_delete_n_confirm, { 'bulk': true, 'form': $form } );
},
/**
* Open confirmation modal.
*
* @since 1.7.3
*
* @param {string} msg Confirmation modal content.
* @param {object} args Additional arguments.
*/
confirmModal: function( msg, args ) {
$.confirm( {
title: wpforms_admin.heads_up,
content: msg,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_admin.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action: function() {
if ( args.url ) {
window.location = args.url;
return;
}
if ( args.bulk ) {
args.form.trigger( 'submit' );
}
},
},
cancel: {
text: wpforms_admin.cancel,
keys: [ 'esc' ],
},
},
} );
},
/**
* Open alert modal.
*
* @since 1.7.5
*
* @param {string} msg Alert modal content.
* @param {object} args Additional arguments.
*/
alertModal: function( msg, args ) {
var error = wpforms_admin_forms_overview.strings.error;
$.confirm( {
title: args.title || wpforms_admin.oops || false,
content: msg ? error + '
' + msg : error,
icon: 'fa fa-exclamation-circle',
type: args.type || 'orange',
buttons: {
confirm: {
text: wpforms_admin.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
},
},
} );
},
/**
* Reset search form.
*
* @since 1.7.3
*
* @param {object} event Event object.
*/
resetSearch: function( event ) {
// Reset search term.
$( '#wpforms-overview-search-term' ).val( '' );
// Submit the form.
$( this ).closest( 'form' ).trigger( 'submit' );
},
/**
* Show form locations. Take them from Locations column and show in the pane under the form row.
*
* @since 1.7.4
*
* @param {object} event Event object.
*
* @returns {false} Event processing status.
*/
formsLocator: function( event ) {
let $pane = $( '#wpforms-overview-table .wpforms-locations-pane' );
event.preventDefault();
const $currentRow = $( event.target.closest( 'tr' ) ),
$paneRow = $pane.prev().prev(),
$rowActions = $paneRow.find( '.row-actions' );
if ( $pane.length > 0 ) {
$pane.prev().remove();
$pane.remove();
$rowActions.removeClass( 'visible' );
if ( $paneRow.is( $currentRow ) ) {
return false;
}
}
const $locationsList = $currentRow.find( '.locations-list' );
if ( $locationsList.length === 0 ) {
return false;
}
const tdNum = $currentRow.find( 'td:not(.hidden)' ).length;
const locationsHtml = $locationsList.html();
const html = `
${ deleted }
${ wpforms_admin_forms_overview.strings.manage_tags_result_text }
`, icon: 'fa fa-exclamation-circle', type: 'green', buttons: { confirm: { text: wpforms_admin_forms_overview.strings.manage_tags_btn_refresh, btnClass: 'btn-confirm', keys: [ 'enter' ], action: function() { window.location.href = wpforms_admin_forms_overview.strings.base_url; }, }, }, } ); }, /** * Bulk edit tags action. * * @since 1.7.5 */ openBulkEditTags: function() { var forms = [], formsValue = [], tagsValue = []; // Iterate checked forms. el.$listTableRows.find( 'input:checked' ).each( function( i ) { var $input = $( this ), $tr = $input.closest( 'tr' ), $name = $tr.find( '.column-name > a:first-child' ), $tags = $tr.find( '.wpforms-column-tags-links' ), formTags = $tags.data( 'tags' ).toString() || ''; if ( $tags.data( 'is-editable' ) !== 1 ) { return; } forms.push( { value: $input.val(), label: _.escape( $name.text() ), } ); formsValue.push( $input.val() ); formTags = formTags.length ? formTags.split( ',' ) : []; tagsValue = _.union( tagsValue, formTags ); } ); if ( forms.length === 0 ) { return; } el.$bulkEditTagsRows.removeClass( 'wpforms-hidden' ); // Init Choices.js instance for forms. app.initChoicesJS( el.$bulkEditTagsForms ) .clearStore() .setChoices( forms, 'value', 'label', true ) .setChoiceByValue( formsValue ); // Init Choices.js instance for tags. app.initChoicesJS( el.$bulkEditTagsTags ) .removeActiveItems() .setChoiceByValue( tagsValue ); // Update message. app.updateBulkEditTagsFormMessage( formsValue ); }, /** * Update the message below the Bulk Edit Tags form. * * @since 1.7.5 * * @param {Array} formsValue Forms value. */ updateBulkEditTagsFormMessage: function( formsValue ) { var msg = wpforms_admin_forms_overview.strings.bulk_edit_n_forms; if ( formsValue.length === 1 ) { msg = wpforms_admin_forms_overview.strings.bulk_edit_one_form; } el.$bulkEditTagsMessage.html( msg.replace( '%d', formsValue.length ) ); }, /** * Remove form from the Bulk Edit Tags form. * * @since 1.7.5 * * @param {object} event Event object. */ bulkEditTagsFormRemoveItem: function( event ) { var formsValue = $( event.target ).data( 'choicesjs' ).getValue( true ); if ( formsValue.length === 0 ) { app.cancelBulkEditTagsClick(); } app.updateBulkEditTagsFormMessage( formsValue ); }, /** * Remove tag from Tags editor event handler. * * @since 1.7.5 * * @param {object} event Event object. */ editTagsRemoveItem: function( event ) { var allValues = _.map( wpforms_admin_forms_overview.all_tags_choices, 'value' ); if ( allValues.indexOf( event.detail.value ) >= 0 ) { return; } // We should remove new tag from the list of choices. var choicesObj = $( event.target ).data( 'choicesjs' ), currentValue = choicesObj.getValue( true ), choices = _.filter( choicesObj._currentState.choices, function( item ) { return item.value !== event.detail.value; } ); choicesObj .clearStore() .setChoices( choices, 'value', 'label', true ) .setChoiceByValue( currentValue ); }, /** * Calculate and set the bulk edit tags form attributes and styles. * * @since 1.7.5 */ adjustBulkEditTagsForm() { const $table = $( '.wp-list-table' ), $columns = $table.find( 'thead .manage-column' ).not( '.hidden' ), $formCells = $( '.wpforms-bulk-edit-tags td' ); // Update colspan attributes. $formCells.attr( 'colspan', $columns.length ); let nameWidth = $table.find( '.column-name' ).outerWidth(); nameWidth = nameWidth < 300 ? 300 : nameWidth; const cellsWidth = $table.outerWidth() - nameWidth - $table.find( '.check-column' ).outerWidth() - 10; const formsInputWidth = `calc( 100% - ${ cellsWidth }px )`; // Update width property of the forms input element. el.$bulkEditTagsForms.closest( '.wpforms-edit-forms' ).css( 'width', formsInputWidth ); }, /** * Click toggle Tags column checkbox event handler. * * @since 1.7.5 */ toggleTagsColumn: function() { $( '.wpforms-tags-filter, .wpforms-manage-tags, .bulkactions option[value="edit_tags"]' ) .toggleClass( 'wpforms-hidden', ! $( this ).is( ':checked' ) || wpforms_admin_forms_overview.all_tags_choices.length === 0 ); }, /** * Click on the Cancel button in the Bulk Edit Tags form. * * @since 1.7.5 */ cancelBulkEditTagsClick: function() { el.$bulkEditTagsRows.addClass( 'wpforms-hidden' ); }, /** * Click on the Save button in the Bulk Edit Tags form. * * @since 1.7.5 * * @param {object} event Event object. */ saveBulkEditTagsClick: function( event ) { var $btn = $( this ), $spinner = $btn.find( '.wpforms-loading-spinner' ), data = { forms: el.$bulkEditTagsForms.data( 'choicesjs' ).getValue( true ), tags: app.getTagsValue( el.$bulkEditTagsTags.data( 'choicesjs' ) ), }; // Show spinner. $spinner.removeClass( 'wpforms-hidden' ); app.saveTagsAjax( data, function( res ) { $( '#the-list .tags.column-tags' ).each( function() { var $td = $( this ), $columnLinks = $td.find( '.wpforms-column-tags-links' ), formID = $columnLinks.data( 'form-id' ) + '', $select = $td.find( '.wpforms-column-tags-form select' ), choicesObj = $select.data( 'choicesjs' ); if ( data.forms.indexOf( formID ) < 0 ) { return; } // Update tags ids. $columnLinks.data( 'tags', res.data.tags_ids ); // Update tags links in the column. $columnLinks.find( '.wpforms-column-tags-links-list' ).html( res.data.tags_links ); // Update tags options in still not converted selects. $select.html( res.data.tags_options ); if ( choicesObj ) { choicesObj .clearStore() .setChoices( wpforms_admin_forms_overview.all_tags_choices, 'value', 'label', true ) .setChoiceByValue( res.data.tags_ids.split( ',' ) ); } } ); }, function() { // Hide spinner. $spinner.addClass( 'wpforms-hidden' ); // Hide the form. el.$bulkEditTagsRows.addClass( 'wpforms-hidden' ); } ); }, /** * Add custom item to Tags dropdown on input. * * @since 1.7.5 * * @param {object} event Event object. */ addCustomItemInput: function( event ) { if ( [ 'Enter', ',' ].indexOf( event.key ) < 0 ) { return; } event.preventDefault(); event.stopPropagation(); var $select = $( this ).closest( '.choices' ).find( 'select' ), choicesObj = $select.data( 'choicesjs' ); if ( ! choicesObj || event.target.value.length === 0 ) { return; } var tagLabel = _.escape( event.target.value ).trim(), labels = _.map( choicesObj.getValue(), 'label' ).map( function( label ) { return label.toLowerCase().trim(); } ); if ( tagLabel === '' || labels.indexOf( tagLabel.toLowerCase() ) >= 0 ) { choicesObj.clearInput(); return; } app.addCustomItemInputTag( choicesObj, tagLabel ); }, /** * Add custom item to Tags dropdown on input (second part). * * @since 1.7.5 * * @param {object} choicesObj Choices.js instance. * @param {object} tagLabel Event object. */ addCustomItemInputTag: function( choicesObj, tagLabel ) { var tag = _.find( wpforms_admin_forms_overview.all_tags_choices, { label: tagLabel } ); if ( tag && tag.value ) { choicesObj.setChoiceByValue( tag.value ); } else { choicesObj.setChoices( [ { value: tagLabel, label: tagLabel, selected: true, }, ], 'value', 'label', false ); } choicesObj.clearInput(); }, }; // Provide access to public functions/properties. return app; }( document, window, jQuery ) ); WPFormsForms.Overview.init();