upskill-event-manager/assets/js/builder.js
Ben Reed cdc5ea85f4 feat: Add comprehensive CSS, JavaScript and theme asset infrastructure
Add massive collection of CSS, JavaScript and theme assets that were previously excluded:

**CSS Files (681 total):**
- HVAC plugin-specific styles (hvac-*.css): 34 files including dashboard, certificates, registration, mobile nav, accessibility fixes, animations, and welcome popup
- Theme framework files (Astra, builder systems, layouts): 200+ files
- Plugin compatibility styles (WooCommerce, WPForms, Elementor, Contact Form 7): 150+ files
- WordPress core and editor styles: 50+ files
- Responsive and RTL language support: 200+ files

**JavaScript Files (400+ total):**
- HVAC plugin functionality (hvac-*.js): 27 files including menu systems, dashboard enhancements, profile sharing, mobile responsive features, accessibility, and animations
- Framework and library files: jQuery plugins, GSAP, AOS, Swiper, Chart.js, Lottie, Isotope
- Plugin compatibility scripts: WPForms, WooCommerce, Elementor, Contact Form 7, LifterLMS
- WordPress core functionality: customizer, admin, block editor compatibility
- Third-party integrations: Stripe, SMTP, analytics, search functionality

**Assets:**
- Certificate background images and logos
- Comprehensive theme styling infrastructure
- Mobile-responsive design systems
- Cross-browser compatibility assets
- Performance-optimized minified versions

**Updated .gitignore:**
- Fixed asset directory whitelisting patterns to properly include CSS/JS/images
- Added proper directory structure recognition (!/assets/css/, !/assets/js/, etc.)
- Maintains security by excluding sensitive files while including essential assets

This commit provides the complete frontend infrastructure needed for:
- Full theme functionality and styling
- Plugin feature implementations
- Mobile responsiveness and accessibility
- Cross-browser compatibility
- Performance optimization
- Developer workflow support
2025-08-11 16:20:31 -03:00

600 lines
15 KiB
JavaScript

/* global WPForms, wpf */
/**
* WPForms Providers Builder ConstantContactV3 module.
*
* @since 1.9.3
*/
WPForms.Admin.Builder.Providers.ConstantContactV3 = WPForms.Admin.Builder.Providers.ConstantContactV3 || ( function( document, window, $ ) {
/**
* Public functions and properties.
*
* @since 1.9.3
*
* @type {Object}
*/
const app = {
/**
* CSS selectors.
*
* @since 1.9.3
*
* @type {Object}
*/
selectors: {
accountField: '.js-wpforms-builder-constant-contact-v3-provider-connection-account',
actionData: '.wpforms-builder-constant-contact-v3-provider-actions-data',
actionField: '.js-wpforms-builder-constant-contact-v3-provider-connection-action',
connection: '.wpforms-panel-content-section-constant-contact-v3 .wpforms-builder-provider-connection',
},
/**
* jQuery elements.
*
* @since 1.9.3
*
* @type {Object}
*/
$elements: {
$connections: $( '.wpforms-panel-content-section-constant-contact-v3 .wpforms-builder-provider-connections' ),
$holder: $( '#wpforms-panel-providers' ),
$panel: $( '#constant-contact-v3-provider' ),
},
/**
* Current provider slug.
*
* @since 1.9.3
*
* @type {string}
*/
provider: 'constant-contact-v3',
/**
* This is a shortcut to the WPForms.Admin.Builder.Providers object,
* that handles the parent all-providers functionality.
*
* @since 1.9.3
*
* @type {Object}
*/
Providers: {},
/**
* This is a shortcut to the WPForms.Admin.Builder.Templates object,
* that handles all the template management.
*
* @since 1.9.3
*
* @type {Object}
*/
Templates: {},
/**
* This is a shortcut to the WPForms.Admin.Builder.Providers.cache object,
* that handles all the cache management.
*
* @since 1.9.3
*
* @type {Object}
*/
Cache: {},
/**
* This is a flag for ready state.
*
* @since 1.9.3
*
* @type {boolean}
*/
isReady: false,
/**
* Start the engine.
*
* Run initialization on the providers panel only.
*
* @since 1.9.3
*/
init() {
// We are requesting/loading a Providers panel.
if ( wpf.getQueryString( 'view' ) === 'providers' ) {
app.$elements.$holder.on( 'WPForms.Admin.Builder.Providers.ready', app.ready );
}
// We have switched to a Providers panel.
$( document ).on( 'wpformsPanelSwitched', function( event, panel ) {
if ( panel === 'providers' ) {
app.ready();
}
} );
},
/**
* Initialized once the DOM and Providers are fully loaded.
*
* @since 1.9.3
*/
ready() {
if ( app.isReady ) {
return;
}
app.Providers = WPForms.Admin.Builder.Providers;
app.Templates = WPForms.Admin.Builder.Templates;
app.Cache = app.Providers.cache;
// Register custom Underscore.js templates.
app.Templates.add( [
'wpforms-constant-contact-v3-builder-content-connection',
'wpforms-constant-contact-v3-builder-content-connection-error',
'wpforms-constant-contact-v3-builder-content-connection-select-field',
'wpforms-constant-contact-v3-builder-content-connection-conditionals',
] );
// Events registration.
app.bindUIActions();
app.bindTriggers();
app.processInitial();
// Save a flag for ready state.
app.isReady = true;
},
/**
* Process various events as a response to UI interactions.
*
* @since 1.9.3
*/
bindUIActions() {
app.$elements.$panel
.on( 'connectionCreate', app.connection.create )
.on( 'connectionDelete', app.connection.delete )
.on( 'change', app.selectors.accountField, app.ui.accountField.change )
.on( 'change', app.selectors.actionField, app.ui.actionField.change );
},
/**
* Fire certain events on certain actions, specific for related connections.
* These are not directly caused by user manipulations.
*
* @since 1.9.3
*/
bindTriggers() {
app.$elements.$connections.on( 'connectionsDataLoaded', function( event, data ) {
if ( _.isEmpty( data.connections ) ) {
return;
}
for ( const connectionId in data.connections ) {
app.connection.generate( {
connection: data.connections[ connectionId ],
conditional: data.conditionals[ connectionId ],
} );
}
} );
app.$elements.$connections.on( 'connectionGenerated', function( event, data ) {
const $connection = app.connection.getById( data.connection.id );
if ( _.has( data.connection, 'isNew' ) && data.connection.isNew ) {
// Run replacing temporary connection ID if it's a new connection.
app.connection.replaceIds( data.connection.id, $connection );
return;
}
$( app.selectors.actionField, $connection ).trigger( 'change' );
} );
},
/**
* Compile template with data if any and display them on a page.
*
* @since 1.9.3
*/
processInitial() {
app.$elements.$connections.prepend( app.tmpl.commonsHTML() );
app.connection.dataLoad();
},
/**
* Connection property.
*
* @since 1.9.3
*/
connection: {
/**
* Sometimes we might need to a get a connection DOM element by its ID.
*
* @since 1.9.3
*
* @param {string} connectionId Connection ID to search for a DOM element by.
*
* @return {jQuery} jQuery object for connection.
*/
getById( connectionId ) {
return app.$elements.$connections.find( '.wpforms-builder-provider-connection[data-connection_id="' + connectionId + '"]' );
},
/**
* Sometimes in DOM we might have placeholders or temporary connection IDs.
* We need to replace them with actual values.
*
* @since 1.9.3
*
* @param {string} connectionId New connection ID to replace to.
* @param {Object} $connection jQuery DOM connection element.
*/
replaceIds( connectionId, $connection ) {
// Replace old temporary %connection_id% from PHP code with the new one.
$connection.find( 'input, select, label' ).each( function() {
const $this = $( this );
if ( $this.attr( 'name' ) ) {
$this.attr( 'name', $this.attr( 'name' ).replace( /%connection_id%/gi, connectionId ) );
}
if ( $this.attr( 'id' ) ) {
$this.attr( 'id', $this.attr( 'id' ).replace( /%connection_id%/gi, connectionId ) );
}
if ( $this.attr( 'for' ) ) {
$this.attr( 'for', $this.attr( 'for' ).replace( /%connection_id%/gi, connectionId ) );
}
if ( $this.attr( 'data-name' ) ) {
$this.attr( 'data-name', $this.attr( 'data-name' ).replace( /%connection_id%/gi, connectionId ) );
}
} );
},
/**
* Create a connection using the user entered name.
*
* @since 1.9.3
*
* @param {Object} event Event object.
* @param {string} name Connection name.
*/
create( event, name ) {
const connectionId = new Date().getTime().toString( 16 ),
connection = {
id: connectionId,
name,
isNew: true,
};
app.Cache.addTo( app.provider, 'connections', connectionId, connection );
app.connection.generate( {
connection,
} );
},
/**
* Connection is deleted - delete a cache as well.
*
* @since 1.9.3
*
* @param {Object} event Event object.
* @param {Object} $connection jQuery DOM element for a connection.
*/
delete( event, $connection ) {
const $holder = app.Providers.getProviderHolder( app.provider );
if ( ! $connection.closest( $holder ).length ) {
return;
}
const connectionId = $connection.data( 'connection_id' );
if ( _.isString( connectionId ) ) {
app.Cache.deleteFrom( app.provider, 'connections', connectionId );
}
},
/**
* Get the template and data for a connection and process it.
*
* @since 1.9.3
*
* @param {Object} data Connection data.
*
* @return {void}
*/
generate( data ) {
const accounts = app.Cache.get( app.provider, 'accounts' );
if ( _.isEmpty( accounts ) || ! app.account.isAccountExists( data.connection.account_id, accounts ) ) {
return;
}
const actions = app.Cache.get( app.provider, 'actions' ),
lists = app.Cache.get( app.provider, 'lists' );
return app.connection.renderConnections( accounts, lists, actions, data );
},
/**
* Render connections.
*
* @since 1.9.3
*
* @param {Object} accounts List of accounts.
* @param {Object} lists List of lists.
* @param {Object} actions List of actions.
* @param {Object} data Connection data.
*/
renderConnections( accounts, lists, actions, data ) {
if ( ! app.account.isAccountExists( data.connection.account_id, accounts ) ) {
return;
}
const tmplConnection = app.Templates.get( 'wpforms-' + app.provider + '-builder-content-connection' ),
tmplConditional = app.Templates.get( 'wpforms-constant-contact-v3-builder-content-connection-conditionals' ),
conditional = _.has( data.connection, 'isNew' ) && data.connection.isNew ? tmplConditional() : data.conditional;
app.$elements.$connections.prepend(
tmplConnection( {
accounts,
lists,
actions,
connection: data.connection,
conditional,
provider: app.provider,
} )
);
app.$elements.$connections.trigger( 'connectionGenerated', [ data ] );
},
/**
* Fire AJAX-request to retrieve the list of all saved connections.
*
* @since 1.9.3
*/
dataLoad() {
app
.Providers.ajax
.request( app.provider, {
data: {
task: 'connections_get',
},
} )
.done( function( response ) {
if (
! response.success ||
! _.has( response.data, 'connections' )
) {
return;
}
[
'accounts',
'actions',
'actions_fields',
'conditionals',
'connections',
'custom_fields',
'lists',
].forEach( ( dataType ) => {
app.Cache.set( app.provider, dataType, jQuery.extend( {}, response.data[ dataType ] ) );
} );
app.$elements.$connections.trigger( 'connectionsDataLoaded', [ response.data ] );
} );
},
},
/**
* Account property.
*
* @since 1.9.3
*/
account: {
/**
* Check if a provided account is listed inside an account list.
*
* @since 1.9.3
*
* @param {string} accountId Connection account ID to check.
* @param {Object} accounts Array of objects, usually received from API.
*
* @return {boolean} True if an account exists.
*/
isAccountExists( accountId, accounts ) {
if ( _.isEmpty( accounts ) ) {
return false;
}
// New connections that have not been saved don't have the account ID yet.
if ( _.isEmpty( accountId ) ) {
return true;
}
return _.has( accounts, accountId );
},
},
/**
* All methods that modify the UI of a page.
*
* @since 1.9.3
*/
ui: {
/**
* Account field methods.
*
* @since 1.9.3
*/
accountField: {
/**
* Callback-function on change event.
*
* @since 1.9.3
*/
change() {
const $this = $( this ),
$connection = $this.closest( app.selectors.connection ),
$actionName = $( app.selectors.actionField, $connection );
$actionName.prop( 'selectedIndex', 0 ).trigger( 'change' );
// If an account is empty.
if ( _.isEmpty( $this.val() ) ) {
$actionName.prop( 'disabled', true );
$( app.selectors.actionData, $connection ).html( '' );
return;
}
$actionName.prop( 'disabled', false );
$this.removeClass( 'wpforms-error' );
},
},
/**
* Action methods.
*
* @since 1.9.3
*/
actionField: {
/**
* Callback-function on change event.
*
* @since 1.9.3
*/
change() {
const $this = $( this ),
$connection = $this.closest( app.selectors.connection ),
$account = $( app.selectors.accountField, $connection ),
$action = $( app.selectors.actionField, $connection );
app.ui.actionField.render( {
action: 'action',
target: $this,
/* eslint-disable camelcase */
account_id: $account.val(),
action_name: $action.val(),
connection_id: $connection.data( 'connection_id' ),
/* eslint-enable camelcase */
} );
$this.removeClass( 'wpforms-error' );
},
/**
* Render HTML.
*
* @since 1.9.3
*
* @param {Object} args Arguments.
*/
render( args ) {
const fields = app.tmpl.renderActionFields( args ),
$connection = app.connection.getById( args.connection_id ),
$connectionData = $( app.selectors.actionData, $connection );
$connectionData.html( fields );
app.$elements.$holder.trigger( 'connectionRendered', [ app.provider, args.connection_id ] );
},
/**
* Get a list of constant-contact lists.
*
* @since 1.9.3
*
* @param {string} accountId Account ID.
*
* @return {Array} List of constant-contact lists.
*/
getList( accountId ) {
const listsCache = app.Cache.get( app.provider, 'lists' );
return ! _.isEmpty( listsCache ) && ! _.isEmpty( listsCache[ accountId ] ) ? listsCache[ accountId ] : [];
},
},
},
/**
* All methods for JavaScript templates.
*
* @since 1.9.3
*/
tmpl: {
/**
* Compile and retrieve an HTML for common elements.
*
* @since 1.9.3
*
* @return {string} Compiled HTML.
*/
commonsHTML() {
const tmplError = app.Templates.get( 'wpforms-' + app.provider + '-builder-content-connection-error' );
return tmplError();
},
/**
* Compile and retrieve an HTML for "Custom Fields Table".
*
* @since 1.9.3
*
* @param {Object} args Arguments
*
* @return {string} Compiled HTML.
*/
renderActionFields( args ) {
const fields = wpf.getFields(),
actionsFields = app.Cache.get( app.provider, 'actions_fields' ),
customFields = app.Cache.get( app.provider, 'custom_fields' ),
connection = app.Cache.getById( app.provider, 'connections', args.connection_id );
let fieldHTML = '';
$.each( actionsFields[ args.target.val() ], function( key, field ) {
if ( key === 'custom_fields' ) {
const tmplFields = app.Templates.get( 'wpforms-providers-builder-content-connection-fields' );
fieldHTML += tmplFields( {
connection,
fields,
provider: {
slug: app.provider,
fields: customFields[ args.account_id ],
},
isSupportSubfields: true,
} );
return;
}
const options = key === 'list' ? app.ui.actionField.getList( args.account_id ) : Object.values( fields );
const templateName = 'wpforms-' + app.provider + '-builder-content-connection-' + field.type + '-field';
const tmplField = app.Templates.get( templateName );
fieldHTML += tmplField( {
connection,
name: key,
field,
provider: {
slug: app.provider,
fields: actionsFields[ args.target.val() ],
},
options,
} );
} );
return fieldHTML;
},
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );
// Initialize.
WPForms.Admin.Builder.Providers.ConstantContactV3.init();