| Server IP : 37.187.148.235 / Your IP : 216.73.217.39 Web Server : Apache/2.4.58 (Ubuntu) mod_fcgid/2.3.9 OpenSSL/3.0.13 System : Linux server01.weblinkdesign.it 6.8.0-107-generic #107-Ubuntu SMP PREEMPT_DYNAMIC Fri Mar 13 19:51:50 UTC 2026 x86_64 User : lucafiask ( 1024) PHP Version : 8.3.30 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,exec,system,passthru,shell_exec,proc_open,popen MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /home/lucafiask/web/dev.acquamark.it/public_html/wp-content/themes/bricks/includes/ |
Upload File : |
<?php
namespace Bricks;
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
/**
* Element and popup interactions
*
* @since 1.6
*/
class Interactions {
public static $global_class_interactions = [];
public static $control_options = [];
public function __construct() {
// Add interaction attributes to root node
add_filter( 'bricks/element/set_root_attributes', [ $this, 'add_data_attributes' ], 10, 2 );
// Add popup interactions (template settings) to popup root
add_filter( 'bricks/popup/attributes', [ $this, 'add_to_template_root' ], 10, 2 );
add_action( 'init', [ $this, 'set_controls' ], 10 );
self::get_global_class_interactions();
}
/**
* Get interaction controls
*
* @return array
*
* @since 1.6
*/
public static function get_controls_data() {
return self::$control_options;
}
/**
* Set interaction controls once initially
*
* @since 1.6.2
*
* @return void
*/
public function set_controls() {
$trigger_options = [
'elementGroupTitle' => esc_html__( 'Element', 'bricks' ),
'click' => esc_html__( 'Click', 'bricks' ),
'mouseover' => esc_html__( 'Hover', 'bricks' ),
'focus' => esc_html__( 'Focus', 'bricks' ),
'blur' => esc_html__( 'Blur', 'bricks' ),
'mouseenter' => esc_html__( 'Mouse enter', 'bricks' ),
'mouseleave' => esc_html__( 'Mouse leave', 'bricks' ),
'enterView' => esc_html__( 'Enter viewport', 'bricks' ),
'leaveView' => esc_html__( 'Leave viewport', 'bricks' ),
'animationEnd' => esc_html__( 'Animation end', 'bricks' ),
'ajaxStart' => esc_html__( 'Query', 'bricks' ) . ' ' . esc_html__( 'AJAX loader', 'bricks' ) . ' (' . esc_html__( 'Start', 'bricks' ) . ')',
'ajaxEnd' => esc_html__( 'Query', 'bricks' ) . ' ' . esc_html__( 'AJAX loader', 'bricks' ) . ' (' . esc_html__( 'End', 'bricks' ) . ')',
'formSubmit' => esc_html__( 'Form', 'bricks' ) . ' ' . esc_html__( 'Submit', 'bricks' ),
'formSuccess' => esc_html__( 'Form', 'bricks' ) . ' ' . esc_html__( 'Success', 'bricks' ),
'formError' => esc_html__( 'Form', 'bricks' ) . ' ' . esc_html__( 'Error', 'bricks' ),
];
// Interactions for browser/window events
$trigger_options['browserGroupTitle'] = esc_html__( 'Browser', 'bricks' ) . ' / ' . esc_html__( 'Window', 'bricks' );
$trigger_options['scroll'] = esc_html__( 'Scroll', 'bricks' );
$trigger_options['contentLoaded'] = esc_html__( 'Content loaded', 'bricks' );
$trigger_options['mouseleaveWindow'] = esc_html__( 'Mouse leave window', 'bricks' );
// Interactions for Query filter (@since 1.11)
if ( Helpers::enabled_query_filters() ) {
$trigger_options['filterGroupTitle'] = esc_html__( 'Query filters', 'bricks' );
$trigger_options['filterOptionEmpty'] = esc_html__( 'Filter', 'bricks' ) . ': ' . esc_html__( 'Empty', 'bricks' );
$trigger_options['filterOptionNotEmpty'] = esc_html__( 'Filter', 'bricks' ) . ': ' . esc_html__( 'Not empty', 'bricks' );
}
// Interactions for WooCommerce events (@since 2.0)
if ( Woocommerce::$is_active ) {
$trigger_options['wooGroupTitle'] = 'WooCommerce';
$trigger_options['wooAddedToCart'] = esc_html__( 'Added to cart', 'bricks' );
$trigger_options['wooAddingToCart'] = esc_html__( 'Adding to cart', 'bricks' );
$trigger_options['wooRemovedFromCart'] = esc_html__( 'Removed from cart', 'bricks' );
$trigger_options['wooUpdateCart'] = esc_html__( 'Cart updated', 'bricks' );
$trigger_options['wooCouponApplied'] = esc_html__( 'Coupon applied', 'bricks' );
$trigger_options['wooCouponRemoved'] = esc_html__( 'Coupon removed', 'bricks' );
}
// STEP: Add interaction controls (= repeater)
self::$control_options = [
'type' => 'repeater',
'titleProperty' => 'trigger',
'titleEditable' => true,
'placeholder' => esc_html__( 'Interaction', 'bricks' ),
'fields' => [
// Show Interaction ID for copy & paste to other interactions
'id' => [
'label' => esc_html__( 'ID', 'bricks' ),
'type' => 'text',
'clearable' => false,
'inline' => true,
'readonly' => true,
'hasDynamicData' => false,
'copyable' => true, // NOTE: Undocumented
],
'trigger' => [
'label' => esc_html__( 'Trigger', 'bricks' ),
'type' => 'select',
'options' => $trigger_options,
'placeholder' => esc_html__( 'Select', 'bricks' ),
],
// @since 2.0
'disablePreventDefault' => [
'label' => esc_html__( 'Disable', 'bricks' ) . ': preventDefault',
'type' => 'checkbox',
'required' => [ 'trigger', '=', 'click' ],
'desc' => esc_html__( 'Allow the element\'s normal click behavior (like following links) instead of blocking it.', 'bricks' ),
],
// @since 2.0
'rootMargin' => [
'label' => 'rootMargin',
'type' => 'text',
'placeholder' => '0px 0px 0px 0px',
'required' => [ 'trigger', '=', 'enterView' ],
'desc' =>
// translators: %s is the value for root margin
sprintf( esc_html__( 'To trigger the interaction when 50%% of the element is in the viewport, set the rootMargin to %s.', 'bricks' ), '<a href="https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin" target="_blank"><code>0px 0px -50% 0px</code></a>' ),
],
'ajaxQueryId' => [
'label' => esc_html__( 'Query', 'bricks' ),
'type' => 'query-list',
'required' => [ 'trigger', '=', [ 'ajaxStart', 'ajaxEnd' ] ],
],
'filterElementId' => [
'label' => esc_html__( 'Filter', 'bricks' ) . ' (Bricks ID)',
'type' => 'text',
'placeholder' => 'ah1yh' ,
'required' => [ 'trigger', '=', [ 'filterOptionEmpty', 'filterOptionNotEmpty' ] ],
'description' => sprintf(
'%s: %s, %s, %s, %s, %s, %s, %s',
esc_html__( 'Supported filters', 'bricks' ),
esc_html__( 'Active filters', 'bricks' ),
esc_html__( 'Checkbox', 'bricks' ),
esc_html__( 'Datepicker', 'bricks' ),
esc_html__( 'Radio', 'bricks' ),
esc_html__( 'Range', 'bricks' ),
esc_html__( 'Search', 'bricks' ),
esc_html__( 'Select', 'bricks' )
),
],
'formId' => [
'label' => esc_html__( 'Form', 'bricks' ) . ' ' . esc_html__( 'ID', 'bricks' ),
'type' => 'text',
'placeholder' => '#brxe-ah1yh' ,
'required' => [ 'trigger', '=', [ 'formSubmit', 'formSuccess', 'formError' ] ],
],
'delay' => [
'label' => esc_html__( 'Delay' ),
'type' => 'text',
'placeholder' => '0s',
'required' => [ 'trigger', '=', [ 'contentLoaded' ] ],
],
'scrollOffset' => [
'label' => esc_html__( 'Scroll offset', 'bricks' ),
'type' => 'text',
'required' => [ 'trigger', '=', 'scroll' ],
],
/**
* To hold the target interaction id for animationEnd trigger.
* Leave it empty and will use the previous interaction id where action is startAnimation
*
* @since 1.8.3
*/
'animationId' => [
'label' => esc_html__( 'Target interaction ID', 'bricks' ),
'type' => 'text',
'placeholder' => esc_html__( 'Previous interaction ID', 'bricks' ),
'info' => esc_html__( 'Not allowed', 'bricks' ) . ': ' . esc_html__( 'Current interaction ID', 'bricks' ),
'required' => [ 'trigger', '=', 'animationEnd' ],
],
'action' => [
'label' => esc_html__( 'Action', 'bricks' ),
'type' => 'select',
'options' => [
'show' => esc_html__( 'Show element', 'bricks' ),
'hide' => esc_html__( 'Hide element', 'bricks' ),
'click' => esc_html__( 'Click element', 'bricks' ),
'setAttribute' => esc_html__( 'Set attribute', 'bricks' ),
'removeAttribute' => esc_html__( 'Remove attribute', 'bricks' ),
'toggleAttribute' => esc_html__( 'Toggle attribute', 'bricks' ),
'toggleOffCanvas' => esc_html__( 'Toggle offcanvas', 'bricks' ),
'loadMore' => esc_html__( 'Load more', 'bricks' ) . ' (' . esc_html__( 'Query loop', 'bricks' ) . ')',
'loadMoreGallery' => esc_html__( 'Load more', 'bricks' ) . ' (' . esc_html__( 'Image Gallery', 'bricks' ) . ')',
'startAnimation' => esc_html__( 'Start animation', 'bricks' ),
'scrollTo' => esc_html__( 'Scroll to', 'bricks' ),
'javascript' => 'JavaScript ' . esc_html__( '(Function)', 'bricks' ),
'openAddress' => esc_html__( 'Open address' ) . ' (' . esc_html__( 'Map', 'bricks' ) . ')', // (@since 2.0)
'closeAddress' => esc_html__( 'Close address' ) . ' (' . esc_html__( 'Map', 'bricks' ) . ')', // (@since 2.0)
'clearForm' => esc_html__( 'Clear form', 'bricks' ), // (@since 2.0)
'storageAdd' => esc_html__( 'Browser storage', 'bricks' ) . ': ' . esc_html__( 'Add', 'bricks' ),
'storageRemove' => esc_html__( 'Browser storage', 'bricks' ) . ': ' . esc_html__( 'Remove', 'bricks' ),
'storageCount' => esc_html__( 'Browser storage', 'bricks' ) . ': ' . esc_html__( 'Count', 'bricks' ),
],
'placeholder' => esc_html__( 'Select', 'bricks' ),
],
'storageType' => [
'label' => esc_html__( 'Type', 'bricks' ),
'type' => 'select',
'options' => [
'storageGroupTitle' => esc_html__( 'Browser storage', 'bricks' ),
'windowStorage' => esc_html__( 'Window storage', 'bricks' ),
'sessionStorage' => esc_html__( 'Session storage', 'bricks' ),
'localStorage' => esc_html__( 'Local storage', 'bricks' ),
],
'placeholder' => esc_html__( 'Select', 'bricks' ),
'required' => [ 'action', '=', [ 'storageAdd', 'storageRemove', 'storageCount' ] ],
],
'actionAttributeKey' => [
'label' => esc_html__( 'Key', 'bricks' ),
'type' => 'text',
'required' => [ 'action', '=', [ 'setAttribute', 'removeAttribute', 'toggleAttribute', 'storageAdd', 'storageRemove', 'storageCount' ] ],
],
'actionAttributeValue' => [
'label' => esc_html__( 'Value', 'bricks' ),
'type' => 'text',
'required' => [ 'action', '=', [ 'setAttribute', 'removeAttribute', 'toggleAttribute', 'storageAdd' ] ],
],
'loadMoreQuery' => [
'label' => esc_html__( 'Query', 'bricks' ),
'type' => 'query-list',
'required' => [ 'action', '=', 'loadMore' ],
],
'loadMoreTargetSelector' => [
'label' => esc_html__( 'Image Gallery', 'bricks' ) . ': ' . esc_html__( 'CSS selector', 'bricks' ),
'type' => 'text',
'placeholder' => '#brxe-abcde',
'required' => [ 'action', '=', 'loadMoreGallery' ],
'description' => esc_html__( 'Copy the CSS ID of your Image Gallery element.', 'bricks' ),
],
'animationType' => [
'label' => esc_html__( 'Animation', 'bricks' ),
'type' => 'select',
'options' => Setup::get_control_options( 'animationTypes' ),
'searchable' => true,
'inline' => true,
'placeholder' => esc_html__( 'None', 'bricks' ),
'required' => [ 'action', '=', 'startAnimation' ],
],
'animationDuration' => [
'label' => esc_html__( 'Animation duration', 'bricks' ),
'type' => 'text',
'hasDynamicData' => false,
'hasVariables' => true,
'placeholder' => '1s',
'required' => [ 'action', '=', 'startAnimation' ],
],
'animationDelay' => [
'label' => esc_html__( 'Animation delay', 'bricks' ),
'type' => 'text',
'inline' => true,
'hasDynamicData' => false,
'hasVariables' => true,
'placeholder' => '0s',
'required' => [ 'action', '=', 'startAnimation' ],
],
// Target Form ID (@since 2.0)
'targetFormSelector' => [
'label' => esc_html__( 'Target form selector', 'bricks' ) ,
'type' => 'text',
'placeholder' => 'form', // If no selector provided, it will clear all forms
'required' => [
[ 'action', '=', [ 'clearForm' ] ],
[ 'trigger', '!=', [ 'formSubmit', 'formSuccess', 'formError' ] ],
],
],
'target' => [
'label' => esc_html__( 'Target', 'bricks' ),
'type' => 'select',
'options' => [
'self' => esc_html__( 'Self', 'bricks' ),
'custom' => esc_html__( 'CSS selector', 'bricks' ),
'popup' => esc_html__( 'Popup', 'bricks' ),
],
'placeholder' => esc_html__( 'Self', 'bricks' ),
'required' => [ 'action', '!=', [ 'loadMore', 'loadMoreGallery', 'storageAdd', 'storageRemove', 'storageCount', 'toggleOffCanvas', 'openAddress', 'closeAddress', 'clearForm' ] ],
],
'targetSelector' => [
'label' => esc_html__( 'CSS selector', 'bricks' ),
'type' => 'text',
'required' => [
[ 'target', '=', 'custom' ],
[ 'action', '!=', [ 'loadMore', 'loadMoreGallery', 'storageAdd', 'storageRemove', 'storageCount', 'toggleOffCanvas', 'openAddress', 'closeAddress' ] ],
],
],
'toggleOffCanvasInfo' => [
'type' => 'info',
'content' => esc_html__( 'Do not set this interaction on a Toggle element.', 'bricks' ),
'required' => [ 'action', '=', 'toggleOffCanvas' ],
],
'offCanvasSelector' => [
'label' => esc_html__( 'Offcanvas', 'bricks' ) . ': ' . esc_html__( 'CSS selector', 'bricks' ),
'type' => 'text',
'placeholder' => '#brxe-off123',
'required' => [ 'action', '=', 'toggleOffCanvas' ],
],
'scrollToOffset' => [
'label' => esc_html__( 'Scroll to', 'bricks' ) . ': ' . esc_html__( 'Offset', 'bricks' ) . ' (px)',
'type' => 'number',
'required' => [ 'action', '=', [ 'scrollTo' ] ],
],
'scrollToDelay' => [
'label' => esc_html__( 'Scroll to', 'bricks' ) . ': ' . esc_html__( 'Delay', 'bricks' ) . ' (ms)',
'type' => 'number',
'required' => [ 'action', '=', [ 'scrollTo' ] ],
],
'templateId' => [
'label' => esc_html__( 'Popup', 'bricks' ),
'type' => 'select',
'options' => bricks_is_builder() ? Templates::get_templates_list( 'popup' ) : [],
'searchable' => true,
'placeholder' => esc_html__( 'Select template', 'bricks' ),
'required' => [
[ 'target', '=', 'popup' ],
[ 'action', '!=', [ 'openAddress', 'closeAddress' ] ],
],
],
'infoBoxId' => [
'label' => esc_html__( 'Info Box', 'bricks' ),
'type' => 'select',
'options' => bricks_is_builder() ? Templates::get_templates_list( 'infobox' ) : [],
'searchable' => true,
'placeholder' => esc_html__( 'Select template', 'bricks' ),
'required' => [ 'action', '=', [ 'openAddress', 'closeAddress' ] ],
],
// @since 1.9.4
'popupContextType' => [
'label' => esc_html__( 'Context type', 'bricks' ),
'type' => 'select',
'options' => [
'post' => esc_html__( 'Post', 'bricks' ),
'term' => esc_html__( 'Term', 'bricks' ),
'user' => esc_html__( 'User', 'bricks' ),
],
'description' => esc_html__( 'Set if your dynamic data in AJAX popup is rendered incorrectly.', 'bricks' ),
'placeholder' => esc_html__( 'Post', 'bricks' ),
'required' => [
[ 'action', '=', [ 'show', 'startAnimation' ] ],
[ 'target', '=', 'popup' ],
],
],
// @since 1.9.4
'popupContextId' => [
'label' => esc_html__( 'Context ID', 'bricks' ),
'type' => 'text',
'description' => esc_html__( 'Set if your dynamic data in AJAX popup is rendered incorrectly.', 'bricks' ),
'required' => [
[ 'action', '=', [ 'show', 'startAnimation' ] ],
[ 'target', '=', 'popup' ],
],
],
// @since 1.9.5
'jsFunction' => [
'label' => esc_html__( 'Function name', 'bricks' ) . ' (JavaScript)',
'type' => 'text',
'placeholder' => 'myFunction',
'required' => [ 'action', '=', 'javascript' ],
'description' => esc_html__( 'JavaScript function name without parentheses or window object.', 'bricks' ) . ' ' . Helpers::article_link( 'interactions/#javascript', esc_html__( 'Learn more', 'bricks' ) ),
],
// @since 1.9.5
'jsFunctionArgs' => [
'label' => esc_html__( 'Arguments', 'bricks' ),
'type' => 'repeater',
'titleProperty' => 'jsFunctionArg',
'fields' => [
'jsFunctionArg' => [
'label' => esc_html__( 'Argument', 'bricks' ),
'type' => 'text',
],
],
'default' => [
[
'jsFunctionArg' => '%brx%',
],
],
'required' => [ 'action', '=', 'javascript' ],
'desc' => sprintf(
__( 'Use %s to pass data such as the source and target elements to your custom function.', 'bricks' ),
'<strong>%brx%</strong>'
),
],
'runOnce' => [
'label' => esc_html__( 'Run only once', 'bricks' ),
'type' => 'checkbox',
'required' => [ 'trigger', '!=', [ 'contentLoaded' ] ],
],
'conditionsSep' => [
'label' => esc_html__( 'Conditions', 'bricks' ),
'description' => esc_html__( 'Run this interaction if the following conditions are met.', 'bricks' ),
'type' => 'separator',
],
'interactionConditions' => [
'type' => 'repeater',
'placeholder' => esc_html__( 'Condition', 'bricks' ),
'titleProperty' => 'conditionType',
'fields' => [
'conditionType' => [
'label' => esc_html__( 'Type', 'bricks' ),
'type' => 'select',
'options' => [
'storageGroupTitle' => esc_html__( 'Browser storage', 'bricks' ),
'windowStorage' => esc_html__( 'Window storage', 'bricks' ),
'sessionStorage' => esc_html__( 'Session storage', 'bricks' ),
'localStorage' => esc_html__( 'Local storage', 'bricks' ),
]
],
'storageKey' => [
'label' => esc_html__( 'Browser storage', 'bricks' ) . ': ' . esc_html__( 'Key', 'bricks' ),
'type' => 'text',
'required' => [ 'conditionType', '=', [ 'windowStorage', 'sessionStorage', 'localStorage' ] ],
],
'storageCompare' => [
'label' => esc_html__( 'Browser storage', 'bricks' ) . ': ' . esc_html__( 'Compare', 'bricks' ),
'type' => 'select',
'options' => [
'exists' => esc_html__( 'Exists', 'bricks' ),
'notExists' => esc_html__( 'Not exists', 'bricks' ),
'==' => '==',
'!=' => '!=',
'>=' => '>=',
'<=' => '<=',
'>' => '>',
'<' => '<',
],
'placeholder' => esc_html__( 'Exists', 'bricks' ),
'required' => [ 'conditionType', '=', [ 'windowStorage', 'sessionStorage', 'localStorage' ] ],
],
'storageCompareValue' => [
'label' => esc_html__( 'Browser storage', 'bricks' ) . ': ' . esc_html__( 'Value', 'bricks' ),
'type' => 'text',
'required' => [ 'storageCompare', '!=', [ '', 'exists', 'notExists' ] ],
],
]
],
'interactionConditionsRelation' => [
'label' => esc_html__( 'Relation', 'bricks' ),
'type' => 'select',
'inline' => true,
'options' => [
'or' => esc_html__( 'Or', 'bricks' ),
'and' => esc_html__( 'And', 'bricks' ),
],
'placeholder' => esc_html__( 'And', 'bricks' )
],
],
];
}
/**
* Get global classes with interaction settings (once initially) to merge with element setting interactions in add_data_attributes()
*
* @since 1.6
*/
public static function get_global_class_interactions() {
if ( ! empty( self::$global_class_interactions ) ) {
return;
}
$global_classes = Database::$global_data['globalClasses'];
if ( empty( $global_classes ) ) {
return;
}
foreach ( $global_classes as $global_class ) {
$class_interactions = ! empty( $global_class['settings']['_interactions'] ) ? $global_class['settings']['_interactions'] : false;
if ( $class_interactions ) {
self::$global_class_interactions[ $global_class['id'] ] = $class_interactions;
}
}
}
/**
* Add element interactions via HTML data attributes to element root node
*
* Can originate from global class and/or element settings.
*
* @since 1.6
*/
public function add_data_attributes( $attributes, $element ) {
$interactions = [];
// STEP: Element class interactions
$class_ids = ! empty( $element->settings['_cssGlobalClasses'] ) ? $element->settings['_cssGlobalClasses'] : false;
if ( is_array( $class_ids ) ) {
foreach ( $class_ids as $class_id ) {
if ( ! empty( self::$global_class_interactions[ $class_id ] ) ) {
$interactions = array_merge( self::$global_class_interactions[ $class_id ], $interactions );
}
}
}
// STEP: Element setting interactions
if ( ! empty( $element->settings['_interactions'] ) ) {
// Parse dynamic data
$element_interactions = map_deep( $element->settings['_interactions'], [ 'Bricks\Integrations\Dynamic_Data\Providers', 'render_content' ] );
$interactions = array_merge( $element_interactions, $interactions );
}
// STEP: Add interaction data attributes to element
if ( count( $interactions ) ) {
// @since 1.7 - Add attribute to element if it should be hidden initially
$hidden_on_load = false;
foreach ( $interactions as $index => $element_interactions ) {
// Interaction data modification for toggleOffCanvas (@since 1.11)
if ( isset( $element_interactions['action'] ) && $element_interactions['action'] === 'toggleOffCanvas' ) {
// Not allowed to set toggleOffCanvas interaction on toggle element
if ( $element->name === 'toggle' ) {
unset( $interactions[ $index ] );
continue;
}
$interactions[ $index ]['target'] = 'offcanvas';
}
// Interaction data modification for loadMore (@since 1.12.2)
if ( isset( $element_interactions['action'] ) && $element_interactions['action'] === 'loadMore' ) {
$load_more_query_id = isset( $element_interactions['loadMoreQuery'] ) ? $element_interactions['loadMoreQuery'] : 'main';
// Retrieve main_query_id from Database class (@since 1.12.2)
$main_query_id = (string) Database::$main_query_id;
// Only replace the actual query id if main_query_id is set and loadMoreQuery is 'main'
if ( $main_query_id !== '' && $load_more_query_id === 'main' ) {
$interactions[ $index ]['loadMoreQuery'] = $main_query_id;
}
// Support Load More inside component
if ( $load_more_query_id !== 'main' && isset( $element->element['instanceId'] ) && ! empty( $element->element['instanceId'] ) ) {
$interactions[ $index ]['loadMoreQuery'] = $load_more_query_id . '-' . $element->element['instanceId'];
}
}
// WPML: Translate popup template IDs in interactions (@since 2.1.3)
if ( \Bricks\Integrations\Wpml\Wpml::$is_active &&
isset( $element_interactions['action'] ) &&
isset( $element_interactions['target'] ) &&
isset( $element_interactions['templateId'] ) &&
$element_interactions['target'] === 'popup' &&
is_numeric( $element_interactions['templateId'] )
) {
$original_popup_id = intval( $element_interactions['templateId'] );
// Get translated popup ID using WPML
$translated_popup_id = apply_filters( 'wpml_object_id', $original_popup_id, BRICKS_DB_TEMPLATE_SLUG, true );
if ( $translated_popup_id && $translated_popup_id !== $original_popup_id ) {
$interactions[ $index ]['templateId'] = $translated_popup_id;
}
}
// Early exit if action is not startAnimation
if ( isset( $element_interactions['action'] ) && $element_interactions['action'] !== 'startAnimation' ) {
continue;
}
$target = ! empty( $element_interactions['target'] ) ? $element_interactions['target'] : 'self';
// Early exit if target is not self
if ( $target != 'self' ) {
continue;
}
$animation_type = $element_interactions['animationType'] ?? false;
// Early exit if animation type is not set
if ( ! $animation_type ) {
continue;
}
// Only set hidden_on_load to true if animationType contains 'In' (case sensitive; e.g.: 'fadeInUp', 'slideInUp', etc.)
if ( stripos( $animation_type, 'In' ) !== false ) {
$hidden_on_load = true;
// Exit foreach loop as long as one interaction needs to hide the element initially
break;
}
}
// Set attributes after modification in foreach loop logic above (@since 1.11)
$attributes['data-interactions'] = htmlspecialchars( wp_json_encode( $interactions ) );
$attributes['data-interaction-id'] = Helpers::generate_random_id( false );
if ( $hidden_on_load ) {
$attributes['data-interaction-hidden-on-load'] = true;
}
// Interaction has animation: Enqueue animate.csss
if ( strpos( $attributes['data-interactions'], 'startAnimation' ) !== false ) {
wp_enqueue_style( 'bricks-animate' );
}
// Interaction has toggleOffcanvas: Add attributes (@since 1.11)
if ( strpos( $attributes['data-interactions'], 'toggleOffCanvas' ) !== false ) {
// For frontend bricksOffcanvas JavaScript
$attributes['data-brx-toggle-offcanvas'] = 'true';
// Set the element focusable
if ( ! isset( $attributes['tabindex'] ) ) {
$attributes['tabindex'] = '0';
}
// Set aria attributes
if ( ! isset( $attributes['aria-expanded'] ) ) {
$attributes['aria-expanded'] = 'false';
}
// Set aria-label (Note: always Open, no option to change or user can set on the attribute itself)
if ( ! isset( $attributes['aria-label'] ) ) {
$attributes['aria-label'] = esc_html__( 'Open', 'bricks' );
}
}
// Add interaction loop attributes for JavaScript logic (@since 1.7.1)
$looping_query_id = Query::is_any_looping();
if ( $looping_query_id ) {
// Unique identifier for each element in query loop to avoid targeting the wrong elements (popups, etc.) (@since 1.8.4)
$attributes['data-interaction-loop-id'] = Query::get_looping_unique_identifier( 'interaction' );
}
}
return $attributes;
}
/**
* Add template (e.g. popup) interaction settings to template root node
*
* @since 1.6
*/
public function add_to_template_root( $attributes, $template_id ) {
$template_settings = Helpers::get_template_settings( $template_id );
if ( ! empty( $template_settings['template_interactions'] ) ) {
// STEP: Parse dynamic data
$interactions = map_deep( $template_settings['template_interactions'], [ 'Bricks\Integrations\Dynamic_Data\Providers', 'render_content' ] );
// WPML: Translate popup template IDs in template interactions (@since 2.1.3)
if ( \Bricks\Integrations\Wpml\Wpml::$is_active ) {
foreach ( $interactions as $index => $interaction ) {
if ( isset( $interaction['action'] ) &&
isset( $interaction['target'] ) &&
isset( $interaction['templateId'] ) &&
$interaction['target'] === 'popup' &&
is_numeric( $interaction['templateId'] )
) {
$original_popup_id = intval( $interaction['templateId'] );
$translated_popup_id = apply_filters( 'wpml_object_id', $original_popup_id, BRICKS_DB_TEMPLATE_SLUG, true );
if ( $translated_popup_id && $translated_popup_id !== $original_popup_id ) {
$interactions[ $index ]['templateId'] = $translated_popup_id;
}
}
}
}
// Ensure animation is enqueued even if the page has no data-interactions (@since 1.8)
$json_interactions = wp_json_encode( $interactions );
if ( strpos( $json_interactions, 'startAnimation' ) !== false ) {
wp_enqueue_style( 'bricks-animate' );
}
$attributes['data-interactions'] = htmlspecialchars( $json_interactions );
$attributes['data-interaction-id'] = Helpers::generate_random_id( false );
}
return $attributes;
}
}