Fix File
•
/
home
/
sportsfe...
/
httpdocs
/
wp-conte...
/
themes
/
Divi
/
includes
/
builder
•
File:
class-et-builder-element.php
•
Content:
); $additional_fields .= sprintf( '<input id="%2$s" type="%11$s" class="%3$s%5$s et_pb_setting_mobile et_pb_setting_mobile_%9$s"%6$s%8$s%1$s data-device="%9$s" %4$s%10$s/>%7$s', $value_mobile, esc_attr( $field['id'] ) . '_' . $device_type, esc_attr( $field['class'] ), $attributes, ( $validate_number ? ' et-validate-number' : '' ), // #5 ( $validate_number ? ' maxlength="3"' : '' ), ( ! empty( $field['additional_button'] ) ? $field['additional_button'] : '' ), ( '' !== $default ? sprintf( ' data-default="%1$s"', esc_attr( $default ) ) : '' ), esc_attr( $device_type ), $has_saved_value, // #10, $type ); } // Replace value HTML of last edited field. Last edited value maybe an empty // string on some range input under Shadow settings. $last_edited_value_html = $default_last_edited_is_arr ? ' value="<%%- typeof( %1$s ) !== \'undefined\' ? %2$s : \'%3$s\' %%>" ' : $value_html; $value_last_edited = sprintf( $last_edited_value_html, esc_attr( $field_var_name . '_last_edited' ), esc_attr( $field_var_name . '_last_edited' ), '' ); $class_last_edited = array( 'et_pb_mobile_last_edited_field', ); $attrs = ''; if ( ! empty( $field['responsive_affects'] ) ) { $class_last_edited[] = 'et-pb-responsive-affects'; $attrs .= sprintf( ' data-responsive-affects="%1$s" data-responsive-desktop-name="%2$s"', esc_attr( implode( ', ', $field['responsive_affects'] ) ), esc_attr( $field['name'] ) ); } // additional field to save the last edited field which will be opened automatically $additional_fields .= sprintf( '<input id="%1$s" type="hidden" class="%3$s"%2$s%4$s>', esc_attr( $field_name . '_last_edited' ), $value_last_edited, esc_attr( implode( ' ', $class_last_edited ) ), $attrs ); } if ( 'range' === $field['type'] ) { $range_value_html = $default_is_arr ? ' value="<%%- typeof( %1$s ) !== \'undefined\' ? %2$s :parseFloat(%3$s) %%>" ' : ' value="<%%- typeof( %1$s ) !== \'undefined\' ? %2$s : parseFloat(\'%3$s\') %%>" '; $value = sprintf( $range_value_html, esc_attr( $field_var_name ), esc_attr( sprintf( 'parseFloat( %1$s )', $field_var_name ) ), $default_value ); $fixed_range = isset($field['fixed_range']) && $field['fixed_range']; $range_settings_html = ''; $range_properties = apply_filters( 'et_builder_range_properties', array( 'min', 'max', 'step' ) ); foreach ( $range_properties as $property ) { if ( isset( $field['range_settings'][ $property ] ) ) { $range_settings_html .= sprintf( ' %2$s="%1$s"', esc_attr( $field['range_settings'][ $property ] ), esc_html( $property ) ); } } $range_el = sprintf( '<input type="range" data-name="%7$s" class="et-pb-main-setting et-pb-range%4$s%6$s" data-default="%2$s"%1$s%3$s%5$s %8$s />', $value, esc_attr( $default ), $range_settings_html, $need_mobile_options ? ' et_pb_setting_mobile et_pb_setting_mobile_desktop et_pb_setting_mobile_active' : '', $need_mobile_options ? ' data-device="desktop"' : '', $fixed_range ? ' et-pb-fixed-range' : '', esc_attr( $field['name'] ), $unit ); if ( $need_mobile_options ) { foreach( array( 'tablet', 'phone' ) as $device_type ) { // additional data attribute to handle default values for the responsive options $has_saved_value = sprintf( ' data-has_saved_value="<%%- typeof( %1$s ) !== \'undefined\' ? \'yes\' : \'no\' %%>" ', esc_attr( $field_var_name . '_' . $device_type ) ); $value_mobile_range = sprintf( $value_html, esc_attr( $field_var_name . '_' . $device_type ), esc_attr( sprintf( 'parseFloat( %1$s )', $field_var_name . '_' . $device_type ) ), $default_value ); $range_el .= sprintf( '<input type="range" class="et-pb-main-setting et-pb-range et_pb_setting_mobile et_pb_setting_mobile_%3$s%6$s" data-default="%1$s"%4$s%2$s data-device="%3$s"%5$s %7$s/>', esc_attr( $default ), $range_settings_html, esc_attr( $device_type ), $value_mobile_range, $has_saved_value, $fixed_range ? ' et-pb-fixed-range' : '', $unit ); } } $field_el = $range_el . "\n" . $field_el; } if ( $need_mobile_options ) { $field_el = $field_el . $additional_fields; } break; } if ( isset( $field['has_preview'] ) && $field['has_preview'] ) { $field_el = sprintf( '<%%= window.et_builder.options_template_output("option_preview_buttons") %%> %1$s', $field_el ); } if ( $need_mobile_options ) { $field_el = $mobile_settings_tabs . "\n" . $field_el; $field_el .= '<span class="et-pb-mobile-settings-toggle"></span>'; } if ( isset( $field['type'] ) && isset( $field['tab_slug'] ) && 'advanced' === $field['tab_slug'] && ! $is_custom_color ) { $field_el .= $reset_button_html; } if ( isset( $field['after'] ) && ! $only_options ) { $field_el .= $this->render_field_before_after_element( $field['after'] ); } return "\t" . $field_el; } public function render_field_before_after_element( $elements ) { $field_el = ''; $elements = is_array( $elements ) ? $elements : array( $elements ); foreach ( $elements as $element ) { $attributes = ''; if ( ! empty( $element['attributes'] ) ) { $this->process_html_attributes( $element, $attributes ); } switch ( $element['type'] ) { case 'button': $class = isset( $element['class'] ) ? esc_attr( $element['class'] ) : ''; $text = isset( $element['text'] ) ? et_core_esc_previously( $element['text'] ) : ''; $field_el .= sprintf( '<button class="button %1$s"%2$s>%3$s</button>', $class, $attributes, $text ); break; } } return $field_el; } function render_font_select( $name, $id = '', $group_label ) { $options_output = '<%= window.et_builder.fonts_template() %>'; $font_weight_output = '<%= window.et_builder.fonts_weight_template() %>'; $output = sprintf( '<div class="et-pb-select-font-outer" data-group_label="%6$s"> <div class="et-pb-settings-custom-select-wrapper et-pb-settings-option-select-searchable"> <div class="et_pb_select_placeholder"></div> <ul class="et-pb-settings-option-select et-pb-settings-option-select-advanced et-pb-main-setting"> <li class="et-pb-select-options-filter"> <input type="text" class="et-pb-settings-option-input et-pb-main-setting regular-text et-pb-menu-filter" placeholder="Search Fonts"> </li> <li class="et_pb_selected_item_container select-option-item"> </li> <li class="et-pb-option-subgroup et-pb-recent-fonts"> <p class="et-pb-subgroup-title">%4$s</p> <ul> </ul> </li> %3$s </ul> </div> </div> %5$s', esc_attr( $name ), ( ! empty( $id ) ? sprintf(' id="%s"', esc_attr( $id ) ) : '' ), $options_output . "\n\t\t\t\t\t", esc_html__( 'Recent', 'et_builder' ), $font_weight_output, esc_attr( $group_label ) ); return $output; } function render_select( $name, $options, $id = '', $class = '', $attributes = '', $field_type = '', $button_options = array(), $default = '', $only_options = false ) { $options_output = ''; $processed_options = $options; if ( 'select_with_option_groups' === $field_type ) { foreach ( $processed_options as $option_group_name => $option_group ) { $option_group_name = esc_attr( $option_group_name ); $options_output .= '0' !== $option_group_name ? "<optgroup label='{$option_group_name}'>" : ''; $options_output .= sprintf( '<%%= window.et_builder.options_template_output("select",%1$s,this.model.toJSON()) %%>', sprintf( '{select_name: "%1$s", list: %2$s, default: %3$s, }', $name, wp_json_encode( $option_group ), $default ) ); $options_output .= '0' !== $option_group_name ? '</optgroup>' : ''; } $class = rtrim( $class ); $name = $id = ''; } else { $class = rtrim( 'et-pb-main-setting ' . $class ); $options_output .= sprintf( '<%%= window.et_builder.options_template_output("select",%1$s,this.model.toJSON()) %%>', sprintf( '{select_name: "%1$s", list: %2$s, default: %3$s, }', $name, wp_json_encode( $options ), $default ) ); } $output = sprintf( '%6$s <select name="%1$s"%2$s%3$s%4$s class="%3$s %8$s"%9$s>%5$s</select> %7$s', esc_attr( $name ), ( ! empty( $id ) ? sprintf(' id="%s"', esc_attr( $id ) ) : '' ), ( ! empty( $class ) ? esc_attr( $class ) : '' ), ( ! empty( $attributes ) ? $attributes : '' ), $options_output . "\n\t\t\t\t\t", 'yes_no_button' === $field_type ? sprintf( '<div class="et_pb_yes_no_button_wrapper %2$s"> %1$s', sprintf( '<%%= window.et_builder.options_template_output("yes_no_button",%1$s) %%>', wp_json_encode( array( 'on' => esc_html( $processed_options['on'] ), 'off' => esc_html( $processed_options['off'] ), ) ) ), ( ! empty( $button_options['button_type'] ) && 'equal' === $button_options['button_type'] ? ' et_pb_button_equal_sides' : '' ) ) : '', 'yes_no_button' === $field_type ? '</div>' : '', esc_attr( $field_type ), '' !== $name ? sprintf( ' data-saved_value="<%%= typeof( %1$s ) !== \'undefined\' ? %1$s : \'\' %%>"', esc_attr( str_replace( '-', '_', $name ) ) ) : '' ); return $only_options ? $options_output : $output; } function render_multiple_buttons( $name, $options, $id = '', $class = '', $attributes = '', $value = '', $default = '' ) { $class = rtrim( 'et-pb-main-setting ' . $class ); $output = sprintf( '<div class="et_pb_multiple_buttons_wrapper"> <input id="%1$s" name="%7$s" type="hidden" class="%2$s" %3$s%5$s %4$s/> %6$s </div>', esc_attr( $id ), esc_attr( $class ), $value, $attributes, ( '' !== $default ? sprintf( ' data-default=%1$s', esc_attr( $default ) ) : '' ), sprintf( '<%%= window.et_builder.options_template_output("multiple_buttons",%1$s) %%>', wp_json_encode( $options ) ), esc_attr( $name ) ); return $output; } /** * @deprecated */ function get_main_tabs() { $tabs = array( 'general' => et_builder_i18n( 'Content' ), 'advanced' => et_builder_i18n( 'Design' ), 'custom_css' => et_builder_i18n( 'Advanced' ), ); return apply_filters( 'et_builder_main_tabs', $tabs ); } function get_validation_attr_rules() { return array( 'minlength', 'maxlength', 'min', 'max', ); } function get_validation_class_rules() { return array( 'required', 'email', 'url', 'date', 'dateISO', 'number', 'digits', 'creditcard', ); } function sort_fields( $fields ) { $tabs_fields = array(); $sorted_fields = array(); $i = 0; // Sort fields array by tab name foreach ( $fields as $field_slug => $field_options ) { // Option template replaces field's array configuration into string which refers to // saved template data & template id; thus add index order if $field_options is array. if ( is_array( $field_options ) ) { $field_options['_order_number'] = $i; } $tab_slug = ! empty( $field_options['tab_slug'] ) ? $field_options['tab_slug'] : 'general'; $tabs_fields[ $tab_slug ][ $field_slug ] = $field_options; $i++; } // Sort fields within tabs by priority foreach ( $tabs_fields as $tab_fields ) { uasort( $tab_fields, array( 'self', 'compare_by_priority' ) ); $sorted_fields = array_merge( $sorted_fields, $tab_fields ); } return $sorted_fields; } function get_options() { $output = ''; $toggle_all_options_slug = 'all_options'; $toggles_used = isset( $this->settings_modal_toggles ); $tabs_output = array( 'general' => array() ); $all_fields = $this->sort_fields( $this->_get_fields() ); $all_fields_keys = array_keys( $all_fields ); $background_fields_names = $this->get_background_fields_names(); $module_has_background_color_field = in_array( 'background_color', $all_fields_keys ); $all_toggles = self::get_toggles( 'post' ); foreach( $all_fields as $field_name => $field ) { if ( ! empty( $field['type'] ) && ( 'skip' === $field['type'] || 'computed' === $field['type'] ) ) { continue; } if ( ! self::$_->array_get( $field, 'bb_support', true ) ) { continue; } // add only options allowed for current user if ( ( ! et_pb_is_allowed( 'edit_colors' ) && ( ! empty( $field['type'] ) && in_array( $field['type'], array( 'color', 'color-alpha' ) ) || ( ! empty( $field['option_category'] ) && 'color_option' === $field['option_category'] ) ) ) || ( ! et_pb_is_allowed( 'edit_content' ) && ! empty( $field['option_category'] ) && 'basic_option' === $field['option_category'] ) || ( ! et_pb_is_allowed( 'edit_layout' ) && ! empty( $field['option_category'] ) && 'layout' === $field['option_category'] ) || ( ! et_pb_is_allowed( 'edit_configuration' ) && ! empty( $field['option_category'] ) && 'configuration' === $field['option_category'] ) || ( ! et_pb_is_allowed( 'edit_fonts' ) && ! empty( $field['option_category'] ) && ( 'font_option' === $field['option_category'] || ( 'button' === $field['option_category'] && ! empty( $field['type'] ) && 'font' === $field['type'] ) ) ) || ( ! et_pb_is_allowed( 'edit_buttons' ) && ! empty( $field['option_category'] ) && 'button' === $field['option_category'] ) || ( ! et_pb_is_allowed( 'edit_borders' ) && ! empty( $field['option_category'] ) && 'border' === $field['option_category'] ) ) { continue; } // check for allowed 3rd party custom options categories if ( ! empty( $field['option_category'] ) && ! et_pb_is_allowed( $field['option_category'] ) ) { continue; } $option_output = ''; if ( 'background_color' === $field_name ) { $background_fields_ui = $this->wrap_settings_background_fields( $all_fields ); // Append background fields UI if applicable. Append standard option otherwise if ( '' !== $background_fields_ui ) { // unset depends_show_if because background fields visibility handled in Background UI. unset( $field['depends_show_if'] ); // append background UI $option_output .= $background_fields_ui; } else { $field['skip_background_ui'] = true; $option_output .= $this->wrap_settings_option_label( $field ); $option_output .= $this->wrap_settings_option_field( $field ); } } elseif ( $module_has_background_color_field && in_array( $field_name , $background_fields_names ) ) { // remove background-related fields from setting modals since it'll be printed by background UI continue; } else { // append normal fields $option_output .= $this->wrap_settings_option_label( $field ); $option_output .= $this->wrap_settings_option_field( $field ); } $tab_slug = ! empty( $field['tab_slug'] ) ? $field['tab_slug'] : 'general'; $is_toggle_option = isset( $field['toggle_slug'] ) && $toggles_used && isset( $this->settings_modal_toggles[ $tab_slug ] ); $toggle_slug = $is_toggle_option ? $field['toggle_slug'] : $toggle_all_options_slug; $sub_toggle_slug = 'all_options' !== $toggle_slug && isset( $field['sub_toggle'] ) && '' !== $field['sub_toggle'] ? $field['sub_toggle'] : 'main'; $tabs_output[ $tab_slug ][ $toggle_slug ][ $sub_toggle_slug ][] = $this->wrap_settings_option( $option_output, $field, $field_name ); if ( isset( $field['toggle_slug'] ) && ! isset( $this->settings_modal_toggles[ $tab_slug ]['toggles'][ $toggle_slug ] ) ) { if ( $toggle = self::$_->array_get( $all_toggles, "{$this->slug}.{$tab_slug}.toggles.{$field['toggle_slug']}" ) ) { self::$_->array_set( $this->settings_modal_toggles, "{$tab_slug}.toggles.{$toggle_slug}", $toggle ); } } } $default_tabs_keys = array_keys( $this->main_tabs ); $module_tabs_keys = array_keys( $tabs_output ); $module_default_tabs = array_intersect( $default_tabs_keys, $module_tabs_keys ); $module_custom_tabs = array_diff( $module_tabs_keys, $default_tabs_keys ); // Make sure tabs order is correct for BB, i.e. custom tabs goes after default tabs and default tabs in following order: // `Content`, `Design`, `Advanced` $module_tabs_sorted = array_merge( $module_default_tabs, $module_custom_tabs ); $tabs_output_processed = array(); // reorder tabs to be sure they're correct foreach( $module_tabs_sorted as $tab_slug ) { $tabs_output_processed[ $tab_slug ] = $tabs_output[ $tab_slug ]; } foreach ( $tabs_output_processed as $tab_slug => $tab_settings ) { // Add only tabs allowed for current user if ( ! et_pb_is_allowed( $tab_slug . '_settings' ) ) { continue; } $tab_output = ''; $this->used_tabs[] = $tab_slug; $i = 0; if ( isset( $tabs_output_processed[ $tab_slug ] ) ) { // Group field with no explicit toggle_slug then append it on top of other toggles if ( isset( $tabs_output_processed[ $tab_slug ][ $toggle_all_options_slug ] ) ) { $toggle_unclassified_output = ''; foreach ( $tabs_output_processed[ $tab_slug ][ $toggle_all_options_slug ] as $no_toggle_option_data ) { foreach( $no_toggle_option_data as $subtoggle_id => $no_toggle_option_output ) { $toggle_unclassified_output .= $no_toggle_option_output; } } $tab_output .= sprintf( '<div class="et-pb-options-toggle-container et-pb-options-toggle-disabled"> <h3 class="et-pb-option-toggle-title">%1$s</h3> <div class="et-pb-option-toggle-content"> %2$s </div> </div>', esc_html__( $this->name, 'et_builder' ), et_core_esc_previously( $toggle_unclassified_output ), 'et-pb-options-toggle-disabled' ); } if ( isset( $this->settings_modal_toggles[ $tab_slug ] ) ) { $this->settings_modal_toggles[ $tab_slug ]['toggles'] = self::et_pb_order_toggles_by_priority( $this->settings_modal_toggles[ $tab_slug ]['toggles'] ); foreach ( $this->settings_modal_toggles[ $tab_slug ]['toggles'] as $toggle_slug => $toggle_data ) { $toggle_heading = is_array( $toggle_data ) ? $toggle_data['title'] : $toggle_data; if ( ! isset( $tabs_output_processed[ $tab_slug ][ $toggle_slug ] ) ) { continue; } $i++; $toggle_output = ''; $is_accordion_enabled = isset( $this->settings_modal_toggles[ $tab_slug ]['settings']['bb_toggles_enabeld'] ) && $this->settings_modal_toggles[ $tab_slug ]['settings']['bb_toggles_enabled'] ? true : false; $is_tabbed_subtoggles = isset( $toggle_data['tabbed_subtoggles'] ); $is_bb_icons_support = isset( $toggle_data['bb_icons_support'] ); $subtoggle_tabs_nav = ''; if ( is_array( $toggle_data ) && ! empty( $toggle_data ) ) { if ( ! isset( $toggle_data['sub_toggles'] ) ) { $toggle_data['sub_toggles'] = array( 'main' => '' ); } foreach( $toggle_data['sub_toggles'] as $sub_toggle_id => $sub_toggle_data ) { if ( ! isset( $tabs_output_processed[ $tab_slug ][ $toggle_slug ][ $sub_toggle_id ] ) ) { continue; } if ( $is_tabbed_subtoggles ) { $subtoggle_tabs_nav .= sprintf( '<li class="subtoggle_tabs_nav_item"><a class="subtoggle_tabs_nav_item_inner%3$s" data-tab_id="%1$s">%2$s</a></li>', $sub_toggle_id, $is_bb_icons_support ? '' : esc_html( $sub_toggle_data['name'] ), $is_bb_icons_support ? sprintf( ' subtoggle_tabs_nav_icon subtoggle_tabs_nav_icon-%1$s', esc_attr( $sub_toggle_data['icon'] ) ) : '' ); } $subtoggle_options = ''; foreach ( $tabs_output_processed[ $tab_slug ][ $toggle_slug ][ $sub_toggle_id ] as $toggle_option_output ) { $subtoggle_options .= $toggle_option_output; } if ( 'main' === $sub_toggle_id ) { $toggle_output .= $subtoggle_options; } else { $toggle_output .= sprintf( '<div class="et_pb_subtoggle_section%2$s"%3$s> %1$s </div>', $subtoggle_options, $is_tabbed_subtoggles ? ' et_pb_tabbed_subtoggle' : '', $is_tabbed_subtoggles ? sprintf( ' data-tab_id="%1$s"', esc_attr( $sub_toggle_id ) ) : '' ); } } } else { foreach ( $tabs_output_processed[ $tab_slug ][ $toggle_slug ] as $toggle_option_id => $toggle_option_data ) { foreach( $toggle_option_data as $toggle_option_output ) { $toggle_output .= $toggle_option_output; } } } if ( '' === $toggle_output ) { continue; } $toggle_output = sprintf( '<div class="et-pb-options-toggle-container%3$s%4$s%5$s"> <h3 class="et-pb-option-toggle-title">%1$s</h3> %6$s <div class="et-pb-option-toggle-content"> %2$s </div> </div>', esc_html( $toggle_heading ), $toggle_output, ( $is_accordion_enabled ? ' et-pb-options-toggle-enabled' : ' et-pb-options-toggle-disabled' ), ( 1 === $i && $is_accordion_enabled ? ' et-pb-option-toggle-content-open' : '' ), $is_tabbed_subtoggles ? ' et_pb_contains_tabbed_subtoggle' : '', $is_tabbed_subtoggles && '' !== $subtoggle_tabs_nav ? sprintf( '<ul class="subtoggle_tabs_nav">%1$s</ul>', $subtoggle_tabs_nav ) : '' ); $tab_output .= $toggle_output; } } } $output .= sprintf( '<div class="et-pb-options-tab et-pb-options-tab-%1$s"> %3$s %2$s </div>', esc_attr( $tab_slug ), $tab_output, ( 'general' === $tab_slug ? $this->children_settings() : '' ) ); } // return error message if no tabs allowed for current user if ( '' === $output ) { $output = esc_html__( "You don't have sufficient permissions to access the settings", 'et_builder' ); } return $output; } function children_settings() { $output = ''; if ( ! empty( $this->child_slug ) ) { $child_module = self::get_module( $this->child_slug ); if ( isset( $child_module->bb_support ) && ! $child_module->bb_support ) { return $output; } $output = sprintf( '%6$s<div class="et-pb-option-advanced-module-settings" data-module_type="%1$s"> <ul class="et-pb-sortable-options"> </ul> %2$s </div> <div class="et-pb-option et-pb-option-main-content et-pb-option-advanced-module"> <label for="et_pb_content">%3$s</label> <div class="et-pb-option-container"> <div id="et_pb_content"><%%= typeof( et_pb_content )!== \'undefined\' && \'\' !== et_pb_content.trim() ? et_pb_content : \'%7$s\' %%></div> <p class="description">%4$s</p> </div> </div>%5$s', esc_attr( $this->child_slug ), ! in_array( $this->child_slug, array( 'et_pb_column', 'et_pb_column_inner' ) ) ? sprintf( '<a href="#" class="et-pb-add-sortable-option"><span>%1$s</span></a>', esc_html( $this->add_new_child_text() ) ) : '', et_builder_i18n( 'Content' ), esc_html__( 'Here you can define the content that will be placed within the current tab.', 'et_builder' ), "\n\n", "\t", $this->predefined_child_modules() ); } return $output; } function add_new_child_text() { $child_slug = ! empty( $this->child_item_text ) ? $this->child_item_text : ''; $child_slug = '' === $child_slug ? esc_html__( 'Add New Item', 'et_builder' ) : sprintf( esc_html__( 'Add New %s', 'et_builder' ), $child_slug ); return $child_slug; } function wrap_settings( $output ) { $tabs_output = ''; $i = 0; $tabs = array(); // General Settings Tab should be added to all modules if allowed if ( et_pb_is_allowed( 'general_settings' ) ) { $tabs['general'] = isset( $this->main_tabs['general'] ) ? $this->main_tabs['general'] : esc_html__( 'General Settings', 'et_builder' ); } foreach ( $this->used_tabs as $tab_slug ) { if ( 'general' === $tab_slug ) { continue; } // Add only tabs allowed for current user if ( et_pb_is_allowed( $tab_slug . '_settings' ) ) { if ( isset( $this->main_tabs[ $tab_slug ] ) ) { // if it's one of 3 default tabs $tabs[ $tab_slug ] = $this->main_tabs[ $tab_slug ]; } else { // Use tab name if it's properly registered custom tab. Fallback to tab slug otherwise $tabs[ $tab_slug ] = isset( $this->settings_modal_tabs ) && isset( $this->settings_modal_tabs[ $tab_slug ] ) ? $this->settings_modal_tabs[ $tab_slug ]['name'] : $tab_slug; } } } $tabs_array = array(); $tabs_json = ''; foreach ( $tabs as $tab_slug => $tab_name ) { $i++; $tabs_array[$i] = array( 'slug' => $tab_slug, 'label' => $tab_name, ); $tabs_json = wp_json_encode( $tabs_array ); } $tabs_output = sprintf( '<%%= window.et_builder.settings_tabs_output(%1$s) %%>', $tabs_json ); $preview_tabs_output = '<%= window.et_builder.preview_tabs_output() %>'; $output = sprintf( '%2$s %3$s <div class="et-pb-options-tabs"> %1$s </div> <div class="et-pb-preview-tab"></div> ', $output, $tabs_output, $preview_tabs_output ); return sprintf( '%2$s<div class="et-pb-main-settings">%1$s</div>%3$s', "\n\t\t" . $output, "\n\t\t", "\n" ); } function wrap_validation_form( $output ) { return '<form class="et-builder-main-settings-form validate">' . $output . '</form>'; } /** * Get the module's props mapped to their default values. * * @since 3.1 Renamed from `get_shortcode_fields()` to `get_default_props()`. * @since 1.0 * * @return array */ public function get_default_props() { if ( method_exists( $this, 'get_shortcode_fields' ) ) { // Backwards compatibility return $this->__call( 'get_shortcode_fields', array() ); } // Get module's default props from static property If current module's default props // have been generated before. if ( isset( self::$_default_props[ $this->slug ] ) ) { return self::$_default_props[ $this->slug ]; } $fields = array(); // Resolve option template foreach( $this->process_fields( $this->fields_unprocessed ) as $field_name => $field ) { $value = ''; if ( isset( $field['composite_type'], $field['composite_structure'] ) ) { require_once ET_BUILDER_DIR . 'module/field/attribute/composite/Parser.php'; $composite_atts = ET_Builder_Module_Field_Attribute_Composite_Parser::parse( $field['composite_type'], $field['composite_structure'] ); $fields = array_merge( $fields, $composite_atts ); } else { if ( isset( $field['default_on_front'] ) ) { $value = $field['default_on_front']; } else if ( isset( $field['default'] ) ) { $value = $field['default']; } $fields[ $field_name ] = $value; } } $fields['disabled'] = 'off'; $fields['disabled_on'] = ''; $fields['global_module'] = ''; $fields['temp_global_module'] = ''; $fields['global_parent'] = ''; $fields['temp_global_parent'] = ''; $fields['saved_tabs'] = ''; $fields['ab_subject'] = ''; $fields['ab_subject_id'] = ''; $fields['ab_goal'] = ''; $fields['locked'] = ''; $fields['template_type'] = ''; $fields['inline_fonts'] = ''; $fields['collapsed'] = ''; // Default props of each modules are always identical; thus saves it as static prop // so the next same modules doesn't need to process all of these again repetitively. self::$_default_props[ $this->slug ] = $fields; return $fields; } function get_module_data_attributes() { $attributes = apply_filters( "{$this->slug}_data_attributes", array(), $this->props, $this->render_count() ); $data_attributes = ''; if ( ! empty( $attributes ) ) { foreach ( $attributes as $name => $value ) { $data_attributes .= sprintf( ' data-%1$s="%2$s"', sanitize_title( $name ), esc_attr( $value ) ); } } return $data_attributes; } function build_microtemplate() { $this->validation_in_use = false; $template_output = ''; if ( 'child' === $this->type ) { $id_attr = sprintf( 'et-builder-advanced-setting-%s', $this->slug ); } else { $id_attr = sprintf( 'et-builder-%s-module-template', $this->slug ); } if ( ! isset( $this->settings_text ) ) { $settings_text = sprintf( __( '%1$s %2$s Settings', 'et_builder' ), esc_html( $this->name ), 'child' === $this->type ? esc_html__( 'Item', 'et_builder' ) : esc_html__( 'Module', 'et_builder' ) ); } else { $settings_text = $this->settings_text; } if ( file_exists( ET_BUILDER_DIR . 'microtemplates/' . $this->slug . '.php' ) ) { ob_start(); include ET_BUILDER_DIR . 'microtemplates/' . $this->slug . '.php'; $output = ob_get_clean(); } else { $output = $this->get_options(); } $output = $this->wrap_settings( $output ); if ( $this->validation_in_use ) { $output = $this->wrap_validation_form( $output ); } $template_output = sprintf( '<script type="text/template" id="%1$s"> <h3 class="et-pb-settings-heading">%2$s</h3> %3$s </script>', esc_attr( $id_attr ), esc_html( $settings_text ), et_core_intentionally_unescaped( $output, 'html' ) ); if ( 'child' === $this->type ) { $title_var = esc_js( $this->child_title_var ); $title_var = false === strpos( $title_var, 'et_pb_' ) && 'admin_label' !== $title_var ? 'et_pb_' . $title_var : $title_var; $title_fallback_var = esc_js( $this->child_title_fallback_var ); $title_fallback_var = false === strpos( $title_fallback_var, 'et_pb_' ) ? 'et_pb_'. $title_fallback_var : $title_fallback_var; $add_new_text = isset( $this->advanced_setting_title_text ) ? $this->advanced_setting_title_text : $this->add_new_child_text(); $template_output .= sprintf( '%6$s<script type="text/template" id="et-builder-advanced-setting-%1$s-title"> <%% if ( typeof( %2$s ) !== \'undefined\' && typeof( %2$s ) === \'string\' && %2$s !== \'\' ) { %%> <%% if ( ET_PageBuilder.isDynamicContent(%2$s) ) { %%> %7$s <%% } else { %%> <%%- %2$s.replace( /%%91/g, "[" ).replace( /%%93/g, "]" ) %%> <%% } %%> <%% } else if ( typeof( %3$s ) !== \'undefined\' && typeof( %3$s ) === \'string\' && %3$s !== \'\' ) { %%> <%% if ( ET_PageBuilder.isDynamicContent(%3$s) ) { %%> %7$s <%% } else { %%> <%%- %3$s.replace( /%%91/g, "[" ).replace( /%%93/g, "]" ) %%> <%% } %%> <%% } else { %%> <%%- \'%4$s\' %%> <%% } %%> </script>%5$s', esc_attr( $this->slug ), esc_html( $title_var ), esc_html( $title_fallback_var ), esc_html( $add_new_text ), "\n\n", "\t", $this->get_icon( 'lock' ) . esc_html__( 'Dynamic Content', 'et_builder' ) ); } return $template_output; } function get_gradient( $args ) { $defaults = apply_filters( 'et_pb_default_gradient', array( 'type' => ET_Global_Settings::get_value( 'all_background_gradient_type' ), 'direction' => ET_Global_Settings::get_value( 'all_background_gradient_direction' ), 'radial_direction' => ET_Global_Settings::get_value( 'all_background_gradient_direction_radial' ), 'color_start' => ET_Global_Settings::get_value( 'all_background_gradient_start' ), 'color_end' => ET_Global_Settings::get_value( 'all_background_gradient_end' ), 'start_position' => ET_Global_Settings::get_value( 'all_background_gradient_start_position' ), 'end_position' => ET_Global_Settings::get_value( 'all_background_gradient_end_position' ), ) ); $args = wp_parse_args( array_filter( $args ), $defaults ); $direction = $args['type'] === 'linear' ? $args['direction'] : "circle at {$args['radial_direction']}"; $start_position = et_sanitize_input_unit( $args['start_position'], false, '%' ); $end_Position = et_sanitize_input_unit( $args['end_position'], false, '%'); return esc_html( "{$args['type']}-gradient( {$direction}, {$args['color_start']} ${start_position}, {$args['color_end']} ${end_Position} )" ); } function get_rel_values() { return array( 'bookmark', 'external', 'nofollow', 'noreferrer', 'noopener', ); } function get_rel_attributes( $saved_value, $add_tag = true ) { $rel_attributes = array(); if ( $saved_value ) { $rel_values = $this->get_rel_values(); $selected_rels = explode( '|', $saved_value ); foreach ( $selected_rels as $index => $selected_rel ) { if ( ! $selected_rel || 'off' === $selected_rel ) { continue; } $rel_attributes[] = $rel_values[ $index ]; } } $attr = empty( $rel_attributes ) ? '' : implode( ' ', $rel_attributes ); return ( $add_tag && '' !== $attr ) ? sprintf( ' rel="%1$s"', esc_attr( $attr ) ) : $attr; } /** * Get text orientation. * * @since 3.23 Add device and desktop default parameter to get responsive value. * * @param string $device Device name. * @param string $desktop_default Default desktop value. * @return string RTL ready text alignment value. */ function get_text_orientation( $device = 'desktop', $desktop_default = '' ) { $text_orientation = 'desktop' === $device && isset( $this->props['text_orientation'] ) ? $this->props['text_orientation'] : ''; if ( 'desktop' !== $device ) { $text_orientation = et_pb_responsive_options()->get_any_value( $this->props, "text_orientation_{$device}", $desktop_default ); } return et_pb_get_alignment( $text_orientation ); } /** * Get text orientation class. * * @since 3.23 Generate text orientation classes for tablet and phone. * * @return string Text orientation class names. */ function get_text_orientation_classname( $print_default = false ) { $text_orientation = $this->get_text_orientation(); $text_orientation_tablet = $this->get_text_orientation( 'tablet' ); $text_orientation_phone = $this->get_text_orientation( 'phone' ); // Should be `justified` instead of justify in classname. $text_orientation = 'justify' === $text_orientation ? 'justified' : $text_orientation; $text_orientation_tablet = 'justify' === $text_orientation_tablet ? 'justified' : $text_orientation_tablet; $text_orientation_phone = 'justify' === $text_orientation_phone ? 'justified' : $text_orientation_phone; $default_classname = $print_default ? ' et_pb_text_align_left' : ''; $text_orientation_classname = ''; if ( '' !== $text_orientation ) { $text_orientation_classname .= " et_pb_text_align_{$text_orientation}"; } if ( '' !== $text_orientation_tablet ) { $text_orientation_classname .= " et_pb_text_align_{$text_orientation_tablet}-tablet"; } if ( '' !== $text_orientation_phone ) { $text_orientation_classname .= " et_pb_text_align_{$text_orientation_phone}-phone"; } return '' !== $text_orientation_classname ? $text_orientation_classname : $default_classname; } // intended to be overridden as needed function get_max_width_additional_css() { return ''; } /** * Get type of element */ public function get_type() { return $this->type; } /** * Remove suffix of a string */ function remove_suffix( $string, $separator = '_' ) { $stringAsArray = explode( $separator, $string ); array_pop( $stringAsArray ); return implode( $separator, $stringAsArray ); } protected function _is_field_applicable( $field ) { $result = true; // Field can be undefined/empty in some 3rd party modules without VB support. Handle this situation if ( ! $field ) { return $result; } $depends_on = self::$_->array_get( $field, 'depends_on', false ); $depends_show_if = self::$_->array_get( $field, 'depends_show_if', false ); if ( $depends_on && $depends_show_if ) { foreach ( $depends_on as $attr_name ) { if ( $result && self::$_->array_get( $this->props, $attr_name ) !== $depends_show_if ) { $result = false; break; } } } return $result; } /** * process the fields. * * @since 3.23 Add function to process advanced form field options set. * * @param string $function_name String of the function_name * @return void */ function process_additional_options( $function_name ) { $module = $this; if ( $function_name && $function_name !== $this->slug ) { if ( ! $module = self::get_module( $function_name, $this->get_post_type() ) ) { $module = $this; } else { $module->props = $this->props; $module->classname = $this->classname; } } if ( ! isset( $module->advanced_fields ) || false === $module->advanced_fields ) { return; } $module->process_advanced_fonts_options( $function_name ); // Process Text Shadow CSS $module->text_shadow->process_advanced_css( $module, $function_name ); $module->process_advanced_background_options( $function_name ); $module->process_advanced_text_options( $function_name ); $module->process_advanced_borders_options( $function_name ); $module->process_advanced_filter_options( $function_name ); $module->process_height_options( $function_name ); $module->process_overflow_options( $function_name ); $module->process_advanced_custom_margin_options( $function_name ); $module->process_max_width_options( $function_name ); $module->process_advanced_button_options( $function_name ); // Process Form Field CSS. $module->process_advanced_form_field_options( $function_name ); $this->process_box_shadow( $function_name ); $this->process_position( $function_name ); $this->process_transform( $function_name ); // Process Margin & Padding CSS. $module->margin_padding->process_advanced_css( $module, $function_name ); $this->setup_hover_transitions( $function_name ); } function process_inline_fonts_option( $fonts_list ) { if ( '' === $fonts_list ) { return; } $fonts_list_array = explode( ',', $fonts_list ); foreach( $fonts_list_array as $font_name ) { et_builder_enqueue_font( $font_name ); } } /** * Process advanced font styles. * * @since 3.23 Add support to generate responsive styles of font, text color, and text align. * And also process styles of block elements sub options group. * * @param string $function_name Module slug. */ function process_advanced_fonts_options( $function_name ) { // Disable if module doesn't set advanced_fields property and has no VB support if ( ! $this->has_vb_support() && ! $this->has_advanced_fields ) { return; } if ( ! self::$_->array_get( $this->advanced_fields, 'fonts', false ) ) { return; } $font_options = array(); $slugs = array( 'font', 'font_size', 'text_color', 'letter_spacing', 'line_height', 'text_align', ); $mobile_options_slugs = array( 'font_tablet', 'font_phone', 'font_size_tablet', 'font_size_phone', 'text_color_tablet', 'text_color_phone', 'line_height_tablet', 'line_height_phone', 'letter_spacing_tablet', 'letter_spacing_phone', 'text_align_tablet', 'text_align_phone', ); $slugs = array_merge( $slugs, $mobile_options_slugs ); // merge all slugs into single array to define them in one place // Separetely defined and merged *_last_edited slugs. It needs to be merged as reference but shouldn't be looped for calling mobile attributes $mobile_options_last_edited_slugs = array( 'font_last_edited', 'text_color_last_edited', 'font_size_last_edited', 'line_height_last_edited', 'letter_spacing_last_edited', 'text_align_last_edited', ); $slugs = array_merge( $slugs, $mobile_options_last_edited_slugs ); foreach ( $this->advanced_fields['fonts'] as $option_name => $option_settings ) { $style = ''; $hover_style = ''; $important_options = array(); $is_important_set = isset( $option_settings['css']['important'] ); $is_placeholder = isset( $option_settings['css']['placeholder'] ); $use_global_important = $is_important_set && 'all' === $option_settings['css']['important']; if ( ! $use_global_important && $is_important_set && 'plugin_only' === $option_settings['css']['important'] && et_builder_has_limitation('force_use_global_important') ) { $use_global_important = true; } if ( $is_important_set && is_array( $option_settings['css']['important'] ) ) { $important_options = $option_settings['css']['important']; if ( et_builder_has_limitation('force_use_global_important') && in_array( 'plugin_all', $option_settings['css']['important'] ) ) { $use_global_important = true; } } foreach ( $slugs as $font_option_slug ) { if ( isset( $this->props["{$option_name}_{$font_option_slug}"] ) ) { $font_options["{$option_name}_{$font_option_slug}"] = $this->props["{$option_name}_{$font_option_slug}"]; } } $field_key = "{$option_name}_{$slugs[0]}"; $global_setting_name = $this->get_global_setting_name( $field_key ); $global_setting_value = ET_Global_Settings::get_value( $global_setting_name ); // Add default parameter to override global setting value, just in case we need to // use another default. $field_option_default = isset( $this->fields_unprocessed[ $field_key ]['default'] ) ? $this->fields_unprocessed[ $field_key ]['default'] : $global_setting_value; $field_option_value = isset( $font_options[ $field_key ] ) ? $font_options[ $field_key ] : ''; if ( '' !== $field_option_value || ! $global_setting_value ) { $important = in_array( 'font', $important_options ) || $use_global_important ? ' !important' : ''; $font_styles = et_builder_set_element_font( $field_option_value, ( '' !== $important ), $field_option_default ); // Get font custom breakpoint if needed on desktop. $font_custom_desktop_breakpoint = et_pb_font_options()->get_breakpoint_by_font_value( $font_options, $field_key ); if ( isset( $option_settings['css']['font'] ) || ! empty( $font_custom_desktop_breakpoint ) ) { // Prepare font styles args. $font_styles_args = array( 'selector' => et_pb_font_options()->get_font_selector( $option_settings, $this->main_css_element ), 'declaration' => rtrim( $font_styles ), 'priority' => $this->_style_priority, ); // Set custom media query if needed. if ( ! empty( $font_custom_desktop_breakpoint ) ) { $font_styles_args['media_query'] = ET_Builder_Element::get_media_query( $font_custom_desktop_breakpoint ); } self::set_style( $function_name, $font_styles_args ); } else { $style .= $font_styles; } } $size_option_name = "{$option_name}_{$slugs[1]}"; $default_size = isset( $this->fields_unprocessed[ $size_option_name ]['default'] ) ? $this->fields_unprocessed[ $size_option_name ]['default'] : ''; $size_option_value = ''; if ( isset( $font_options[ $size_option_name ] ) && ! in_array( trim( $font_options[ $size_option_name ] ), array( '', 'px', $default_size ) ) ) { $important = in_array( 'size', $important_options ) || $use_global_important ? ' !important' : ''; $size_option_value = et_builder_process_range_value( $font_options[ $size_option_name ] ); $style .= sprintf( 'font-size: %1$s%2$s; ', esc_html( $size_option_value ), esc_html( $important ) ); } // Hover font size $size_hover = trim( et_pb_hover_options()->get_value( $size_option_name, $this->props, '' ) ); if ( ! in_array( $size_hover, array( '', 'px', $size_option_value ) ) ) { $important = in_array( 'size', $important_options ) || $use_global_important ? ' !important' : ''; $hover_style .= sprintf( 'font-size: %1$s%2$s; ', esc_html( et_builder_process_range_value( $size_hover ) ), esc_html( $important ) ); } $text_color_option_name = "{$option_name}_{$slugs[2]}"; // Ensure if text color option is not disabled on current font options. $hide_text_color = isset( $option_settings['hide_text_color'] ) && true === $option_settings['hide_text_color']; // handle the value from old option $old_option_ref = isset( $option_settings['text_color'] ) && isset( $option_settings['text_color']['old_option_ref'] ) ? $option_settings['text_color']['old_option_ref'] : ''; $old_option_val = '' !== $old_option_ref && isset( $this->props[ $old_option_ref ] ) ? $this->props[ $old_option_ref ] : ''; $default_value = '' !== $old_option_val && isset( $option_settings['text_color'] ) && isset( $option_settings['text_color']['default'] ) ? $option_settings['text_color']['default'] : ''; if ( isset( $font_options[ $text_color_option_name ] ) && '' !== $font_options[ $text_color_option_name ] && ! $hide_text_color ) { $important = ' !important'; if ( $default_value !== $font_options[ $text_color_option_name ] ) { if ( isset( $option_settings['css']['color'] ) ) { self::set_style( $function_name, array( 'selector' => $option_settings['css']['color'], 'declaration' => sprintf( 'color: %1$s%2$s;', esc_html( $font_options[ $text_color_option_name ] ), esc_html( $important ) ), 'priority' => $this->_style_priority, ) ); } else { $style .= sprintf( 'color: %1$s%2$s; ', esc_html( $font_options[ $text_color_option_name ] ), esc_html( $important ) ); } } } $text_color_hover = et_pb_hover_options()->get_value( $text_color_option_name, $this->props ); if ( $default_value !== $text_color_hover && ! empty( $text_color_hover ) && ! $hide_text_color ) { $important = ' !important'; if ( isset( $option_settings['css']['color'] ) ) { $sel = et_pb_hover_options()->add_hover_to_selectors( $option_settings['css']['color'] ); self::set_style( $function_name, array( 'selector' => self::$_->array_get( $option_settings, 'css.color_hover', $sel ), 'declaration' => sprintf( 'color: %1$s%2$s;', esc_html( $text_color_hover ), esc_html( $important ) ), 'priority' => $this->_style_priority, ) ); } else { $hover_style .= sprintf( 'color: %1$s%2$s; ', esc_html( $text_color_hover ), esc_html( $important ) ); } } $letter_spacing_option_name = "{$option_name}_{$slugs[3]}"; $default_letter_spacing = isset( $this->fields_unprocessed[ $letter_spacing_option_name ]['default'] ) ? $this->fields_unprocessed[ $letter_spacing_option_name ]['default'] : ''; $letter_spacing_value = ''; if ( isset( $font_options[ $letter_spacing_option_name ] ) && ! in_array( trim( $font_options[ $letter_spacing_option_name ] ), array( '', 'px', $default_letter_spacing ) ) ) { $important = in_array( 'letter-spacing', $important_options ) || $use_global_important ? ' !important' : ''; $letter_spacing_value = et_builder_process_range_value( $font_options[ $letter_spacing_option_name ], 'letter_spacing' ); $style .= sprintf( 'letter-spacing: %1$s%2$s; ', esc_html( $letter_spacing_value ), esc_html( $important ) ); if ( isset( $option_settings['css']['letter_spacing'] ) ) { self::set_style( $function_name, array( 'selector' => $option_settings['css']['letter_spacing'], 'declaration' => sprintf( 'letter-spacing: %1$s%2$s;', esc_html( $letter_spacing_value ), esc_html( $important ) ), 'priority' => $this->_style_priority, ) ); } } // Hover letter spacing $letter_spacing_hover = trim( et_pb_hover_options()->get_value( $letter_spacing_option_name, $this->props, '' ) ); if ( ! in_array( $letter_spacing_hover, array( '', 'px', $letter_spacing_value ) ) ) { $important = in_array( 'letter-spacing', $important_options ) || $use_global_important ? ' !important' : ''; if ( et_builder_is_hover_enabled( $letter_spacing_option_name, $this->props ) ) { if ( isset( $option_settings['css']['letter_spacing_hover'] ) ) { self::set_style( $function_name, array( 'selector' => $option_settings['css']['letter_spacing_hover'], 'declaration' => sprintf( 'letter-spacing: %1$s%2$s;', esc_html( et_builder_process_range_value( $letter_spacing_hover ) ), esc_html( $important ) ), 'priority' => $this->_style_priority, ) ); } else { $hover_style .= sprintf( 'letter-spacing: %1$s%2$s; ', esc_html( et_builder_process_range_value( $letter_spacing_hover ) ), esc_html( $important ) ); } } if ( isset( $option_settings['css']['letter_spacing'] ) ) { if ( et_builder_is_hover_enabled( $letter_spacing_option_name, $this->props ) ) { if ( $default_letter_spacing !== $letter_spacing_hover ) { if ( isset( $option_settings['css']['color'] ) ) { $sel = et_pb_hover_options()->add_hover_to_selectors( $option_settings['css']['letter_spacing'] ); self::set_style( $function_name, array( 'selector' => self::$_->array_get( $option_settings, 'css.letter_spacing_hover', $sel ), 'declaration' => sprintf( 'color: %1$s%2$s;', esc_html( $letter_spacing_hover ), esc_html( $important ) ), 'priority' => $this->_style_priority, ) ); } } } } } $line_height_option_name = "{$option_name}_{$slugs[4]}"; $line_height_value = ''; if ( isset( $font_options[ $line_height_option_name ] ) ) { $default_line_height = isset( $this->fields_unprocessed[ $line_height_option_name ]['default'] ) ? $this->fields_unprocessed[ $line_height_option_name ]['default'] : ''; if ( ! in_array( trim( $font_options[ $line_height_option_name ] ), array( '', 'px', $default_line_height ) ) ) { $important = in_array( 'line-height', $important_options ) || $use_global_important ? ' !important' : ''; $line_height_value = et_builder_process_range_value( $font_options[ $line_height_option_name ], 'line_height' ); $style .= sprintf( 'line-height: %1$s%2$s; ', esc_html( $line_height_value ), esc_html( $important ) ); if ( isset( $option_settings['css']['line_height'] ) ) { self::set_style( $function_name, array( 'selector' => $option_settings['css']['line_height'], 'declaration' => sprintf( 'line-height: %1$s%2$s;', esc_html( $line_height_value ), esc_html( $important ) ), 'priority' => $this->_style_priority, ) ); } } } // Hover line height $line_height_hover = trim( et_pb_hover_options()->get_value( $line_height_option_name, $this->props, '' ) ); if ( ! in_array( $line_height_hover, array( '', 'px', $line_height_value ) ) ) { $important = in_array( 'line-height', $important_options ) || $use_global_important ? ' !important' : ''; if ( et_builder_is_hover_enabled( $line_height_option_name, $this->props ) ) { $hover_style .= sprintf( 'line-height: %1$s%2$s; ', esc_html( et_builder_process_range_value( $line_height_hover, 'line_height' ) ), esc_html( $important ) ); } if ( isset( $option_settings['css']['line_height'] ) ) { if ( et_builder_is_hover_enabled( $line_height_option_name, $this->props ) ) { if ( isset( $option_settings['css']['color'] ) ) { $sel = et_pb_hover_options()->add_hover_to_selectors( $option_settings['css']['line_height'] ); self::set_style( $function_name, array( 'selector' => self::$_->array_get( $option_settings, 'css.line_height_hover', $sel ), 'declaration' => sprintf( 'line-height: %1$s%2$s;', esc_html( $line_height_hover ), esc_html( $important ) ), 'priority' => $this->_style_priority, ) ); } } } } $text_align_option_name = "{$option_name}_{$slugs[5]}"; // Ensure to not print text alignment if current font hide text alignment option. $hide_text_align = self::$_->array_get( $option_settings, 'hide_text_align', false ); if ( isset( $font_options[ $text_align_option_name ] ) && '' !== $font_options[ $text_align_option_name ] && ! $hide_text_align ) { $important = in_array( 'text-align', $important_options ) || $use_global_important ? ' !important' : ''; $text_align = et_pb_get_alignment( $font_options[ $text_align_option_name ] ); if ( isset( $option_settings['css']['text_align'] ) ) { self::set_style( $function_name, array( 'selector' => $option_settings['css']['text_align'], 'declaration' => sprintf( 'text-align: %1$s%2$s;', esc_html( $text_align ), esc_html( $important ) ), 'priority' => $this->_style_priority, ) ); } else { $style .= sprintf( 'text-align: %1$s%2$s; ', esc_html( $text_align ), esc_html( $important ) ); } } if ( isset( $option_settings['use_all_caps'] ) && $option_settings['use_all_caps'] && 'on' === $this->props["{$option_name}_all_caps"] ) { $important = in_array( 'all_caps', $important_options ) || $use_global_important ? ' !important' : ''; $style .= sprintf( 'text-transform: uppercase%1$s; ', esc_html( $important ) ); } // apply both default and hover styles $style_states = array( 'default', 'hover' ); foreach ( $style_states as $style_state ) { $is_hover = 'hover' === $style_state; $style = $is_hover ? $hover_style : $style; if ( '' !== $style ) { $css_element = ! empty( $option_settings['css']['main'] ) ? $option_settings['css']['main'] : $this->main_css_element; // use different selector for plugin if defined if ( et_builder_has_limitation('use_limited_main') && ! empty( $option_settings['css']['limited_main'] ) ) { $css_element = $option_settings['css']['limited_main']; } // $css_element might be an array, for example to apply the css for placeholders if ( is_array( $css_element ) ) { foreach( $css_element as $selector ) { if ( $is_hover ) { $selector = self::$_->array_get( $option_settings, 'css.hover', $this->add_hover_to_selectors( $selector, $is_hover ) ); } self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => rtrim( $style ), 'priority' => $this->_style_priority, ) ); $this->maybe_push_element_to_letter_spacing_fix_list( $selector, array( 'body.safari ', 'body.iphone ', 'body.uiwebview ' ), rtrim( $style ), $default_letter_spacing ); } } else { if ( $is_hover ) { $css_element = self::$_->array_get( $option_settings, 'css.hover', $this->add_hover_to_selectors( $css_element, $is_hover ) ); } self::set_style( $function_name, array( 'selector' => $css_element, 'declaration' => rtrim( $style ), 'priority' => $this->_style_priority, ) ); $this->maybe_push_element_to_letter_spacing_fix_list( $css_element, array( 'body.safari ', 'body.iphone ', 'body.uiwebview ' ), rtrim( $style ), $default_letter_spacing ); if ( $is_placeholder ) { self::set_style( $function_name, array( 'selector' => $this->_maybe_add_hover_to_order_class( $css_element . '::-webkit-input-placeholder', $is_hover ), 'declaration' => rtrim( $style ), 'priority' => $this->_style_priority, ) ); self::set_style( $function_name, array( 'selector' => $this->_maybe_add_hover_to_order_class( $css_element . '::-moz-placeholder', $is_hover ), 'declaration' => rtrim( $style ), 'priority' => $this->_style_priority, ) ); self::set_style( $function_name, array( 'selector' => $this->_maybe_add_hover_to_order_class( $css_element . '::-ms-input-placeholder', $is_hover ), 'declaration' => rtrim( $style ), 'priority' => $this->_style_priority, ) ); } } } } // process mobile options foreach( $mobile_options_slugs as $mobile_option ) { $current_option_name = "{$option_name}_{$mobile_option}"; if ( isset( $font_options[ $current_option_name ] ) && '' !== $font_options[ $current_option_name ] ) { $current_desktop_option = $this->remove_suffix($mobile_option); $current_last_edited_slug = "{$option_name}_{$current_desktop_option}_last_edited"; $current_last_edited = isset( $font_options[ $current_last_edited_slug ] ) ? $font_options[ $current_last_edited_slug ] : ''; $current_responsive_status = et_pb_get_responsive_status( $current_last_edited ); // Don't print mobile styles if responsive UI isn't toggled on if ( ! $current_responsive_status ) { continue; } $current_media_query = false === strpos( $mobile_option, 'phone' ) ? 'max_width_980' : 'max_width_767'; $main_option_name = str_replace( array( '_tablet', '_phone' ), '', $mobile_option ); // 1. Generate CSS property. $css_property = str_replace( '_', '-', $main_option_name ); if ( 'text_color' === $main_option_name ) { $css_property = 'color'; } // 2. Custom important. $css_option_name = 'font-size' === $css_property ? 'size' : $css_property; $important = in_array( $css_option_name, $important_options ) || $use_global_important ? ' !important' : ''; // As default, text color should be important on tablet and phone. if ( 'text_color' === $main_option_name ) { $important = ' !important'; } // Allow specific selector tablet and mobile, simply add _tablet or _phone suffix if ( isset( $option_settings['css'][ $mobile_option ] ) && "" !== $option_settings['css'][ $mobile_option ] ) { $selector = $option_settings['css'][ $mobile_option ]; } elseif ( 'text_color' === $main_option_name && ! empty( $option_settings['css']['color'] ) ) { // We define custom selector for text color as 'color', not 'text_color'. $selector = $option_settings['css']['color']; } elseif ( isset( $option_settings['css'][ $main_option_name ] ) || isset( $option_settings['css']['main'] ) ) { $selector = isset( $option_settings['css'][ $main_option_name ] ) ? $option_settings['css'][ $main_option_name ] : $option_settings['css']['main']; } elseif ( et_builder_has_limitation( 'use_limited_main' ) && ! empty( $option_settings['css']['limited_main'] ) ) { $selector = $option_settings['css']['limited_main']; } else { $selector = $this->main_css_element; } // 3. Process value based on property name. $text_range_inputs = array( 'font_size', 'line_height', 'letter_spacing' ); $processed_value = $font_options[ $current_option_name ]; if ( in_array( $main_option_name, $text_range_inputs ) ) { $processed_value = et_builder_process_range_value( $font_options[ $current_option_name ] ); } // 4. Declare CSS property, value, and important status. if ( 'font' === $main_option_name ) { $global_font_name = $this->get_global_setting_name( $current_option_name ); $global_font_value = ET_Global_Settings::get_value( $global_font_name ); $declaration = et_builder_set_element_font( $processed_value, ( '' !== $important ), $global_font_value ); } else { $declaration = sprintf( '%1$s: %2$s%3$s;', esc_html( $css_property ), esc_html( $processed_value ), esc_html( $important ) ); } // Reset font style: italic/normal, uppercase/normal/smallcaps, underline/ // linethrough. There is a case where a font option group inherit font style // value from another font option group. Most of the time, we can't toggle // on/off the inherited options. if ( 'font' === $main_option_name ) { $processed_prev_value = et_pb_responsive_options()->get_default_value( $this->props, $current_option_name ); $reset_declaration = et_builder_set_reset_font_style( $processed_value, $processed_prev_value, '' !== $important ); $declaration .= ! empty( $reset_declaration ) ? $reset_declaration : ''; } // $selector might be an array, for example to apply the css for placeholders if ( is_array( $selector ) ) { foreach( $selector as $selector_item ) { self::set_style( $function_name, array( 'selector' => $selector_item, 'declaration' => $declaration, 'priority' => $this->_style_priority, 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } } else { self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => $declaration, 'priority' => $this->_style_priority, 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); if( ! empty( $selector ) && in_array( $mobile_option, array( 'letter_spacing_phone', 'letter_spacing_tablet' ) ) ) { switch( $mobile_option ) { case 'letter_spacing_phone': $css_prefix = 'body.iphone '; break; case 'letter_spacing_tablet': $css_prefix = 'body.uiwebview '; break; } $this->maybe_push_element_to_letter_spacing_fix_list( $selector, $css_prefix, $declaration, $default_letter_spacing ); } if ( $is_placeholder ) { self::set_style( $function_name, array( 'selector' => $selector . '::-webkit-input-placeholder', 'declaration' => $declaration, 'priority' => $this->_style_priority, 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); self::set_style( $function_name, array( 'selector' => $selector . '::-moz-placeholder', 'declaration' => $declaration, 'priority' => $this->_style_priority, 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); self::set_style( $function_name, array( 'selector' => $selector . '::-ms-input-placeholder', 'declaration' => $declaration, 'priority' => $this->_style_priority, 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } } } } $sub_toggle = isset( $option_settings['sub_toggle'] ) ? $option_settings['sub_toggle'] : ''; // Ignore the process if the current module is Text since the process will be handled // by the module itself. if ( 'et_pb_text' !== $function_name ) { // Build sub toggle selector. $sub_toggle_selector = ''; if ( et_builder_has_limitation( 'use_limited_main' ) && ! empty( $option_settings['css']['limited_main'] ) ) { $sub_toggle_selector = $option_settings['css']['limited_main']; } elseif ( isset( $option_settings['css']['main'] ) ) { $sub_toggle_selector = $option_settings['css']['main']; } // Additional ul and ol option slugs. if ( in_array( $sub_toggle, array( 'ul', 'ol' ) ) ) { $list_selector = '' !== $sub_toggle_selector ? $sub_toggle_selector : "{$this->main_css_element} {$sub_toggle}"; // Option ul / ol type. $list_type_name = "{$option_name}_type"; $is_list_type_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, $list_type_name ); $list_type_values = array( 'desktop' => esc_html( et_pb_responsive_options()->get_any_value( $this->props, $list_type_name, '', false, 'desktop' ) ), 'tablet' => $is_list_type_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$list_type_name}_tablet" ) ) : '', 'phone' => $is_list_type_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$list_type_name}_tablet" ) ) : '', ); et_pb_responsive_options()->generate_responsive_css( $list_type_values, $list_selector, 'list-style-type', $function_name, ' !important;', 'select' ); // Option ul / ol position. $list_position_name = "{$option_name}_position"; $is_list_position_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, $list_position_name ); $list_position_values = array( 'desktop' => esc_html( et_pb_responsive_options()->get_any_value( $this->props, $list_position_name ) ), 'tablet' => $is_list_position_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$list_position_name}_tablet" ) ) : '', 'phone' => $is_list_position_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$list_position_name}_phone" ) ) : '', ); et_pb_responsive_options()->generate_responsive_css( $list_position_values, $list_selector, 'list-style-position', $function_name, '', 'select' ); // Option ul / ol indent. $list_indent_name = "{$option_name}_item_indent"; $is_list_indent_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, $list_indent_name ); $list_indent_values = array( 'desktop' => esc_html( et_pb_responsive_options()->get_any_value( $this->props, $list_indent_name ) ), 'tablet' => $is_list_indent_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$list_indent_name}_tablet" ) ) : '', 'phone' => $is_list_indent_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$list_indent_name}_phone" ) ) : '', ); $list_item_indent_selector = et_()->array_get( $option_settings, 'css.item_indent', $list_selector ); et_pb_responsive_options()->generate_responsive_css( $list_indent_values, $list_item_indent_selector, 'padding-left', $function_name, ' !important;' ); } // Additional quote option slugs. if ( 'quote' === $sub_toggle ) { $quote_selector = '' !== $sub_toggle_selector ? $sub_toggle_selector : "{$this->main_css_element} blockquote"; // Option quote border weight. $border_weight_name = "{$option_name}_border_weight"; $is_border_weight_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, $border_weight_name ); $border_weight_values = array( 'desktop' => esc_html( et_pb_responsive_options()->get_any_value( $this->props, $border_weight_name ) ), 'tablet' => $is_border_weight_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$border_weight_name}_tablet" ) ) : '', 'phone' => $is_border_weight_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$border_weight_name}_phone" ) ) : '', ); et_pb_responsive_options()->generate_responsive_css( $border_weight_values, $quote_selector, 'border-width', $function_name ); // Option quote border weight on hover. $border_weight_hover_value = et_pb_hover_options()->get_value( $border_weight_name, $this->props ); if ( '' !== $border_weight_hover_value && et_builder_is_hover_enabled( $border_weight_name, $this->props ) ) { self::set_style( $function_name, array( 'selector' => "{$quote_selector}:hover", 'declaration' => sprintf( 'border-width: %1$s%2$s;', esc_html( et_builder_process_range_value( $border_weight_hover_value ) ), esc_html( $important ) ), ) ); } // Option quote border color. $border_color_name = "{$option_name}_border_color"; $is_border_color_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, $border_color_name ); $border_color_values = array( 'desktop' => esc_html( et_pb_responsive_options()->get_any_value( $this->props, $border_color_name ) ), 'tablet' => $is_border_color_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$border_color_name}_tablet" ) ) : '', 'phone' => $is_border_color_responsive ? esc_html( et_pb_responsive_options()->get_any_value( $this->props, "{$border_color_name}_phone" ) ) : '', ); et_pb_responsive_options()->generate_responsive_css( $border_color_values, $quote_selector, 'border-color', $function_name, '', 'color' ); // Option quote border weight on hover. $border_color_hover_value = et_pb_hover_options()->get_value( $border_color_name, $this->props ); if ( '' !== $border_color_hover_value && et_builder_is_hover_enabled( $border_color_name, $this->props ) ) { self::set_style( $function_name, array( 'selector' => "{$quote_selector}:hover", 'declaration' => sprintf( 'border-color: %1$s%2$s;', esc_html( $border_color_hover_value ), esc_html( $important ) ), ) ); } } } } // sets ligatures disabling for all selectors // from the list $this->letter_spacing_fix_selectors foreach ($this->letter_spacing_fix_selectors as $selector_with_prefix) { self::set_style( $function_name, array( 'selector' => $selector_with_prefix, 'declaration' => 'font-variant-ligatures: no-common-ligatures;', 'priority' => $this->_style_priority ) ); } } /** * Maybe push element to the letter spacing fix list * * @since 4.4.7 Checks a element for the having of the letter-spacing property, * adds a prefix to all its selectors, push prefixed selector * to the array ($this->letter_spacing_fix_selectors) of elements * that need to have ligature fix (same elements will be overridden). * * @param string $selector CSS selector of the current element. * @param array $css_prefixes array or string of CSS prefixes which will be added to the current element selector. * @param string $declaration CSS declaration of the current element. * @param string $default_letter_spacing default letter-spacing value at the current element. */ function maybe_push_element_to_letter_spacing_fix_list( $selector, $css_prefixes, $declaration, $default_letter_spacing ) { if ( false === strpos( trim( $declaration ), 'letter-spacing' ) || empty( $css_prefixes ) || empty( $selector ) ) { return; } $selectors = ! is_array( $selector ) ? array( $selector ) : $selector; foreach ( $selectors as $selector ) { if ( empty( $selector ) ) { continue; } $css_value = str_replace( 'letter-spacing', '', $declaration ); $css_value = preg_replace( '/[^a-zA-Z0-9]/', '', $css_value ); if ( ! is_array( $css_prefixes ) ) { $css_prefixes = array( $css_prefixes ); } foreach ( $css_prefixes as $css_prefix ) { $selector_with_prefix = ''; $selector_elements = explode( ',', $selector ); if ( is_array( $selector_elements ) && count( $selector_elements ) > 0 ) { $selector_with_prefix = implode( ',', preg_filter( '/^/', $css_prefix, $selector_elements ) ); } if ( ! empty( $selector_with_prefix ) ) { $hash_id_for_fix_selectors = crc32( $selector_with_prefix ); // Checking: if the current value of the sector is the default, // given that the default value can be set in a different css-unit // (px, em, rem... etc) than the current value // (for example, the predefined default value can be '0px', while the current selector value is '0em') $maybe_selector_has_default_value = 0 === intval( $default_letter_spacing ) && 0 === intval( $css_value ) || ( $css_value === $default_letter_spacing ); if ( ! ( $maybe_selector_has_default_value ) ) { $this->letter_spacing_fix_selectors[ $hash_id_for_fix_selectors ] = $selector_with_prefix; } elseif ( isset ( $this->letter_spacing_fix_selectors[ $hash_id_for_fix_selectors ] ) ) { // If the selector has a default value, should delete it from // array of selectors ($this->letter_spacing_fix_selectors) that need to be fixed, // if it was added earlier. unset( $this->letter_spacing_fix_selectors[ $hash_id_for_fix_selectors ] ); } } } } } /** * Process background CSS styles. * * @since 3.23 Add responsive support. * * @param string $function_name Module slug. */ function process_advanced_background_options( $function_name ) { // Disable if module doesn't set advanced_fields property and has no VB support if ( ! $this->has_vb_support() && ! $this->has_advanced_fields ) { return; } if ( ! self::$_->array_get( $this->advanced_fields, 'background', false ) ) { return; } // Reset processed background if ( $this->save_processed_background ) { $this->processed_background = array(); } $settings = $this->advanced_fields['background']; $important = isset( $settings['css']['important'] ) && $settings['css']['important'] ? ' !important' : ''; // Possible values for use_background_* variables are true, false, or 'fields_only' $has_background_color_toggle_options = $this->advanced_fields['background']['has_background_color_toggle']; $use_background_color_gradient_options = $this->advanced_fields['background']['use_background_color_gradient']; $use_background_image_options = $this->advanced_fields['background']['use_background_image']; $use_background_color_options = $this->advanced_fields['background']['use_background_color']; $use_background_color_reset_options = self::$_->array_get( $this->advanced_fields, 'background.use_background_color_reset', true ); // Place to store processed background. It will be compared with the smaller device background // processed value to avoid rendering the same styles. $processed_background_color = ''; $processed_background_image = ''; $gradient_properties_desktop = array(); $processed_background_blend = ''; $background_color_gradient_overlays_image_desktop = 'off'; // Store background images status because the process is extensive. $background_image_status = array( 'desktop' => false, 'tablet' => false, 'phone' => false, ); // Background Desktop, Tablet, and Phone. foreach ( et_pb_responsive_options()->get_modes() as $device ) { $is_desktop = 'desktop' === $device; $suffix = ! $is_desktop ? "_{$device}" : ''; $style = ''; $has_background_color_gradient = false; $has_background_image = false; $has_background_gradient_and_image = false; $is_background_color_gradient_disabled = false; $is_background_image_disabled = false; // Ensure responsive settings is enabled on mobile. if ( ! $is_desktop && ! et_pb_responsive_options()->is_responsive_enabled( $this->props, 'background' ) ) { continue; } $background_image_style = ''; $background_color_style = ''; $background_images = array(); $background_color_gradient_overlays_image = 'off'; // A. Background Gradient. if ( $use_background_color_gradient_options && 'fields_only' !== $use_background_color_gradient_options ) { $use_background_color_gradient = et_pb_responsive_options()->get_inheritance_background_value( $this->props, 'use_background_color_gradient', $device, 'background', $this->fields_unprocessed ); // 1. Ensure gradient color is active. if ( 'on' === $use_background_color_gradient ) { $background_color_gradient_overlays_image = et_pb_responsive_options()->get_any_value( $this->props, "background_color_gradient_overlays_image{$suffix}", '', true ); $gradient_properties = array( 'type' => et_pb_responsive_options()->get_any_value( $this->props, "background_color_gradient_type{$suffix}", '', true ), 'direction' => et_pb_responsive_options()->get_any_value( $this->props, "background_color_gradient_direction{$suffix}", '', true ), 'radial_direction' => et_pb_responsive_options()->get_any_value( $this->props, "background_color_gradient_direction_radial{$suffix}", '', true ), 'color_start' => et_pb_responsive_options()->get_any_value( $this->props, "background_color_gradient_start{$suffix}", '', true ), 'color_end' => et_pb_responsive_options()->get_any_value( $this->props, "background_color_gradient_end{$suffix}", '', true ), 'start_position' => et_pb_responsive_options()->get_any_value( $this->props, "background_color_gradient_start_position{$suffix}", '', true ), 'end_position' => et_pb_responsive_options()->get_any_value( $this->props, "background_color_gradient_end_position{$suffix}", '', true ), ); // Will be used as default of Gradient hover. if ( $is_desktop ) { $gradient_properties_desktop = $gradient_properties; $background_color_gradient_overlays_image_desktop = $background_color_gradient_overlays_image; } // Save background gradient into background images list. $background_gradient = $this->get_gradient( $gradient_properties ); $background_images[] = $background_gradient; // Save resulted gradient into property for later usage if ( $this->save_processed_background ) { et_()->array_set( $this->processed_background, "{$device}.gradient", $background_gradient ); } // Flag to inform BG Color if current module has Gradient. $has_background_color_gradient = true; } else if ( 'off' === $use_background_color_gradient ) { $is_background_color_gradient_disabled = true; } } // B. Background Image. if ( $use_background_image_options && 'fields_only' !== $use_background_image_options ) { $background_image = et_pb_responsive_options()->get_inheritance_background_value( $this->props, 'background_image', $device, 'background', $this->fields_unprocessed ); $parallax = et_pb_responsive_options()->get_any_value( $this->props, "parallax{$suffix}", 'off' ); // Featured image as background is in higher priority. if ( $this->featured_image_background ) { $featured_image = self::$_->array_get( $this->props, 'featured_image', '' ); $featured_placement = self::$_->array_get( $this->props, 'featured_placement', '' ); $featured_image_src_obj = wp_get_attachment_image_src( get_post_thumbnail_id( self::_get_main_post_id() ), 'full' ); $featured_image_src = isset( $featured_image_src_obj[0] ) ? $featured_image_src_obj[0] : ''; if ( 'on' === $featured_image && 'background' === $featured_placement && '' !== $featured_image_src ) { $background_image = $featured_image_src; } } // BG image and parallax status. $is_background_image_active = '' !== $background_image && 'on' !== $parallax; $background_image_status[ $device ] = $is_background_image_active; // 1. Ensure image exists and parallax is off. if ( $is_background_image_active ) { // Flag to inform BG Color if current module has Image. $has_background_image = true; // Check previous BG image status. Needed to get the correct value. $is_prev_background_image_active = true; if ( ! $is_desktop ) { $is_prev_background_image_active = 'tablet' === $device ? $background_image_status['desktop'] : $background_image_status['tablet']; } // Size. $background_size_default = self::$_->array_get( $this->fields_unprocessed, 'background_size.default', '' ); $background_size = et_pb_responsive_options()->get_any_value( $this->props, "background_size{$suffix}", $background_size_default, ! $is_prev_background_image_active ); if ( '' !== $background_size ) { $style .= sprintf( 'background-size: %1$s; ', esc_html( $background_size ) ); } // Position. $background_position_default = self::$_->array_get( $this->fields_unprocessed, 'background_position.default', '' ); $background_position = et_pb_responsive_options()->get_any_value( $this->props, "background_position{$suffix}", $background_position_default, ! $is_prev_background_image_active ); if ( '' !== $background_position ) { $style .= sprintf( 'background-position: %1$s; ', esc_html( str_replace( '_', ' ', $background_position ) ) ); } // Repeat. $background_repeat_default = self::$_->array_get( $this->fields_unprocessed, 'background_repeat.default', '' ); $background_repeat = et_pb_responsive_options()->get_any_value( $this->props, "background_repeat{$suffix}", $background_repeat_default, ! $is_prev_background_image_active ); if ( '' !== $background_repeat ) { $style .= sprintf( 'background-repeat: %1$s; ', esc_html( $background_repeat ) ); } // Blend. $background_blend_default = self::$_->array_get( $this->fields_unprocessed, 'background_blend.default', '' ); $background_blend = et_pb_responsive_options()->get_any_value( $this->props, "background_blend{$suffix}", $background_blend_default, ! $is_prev_background_image_active ); $background_blend_inherit = et_pb_responsive_options()->get_any_value( $this->props, "background_blend{$suffix}", '', true ); if ( '' !== $background_blend_inherit ) { // Don't print the same image blend style. if ( '' !== $background_blend ) { $style .= sprintf( 'background-blend-mode: %1$s; ', esc_html( $background_blend ) ); } // Reset - If background has image and gradient, force background-color: initial. if ( $has_background_color_gradient && $has_background_image && $use_background_color_reset_options !== 'fields_only' && $background_blend_inherit !== $background_blend_default ) { $has_background_gradient_and_image = true; $background_color_style = 'initial'; $style .= sprintf( 'background-color: initial%1$s; ', esc_html( $important ) ); } $processed_background_blend = $background_blend; } // Only append background image when the image is exist. $background_images[] = sprintf( 'url(%1$s)', esc_html( $background_image ) ); } else if ( '' === $background_image ) { // Reset - If background image is disabled, ensure we reset prev background blend mode. if ( '' !== $processed_background_blend ) { $style .= 'background-blend-mode: normal; '; $processed_background_blend = ''; } $is_background_image_disabled = true; } } if ( ! empty( $background_images ) ) { // The browsers stack the images in the opposite order to what you'd expect. if ( 'on' !== $background_color_gradient_overlays_image ) { $background_images = array_reverse( $background_images ); } else { // Save gradient setting into property for later usage if ( $this->save_processed_background ) { et_()->array_set( $this->processed_background, "{$device}.gradient_overlays_image", true ); } } // Set background image styles only it's different compared to the larger device. $background_image_style = join( ', ', $background_images ); if ( $processed_background_image !== $background_image_style ) { $style .= sprintf( 'background-image: %1$s%2$s;', esc_html( $background_image_style ), $important ); } } else if ( ! $is_desktop && $is_background_color_gradient_disabled && $is_background_image_disabled ) { // Reset - If background image and gradient are disabled, reset current background image. $background_image_style = 'initial'; $style .= sprintf( 'background-image: %1$s%2$s;', esc_html( $background_image_style ), $important ); } // Save processed background images. $processed_background_image = $background_image_style; // C. Background Color. if ( $use_background_color_options && 'fields_only' !== $use_background_color_options ) { $use_background_color_value = et_pb_responsive_options()->get_any_value( $this->props, "use_background_color{$suffix}", 'on', true ); if ( ! $has_background_gradient_and_image && 'off' !== $use_background_color_value ) { $background_color = et_pb_responsive_options()->get_inheritance_background_value( $this->props, 'background_color', $device, 'background', $this->fields_unprocessed ); $background_color = ! $is_desktop && '' === $background_color ? 'initial' : $background_color; $background_color_style = $background_color; if ( '' !== $background_color && $processed_background_color !== $background_color ) { $style .= sprintf( 'background-color: %1$s%2$s; ', esc_html( $background_color ), esc_html( $important ) ); // If text module has background color set position to relative, as opposed to set text module as relative by default. // Changing background selector to point to et_pb_text_inner will not render background correctly // If position options are set they will override this value. if ( 'et_pb_text' === $function_name ) { $style .= 'position: relative; '; } } } else if ( $has_background_color_toggle_options && 'off' === $use_background_color_value && ! $is_desktop ) { // Reset - If current module has background color toggle, it's off, and current mode // it's not desktop, we should reset the background color. $style .= sprintf( 'background-color: initial %1$s; ', esc_html( $important ) ); } } // Save processed background color. $processed_background_color = $background_color_style; // Render background styles. if ( '' !== $style ) { // Add media query parameter. $background_args = array(); if ( ! $is_desktop ) { $current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767'; $background_args['media_query'] = ET_Builder_Element::get_media_query( $current_media_query ); } $css_element = ! empty( $settings['css']['main'] ) ? $settings['css']['main'] : $this->main_css_element; self::set_style( $function_name, wp_parse_args( $background_args, array( 'selector' => $css_element, 'declaration' => rtrim( $style ), 'priority' => $this->_style_priority, ) ) ); } } // Background Hover. if ( et_builder_is_hover_enabled( 'background', $this->props ) ) { $background_images_hover = array(); $style_hover = ''; $has_background_color_gradient_hover = false; $has_background_image_hover = false; $has_background_gradient_and_image_hover = false; $is_background_color_gradient_hover_disabled = false; $is_background_image_hover_disabled = false; $background_color_gradient_overlays_image_hover = 'off'; // Background Gradient Hover. // This part is little bit different compared to other hover implementation. In this case, // hover is enabled on the background field, not on the each of those fields. So, built // in function get_value() doesn't work in this case. Temporarily, we need to fetch the // the value from get_raw_value(). if ( $use_background_color_gradient_options && 'fields_only' !== $use_background_color_gradient_options ) { $use_background_color_gradient_hover = et_pb_responsive_options()->get_inheritance_background_value( $this->props, 'use_background_color_gradient', 'hover', 'background', $this->fields_unprocessed ); // 1. Ensure gradient color is active and values are not null. if ( 'on' === $use_background_color_gradient_hover ) { // Desktop value as default. $background_color_gradient_type_desktop = self::$_->array_get( $gradient_properties_desktop, 'type', '' ); $background_color_gradient_direction_desktop = self::$_->array_get( $gradient_properties_desktop, 'direction', '' ); $background_color_gradient_radial_direction_desktop = self::$_->array_get( $gradient_properties_desktop, 'radial_direction', '' ); $background_color_gradient_color_start_desktop = self::$_->array_get( $gradient_properties_desktop, 'color_start', '' ); $background_color_gradient_color_end_desktop = self::$_->array_get( $gradient_properties_desktop, 'color_end', '' ); $background_color_gradient_start_position_desktop = self::$_->array_get( $gradient_properties_desktop, 'start_position', '' ); $background_color_gradient_end_position_desktop = self::$_->array_get( $gradient_properties_desktop, 'end_position', '' ); // Hover value. $background_color_gradient_type_hover = et_pb_hover_options()->get_raw_value( 'background_color_gradient_type', $this->props, $background_color_gradient_type_desktop ); $background_color_gradient_direction_hover = et_pb_hover_options()->get_raw_value( 'background_color_gradient_direction', $this->props, $background_color_gradient_direction_desktop ); $background_color_gradient_direction_radial_hover = et_pb_hover_options()->get_raw_value( 'background_color_gradient_direction_radial', $this->props, $background_color_gradient_radial_direction_desktop ); $background_color_gradient_start_hover = et_pb_hover_options()->get_raw_value( 'background_color_gradient_start', $this->props, $background_color_gradient_color_start_desktop ); $background_color_gradient_end_hover = et_pb_hover_options()->get_raw_value( 'background_color_gradient_end', $this->props, $background_color_gradient_color_end_desktop ); $background_color_gradient_start_position_hover = et_pb_hover_options()->get_raw_value( 'background_color_gradient_start_position', $this->props, $background_color_gradient_start_position_desktop ); $background_color_gradient_end_position_hover = et_pb_hover_options()->get_raw_value( 'background_color_gradient_end_position', $this->props, $background_color_gradient_end_position_desktop ); $background_color_gradient_overlays_image_hover = et_pb_hover_options()->get_raw_value( 'background_color_gradient_overlays_image', $this->props, $background_color_gradient_overlays_image_desktop ); // Flag to inform BG Color if current module has Gradient. $has_background_color_gradient_hover = true; $gradient_values_hover = array( 'type' => '' !== $background_color_gradient_type_hover ? $background_color_gradient_type_hover : $background_color_gradient_type_desktop, 'direction' => '' !== $background_color_gradient_direction_hover ? $background_color_gradient_direction_hover : $background_color_gradient_direction_desktop, 'radial_direction' => '' !== $background_color_gradient_direction_radial_hover ? $background_color_gradient_direction_radial_hover : $background_color_gradient_radial_direction_desktop, 'color_start' => '' !== $background_color_gradient_start_hover ? $background_color_gradient_start_hover : $background_color_gradient_color_start_desktop, 'color_end' => '' !== $background_color_gradient_end_hover ? $background_color_gradient_end_hover : $background_color_gradient_color_end_desktop, 'start_position' => '' !== $background_color_gradient_start_position_hover ? $background_color_gradient_start_position_hover : $background_color_gradient_start_position_desktop, 'end_position' => '' !== $background_color_gradient_end_position_hover ? $background_color_gradient_end_position_hover : $background_color_gradient_end_position_desktop, ); $background_gradient_hover = $this->get_gradient( $gradient_values_hover ); $background_images_hover[] = $background_gradient_hover; // Save resulted gradient into property for later usage if ( $this->save_processed_background ) { et_()->array_set( $this->processed_background, "hover.gradient", $background_gradient_hover ); } } else if ( 'off' === $use_background_color_gradient_hover ) { $is_background_color_gradient_hover_disabled = true; } } // Background Image Hover. // This part is little bit different compared to other hover implementation. In this case, // hover is enabled on the background field, not on the each of those fields. So, built // in function get_value() doesn't work in this case. Temporarily, we need to fetch the // the value from get_raw_value(). if ( $use_background_image_options && 'fields_only' !== $use_background_image_options ) { $background_image_hover = et_pb_responsive_options()->get_inheritance_background_value( $this->props, 'background_image', 'hover', 'background', $this->fields_unprocessed ); $parallax_hover = et_pb_hover_options()->get_raw_value( 'parallax', $this->props ); // Featured image as background is in higher priority. if ( $this->featured_image_background ) { $featured_image = self::$_->array_get( $this->props, 'featured_image', '' ); $featured_placement = self::$_->array_get( $this->props, 'featured_placement', '' ); $featured_image_src_obj = wp_get_attachment_image_src( get_post_thumbnail_id( self::_get_main_post_id() ), 'full' ); $featured_image_src = isset( $featured_image_src_obj[0] ) ? $featured_image_src_obj[0] : ''; if ( 'on' === $featured_image && 'background' === $featured_placement && '' !== $featured_image_src ) { $background_image = $featured_image_src; } } if ( '' !== $background_image_hover && null !== $background_image_hover && 'on' !== $parallax_hover ) { // Flag to inform BG Color if current module has Image. $has_background_image_hover = true; // Size. $background_size_hover = et_pb_hover_options()->get_raw_value( 'background_size', $this->props ); $background_size_desktop = self::$_->array_get( $this->props, 'background_size', '' ); $is_same_background_size = $background_size_hover === $background_size_desktop; if ( empty( $background_size_hover ) && ! empty( $background_size_desktop ) ) { $background_size_hover = $background_size_desktop; } if ( ! empty( $background_size_hover ) && ! $is_same_background_size ) { $style_hover .= sprintf( 'background-size: %1$s; ', esc_html( $background_size_hover ) ); } // Position. $background_position_hover = et_pb_hover_options()->get_raw_value( 'background_position', $this->props ); $background_position_desktop = self::$_->array_get( $this->props, 'background_position', '' ); $is_same_background_position = $background_position_hover === $background_position_desktop; if ( empty( $background_position_hover ) && ! empty( $background_position_desktop ) ) { $background_position_hover = $background_position_desktop; } if ( ! empty( $background_position_hover ) && ! $is_same_background_position ) { $style_hover .= sprintf( 'background-position: %1$s; ', esc_html( str_replace( '_', ' ', $background_position_hover ) ) ); } // Repeat. $background_repeat_hover = et_pb_hover_options()->get_raw_value( 'background_repeat', $this->props ); $background_repeat_desktop = self::$_->array_get( $this->props, 'background_repeat', '' ); $is_same_background_repeat = $background_repeat_hover === $background_repeat_desktop; if ( empty( $background_repeat_hover ) && ! empty( $background_repeat_desktop ) ) { $background_repeat_hover = $background_repeat_desktop; } if ( ! empty( $background_repeat_hover ) && ! $is_same_background_repeat ) { $style_hover .= sprintf( 'background-repeat: %1$s; ', esc_html( $background_repeat_hover ) ); } // Blend. $background_blend_hover = et_pb_hover_options()->get_raw_value( 'background_blend', $this->props ); $background_blend_default = self::$_->array_get( $this->fields_unprocessed, 'background_blend.default', '' ); $background_blend_desktop = self::$_->array_get( $this->props, 'background_blend', '' ); $is_same_background_blend = $background_blend_hover === $background_blend_desktop; if ( empty( $background_blend_hover ) && ! empty( $background_blend_desktop ) ) { $background_blend_hover = $background_blend_desktop; } if ( ! empty( $background_blend_hover ) ) { // Don't print the same background blend. if ( ! $is_same_background_blend ) { $style_hover .= sprintf( 'background-blend-mode: %1$s; ', esc_html( $background_blend_hover ) ); } // Force background-color: initial; if ( $has_background_color_gradient_hover && $has_background_image_hover && $background_blend_hover !== $background_blend_default ) { $has_background_gradient_and_image_hover = true; $style_hover .= sprintf( 'background-color: initial%1$s; ', esc_html( $important ) ); } } // Only append background image when the image is exist. $background_images_hover[] = sprintf( 'url(%1$s)', esc_html( $background_image_hover ) ); } else if ( '' === $background_image_hover ) { $is_background_image_hover_disabled = true; } } if ( ! empty( $background_images_hover ) ) { // The browsers stack the images in the opposite order to what you'd expect. if ( 'on' !== $background_color_gradient_overlays_image_hover ) { $background_images_hover = array_reverse( $background_images_hover ); } else { // Save gradient setting into property for later usage if ( $this->save_processed_background ) { et_()->array_set( $this->processed_background, "hover.gradient_overlays_image", true ); } } $style_hover .= sprintf( 'background-image: %1$s%2$s;', esc_html( join( ', ', $background_images_hover ) ), $important ); } else if ( $is_background_color_gradient_hover_disabled && $is_background_image_hover_disabled ) { $style_hover .= sprintf( 'background-image: initial %1$s;', $important ); } // Background Color Hover. if ( $use_background_color_options && 'fields_only' !== $use_background_color_options ) { $use_background_color_hover_value = self::$_->array_get( $this->props, 'use_background_color__hover', '' ); $use_background_color_hover_value = ! empty( $use_background_color_hover_value ) ? $use_background_color_hover_value : self::$_->array_get( $this->props, 'use_background_color', 'on' ); if ( ! $has_background_gradient_and_image_hover && 'off' !== $use_background_color_hover_value ) { $background_color_hover = et_pb_responsive_options()->get_inheritance_background_value( $this->props, 'background_color', 'hover', 'background', $this->fields_unprocessed ); $background_color_hover = '' !== $background_color_hover ? $background_color_hover : 'transparent'; if ( '' !== $background_color_hover ) { $style_hover .= sprintf( 'background-color: %1$s%2$s; ', esc_html( $background_color_hover ), esc_html( $important ) ); } } else if ( $has_background_color_toggle_options && 'off' === $use_background_color_hover_value ) { // Reset - If current module has background color toggle, it's off, and current mode // it's not desktop, we should reset the background color. $style .= sprintf( 'background-color: initial %1$s; ', esc_html( $important ) ); } } // Render background hover styles. if ( '' !== $style_hover ) { $css_element_main = self::$_->array_get( $settings, 'css.main', $this->main_css_element ); $css_element_hover = self::$_->array_get( $settings, 'css.hover', et_pb_hover_options()->add_hover_to_order_class( $css_element_main ) ); self::set_style( $function_name, array( 'selector' => $css_element_hover, 'declaration' => rtrim( $style_hover ), 'priority' => $this->_style_priority, ) ); } } } /** * Process advanced text options. * * @since 3.23 Add support to generate responsive styles of text orientation. * * @param string $function_name Module slug. */ function process_advanced_text_options( $function_name ) { // Disable if module doesn't set advanced_fields property and has no VB support if ( ! $this->has_vb_support() && ! $this->has_advanced_fields ) { return; } if ( ! self::$_->array_get( $this->advanced_fields, 'text', false ) ) { return; } $text_options = $this->advanced_fields['text']; if ( isset( $text_options['css'] ) && is_array( $text_options['css'] ) ) { $text_css = $text_options['css']; $text_orientation_default = isset( $this->fields_unprocessed['text_orientation']['default'] ) ? $this->fields_unprocessed['text_orientation']['default'] : ''; $text_orientation = $this->get_text_orientation() !== $text_orientation_default ? $this->get_text_orientation() : ''; $text_orientation_tablet = $this->get_text_orientation( 'tablet', $text_orientation_default ); $text_orientation_phone = $this->get_text_orientation( 'phone', $text_orientation_default ); // Normally, text orientation attr adds et_pb_text_align_* class name to its module wrapper // In some cases, it needs to target particular children inside the module. Thus, only prints // styling if selector is given if ( isset( $text_css['text_orientation'] ) ) { $text_orientation_values = array( 'desktop' => esc_attr( $text_orientation ), 'tablet' => esc_attr( $text_orientation_tablet ), 'phone' => esc_attr( $text_orientation_phone ), ); et_pb_responsive_options()->generate_responsive_css( $text_orientation_values, $text_css['text_orientation'], 'text-align', $function_name, '', 'alignment', $this->_style_priority ); } } } /** * Output border and border radius styling * * @since 3.23 Add support to generate responsive styles of border styles and radii.] */ function process_advanced_borders_options( $function_name ) { // Disable if module doesn't set advanced_fields property and has no VB support if ( ! $this->has_vb_support() && ! $this->has_advanced_fields ) { return; } global $et_fb_processing_shortcode_object; $borders = self::$_->array_get( $this->advanced_fields, 'borders', array( 'default' => array() ) ); $border_field = ET_Builder_Module_Fields_Factory::get( 'Border' ); if ( is_array( $borders ) && ! empty( $borders ) ) { foreach ( $borders as $border_name => $border ) { // Enable module to disable border options if ( false === $border ) { continue; } // Blurb image specific adjustment if ( 'image' === $border_name && 'et_pb_blurb' === $this->slug && 'on' === self::$_->array_get( $this->props, 'use_icon' ) ) { continue; } // Blog specific adjustment if ( 'fullwidth' === $border_name && 'et_pb_blog' === $this->slug && 'on' !== self::$_->array_get( $this->props, 'fullwidth' ) ) { continue; } // Login & signup specific adjustment if ( 'fields_focus' === $border_name && in_array( $this->slug, array( 'et_pb_login', 'et_pb_signup' ) ) && 'on' !== self::$_->array_get( $this->props, 'use_focus_border_color' ) ) { continue; } // Check field visibility against its dependency if ( ! $this->_is_field_applicable( $border ) ) { continue; } $is_border_default = 'default' === $border_name; $suffix = $is_border_default ? '' : "_{$border_name}"; if ( $is_border_default && $this->slug !== $function_name ) { // This module's shortcode callback is being used to render another module (like accordion item // uses toggle ) so we need to make sure border option overrides are taken from the other module // instead of this one. $fields = self::get_advanced_fields( $this->get_post_type(), 'all', $function_name ); $border = self::$_->array_get( $fields, 'advanced_common.border', array() ); } // Backward compatibility. For 3rd party modules which define `_add_additional_border_fields` and do not have `process_advanced_border_options` if ( $is_border_default && method_exists( $this, '_add_additional_border_fields' ) ) { $border = self::$_->array_get( $this->advanced_fields, 'border', array() ); } // Do not add overflow:hidden for some modules. $no_overflow_module = array( 'et_pb_social_media_follow', 'et_pb_social_media_follow_network', 'et_pb_menu', 'et_pb_fullwidth_menu', ); $overflow = ! in_array( $function_name, $no_overflow_module ); $overflow_x = ! in_array( self::$_->array_get( $this->props, 'overflow-x' ), array( '', 'hidden' ) ); $overflow_y = ! in_array( self::$_->array_get( $this->props, 'overflow-y' ), array( '', 'hidden' ) ); // Remove "overflow: hidden" if both overflow-x and overflow-y are not empty or not set to "hidden" // Add "overflow-y: hidden" if overflow-x is not empty or not set to "hidden" (or vice versa) if ( $overflow_x && $overflow_y ) { $overflow = false; } else if ( $overflow_x ) { $overflow = 'overflow-y'; } else if ( $overflow_y ) { $overflow = 'overflow-x'; } // Render border radii for all devices. foreach( et_pb_responsive_options()->get_modes() as $device ) { $border_radii_attrs = array( 'selector' => self::$_->array_get( $border, 'css.main.border_radii', $this->main_css_element ), 'declaration' => $border_field->get_radii_style( $this->props, $this->advanced_fields, $suffix, $overflow, false, $device ), 'priority' => $this->_style_priority, ); // Set media query attribute for non-desktop. if ( 'desktop' !== $device ) { $media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767'; $border_radii_attrs['media_query'] = ET_Builder_Element::get_media_query( $media_query ); } self::set_style( $function_name, $border_radii_attrs ); } if ( et_builder_is_hover_enabled( "border_radii$suffix", $this->props ) ) { $main = self::$_->array_get( $border, 'css.hover', $this->main_css_element ); $main = self::$data_utils->array_get( $border, 'css.main.border_radii', $main ); $main = 'default' !== $border_name ? et_pb_hover_options()->add_hover_to_selectors( $main ) : et_pb_hover_options()->add_hover_to_order_class( $main ); $selector = self::$data_utils->array_get( $border, 'css.main.border_radii_hover', $main ); self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => $border_field->get_radii_style( $this->props, $this->advanced_fields, $suffix, $overflow, true ), 'priority' => $this->_style_priority, ) ); } // Render border styles for all devices. foreach( et_pb_responsive_options()->get_modes() as $device ) { $border_styles_attrs = array( 'selector' => self::$_->array_get( $border, 'css.main.border_styles', $this->main_css_element ), 'declaration' => $border_field->get_borders_style( $this->props, $this->advanced_fields, $suffix, false, $device ), 'priority' => $this->_style_priority, ); // Set media query attribute for non-desktop. if ( 'desktop' !== $device ) { $media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767'; $border_styles_attrs['media_query'] = ET_Builder_Element::get_media_query( $media_query ); } self::set_style( $function_name, $border_styles_attrs ); } $main = self::$_->array_get( $border, 'css.hover', $this->main_css_element ); $main = self::$data_utils->array_get( $border, 'css.main.border_styles', $main ); $main = 'default' !== $border_name ? et_pb_hover_options()->add_hover_to_selectors( $main ) : et_pb_hover_options()->add_hover_to_order_class( $main ); $selector = self::$data_utils->array_get( $border, 'css.main.border_styles_hover', $main ); self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => $border_field->get_borders_style( $this->props, $this->advanced_fields, $suffix, true ), 'priority' => $this->_style_priority, ) ); } } if ( ! $et_fb_processing_shortcode_object && $border_field->needs_border_reset_class( $function_name, $this->props ) ) { // Try to apply old method for plugins without vb support if ( 'on' !== $this->vb_support ) { add_filter( "{$function_name}_shortcode_output", array( $border_field, 'add_border_reset_class' ), 10, 2 ); } $this->add_classname( 'et_pb_with_border' ); } if ( method_exists( $this, 'process_advanced_border_options' ) ) { // Backwards Compatibility // Call it after processing default fields because it's additional processing and is not replacement. $this->process_advanced_border_options( $function_name ); } } function get_position_locations() { return $this->position_locations; } function set_position_locations( $locations ) { $this->position_locations = $locations; } function process_transform( $function_name ) { $transform = self::$_->array_get( $this->advanced_fields, 'transform', array() ); if ( false === $transform || ! is_array( $transform ) ) { return; } $selector = self::$_->array_get( $transform, 'css.main', '%%order_class%%' ); $important = self::$_->array_get( $transform, 'css.important', false ); $hover = et_pb_hover_options(); $isHoverEnabled = $hover->is_enabled( 'transform_styles', $this->props ); $isResponsiveEnabled = isset( $this->props['transform_styles_last_edited'] ) && et_pb_get_responsive_status( $this->props['transform_styles_last_edited'] ); $responsiveDirection = isset( $this->props['animation_direction_last_edited'] ) && et_pb_get_responsive_status( $this->props['animation_direction_last_edited'] ); $animationType = self::$_->array_get( $this->props, 'animation_style', 'none' ); /** @var $class ET_Builder_Module_Field_Transform */ $class = ET_Builder_Module_Fields_Factory::get( 'Transform' ); $class->set_props( $this->props + array( 'transforms_important' => $important ) ); $position_locations = $this->get_position_locations(); $views = array( 'desktop' ); if ( $isHoverEnabled || isset( $position_locations['hover'] ) ) { array_push( $views, 'hover' ); } if ( $isResponsiveEnabled || ( 'none' !== $animationType && $responsiveDirection ) || ( isset( $position_locations['hover'] ) || isset( $position_locations['phone'] ) ) ) { array_push( $views, 'tablet', 'phone' ); } foreach ( $views as $view ) { $viewSelector = $selector; $device = $view; if ( ! $isResponsiveEnabled && in_array( $view, array( 'phone', 'tablet' ) ) || ( 'hover' === $view && ! $isHoverEnabled ) ) { $device = 'desktop'; } $elements = $class->get_elements( $device ); $media_query = array(); if ( 'hover' === $view ) { $viewSelector = $selector . ':hover'; } elseif ( 'tablet' === $view ) { $media_query = array( 'media_query' => self::get_media_query( 'max_width_980' ), ); } elseif ( 'phone' === $view ) { $media_query = array( 'media_query' => self::get_media_query( 'max_width_767' ), ); } if ( isset( $position_locations[ $view ] ) ) { $default_strpos = strpos( $position_locations[ $view ], '_is_default' ); $location = $position_locations[ $view ]; if ( $default_strpos !== false ) { $location = substr( $position_locations[ $view ], 0, $default_strpos ); } if ( ! isset( $elements['transform']['translateX'] ) ) { if ( in_array( $location, array( 'top_center', 'bottom_center', 'center_center' ) ) ) { $elements['transform']['translateX'] = '-50%'; } elseif ( $view !== 'desktop' ) { $elements['transform']['translateX'] = '0px'; } } if ( ! isset( $elements['transform']['translateY'] ) ) { if ( in_array( $location, array( 'center_left', 'center_right', 'center_center' ) ) ) { $elements['transform']['translateY'] = '-50%'; } elseif ( $view !== 'desktop' ) { $elements['transform']['translateY'] = '0px'; } } } if ( ! empty( $elements['transform'] ) || ! empty( $elements['origin'] ) ) { if ( 'hover' !== $view && ! empty( $animationType ) && 'none' !== $animationType && 'fade' !== $animationType ) { $transformedAnimation = $class->transformedAnimation( $animationType, $elements, $function_name, $device ); if ( ! empty( $transformedAnimation ) ) { self::set_style( $function_name, $transformedAnimation['keyframe'] + $media_query ); self::set_style( $function_name, $transformedAnimation['animationRules'] + $media_query ); self::set_style( $function_name, array( 'selector' => $viewSelector, 'declaration' => $transformedAnimation['declaration'], 'priority' => $this->_style_priority, ) + $media_query ); } } else { $declaration = ''; if ( ! empty( $elements['transform'] ) ) { $declaration .= $class->getTransformDeclaration( $elements['transform'], $view ); } if ( ! empty( $elements['origin'] ) ) { if ( $important ) { array_push( $elements['origin'], '!important' ); } $declaration .= sprintf( "transform-origin:%s;", implode( ' ', $elements['origin'] ) ); } self::set_style( $function_name, array( 'selector' => $viewSelector, 'declaration' => $declaration, 'priority' => $this->_style_priority, ) + $media_query ); } } } } function process_position( $function_name ) { /** @var $position_class ET_Builder_Module_Field_Position */ $position_class = ET_Builder_Module_Fields_Factory::get( 'Position' ); $position_class->set_module( $this ); $position_class->process( $function_name ); // Expose position settings on layout block preview so necesary adjustment can be applied if ( ET_GB_Block_Layout::is_layout_block_preview() ) { $layout_block_settings = $position_class->get_layout_block_settings( $function_name ); if ( is_array( $layout_block_settings ) && ! empty( $layout_block_settings ) ) { self::$layout_block_assistive_settings['position'][] = array( 'selector' => '.' . self::get_module_order_class( $function_name ), 'settings' => $layout_block_settings, ); } } } /** * Adds Filter styles to the page custom css code * * Wrapper for `generate_css_filters` used for module defaults */ function process_advanced_filter_options( $function_name ) { // Disable if module doesn't set advanced_fields property and has no VB support if ( ! $this->has_vb_support() && ! $this->has_advanced_fields ) { return; } // Module has to explicitly set false to disable filters options if ( false === self::$_->array_get( $this->advanced_fields, 'filters', false ) ) { return; } return $this->generate_css_filters( $function_name ); } function process_max_width_options( $function_name ) { // Disable if module doesn't set advanced_fields property and has no VB support if ( ! $this->has_vb_support() && ! $this->has_advanced_fields ) { return; } if ( ! is_array( self::$_->array_get( $this->advanced_fields, 'max_width', false ) ) ) { return; } $max_width = self::$_->array_get( $this->advanced_fields, 'max_width', array() ); $fields = array_merge( array('' => $max_width), self::$_->array_get( $max_width, 'extra', array() ) ); foreach ( $fields as $prefix => $field ) { $is_customized = ! self::$_->array_get( $field, 'use_max_width', true ) && ! self::$_->array_get( $field, 'use_width', true ); $hover = et_pb_hover_options(); if ( 'et_pb_section' === $this->slug && 'inner' === $prefix && 'on' !== $this->prop( 'specialty' ) ) { // https://github.com/elegantthemes/Divi/issues/14445 // This is a hot fix due to the fact that in near future // modules will be processed and rendered in VB // The real solution requires handling modules fields dependencies in FE // As section inner sizing depends on section `speciality` continue; } // Max width foreach ( array( 'width', 'max_width' ) as $key ) { if ( ! self::$_->array_get( $field, "use_$key", true ) ) { continue; } $slug = et_builder_add_prefix( $prefix, $key ); $css_prop = $this->field_to_css_prop( $key ); $option = self::$_->array_get( $this->fields_unprocessed, $slug, array() ); $width_options_css = self::$_->array_get($field, 'css', array()); $default_selector = self::$_->array_get( $width_options_css, 'main', '%%order_class%%' ); $selector = self::$_->array_get( $width_options_css, $key, $default_selector ); $desktop_default = self::$_->array_get( $option, 'default' ); $default = $desktop_default; $width = $this->prop( $slug, $default ); $default_tablet = self::$_->array_get( $option, 'default_tablet', $width ); $width_tablet = $this->prop( "{$slug}_tablet", $default_tablet ); $default_phone = self::$_->array_get( $option, 'default_phone', $width_tablet ); $width_phone = $this->prop( "{$slug}_phone", $default_phone ); $width_hover = $hover->get_value( $slug, $this->props, '' ); $width_last_edited = $this->prop( "{$slug}_last_edited", '' ); $width_responsive_active = et_pb_get_responsive_status( $width_last_edited ); $width = $width === $default ? '' : $width; $width_tablet = $width_tablet === $default_tablet ? '' : $width_tablet; $width_phone = $width_phone === $default_phone ? '' : $width_phone; if ( '' !== $width_tablet || '' !== $width_phone || '' !== $width ) { $additional_css = $this->get_max_width_additional_css(); $width_attrs = array( $slug ); // Append !important tag if ( isset( $width_options_css['important'] ) ) { $additional_css = ' !important;'; } if ( $width_responsive_active ) { $width_values = array( 'desktop_only' => $width, 'tablet' => $width_tablet, 'phone' => $width_phone, ); $width_attrs = array_merge( $width_attrs, array( "{$slug}_tablet", "{$slug}_phone" ) ); } else { $width_values = array( 'desktop' => $width, ); } // Update $is_max_width_customized if one of max_width* value is modified foreach ( $width_attrs as $width_attr ) { if ( $is_customized ) { break; } if ( ! in_array( self::$_->array_get($this->props, $width_attr ), array( '', $default ) ) ) { $is_customized = true; } } et_pb_generate_responsive_css( $width_values, $selector, $css_prop, $function_name, $additional_css ); } else if ( '' !== $default && '100%' !== $default && ! in_array( $default, array( 'auto', 'none' ) ) ) { $is_customized = true; } // Hover styles if ( '' !== $width_hover ) { // Apply 100% max-width if there is only hover max-width set so that transition works. $selector = isset( $width_options_css['main'] ) ? $width_options_css['main'] : '%%order_class%%'; $is_customized = true; if ( '' === $width ) { $hover_width = $desktop_default ? $desktop_default : '100%'; $hover_base = array( 'selector' => $selector, 'declaration' => esc_html( "$css_prop: $hover_width;" ), ); ET_Builder_Element::set_style( $function_name, $hover_base ); } $selector_hover = et_pb_hover_options()->add_hover_to_order_class( $selector ); $additional_css = $this->get_max_width_additional_css(); $hover_style = array( 'selector' => $selector_hover, 'declaration' => esc_html( "$css_prop: {$width_hover}{$additional_css};" ) ); ET_Builder_Element::set_style( $function_name, $hover_style ); } } // Module Alignment if ( self::$_->array_get( $field, 'use_module_alignment', true ) ) { $module_alignment_styles = array( 'left' => 'margin-left: 0px !important; margin-right: auto !important;', 'center' => 'margin-left: auto !important; margin-right: auto !important;', 'right' => 'margin-left: auto !important; margin-right: 0px !important;', ); $slug = et_builder_add_prefix( $prefix, 'module_alignment' ); $module_alignment = $this->prop( $slug, '' ); if ( $is_customized && isset( $module_alignment_styles[ $module_alignment ] ) ) { $default_selector = self::$_->array_get( $field, 'css.main', '%%order_class%%.et_pb_module' ); $selector = self::$_->array_get( $field, 'css.module_alignment', $default_selector ); self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => $module_alignment_styles[ $module_alignment ], 'priority' => 20, ) ); } $is_module_alignment_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, $slug ); $module_alignment_tablet = $this->prop( "{$slug}_tablet", '' ); if ( $is_customized && isset( $module_alignment_styles[ $module_alignment_tablet ] ) && $is_module_alignment_responsive ) { $default_selector = self::$_->array_get( $field, 'css.main', '%%order_class%%.et_pb_module' ); $selector = self::$_->array_get( $field, 'css.module_alignment', $default_selector ); self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => $module_alignment_styles[ $module_alignment_tablet ], 'priority' => 20, 'media_query' => ET_Builder_Element::get_media_query( 'max_width_980' ), ) ); } $module_alignment_phone = $this->prop( "{$slug}_phone", '' ); if ( $is_customized && isset( $module_alignment_styles[ $module_alignment_phone ] ) && $is_module_alignment_responsive ) { $default_selector = self::$_->array_get( $field, 'css.main', '%%order_class%%.et_pb_module' ); $selector = self::$_->array_get( $field, 'css.module_alignment', $default_selector ); self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => $module_alignment_styles[ $module_alignment_phone ], 'priority' => 20, 'media_query' => ET_Builder_Element::get_media_query( 'max_width_767' ), ) ); } } } } function process_scroll_effects( $function_name ) { $advanced_fields = self::$_->array_get( $this->advanced_fields, 'scroll_effects', array( 'default' => array() ) ); if ( ! $advanced_fields ) { return; } // Accordion Module reuses the Toggle Module and its child are not marked as child on FE, so check this specific case. $is_child_element = 'child' === $this->type || 'et_pb_accordion_item' === $function_name; $options = $this->get_scroll_effects_options(); $motion = ET_Builder_Module_Helper_Motion::instance(); $responsive = et_pb_responsive_options(); $devices = array( $responsive::DESKTOP, $responsive::TABLET, $responsive::PHONE, ); // Reset saved parent effects to not apply them on subsequent modules. if ( !$is_child_element ) { self::$parent_motion_effects = array(); } foreach ( $options as $id => $option ) { $is_effect_enabled = 'on' === $this->prop( $id . '_enable' ); $is_inherit_parent = $is_child_element && !empty( self::$parent_motion_effects ) && isset( self::$parent_motion_effects[ $id ] ); if ( !$is_effect_enabled && !$is_inherit_parent ) { continue; } $default = $option['default']; foreach ( $devices as $device ) { if ( ! $is_effect_enabled ) { $item = self::$parent_motion_effects[ $id ]; $item['id'] = '.' . self::get_module_order_class( $function_name ); $item['module_type'] = esc_html( $function_name ); } else { $field = $responsive->get_field( $id, $device ); $default_value = $responsive->get_default_value( $this->props, $field, $default ); $saved_value = $this->prop( $field, $default_value ); $value = $motion->getValue( $saved_value, $default_value ); $grid_motion = $this->prop( 'enable_grid_motion', 'off' ); $trigger_start = $this->prop( 'motion_trigger_start', 'middle' ); $trigger_end = $this->prop( 'motion_trigger_end', 'middle' ); $grid_modules = array('et_pb_gallery', 'et_pb_portfolio', 'et_pb_fullwidth_portfolio', 'et_pb_filterable_portfolio', 'et_pb_shop', 'et_pb_blog'); $item = array( 'id' => '.' . self::get_module_order_class( $function_name ), 'start' => $motion->getStartLimit( $value ), 'midStart' => $motion->getStartMiddle( $value ), 'midEnd' => $motion->getEndMiddle( $value ), 'end' => $motion->getEndLimit( $value ), 'startValue' => (float) $motion->getStartValue( $value ), 'midValue' => (float) $motion->getMiddleValue( $value ), 'endValue' => (float) $motion->getEndValue( $value ), 'resolver' => $option['resolver'], 'module_type' => esc_html( $function_name ), 'trigger_start' => $trigger_start, 'trigger_end' => $trigger_end, ); $transform_class = ET_Builder_Module_Fields_Factory::get( 'Transform' ); $transform_class->set_props( $this->props + array( 'transforms_important' => true ) ); $elements = $transform_class->get_elements( $device ); // Process transforms if defined if ( !empty( $elements ) && !empty( $elements['transform'] ) ) { $item['transforms'] = $elements['transform']; } if ( 'on' === $grid_motion ) { $item['grid_motion'] = $grid_motion; $item['children_count'] = in_array( $function_name, $grid_modules ) ? $this->prop( 'posts_number', 10 ) : 0; $item['module_index'] = self::_get_index( array( self::INDEX_MODULE_ORDER, $function_name ) ); } if ( $this->child_slug && 'on' === $grid_motion ) { self::$parent_motion_effects[ $id ] = $item; unset(self::$parent_motion_effects[ $id ]['id'], self::$parent_motion_effects[ $id ]['grid_motion'], self::$parent_motion_effects[ $id ]['children_count'], self::$parent_motion_effects[ $id ]['module_index']); $item['child_slug'] = $this->child_slug; } if ( $is_child_element ) { if ( !empty( self::$parent_motion_effects[ $id ] ) ) { $additional_item = self::$parent_motion_effects[ $id ]; $additional_item['id'] = $item['id']; self::$_scroll_effects_fields[ $device ][] = $additional_item; } } else if ( 'on' !== $grid_motion ) { self::$parent_motion_effects = array(); } } self::$_scroll_effects_fields[ $device ][] = $item; } } } public function process_height_options( $function_name ) { if ( ! is_array( self::$_->array_get( $this->advanced_fields, 'height' ) ) ) { return; } $hover = et_pb_hover_options(); $responsive = et_pb_responsive_options(); $settings = self::$_->array_get( $this->advanced_fields, "height", array() ); $fields = array_merge( array( '' => $settings ), self::$_->array_get( $settings, 'extra', array() ) ); foreach ( $fields as $prefix => $settings ) { $prefix = et_builder_add_prefix( $prefix, '' ); $default_selector = self::$_->array_get( $settings, "css.main", $this->main_css_element ); $helpers = array( 'height' => et_pb_height_options( $prefix ), 'min_height' => et_pb_min_height_options( $prefix ), 'max_height' => et_pb_max_height_options( $prefix ), ); foreach ( $helpers as $key => $helper ) { if ( ! self::$_->array_get( $settings, "use_{$key}", true ) ) { continue; } $slug = $helper->get_field( $prefix ); $field = self::$_->array_get( $this->fields_unprocessed, $slug, array() ); $css_props = $this->field_to_css_prop( $key ); $selector = self::$_->array_get( $settings, "css.{$key}", $default_selector ); if ( $responsive->is_enabled( $slug, $this->props ) ) { $values = array(); foreach ( $responsive->get_modes() as $mode ) { $default_field = $mode == ET_Builder_Module_Helper_ResponsiveOptions::DESKTOP ? 'default' : "default_$mode"; $default = self::$_->array_get( $field, $default_field ); $values[ $mode ] = $responsive->get_value( $slug, $this->props, $mode, $default ); } et_pb_generate_responsive_css( $values, $selector, $css_props, $function_name ); } else { $default = self::$_->array_get( $field, 'default' ); $value = $helper->get_value( $this->props, $default ); if ( $value !== '' && $value !== $default ) { self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => sprintf( '%1$s: %2$s;', $css_props, esc_attr( $value ) ), ) ); } } if ( $hover->is_enabled( $slug, $this->props ) ) { $default = self::$_->array_get( $field, 'default' ); $value = $helper->get_value( $this->props, $default ); $hover_value = $hover->get_value( $slug, $this->props, $value ); $selector = $hover->add_hover_to_selectors( $selector ); if ( $hover_value !== '' && $hover_value !== $value ) { self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => sprintf( '%1$s: %2$s;', $css_props, esc_attr( $hover_value ) ), ) ); } } } } } public function process_overflow_options( $function_name ) { if ( ! is_array( self::$_->array_get( $this->advanced_fields, 'overflow', array() ) ) ) { return; } $overflow = et_pb_overflow(); $hover = et_pb_hover_options(); $responsive = et_pb_responsive_options(); $selector = self::$_->array_get( $this->advanced_fields, 'overflow.css.main', $this->main_css_element ); $fields = array( 'overflow-x' => $overflow->get_field_x(), 'overflow-y' => $overflow->get_field_y(), ); $controls = ET_Builder_Module_Fields_Factory::get( 'Overflow' )->get_fields( array(), true ); // Rebuilt template if template id is returned by get_fields() if ( self::$option_template->is_enabled() && is_string( $controls ) ) { $controls = self::$option_template->rebuild_field_template( $controls ); } foreach ( $fields as $prop => $field ) { $default_value = self::$_->array_get( $controls[ $field ], 'default', '' ); $overflow_values = et_pb_responsive_options()->get_property_values( $this->props, $field, $default_value ); et_pb_responsive_options()->generate_responsive_css( $overflow_values, $selector, $field, $function_name, '', 'overflow' ); if ( $hover->is_enabled( $field, $this->props ) ) { $value = $hover->get_value( $field, $this->props, '' ); if ( '' !== $value ) { self::set_style( $function_name, array( 'selector' => $hover->add_hover_to_selectors( $selector ), 'declaration' => sprintf( '%1$s: %2$s;', $field, esc_attr( $value ) ), ) ); } } } } function process_advanced_custom_margin_options( $function_name ) { // Disable if module doesn't set advanced_fields property and has no VB support if ( ! $this->has_vb_support() && ! $this->has_advanced_fields ) { return; } if ( ! self::$_->array_get( $this->advanced_fields, 'margin_padding', false ) ) { return; } $hover = et_pb_hover_options(); $style = ''; $style_padding = ''; $style_margin = ''; $style_mobile = array(); $style_mobile_padding = array(); $style_mobile_margin = array(); $important_options = array(); $is_important_set = isset( $this->advanced_fields['margin_padding']['css']['important'] ); $use_global_important = $is_important_set && 'all' === $this->advanced_fields['margin_padding']['css']['important']; $css = isset( $this->advanced_fields['margin_padding']['css'] ) ? $this->advanced_fields['margin_padding']['css'] : array(); $item_mappings = array( 'top' => 0, 'right' => 1, 'bottom' => 2, 'left' => 3, ); if ( $is_important_set && is_array( $this->advanced_fields['margin_padding']['css']['important'] ) ) { $important_options = $this->advanced_fields['margin_padding']['css']['important']; } $custom_margin = $this->advanced_fields['margin_padding']['use_margin'] ? $this->props['custom_margin'] : ''; $custom_padding = $this->advanced_fields['margin_padding']['use_padding'] ? $this->props['custom_padding'] : ''; $custom_margin_responsive_active = isset( $this->props['custom_margin_last_edited'] ) ? et_pb_get_responsive_status( $this->props['custom_margin_last_edited'] ) : false; $custom_margin_mobile = $custom_margin_responsive_active && $this->advanced_fields['margin_padding']['use_margin'] && ( isset( $this->props['custom_margin_tablet'] ) || isset( $this->props['custom_margin_phone'] ) ) ? array ( 'tablet' => isset( $this->props['custom_margin_tablet'] ) ? $this->props['custom_margin_tablet'] : '', 'phone' => isset( $this->props['custom_margin_phone'] ) ? $this->props['custom_margin_phone'] : '', ) : ''; $custom_padding_responsive_active = isset( $this->props['custom_padding_last_edited'] ) ? et_pb_get_responsive_status( $this->props['custom_padding_last_edited'] ) : false; $custom_padding_mobile = $custom_padding_responsive_active && $this->advanced_fields['margin_padding']['use_padding'] && ( isset( $this->props['custom_padding_tablet'] ) || isset( $this->props['custom_padding_phone'] ) ) ? array ( 'tablet' => isset( $this->props['custom_padding_tablet'] ) ? $this->props['custom_padding_tablet'] : '', 'phone' => isset( $this->props['custom_padding_phone'] ) ? $this->props['custom_padding_phone'] : '', ) : ''; if ( '' !== $custom_padding || ! empty( $custom_padding_mobile ) ) { $important = in_array( 'custom_padding', $important_options ) || $use_global_important ? true : false; $has_padding_selector = isset( $this->advanced_fields['margin_padding']['css'] ) && isset( $this->advanced_fields['margin_padding']['css']['padding'] ); $padding_styling = '' !== $custom_padding ? et_builder_get_element_style_css( $custom_padding, 'padding', $important ) : ''; if ( $has_padding_selector ) { $style_padding .= $padding_styling; } else { $style .= $padding_styling; } if ( ! empty( $custom_padding_mobile ) ) { foreach ( $custom_padding_mobile as $device => $settings ) { $padding_mobile_styling = '' !== $settings ? et_builder_get_element_style_css( $settings, 'padding', $important ) : ''; if ( $has_padding_selector ) { $style_mobile_padding[ $device ][] = $padding_mobile_styling; } else { $style_mobile[ $device ][] = $padding_mobile_styling; } } } // Selective Paddings $selective_paddings = array_filter( array( 'top' => isset( $css['padding-top'] ) ? $css['padding-top'] : false, 'right' => isset( $css['padding-right'] ) ? $css['padding-right'] : false, 'bottom' => isset( $css['padding-bottom'] ) ? $css['padding-bottom'] : false, 'left' => isset( $css['padding-left'] ) ? $css['padding-left'] : false, ) ); // Only run the following if selective-padding selector is defined if ( ! empty( $selective_paddings ) ) { // Loop each padding sides. Selective padding works by creating filtered custom_margin value on the fly, then pass it to existin declaration builder // Ie custom_padding = 10px|10px|10px|10px. Selective padding for padding-top works by creating 10px||| value on the fly then pass it to declaration builder foreach ( $selective_paddings as $corner => $selective_padding_selectors ) { // Default selective padding value: empty on all sides $selective_padding = array( '', '', '', '' ); // Get padding order key. Expected order: top|right|bottom|left $selective_padding_key = $item_mappings[ $corner ]; // Explode custom padding value into array $selective_padding_array = explode( '|', $custom_padding ); // Pick current padding side's value $selective_padding_value = isset( $selective_padding_array[ $selective_padding_key ] ) ? $selective_padding_array[ $selective_padding_key ] : ''; // Set selective padding value to $selective_padding $selective_padding[ $selective_padding_key ] = $selective_padding_value; // If selective padding for current side is found, set style for it $selective_padding_filtered = array_filter( $selective_padding ); if ( ! empty( $selective_padding_filtered ) ) { self::set_style( $function_name, array( 'selector' => $selective_padding_selectors, 'declaration' => rtrim( et_builder_get_element_style_css( implode( '|', $selective_padding ), 'padding' ) ), 'priority' => $this->_style_priority, ) ); } // Check wheter responsive padding is activated and padding has mobile value if ( $custom_padding_responsive_active && is_array( $custom_padding_mobile ) ) { // Assume no mobile padding value first $has_selective_padding_mobile = false; // Set default selective padding mobile $selective_padding_mobile = array( 'tablet' => array( '', '', '', '' ), 'phone' => array( '', '', '', '' ), ); // Loop padding mobile. This results per-breakpoint padding value foreach ( $custom_padding_mobile as $breakpoint => $custom_padding_device ) { // Explode per-breakpoint padding value into array $custom_padding_device_array = explode( '|', $custom_padding_device ); // Get current padding side value on current breakpoint $selective_padding_mobile_value = isset( $custom_padding_device_array[ $selective_padding_key ] ) ? $custom_padding_device_array[ $selective_padding_key ] : ''; // Set picked value into current padding side on current breakpoint $selective_padding_mobile[ $breakpoint ][ $selective_padding_key ] = $selective_padding_mobile_value; // If the side of padding on current breakpoint has value, build CSS declaration for it mark selective padding mobile as exist $selective_padding_mobile[ $breakpoint ] = array_filter( $selective_padding_mobile[ $breakpoint ] ); if ( ! empty( $selective_padding_mobile[ $breakpoint ] ) ) { $selective_padding_mobile[ $breakpoint ] = array( et_builder_get_element_style_css( implode( '|', $selective_padding_mobile[ $breakpoint ] ), 'padding' ) ); $has_selective_padding_mobile = true; } } // Set style for selective padding on mobile if ( $has_selective_padding_mobile ) { $this->process_advanced_mobile_margin_options( $function_name, $selective_padding_mobile, $selective_padding_selectors ); } } } } } if ( '' !== $custom_margin || ! empty( $custom_margin_mobile ) ) { $important = in_array( 'custom_margin', $important_options ) || $use_global_important ? true : false; $has_margin_selector = isset( $this->advanced_fields['margin_padding']['css'] ) && isset( $this->advanced_fields['margin_padding']['css']['margin'] ); $margin_styling = '' !== $custom_margin ? et_builder_get_element_style_css( $custom_margin, 'margin', $important ) : ''; if ( $has_margin_selector ) { $style_margin .= $margin_styling; } else { $style .= $margin_styling; } if ( ! empty( $custom_margin_mobile ) ) { foreach ( $custom_margin_mobile as $device => $settings ) { $margin_mobile_styling = '' !== $settings ? et_builder_get_element_style_css( $settings, 'margin', $important ) : ''; if ( $has_margin_selector ) { $style_mobile_margin[ $device ][] = $margin_mobile_styling; } else { $style_mobile[ $device ][] = $margin_mobile_styling; } } } } if ( '' !== $style_padding ) { $css_element_padding = $this->advanced_fields['margin_padding']['css']['padding']; self::set_style( $function_name, array( 'selector' => $css_element_padding, 'declaration' => rtrim( $style_padding ), 'priority' => $this->_style_priority, ) ); } if ( '' !== $style_margin ) { $css_element_margin = $this->advanced_fields['margin_padding']['css']['margin']; self::set_style( $function_name, array( 'selector' => $css_element_margin, 'declaration' => rtrim( $style_margin ), 'priority' => $this->_style_priority, ) ); } if ( '' !== $style ) { $css_element = ! empty( $this->advanced_fields['margin_padding']['css']['main'] ) ? $this->advanced_fields['margin_padding']['css']['main'] : $this->main_css_element; self::set_style( $function_name, array( 'selector' => $css_element, 'declaration' => rtrim( $style ), 'priority' => $this->_style_priority, ) ); } if ( ! empty( $style_mobile_padding ) ) { $this->process_advanced_mobile_margin_options( $function_name, $style_mobile_padding, $this->advanced_fields['margin_padding']['css']['padding'] ); } if ( ! empty( $style_mobile_margin ) ) { $this->process_advanced_mobile_margin_options( $function_name, $style_mobile_margin, $this->advanced_fields['margin_padding']['css']['margin'] ); } if ( ! empty( $style_mobile ) ) { $css_element = ! empty( $this->advanced_fields['margin_padding']['css']['main'] ) ? $this->advanced_fields['margin_padding']['css']['main'] : $this->main_css_element; $this->process_advanced_mobile_margin_options( $function_name, $style_mobile, $css_element ); } // Hover styles $custom_margin_hover = $hover->get_value( 'custom_margin', $this->props ); if ( '' !== $custom_margin_hover && et_builder_is_hover_enabled( 'custom_margin', $this->props ) ) { $css_element_margin = self::$_->array_get( $this->advanced_fields, 'margin_padding.css.margin', $this->main_css_element ); self::set_style( $function_name, array( 'selector' => $this->add_hover_to_order_class( $css_element_margin ), 'declaration' => rtrim( et_builder_get_element_style_css( $custom_margin_hover, 'margin', true ) ), 'priority' => 20, ) ); } $custom_padding_hover = $hover->get_value( 'custom_padding', $this->props, '' ); if ( '' !== $custom_padding_hover && et_builder_is_hover_enabled( 'custom_padding', $this->props ) ) { $css_element_padding = self::$_->array_get( $this->advanced_fields, 'margin_padding.css.padding', $this->main_css_element ); self::set_style( $function_name, array( 'selector' => $this->add_hover_to_order_class( $css_element_padding ), 'declaration' => rtrim( et_builder_get_element_style_css( $custom_padding_hover, 'padding', true ) ), 'priority' => 20, ) ); } } function process_advanced_mobile_margin_options( $function_name, $style_mobile, $css_element ) { foreach( $style_mobile as $device => $style ) { if ( ! empty( $style ) ) { $current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767'; $current_media_css = ''; foreach( $style as $css_code ) { $current_media_css .= $css_code; } if ( '' === $current_media_css ) { continue; } self::set_style( $function_name, array( 'selector' => $css_element, 'declaration' => rtrim( $current_media_css ), 'priority' => $this->_style_priority, 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } } } protected function get_hover_value( $option ) { $enabled_option = $option === 'background_color' ? 'background' : $option; $original_value = self::$_->array_get( $this->props, $option ); $hover_enabled = et_pb_hover_options()->is_enabled( $enabled_option, $this->props ); $value = et_pb_hover_options()->get_value( $option, $this->props ); return ( ! $hover_enabled || $original_value === $value ) ? null : $value; } /** * Process advanced button options. * * @since 3.23 Add support to generate responsive styles of padding and button alignment. * * @param string $function_name Module slug. */ function process_advanced_button_options( $function_name ) { // Disable if module doesn't set advanced_fields property and has no VB support if ( ! $this->has_advanced_fields ) { return; } if ( ! self::$_->array_get( $this->advanced_fields, 'button', false ) ) { return; } $hover = et_pb_hover_options(); foreach ( $this->advanced_fields['button'] as $option_name => $option_settings ) { $button_custom = $this->props["custom_{$option_name}"]; $button_use_icon = isset( $this->props["{$option_name}_use_icon"] ) ? $this->props["{$option_name}_use_icon"] : 'on'; // Button Icon. $button_icon_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_icon" ); $button_icon = isset( $button_icon_values['desktop'] ) ? $button_icon_values['desktop'] : ''; $button_icon_tablet = isset( $button_icon_values['tablet'] ) ? $button_icon_values['tablet'] : ''; $button_icon_phone = isset( $button_icon_values['phone'] ) ? $button_icon_values['phone'] : ''; $important = et_()->array_get( $option_settings, 'css.important', false ) ? ' !important' : ''; // Button Icon Placement. $button_icon_placement_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_icon_placement" ); $button_icon_placement = isset( $button_icon_placement_values['desktop'] ) ? $button_icon_placement_values['desktop'] : 'right'; $button_icon_placement_tablet = isset( $button_icon_placement_values['tablet'] ) ? $button_icon_placement_values['tablet'] : ''; $button_icon_placement_phone = isset( $button_icon_placement_values['phone'] ) ? $button_icon_placement_values['phone'] : ''; // Button Icon On Hover. $button_on_hover_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_on_hover" ); $button_on_hover = isset( $button_on_hover_values['desktop'] ) ? $button_on_hover_values['desktop'] : ''; $button_on_hover_tablet = isset( $button_on_hover_values['tablet'] ) ? $button_on_hover_values['tablet'] : ''; $button_on_hover_phone = isset( $button_on_hover_values['phone'] ) ? $button_on_hover_values['phone'] : ''; // Button Text Size. $button_text_size_hover = $this->get_hover_value( "{$option_name}_text_size" ); $button_text_size_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_text_size" ); $button_text_size = isset( $button_text_size_values['desktop'] ) ? $button_text_size_values['desktop'] : ''; $button_text_size_tablet = isset( $button_text_size_values['tablet'] ) ? $button_text_size_values['tablet'] : ''; $button_text_size_phone = isset( $button_text_size_values['phone'] ) ? $button_text_size_values['phone'] : ''; // Button Text Color. $button_text_color_hover = $this->get_hover_value( "{$option_name}_text_color" ); $button_text_color_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_text_color" ); $button_text_color = isset( $button_text_color_values['desktop'] ) ? $button_text_color_values['desktop'] : ''; $button_text_color_tablet = isset( $button_text_color_values['tablet'] ) ? $button_text_color_values['tablet'] : ''; $button_text_color_phone = isset( $button_text_color_values['phone'] ) ? $button_text_color_values['phone'] : ''; // Button Border Width. $button_border_width_hover = $this->get_hover_value( "{$option_name}_border_width" ); $button_border_width_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_border_width" ); $button_border_width = isset( $button_border_width_values['desktop'] ) ? $button_border_width_values['desktop'] : ''; $button_border_width_tablet = isset( $button_border_width_values['tablet'] ) ? $button_border_width_values['tablet'] : ''; $button_border_width_phone = isset( $button_border_width_values['phone'] ) ? $button_border_width_values['phone'] : ''; // Button Border Color. $button_border_color_hover = $this->get_hover_value( "{$option_name}_border_color" ); $button_border_color_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_border_color" ); $button_border_color = isset( $button_border_color_values['desktop'] ) ? $button_border_color_values['desktop'] : ''; $button_border_color_tablet = isset( $button_border_color_values['tablet'] ) ? $button_border_color_values['tablet'] : ''; $button_border_color_phone = isset( $button_border_color_values['phone'] ) ? $button_border_color_values['phone'] : ''; // Button Border Radius. $button_border_radius_hover = $this->get_hover_value( "{$option_name}_border_radius" ); $button_border_radius_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_border_radius" ); $button_border_radius = isset( $button_border_radius_values['desktop'] ) ? $button_border_radius_values['desktop'] : ''; $button_border_radius_tablet = isset( $button_border_radius_values['tablet'] ) ? $button_border_radius_values['tablet'] : ''; $button_border_radius_phone = isset( $button_border_radius_values['phone'] ) ? $button_border_radius_values['phone'] : ''; // Button Font. $button_font_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_font" ); $button_font = isset( $button_font_values['desktop'] ) ? $button_font_values['desktop'] : ''; $button_font_tablet = isset( $button_font_values['tablet'] ) ? $button_font_values['tablet'] : ''; $button_font_phone = isset( $button_font_values['phone'] ) ? $button_font_values['phone'] : ''; // Button Letter Spacing. $button_letter_spacing_hover = $this->get_hover_value( "{$option_name}_letter_spacing" ); $button_letter_spacing_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_letter_spacing" ); $button_letter_spacing = isset( $button_letter_spacing_values['desktop'] ) ? $button_letter_spacing_values['desktop'] : ''; $button_letter_spacing_tablet = isset( $button_letter_spacing_values['tablet'] ) ? $button_letter_spacing_values['tablet'] : ''; $button_letter_spacing_phone = isset( $button_letter_spacing_values['phone'] ) ? $button_letter_spacing_values['phone'] : ''; // Button Icon Color. $button_icon_color_hover = et_pb_hover_options()->get_value( "{$option_name}_icon_color", $this->props ); $button_icon_color_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_icon_color" ); $button_icon_color = isset( $button_icon_color_values['desktop'] ) ? $button_icon_color_values['desktop'] : ''; $button_icon_color_tablet = isset( $button_icon_color_values['tablet'] ) ? $button_icon_color_values['tablet'] : ''; $button_icon_color_phone = isset( $button_icon_color_values['phone'] ) ? $button_icon_color_values['phone'] : ''; $button_icon_pseudo_selector = $button_icon_placement === 'left' ? ':before' : ':after'; // Hide button settings. $hide_icon_setting = isset( $option_settings['hide_icon'] ) ? $option_settings['hide_icon'] : false; $hide_custom_padding_setting = isset( $option_settings['hide_custom_padding'] ) ? $option_settings['hide_custom_padding'] : false; // If module hides the button icon settings, no need to render button icon. So, we need // to the button_use_icon value as 'off'. if ( $hide_icon_setting ) { $button_use_icon = 'off'; } // Specific selector needs to be explicitly defined to make button alignment works if ( isset( $option_settings['use_alignment'] ) && $option_settings['use_alignment'] && isset( $option_settings['css'] ) && isset( $option_settings['css']['alignment'] ) ) { $button_alignment_selector = $option_settings['css']['alignment']; // Button alignment. if ( '' !== $button_alignment_selector ) { // Get button alignment responsive status. $button_alignment_responsive_active = isset( $this->props["{$option_name}_alignment_last_edited"] ) ? et_pb_get_responsive_status( $this->props["{$option_name}_alignment_last_edited"] ) : false; // Print styles for each devices. foreach ( array( 'desktop', 'tablet', 'phone' ) as $device ) { $is_desktop = 'desktop' === $device; $button_key = ! $is_desktop ? "{$option_name}_alignment_{$device}" : "{$option_name}_alignment"; $button_alignment = $this->props["{$button_key}"]; // Ensure button alignment value is not empty. if ( empty( $button_alignment ) ) { continue; } $button_alignment_data = array( 'selector' => $button_alignment_selector, 'declaration' => esc_html( "text-align: {$button_alignment};" ), ); if ( ! $is_desktop ) { // Skip tablet/phone if responsive setting is disabled. if ( ! $button_alignment_responsive_active ) { continue; } // Set media query for tablet/phone. $current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767'; $button_alignment_data['media_query'] = ET_Builder_Element::get_media_query( $current_media_query ); } self::set_style( $function_name, $button_alignment_data ); } } } if ( 'on' === $button_custom ) { // Default. $is_default_button_text_size = $this->_is_field_default( 'button_text_size', $button_text_size ); $is_default_button_icon_placement = $this->_is_field_default( 'button_icon_placement', $button_icon_placement ); $is_default_button_on_hover = $this->_is_field_default( 'button_on_hover', $button_on_hover ); $is_default_button_icon = $this->_is_field_default( 'button_icon', $button_icon ); $is_default_hover_placement = $is_default_button_on_hover && $is_default_button_icon_placement; // Processed values. $button_text_size_processed = $is_default_button_text_size ? '20px' : et_builder_process_range_value( $button_text_size ); $button_text_size_hover_processed = strlen( $button_text_size_hover ) && $button_text_size !== $button_text_size_hover ? et_builder_process_range_value( $button_text_size_hover ) : ''; $button_border_radius_processed = '' !== $button_border_radius && 'px' !== $button_border_radius ? et_builder_process_range_value( $button_border_radius ) : ''; $button_border_radius_hover_processed = null !== $button_border_radius_hover && 'px' !== $button_border_radius_hover && $button_border_radius_hover !== $button_border_radius ? et_builder_process_range_value( $button_border_radius_hover ) : ''; $button_use_icon = '' === $button_use_icon ? 'on' : $button_use_icon; $css_element = ! empty( $option_settings['css']['main'] ) ? $option_settings['css']['main'] : $this->main_css_element . ' .et_pb_button'; $css_element_processed = $css_element; $is_dbp = et_builder_has_limitation( 'use_limited_main' ); if ( $is_dbp && ! empty( $option_settings['css']['limited_main'] ) ) { $css_element_processed = $option_settings['css']['limited_main']; } else if ( ! $is_dbp ) { // Explicitly add '.et_pb_section' to the selector so selector splitting during prefixing // does not incorrectly add third party classes before #et-boc. $css_element_processed = "body #page-container .et_pb_section {$css_element}"; } if ( et_builder_has_limitation('force_use_global_important') ) { $button_border_radius_processed .= '' !== $button_border_radius_processed ? ' !important' : ''; $button_border_radius_hover_processed .= '' !== $button_border_radius_hover_processed ? ' !important' : ''; } $global_use_icon_value = et_builder_option( 'all_buttons_icon' ); $main_element_styles_padding_important = 'no' === $global_use_icon_value && 'off' !== $button_use_icon; // Check existing button custom padding on desktop before generating padding. // If current button has custom padding, we should not set default padding, // just leave it empty. $button_padding_name = 'et_pb_button' !== $function_name ? "{$option_name}_custom_padding" : 'custom_padding'; $button_padding_value = et_pb_responsive_options()->get_any_value( $this->props, $button_padding_name ); $button_padding_value = ! empty( $button_padding_value ) ? explode( '|', $button_padding_value ) : array(); $button_padding_right = self::$_->array_get( $button_padding_value, 1, '' ); $button_padding_left = self::$_->array_get( $button_padding_value, 3, '' ); $main_element_styles = sprintf( '%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s', '' !== $button_text_color ? sprintf( 'color:%1$s !important;', $button_text_color ) : '', '' !== $button_border_width && 'px' !== $button_border_width ? sprintf( 'border-width:%1$s !important;', et_builder_process_range_value( $button_border_width ) ) : '', '' !== $button_border_color ? sprintf( 'border-color:%1$s;', $button_border_color ) : '', '' !== $button_border_radius_processed ? sprintf( 'border-radius:%1$s;', $button_border_radius_processed ) : '', '' !== $button_letter_spacing && 'px' !== $button_letter_spacing ? sprintf( 'letter-spacing:%1$s;', et_builder_process_range_value( $button_letter_spacing ) ) : '', // #5 ! $is_default_button_text_size ? sprintf( 'font-size:%1$s;', $button_text_size_processed ) : '', '' !== $button_font ? et_builder_set_element_font( $button_font, true ) : '', 'off' === $button_on_hover && empty( $button_padding_right ) ? sprintf( 'padding-right: %1$s%2$s;', 'left' === $button_icon_placement ? '0.7em' : '2em', $main_element_styles_padding_important ? ' !important' : '' ) : '', 'off' === $button_on_hover && empty( $button_padding_left ) ? sprintf( 'padding-left:%1$s%2$s;', 'left' === $button_icon_placement ? '2em' : '0.7em', $main_element_styles_padding_important ? ' !important' : '' ) : '' ); self::set_style( $function_name, array( 'selector' => $css_element_processed, 'declaration' => rtrim( $main_element_styles ), ) ); // Check existing button custom padding on hover before generating padding on // hover. If current button has custom padding on hover, we should not set // default padding on hover, just leave it empty. $button_padding_hover_value = et_pb_hover_options()->get_value( $button_padding_name, $this->props, '' ); $button_padding_hover_value = ! empty( $button_padding_hover_value ) ? explode( '|', $button_padding_hover_value ) : array(); $button_padding_hover_right = self::$_->array_get( $button_padding_hover_value, 1, '' ); $button_padding_hover_left = self::$_->array_get( $button_padding_hover_value, 3, '' ); $on_hover_padding_right = ! empty( $button_padding_hover_right ) ? '' : sprintf( 'padding-right: %1$s%2$s;', 'left' === $button_icon_placement ? '0.7em' : '2em', $main_element_styles_padding_important ? ' !important' : '' ); $on_hover_padding_left = ! empty( $button_padding_hover_left ) ? '' : sprintf( 'padding-left: %1$s%2$s;', 'left' === $button_icon_placement ? '2em' : '0.7em', $main_element_styles_padding_important ? ' !important' : '' ); // if button has default icon position or disabled globally and not enabled in module then no padding css should be generated. $on_hover_padding = $is_default_button_icon_placement || ('default' === $button_use_icon && 'no' === $global_use_icon_value) ? '' : sprintf( '%1$s%2$s', $on_hover_padding_right, $on_hover_padding_left ); // Avoid adding useless style when value equals its default $button_letter_spacing_hover = $this->_is_field_default( $hover->get_hover_field( 'button_letter_spacing' ), $button_letter_spacing_hover) ? '' : $button_letter_spacing_hover; $main_element_styles_hover = sprintf( '%1$s %2$s %3$s %4$s %5$s %6$s %7$s', ! empty( $button_text_color_hover ) ? sprintf( 'color:%1$s !important;', $button_text_color_hover ) : '', ! empty( $button_border_color_hover ) ? sprintf( 'border-color:%1$s !important;', $button_border_color_hover ) : '', '' !== $button_border_radius_hover_processed ? sprintf( 'border-radius:%1$s;', $button_border_radius_hover_processed ) : '', ! empty( $button_letter_spacing_hover ) && 'px' !== $button_letter_spacing_hover && $button_letter_spacing_hover !== $button_letter_spacing ? sprintf( 'letter-spacing:%1$s;', et_builder_process_range_value( $button_letter_spacing_hover ) ) : '', 'off' === $button_on_hover || $hide_custom_padding_setting ? '' : $on_hover_padding, '' !== $button_text_size_hover_processed ? sprintf( 'font-size:%1$s !important;', $button_text_size_hover_processed ) : '', ! empty( $button_border_width_hover ) ? sprintf( 'border-width:%1$s !important;', $button_border_width_hover ) : '' ); $main_element_styles_hover_declaration = rtrim( $main_element_styles_hover ); if ( $main_element_styles_hover_declaration ) { self::set_style( $function_name, array( 'selector' => $css_element_processed . ':hover', 'declaration' => $main_element_styles_hover_declaration, ) ); } $main_element_styles_after_hover = ''; if ( 'off' === $button_use_icon ) { $main_element_styles_after = 'display:none !important;'; $selector = sprintf( '%1$s:before, %1$s:after', $css_element_processed ); $no_icon_styles = ''; // Check button custom padding. Prepend option name to get the correct padding. $custom_padding = self::$_->array_get( $this->props, 'custom_padding', '' ); if ( 'et_pb_button' !== $function_name ) { $custom_padding = self::$_->array_get( $this->props, "{$option_name}_custom_padding", '' ); } if ( empty( $custom_padding ) ) { $no_icon_styles .= 'padding: 0.3em 1em !important;'; } else { $padding_array = explode( '|', $custom_padding ); if ( empty( $padding_array[1] ) ) { $no_icon_styles .= 'padding-right: 1em !important;'; } if ( empty( $padding_array[3] ) ) { $no_icon_styles .= 'padding-left: 1em !important;'; } } // No need to print custom padding if custom padding setting is disabled. if ( ! empty( $no_icon_styles ) && ! $hide_custom_padding_setting ) { self::set_style( $function_name, array( 'selector' => $css_element_processed . ',' . $css_element_processed . ':hover', 'declaration' => rtrim( $no_icon_styles ), ) ); } } else { $button_icon_code = '' !== $button_icon ? str_replace( ';', '', str_replace( '&#x', '', html_entity_decode( et_pb_process_font_icon( $button_icon ) ) ) ) : ''; $main_element_styles_after = sprintf( '%1$s %2$s %3$s %4$s %5$s %6$s %7$s', '' !== $button_icon_color ? sprintf( 'color:%1$s;', $button_icon_color ) : '', '' !== $button_icon_code ? 'line-height: inherit;' : '', '' !== $button_icon_code ? 'font-size: inherit !important;' : '', $is_default_hover_placement ? '' : sprintf( 'opacity:%1$s;', 'off' !== $button_on_hover ? '0' : '1' ), 'off' !== $button_on_hover && '' !== $button_icon_code ? sprintf( 'margin-left: %1$s; %2$s: auto;', 'left' === $button_icon_placement ? '-1.3em' : '-1em', 'left' === $button_icon_placement ? 'right' : 'left' ) : '', 'off' === $button_on_hover ? sprintf( 'margin-left: %1$s; %2$s:auto;', 'left' === $button_icon_placement ? '-1.3em' : '.3em', 'left' === $button_icon_placement ? 'right' : 'left' ) : '', ( ! $is_default_button_icon_placement && in_array( $button_use_icon , array( 'default', 'on' ) ) ? 'display: inline-block;' : '' ) ); if ( ! empty( $button_icon_color_hover ) && $button_icon_color_hover !== $button_icon_color ) { $main_element_styles_after_hover = sprintf( 'color: %1$s', $button_icon_color_hover ); } // Reverse icon position if ( 'left' === $button_icon_placement ) { $button_icon_left_content = '' !== $button_icon_code ? 'content: attr(data-icon);' : ''; self::set_style( $function_name, array( 'selector' => $css_element_processed . ':after', 'declaration' => 'display: none;', ) ); if ( et_builder_has_limitation('use_additional_limiting_styles') ) { self::set_style( $function_name, array( 'selector' => '.et_pb_row ' . $css_element_processed . ':hover', 'declaration' => 'padding-right: 1em; padding-left: 2em;', ) ); } self::set_style( $function_name, array( 'selector' => $css_element_processed . ':before', 'declaration' => $button_icon_left_content . ' ; font-family: "ETmodules" !important;', ) ); } // if button has default icon/hover/placement and disabled globally or not enabled in module then no :after:hover css should be generated. if ( ! ( $is_default_button_icon && $is_default_hover_placement ) && ( 'default' !== $button_use_icon || 'no' !== $global_use_icon_value ) ) { $hover_after_styles = sprintf( '%1$s %2$s %3$s', '' !== $button_icon_code ? sprintf( 'margin-left:%1$s;', '35' !== $button_icon_code ? '.3em' : '0' ) : '', '' !== $button_icon_code ? sprintf( '%1$s: auto; margin-left: %2$s;', 'left' === $button_icon_placement ? 'right' : 'left', 'left' === $button_icon_placement ? '-1.3em' : '.3em' ) : '', 'off' !== $button_on_hover ? 'opacity: 1;' : '' ); self::set_style( $function_name, array( 'selector' => $css_element_processed . ':hover' . $button_icon_pseudo_selector, 'declaration' => rtrim( $hover_after_styles ), ) ); } if ( '' === $button_icon && ! $is_default_button_text_size ) { $default_icons_size = '1.6em'; $custom_icon_size = $button_text_size_processed; self::set_style( $function_name, array( 'selector' => $css_element_processed . $button_icon_pseudo_selector, 'declaration' => sprintf( 'font-size:%1$s;', $default_icons_size ), ) ); self::set_style( $function_name, array( 'selector' => 'body.et_button_custom_icon #page-container ' . $css_element . $button_icon_pseudo_selector, 'declaration' => sprintf( 'font-size:%1$s;', $custom_icon_size ), ) ); } if ( '' === $button_icon && '' !== $button_text_size_hover_processed ) { $default_icons_size = '1.6em'; $custom_icon_size = $button_text_size_hover_processed; self::set_style( $function_name, array( 'selector' => $css_element_processed . ':hover' . $button_icon_pseudo_selector, 'declaration' => sprintf( 'font-size:%1$s;', $default_icons_size ), ) ); self::set_style( $function_name, array( 'selector' => 'body.et_button_custom_icon #page-container ' . $css_element . ':hover' . $button_icon_pseudo_selector, 'declaration' => sprintf( 'font-size:%1$s;', $custom_icon_size ), ) ); } $selector = $css_element_processed . $button_icon_pseudo_selector; } self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => rtrim( $main_element_styles_after ), ) ); self::set_style( $function_name, array( 'selector' => et_pb_hover_options()->add_hover_to_selectors( $selector ), 'declaration' => rtrim( $main_element_styles_after_hover ), ) ); // Responsive Button Styles. $prev_icon = $button_icon; foreach( array( 'tablet', 'phone' ) as $device ) { $current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767'; $current_text_size = 'tablet' === $device ? $button_text_size_tablet : $button_text_size_phone; $current_text_size = '' !== $current_text_size ? et_builder_process_range_value( $current_text_size ) : ''; $current_text_color = 'tablet' === $device ? $button_text_color_tablet : $button_text_color_phone; $current_border_width = 'tablet' === $device ? $button_border_width_tablet : $button_border_width_phone; $current_border_width = '' !== $current_border_width ? et_builder_process_range_value( $current_border_width ) : ''; $current_border_color = 'tablet' === $device ? $button_border_color_tablet : $button_border_color_phone; $current_border_radius = 'tablet' === $device ? $button_border_radius_tablet : $button_border_radius_phone; $current_border_radius = '' !== $current_border_radius ? et_builder_process_range_value( $current_border_radius ) : ''; $current_letter_spacing = 'tablet' === $device ? $button_letter_spacing_tablet : $button_letter_spacing_phone; $current_letter_spacing = '' !== $current_letter_spacing ? et_builder_process_range_value( $current_letter_spacing ) : ''; $current_font = 'tablet' === $device ? $button_font_tablet : $button_font_phone; $current_icon_color = 'tablet' === $device ? $button_icon_color_tablet : $button_icon_color_phone; // The attributes below should inherit larger device. $current_icon = et_pb_responsive_options()->get_property_value( $this->props, "{$option_name}_icon", $button_icon, $device, true ); $current_icon_placement = et_pb_responsive_options()->get_property_value( $this->props, "{$option_name}_icon_placement", $button_icon_placement, $device, true ); $current_on_hover = et_pb_responsive_options()->get_property_value( $this->props, "{$option_name}_on_hover", $button_on_hover, $device, true ); $is_default_hover_placement = '' === $current_on_hover && '' === $current_icon_placement; $button_icon_pseudo_selector = 'left' === $current_icon_placement ? ':before' : ':after'; // Force to have important tag. if ( et_builder_has_limitation('force_use_global_important') ) { $current_border_radius .= '' !== $current_border_radius ? ' !important' : ''; } // Get right and left custom padding value. The reset padding should not // be applied if current button has custom padding defined. $current_padding_name = et_pb_responsive_options()->get_field_name( $button_padding_name, $device ); $current_padding_value = et_pb_responsive_options()->get_any_value( $this->props, $current_padding_name, '', true ); $current_padding_value = ! empty( $current_padding_value ) ? explode( '|', $current_padding_value ) : array(); $current_padding_default = et_pb_responsive_options()->get_default_value( $this->props, $current_padding_name ); $current_padding_default = ! empty( $current_padding_default ) ? explode( '|', $current_padding_default ) : array(); $current_padding_right = self::$_->array_get( $current_padding_value, 1, '' ); $current_padding_left = self::$_->array_get( $current_padding_value, 3, '' ); $current_padding_default_right = self::$_->array_get( $current_padding_default, 1, '' ); $current_padding_default_left = self::$_->array_get( $current_padding_default, 3, '' ); // Reset responsive padding right. Only reset padding if current device // doesn't have value and the previous device has value to be reset. $responsive_padding_right = ''; $responsive_hover_padding_right = ''; if ( empty( $current_padding_right ) && ! empty( $current_padding_default_right ) ) { // Default padding for normal and hover. $responsive_padding_right = '1em'; // If padding hover right deosn't exist, add default padding for hover. if ( empty( $button_padding_hover_right ) ) { $responsive_hover_padding_right = 'left' === $current_icon_placement ? '2em' : '0.7em'; } // If icon on hover is disabled, set padding value like hover state // and remove padding for hover because it's same. if ( 'off' === $current_on_hover ) { $responsive_padding_right = 'left' === $current_icon_placement ? '2em' : '0.7em'; $responsive_hover_padding_right = ''; } } // Reset responsive padding left. Only reset padding if current device // doesn't have value and the previous device has value to be reset. $responsive_padding_left = ''; $responsive_hover_padding_left = ''; if ( empty( $current_padding_left ) && ! empty( $current_padding_default_left ) ) { // Default padding for normal and hover. $responsive_padding_left = '1em'; // If padding hover left deosn't exist, add default padding for hover. if ( empty( $button_padding_hover_left ) ) { $responsive_hover_padding_left = 'left' === $current_icon_placement ? '2em' : '0.7em'; } // If icon on hover is disabled, set padding value like hover state // and remove padding for hover because it's same. if ( 'off' === $current_on_hover ) { $responsive_padding_left = 'left' === $current_icon_placement ? '0.7em' : '2em'; $responsive_hover_padding_left = ''; } } // Remove responsive on hover padding left & right. if ( '' === $current_icon_placement || ( 'default' === $button_use_icon && 'no' === $global_use_icon_value ) || $hide_custom_padding_setting ) { $responsive_hover_padding_left = ''; $responsive_hover_padding_right = ''; } // Responsive button declaration. $responsive_button_declaration = trim( sprintf( '%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s', '' !== $current_text_size ? sprintf( 'font-size:%1$s !important;', $current_text_size ) : '', '' !== $current_letter_spacing ? sprintf( 'letter-spacing:%1$s;', $current_letter_spacing ) : '', '' !== $current_text_color ? sprintf( 'color:%1$s !important;', $current_text_color ) : '', '' !== $current_border_width ? sprintf( 'border-width:%1$s !important;', $current_border_width ) : '', '' !== $current_border_color ? sprintf( 'border-color:%1$s;', $current_border_color ) : '', // #5 '' !== $current_border_radius ? sprintf( 'border-radius:%1$s;', $current_border_radius ) : '', '' !== $current_font ? et_builder_set_element_font( $current_font, true ) : '', '' !== $responsive_padding_right ? sprintf( 'padding-right: %1$s%2$s;', $responsive_padding_right, $main_element_styles_padding_important ? ' !important' : '' ) : '', '' !== $responsive_padding_left ? sprintf( 'padding-left: %1$s%2$s;', $responsive_padding_left, $main_element_styles_padding_important ? ' !important' : '' ) : '' ) ); if ( ! empty( $responsive_button_declaration ) ) { self::set_style( $function_name, array( 'selector' => $css_element_processed, 'declaration' => $responsive_button_declaration, 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } // Responsive button hover declaration. $responsive_button_hover_declaration = trim( sprintf( '%1$s %2$s', '' !== $responsive_hover_padding_right ? sprintf( 'padding-right: %1$s%2$s;', $responsive_hover_padding_right, $main_element_styles_padding_important ? ' !important' : '' ) : '', '' !== $responsive_hover_padding_left ? sprintf( 'padding-left: %1$s%2$s;', $responsive_hover_padding_left, $main_element_styles_padding_important ? ' !important' : '' ) : '' ) ); // Responsive button hover styles. if ( ! empty( $responsive_button_hover_declaration ) ) { self::set_style( $function_name, array( 'selector' => $css_element_processed . ':hover', 'declaration' => $responsive_button_hover_declaration, 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } // Responsive button after styles. if ( 'off' !== $button_use_icon ) { // Button Icon Code. $current_icon_code = '' !== $current_icon ? str_replace( ';', '', str_replace( '&#x', '', html_entity_decode( et_pb_process_font_icon( $current_icon ) ) ) ) : ''; // 1. Set button color, line-height, font-size, and icon placement. $responsive_button_after_declaration = trim( sprintf( '%1$s %2$s %3$s %4$s %5$s %6$s %7$s', '' !== $current_icon_color ? sprintf( 'color:%1$s;', $current_icon_color ) : '', '' !== $current_icon_code ? 'line-height: inherit;' : '', '' !== $current_icon_code ? 'font-size: inherit !important;' : '', 'off' !== $current_on_hover && '' !== $current_icon_code ? sprintf( 'margin-left: %1$s; %2$s: auto;', 'left' === $current_icon_placement ? '-1.3em' : '-1em', 'left' === $current_icon_placement ? 'right' : 'left' ) : '', 'off' === $current_on_hover ? sprintf( 'margin-left: %1$s; %2$s: auto;', 'left' === $current_icon_placement ? '-1.3em' : '.3em', 'left' === $current_icon_placement ? 'right' : 'left' ) : '', // #5 '' !== $current_icon_placement && in_array( $button_use_icon , array( 'default', 'on' ) ) ? 'display: inline-block;' : '', 'off' !== $current_on_hover ? 'opacity: 0;' : 'opacity: 1;' ) ); if ( ! empty( $responsive_button_after_declaration ) ) { self::set_style( $function_name, array( 'selector' => $css_element_processed . $button_icon_pseudo_selector, 'declaration' => $responsive_button_after_declaration, 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } // 2. DONE - Set custom icon and icon placement. if ( '' !== $current_icon_code ) { $button_icon_suffix = $prev_icon !== $current_icon ? "-{$device}" : ''; $button_icon_content = "content: attr(data-icon{$button_icon_suffix});"; $button_side_hide = ':before'; $button_side_display = ':after'; // Reverse icon position. if ( 'left' === $current_icon_placement ) { $button_side_hide = ':after'; $button_side_display = ':before'; } self::set_style( $function_name, array( 'selector' => $css_element_processed . $button_side_hide, 'declaration' => 'display: none;', 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); self::set_style( $function_name, array( 'selector' => $css_element_processed . $button_side_display, 'declaration' => $button_icon_content . ' font-family: "ETmodules" !important;', 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } // 3. If button has default icon/hover/placement and disabled globally or not enabled in module then // no :after:hover css should be generated. if ( ! ( '' === $current_icon && $is_default_hover_placement ) && ( 'default' !== $button_use_icon || 'no' !== $global_use_icon_value ) ) { $hover_after_styles = sprintf( '%1$s %2$s %3$s', '' !== $current_icon_code ? sprintf( 'margin-left:%1$s;', '35' !== $current_icon_code ? '.3em' : '0' ) : '', '' !== $current_icon_code ? sprintf( '%1$s: auto; margin-left: %2$s;', 'left' === $current_icon_placement ? 'right' : 'left', 'left' === $current_icon_placement ? '-1.3em' : '.3em' ) : '', 'off' !== $current_on_hover ? 'opacity: 1;' : '' ); self::set_style( $function_name, array( 'selector' => $css_element_processed . ':hover' . $button_icon_pseudo_selector, 'declaration' => rtrim( $hover_after_styles ), 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } // Set button icon font size for default. if ( '' === $current_icon && '' !== $current_text_size ) { $default_icons_size = '1.6em'; $custom_icon_size = $current_text_size; self::set_style( $function_name, array( 'selector' => $css_element_processed . $button_icon_pseudo_selector, 'declaration' => sprintf( 'font-size:%1$s;', $default_icons_size ), 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); self::set_style( $function_name, array( 'selector' => 'body.et_button_custom_icon #page-container ' . $css_element . $button_icon_pseudo_selector, 'declaration' => sprintf( 'font-size:%1$s;', $custom_icon_size ), 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } // Set button icon font size on hover for default. if ( '' === $current_icon && '' !== $button_icon && '' !== $button_text_size_hover_processed ) { $default_icons_size = '1.6em'; $custom_icon_size = $button_text_size_hover_processed; self::set_style( $function_name, array( 'selector' => $css_element_processed . ':hover' . $button_icon_pseudo_selector, 'declaration' => sprintf( 'font-size:%1$s;', $default_icons_size ), 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); self::set_style( $function_name, array( 'selector' => 'body.et_button_custom_icon #page-container ' . $css_element . ':hover' . $button_icon_pseudo_selector, 'declaration' => sprintf( 'font-size:%1$s;', $custom_icon_size ), 'media_query' => ET_Builder_Element::get_media_query( $current_media_query ), ) ); } } // Set flag. $prev_icon = $current_icon; } // Place to store processed background. It will be compared with the smaller device // background processed value to avoid rendering the same styles. $processed_background_color = ''; $processed_background_image = ''; $gradient_properties_desktop = ''; $processed_background_blend = ''; // Store background images status because the process is extensive. $background_image_status = array( 'desktop' => false, 'tablet' => false, 'phone' => false, ); $background_color_gradient_overlays_image_desktop = 'off'; // Background Options Styling. foreach ( et_pb_responsive_options()->get_modes() as $device ) { $background_base_name = "{$option_name}_bg"; $background_prefix = "{$background_base_name}_"; $background_style = ''; $is_desktop = 'desktop' === $device; $suffix = ! $is_desktop ? "_{$device}" : ''; $background_color_style = ''; $background_image_style = ''; $background_images = array(); $has_background_color_gradient = false; $has_background_image = false; $has_background_gradient_and_image = false; $is_background_color_gradient_disabled = false; $is_background_image_disabled = false; $background_color_gradient_overlays_image = 'off'; // Ensure responsive is active. if ( ! $is_desktop && ! et_pb_responsive_options()->is_responsive_enabled( $this->props, "{$option_name}_bg_color" ) ) { continue; } // A. Background Gradient. $use_background_color_gradient = et_pb_responsive_options()->get_inheritance_background_value( $this->props, "{$background_prefix}use_color_gradient", $device, $background_base_name, $this->fields_unprocessed ); if ( 'on' === $use_background_color_gradient ) { $background_color_gradient_overlays_image = et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}color_gradient_overlays_image{$suffix}", '', true ); $gradient_properties = array( 'type' => et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}color_gradient_type{$suffix}", '', true ), 'direction' => et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}color_gradient_direction{$suffix}", '', true ), 'radial_direction' => et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}color_gradient_direction_radial{$suffix}", '', true ), 'color_start' => et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}color_gradient_start{$suffix}", '', true ), 'color_end' => et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}color_gradient_end{$suffix}", '', true ), 'start_position' => et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}color_gradient_start_position{$suffix}", '', true ), 'end_position' => et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}color_gradient_end_position{$suffix}", '', true ), ); // Will be used as hover default. if ( 'desktop' === $device ) { $gradient_properties_desktop = $gradient_properties; $background_color_gradient_overlays_image_desktop = $background_color_gradient_overlays_image; } // Save background gradient into background images list. $background_images[] = $this->get_gradient( $gradient_properties ); // Flag to inform BG Color if current module has Gradient. $has_background_color_gradient = true; } else if ( 'off' === $use_background_color_gradient ) { $is_background_color_gradient_disabled = true; } // B. Background Image. $background_image = et_pb_responsive_options()->get_inheritance_background_value( $this->props, "{$background_prefix}image", $device, $background_base_name, $this->fields_unprocessed ); $parallax = et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}parallax{$suffix}", 'off' ); // BG image and parallax status. $is_background_image_active = '' !== $background_image && 'on' !== $parallax; $background_image_status[ $device ] = $is_background_image_active; if ( $is_background_image_active ) { // Flag to inform BG Color if current module has Image. $has_background_image = true; // Check previous BG image status. Needed to get the correct value. $is_prev_background_image_active = true; if ( ! $is_desktop ) { $is_prev_background_image_active = 'tablet' === $device ? $background_image_status['desktop'] : $background_image_status['tablet']; } // Size. $background_size_default = self::$_->array_get( $this->fields_unprocessed, "{$background_prefix}size.default", '' ); $background_size = et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}size{$suffix}", $background_size_default, ! $is_prev_background_image_active ); if ( '' !== $background_size ) { $background_style .= sprintf( 'background-size: %1$s; ', esc_html( $background_size ) ); } // Position. $background_position_default = self::$_->array_get( $this->fields_unprocessed, "{$background_prefix}position.default", '' ); $background_position = et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}position{$suffix}", $background_position_default, ! $is_prev_background_image_active ); if ( '' !== $background_position ) { $background_style .= sprintf( 'background-position: %1$s; ', esc_html( str_replace( '_', ' ', $background_position ) ) ); } // Repeat. $background_repeat_default = self::$_->array_get( $this->fields_unprocessed, "{$background_prefix}repeat.default", '' ); $background_repeat = et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}repeat{$suffix}", $background_repeat_default, ! $is_prev_background_image_active ); if ( '' !== $background_repeat ) { $background_style .= sprintf( 'background-repeat: %1$s; ', esc_html( $background_repeat ) ); } // Blend. $background_blend_default = self::$_->array_get( $this->fields_unprocessed, "{$background_prefix}blend.default", '' ); $background_blend = et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}blend{$suffix}", $background_blend_default, ! $is_prev_background_image_active ); $background_blend_inherit = et_pb_responsive_options()->get_any_value( $this->props, "{$background_prefix}blend{$suffix}", '', true ); if ( '' !== $background_blend_inherit ) { // Don't print the same image blend style. if ( '' !== $background_blend ) { $background_style .= sprintf( 'background-blend-mode: %1$s; ', esc_html( $background_blend ) ); } // Reset - If background has image and gradient, force background-color: initial. if ( $has_background_color_gradient && $has_background_image && $background_blend_inherit !== $background_blend_default ) { $has_background_gradient_and_image = true; $background_color_style = 'initial'; $background_style .= 'background-color: initial; '; } $processed_background_blend = $background_blend; } // Only append background image when the image is exist. $background_images[] = sprintf( 'url(%1$s)', esc_html( $background_image ) ); } else if ( '' === $background_image ) { // Reset - If background image is disabled, ensure we reset prev background blend mode. if ( '' !== $processed_background_blend ) { $background_style .= 'background-blend-mode: normal; '; $processed_background_blend = ''; } $is_background_image_disabled = true; } if ( ! empty( $background_images ) ) { // The browsers stack the images in the opposite order to what you'd expect. if ( 'on' !== $background_color_gradient_overlays_image ) { $background_images = array_reverse( $background_images ); } // Set background image styles only it's different compared to the larger device. $background_image_style = join( ', ', $background_images ); if ( $processed_background_image !== $background_image_style ) { $background_style .= sprintf( 'background-image: %1$s !important;', esc_html( $background_image_style ) ); } } else if ( ! $is_desktop && $is_background_color_gradient_disabled && $is_background_image_disabled ) { // Reset - If background image and gradient are disabled, reset current background image. $background_image_style = 'initial'; $background_style .= 'background-image: initial !important;'; } // Save processed background images. $processed_background_image = $background_image_style; // C. Background Color. if ( ! $has_background_gradient_and_image ) { // Background color `initial` was added by default to reset button background // color when user disable it on mobile preview mode. However, it should // be applied only when the background color is really disabled because user // may use theme customizer to setup global button background color. We also // need to ensure user still able to disable background color on mobile. $background_color_enable = self::$_->array_get( $this->props, "{$background_prefix}enable_color{$suffix}", '' ); $background_color_initial = 'off' === $background_color_enable && ! $is_desktop ? 'initial' : ''; $background_color = et_pb_responsive_options()->get_inheritance_background_value( $this->props, "{$background_prefix}color", $device, $background_base_name, $this->fields_unprocessed ); $background_color = '' !== $background_color ? $background_color : $background_color_initial; $background_color_style = $background_color; if ( '' !== $background_color && $processed_background_color !== $background_color ) { $background_style .= sprintf( 'background-color: %1$s%2$s; ', esc_html( $background_color ), esc_html( $important ) ); } } // Save processed background color. $processed_background_color = $background_color_style; // Print background gradient and image styles. if ( '' !== $background_style ) { $background_style_attrs = array( 'selector' => $css_element_processed, 'declaration' => rtrim( $background_style ), 'priority' => $this->_style_priority, ); // Add media query attribute to background style attrs. if ( 'desktop' !== $device ) { $current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767'; $background_style_attrs['media_query'] = ET_Builder_Element::get_media_query( $current_media_query ); } self::set_style( $function_name, $background_style_attrs ); } } // Background Hover. if ( et_builder_is_hover_enabled( "{$option_name}_bg_color", $this->props ) ) { $background_base_name = "{$option_name}_bg"; $background_prefix = "{$background_base_name}_"; $background_images_hover = array(); $background_hover_style = ''; $has_background_color_gradient_hover = false; $has_background_image_hover = false; $has_background_gradient_and_image_hover = false; $is_background_color_gradient_hover_disabled = false; $is_background_image_hover_disabled = false; $background_color_gradient_overlays_image_hover = 'off'; // Background Gradient Hover. // This part is little bit different compared to other hover implementation. In // this case, hover is enabled on the background field, not on the each of those // fields. So, built in function get_value() doesn't work in this case. // Temporarily, we need to fetch the the value from get_raw_value(). $use_background_color_gradient_hover = et_pb_responsive_options()->get_inheritance_background_value( $this->props, "{$background_prefix}use_color_gradient", 'hover', $background_base_name, $this->fields_unprocessed ); if ( 'on' === $use_background_color_gradient_hover ) { // Desktop value as default. $background_color_gradient_type_desktop = self::$_->array_get( $gradient_properties_desktop, 'type', '' ); $background_color_gradient_direction_desktop = self::$_->array_get( $gradient_properties_desktop, 'direction', '' ); $background_color_gradient_radial_direction_desktop = self::$_->array_get( $gradient_properties_desktop, 'radial_direction', '' ); $background_color_gradient_color_start_desktop = self::$_->array_get( $gradient_properties_desktop, 'color_start', '' ); $background_color_gradient_color_end_desktop = self::$_->array_get( $gradient_properties_desktop, 'color_end', '' ); $background_color_gradient_start_position_desktop = self::$_->array_get( $gradient_properties_desktop, 'start_position', '' ); $background_color_gradient_end_position_desktop = self::$_->array_get( $gradient_properties_desktop, 'end_position', '' ); // Hover value. $background_color_gradient_type_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}color_gradient_type", $this->props, $background_color_gradient_type_desktop ); $background_color_gradient_direction_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}color_gradient_direction", $this->props, $background_color_gradient_direction_desktop ); $background_color_gradient_direction_radial_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}color_gradient_direction_radial", $this->props, $background_color_gradient_radial_direction_desktop ); $background_color_gradient_start_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}color_gradient_start", $this->props, $background_color_gradient_color_start_desktop ); $background_color_gradient_end_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}color_gradient_end", $this->props, $background_color_gradient_color_end_desktop ); $background_color_gradient_start_position_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}color_gradient_start_position", $this->props, $background_color_gradient_start_position_desktop ); $background_color_gradient_end_position_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}color_gradient_end_position", $this->props, $background_color_gradient_end_position_desktop ); $background_color_gradient_overlays_image_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}color_gradient_overlays_image", $this->props, $background_color_gradient_overlays_image_desktop ); $has_background_color_gradient_hover = true; $gradient_values_hover = array( 'type' => '' !== $background_color_gradient_type_hover ? $background_color_gradient_type_hover : $background_color_gradient_type_desktop, 'direction' => '' !== $background_color_gradient_direction_hover ? $background_color_gradient_direction_hover : $background_color_gradient_direction_desktop, 'radial_direction' => '' !== $background_color_gradient_direction_radial_hover ? $background_color_gradient_direction_radial_hover : $background_color_gradient_radial_direction_desktop, 'color_start' => '' !== $background_color_gradient_start_hover ? $background_color_gradient_start_hover : $background_color_gradient_color_start_desktop, 'color_end' => '' !== $background_color_gradient_end_hover ? $background_color_gradient_end_hover : $background_color_gradient_color_end_desktop, 'start_position' => '' !== $background_color_gradient_start_position_hover ? $background_color_gradient_start_position_hover : $background_color_gradient_start_position_desktop, 'end_position' => '' !== $background_color_gradient_end_position_hover ? $background_color_gradient_end_position_hover : $background_color_gradient_end_position_desktop, ); $background_images_hover[] = $this->get_gradient( $gradient_values_hover ); } else if ( 'off' === $use_background_color_gradient_hover ) { $is_background_color_gradient_hover_disabled = true; } // Background Image Hover. // This part is little bit different compared to other hover implementation. In // this case, hover is enabled on the background field, not on the each of those // fields. So, built in function get_value() doesn't work in this case. // Temporarily, we need to fetch the the value from get_raw_value(). $background_image_hover = et_pb_responsive_options()->get_inheritance_background_value( $this->props, "{$background_prefix}image", 'hover', $background_base_name, $this->fields_unprocessed ); $parallax_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}parallax", $this->props ); if ( '' !== $background_image_hover && null !== $background_image_hover && 'on' !== $parallax_hover ) { // Flag to inform BG Color if current module has Image. $has_background_image_hover = true; // Size. $background_size_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}size", $this->props ); $background_size_desktop = self::$_->array_get( $this->props, "{$background_prefix}size", '' ); $is_same_background_size = $background_size_hover === $background_size_desktop; if ( empty( $background_size_hover ) && ! empty( $background_size_desktop ) ) { $background_size_hover = $background_size_desktop; } if ( ! empty( $background_size_hover ) && ! $is_same_background_size ) { $background_hover_style .= sprintf( 'background-size: %1$s; ', esc_html( $background_size_hover ) ); } // Position. $background_position_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}position", $this->props ); $background_position_desktop = self::$_->array_get( $this->props, "{$background_prefix}position", '' ); $is_same_background_position = $background_position_hover === $background_position_desktop; if ( empty( $background_position_hover ) && ! empty( $background_position_desktop ) ) { $background_position_hover = $background_position_desktop; } if ( ! empty( $background_position_hover ) && ! $is_same_background_position ) { $background_hover_style .= sprintf( 'background-position: %1$s; ', esc_html( str_replace( '_', ' ', $background_position_hover ) ) ); } // Repeat. $background_repeat_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}repeat", $this->props ); $background_repeat_desktop = self::$_->array_get( $this->props, "{$background_prefix}repeat", '' ); $is_same_background_repeat = $background_repeat_hover === $background_repeat_desktop; if ( empty( $background_repeat_hover ) && ! empty( $background_repeat_desktop ) ) { $background_repeat_hover = $background_repeat_desktop; } if ( ! empty( $background_repeat_hover ) && ! $is_same_background_repeat ) { $background_hover_style .= sprintf( 'background-repeat: %1$s; ', esc_html( $background_repeat_hover ) ); } // Blend. $background_blend_hover = et_pb_hover_options()->get_raw_value( "{$background_prefix}blend", $this->props ); $background_blend_default = self::$_->array_get( $this->fields_unprocessed, "{$background_prefix}blend.default", '' ); $background_blend_desktop = self::$_->array_get( $this->props, "{$background_prefix}blend", '' ); $is_same_background_blend = $background_blend_hover === $background_blend_desktop; if ( empty( $background_blend_hover ) && ! empty( $background_blend_desktop ) ) { $background_blend_hover = $background_blend_desktop; } if ( ! empty( $background_blend_hover ) ) { if ( ! $is_same_background_blend ) { $background_hover_style .= sprintf( 'background-blend-mode: %1$s; ', esc_html( $background_blend_hover ) ); } // Force background-color: initial; if ( $has_background_color_gradient_hover && $has_background_image_hover && $background_blend_hover !== $background_blend_default ) { $has_background_gradient_and_image_hover = true; $background_hover_style .= 'background-color: initial !important;'; } } // Only append background image when the image exists. $background_images_hover[] = sprintf( 'url(%1$s)', esc_html( $background_image_hover ) ); } else if ( '' === $background_image_hover ) { $is_background_image_hover_disabled = true; } if ( ! empty( $background_images_hover ) ) { // The browsers stack the images in the opposite order to what you'd expect. if ( 'on' !== $background_color_gradient_overlays_image_hover ) { $background_images_hover = array_reverse( $background_images_hover ); } $background_hover_style .= sprintf( 'background-image: %1$s !important;', esc_html( join( ', ', $background_images_hover ) ) ); } else if ( $is_background_color_gradient_hover_disabled && $is_background_image_hover_disabled ) { $background_hover_style .= 'background-image: initial !important;'; } // Background Color Hover. if ( ! $has_background_gradient_and_image_hover ) { $background_color_hover = et_pb_responsive_options()->get_inheritance_background_value( $this->props, "{$background_prefix}color", 'hover', $background_base_name, $this->fields_unprocessed ); $background_color_hover = '' !== $background_color_hover ? $background_color_hover : 'transparent'; if ( '' !== $background_color_hover ) { $background_hover_style .= sprintf( 'background-color: %1$s !important; ', esc_html( $background_color_hover ) ); } } // Print background hover gradient and image styles. if ( '' !== $background_hover_style ) { $background_hover_style_attrs = array( 'selector' => $css_element_processed . ':hover', 'declaration' => rtrim( $background_hover_style ), 'priority' => $this->_style_priority, ); self::set_style( $function_name, $background_hover_style_attrs ); } } } } } /** * Process form field options into correct CSS styles. * * Fields will be processed here (name, mode, custom selector): * * - Background Color -> Hover -> Form field selector * - Background Focus Color -> Hover -> Form field focus selector * - Text Color -> Hover -> Form field & placeholder selector * - Text Focus Color -> Hover -> Form field & placeholder focus selector * * @since 3.23 * * @param string $function_name Module slug. */ function process_advanced_form_field_options( $function_name ) { // Disable if module doesn't set advanced_fields property and has no VB support. if ( ! $this->has_advanced_fields ) { return; } // Ensure form field exist on advanced fields. if ( ! self::$_->array_get( $this->advanced_fields, 'form_field', false ) ) { return; } // Fetch every single form field instances. foreach ( $this->advanced_fields['form_field'] as $option_name => $option_settings ) { // 1.a. Build main element selector. $element_selector = ! empty( $option_settings['css']['main'] ) ? $option_settings['css']['main'] : "{$this->main_css_element} .input"; if ( et_builder_has_limitation( 'use_limited_main' ) && ! empty( $option_settings['css']['limited_main'] ) ) { $element_selector = $option_settings['css']['limited_main']; } // 1.b. Build pseudo element selector. $element_hover_selector = ! empty( $option_settings['css']['hover'] ) ? $option_settings['css']['hover'] : "{$element_selector}:hover"; $element_focus_selector = ! empty( $option_settings['css']['focus'] ) ? $option_settings['css']['focus'] : "{$element_selector}:focus"; $element_focus_hover_selector = ! empty( $option_settings['css']['focus_hover'] ) ? $option_settings['css']['focus_hover'] : "{$element_selector}:focus:hover"; // 1.c. Build custom form field selector. $bg_color_selector = ! empty( $option_settings['css']['background_color'] ) ? $option_settings['css']['background_color'] : $element_selector; $bg_color_hover_selector = ! empty( $option_settings['css']['background_color_hover'] ) ? $option_settings['css']['background_color_hover'] : $element_hover_selector; $bg_color_focus_selector = ! empty( $option_settings['css']['focus_background_color'] ) ? $option_settings['css']['focus_background_color'] : $element_focus_selector; $bg_color_focus_hover_selector = ! empty( $option_settings['css']['focus_background_color_hover'] ) ? $option_settings['css']['focus_background_color_hover'] : $element_focus_hover_selector; $text_color_selector = ! empty( $option_settings['css']['form_text_color'] ) ? $option_settings['css']['form_text_color'] : $element_selector; $text_color_hover_selector = ! empty( $option_settings['css']['form_text_color_hover'] ) ? $option_settings['css']['form_text_color_hover'] : $element_hover_selector; $text_color_focus_selector = ! empty( $option_settings['css']['focus_text_color'] ) ? $option_settings['css']['focus_text_color'] : $element_focus_selector; $text_color_focus_hover_selector = ! empty( $option_settings['css']['focus_text_color_hover'] ) ? $option_settings['css']['focus_text_color_hover'] : $element_focus_hover_selector; $placeholder_option = self::$_->array_get( $option_settings, 'placeholder', true ); $base_selector = false !== strpos( $element_selector, ',' ) ? "{$this->main_css_element} .input" : $element_selector; $placeholder_selector = ! empty( $option_settings['css']['placeholder'] ) ? $option_settings['css']['placeholder'] : "{$base_selector}::placeholder, {$base_selector}::-webkit-input-placeholder, {$base_selector}::-moz-placeholder, {$base_selector}::-ms-input-placeholder"; $placeholder_hover_selector = ! empty( $option_settings['css']['placeholder_hover'] ) ? $option_settings['css']['placeholder_hover'] : "{$base_selector}:hover::placeholder, {$base_selector}:hover::-webkit-input-placeholder, {$base_selector}:hover::-moz-placeholder, {$base_selector}:hover::-ms-input-placeholder"; $placeholder_focus_selector = ! empty( $option_settings['css']['placeholder_focus'] ) ? $option_settings['css']['placeholder_focus'] : "{$base_selector}:focus::placeholder, {$base_selector}:focus::-webkit-input-placeholder, {$base_selector}:focus::-moz-placeholder, {$base_selector}:focus::-ms-input-placeholder"; $placeholder_focus_hover_selector = ! empty( $option_settings['css']['placeholder_focus_hover'] ) ? $option_settings['css']['placeholder_focus_hover'] : "{$base_selector}:focus:hover::placeholder, {$base_selector}:focus:hover::-webkit-input-placeholder, {$base_selector}:focus:hover::-moz-placeholder, {$base_selector}:focus:hover::-ms-input-placeholder"; // 2. Default important status. $force_global_important = et_builder_has_limitation( 'force_use_global_important' ); $important_list = isset( $option_settings['css']['important'] ) ? $option_settings['css']['important'] : array(); // 3.a.1. Field Background Color. $is_field_bg_color_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, "{$option_name}_background_color" ); $field_bg_color_values = array( 'desktop' => esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_background_color" ) ), 'tablet' => $is_field_bg_color_responsive ? esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_background_color_tablet" ) ) : '', 'phone' => $is_field_bg_color_responsive ? esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_background_color_phone" ) ) : '', ); $field_bg_color_important = $force_global_important || in_array( 'background_color', $important_list, true ) ? ' !important;' : ''; et_pb_responsive_options()->generate_responsive_css( $field_bg_color_values, $bg_color_selector, 'background-color', $function_name, $field_bg_color_important, 'color' ); // 3.a.2. Field Background Hover Color. $field_bg_color_hover = $this->get_hover_value("{$option_name}_background_color" ); if ( ! empty( $field_bg_color_hover ) ) { self::set_style( $function_name, array( 'selector' => $bg_color_hover_selector, 'declaration' => sprintf( 'background-color:%1$s%2$s;', $field_bg_color_hover, $field_bg_color_important ), ) ); } // 3.b.1. Field Focus Background Color. $is_field_focus_bg_color_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, "{$option_name}_focus_background_color" ); $field_focus_bg_color_values = array( 'desktop' => esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_focus_background_color" ) ), 'tablet' => $is_field_focus_bg_color_responsive ? esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_focus_background_color_tablet" ) ) : '', 'phone' => $is_field_focus_bg_color_responsive ? esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_focus_background_color_phone" ) ) : '', ); $field_focus_bg_color_important = $force_global_important || in_array( 'focus_background_color', $important_list, true ) ? ' !important' : ''; et_pb_responsive_options()->generate_responsive_css( $field_focus_bg_color_values, $bg_color_focus_selector, 'background-color', $function_name, $field_focus_bg_color_important, 'color' ); // 3.b.2. Field Focus Background Hover Color. $field_focus_bg_color_hover = $this->get_hover_value("{$option_name}_focus_background_color" ); if ( ! empty( $field_focus_bg_color_hover ) ) { self::set_style( $function_name, array( 'selector' => $bg_color_focus_hover_selector, 'declaration' => sprintf( 'background-color:%1$s%2$s;', $field_focus_bg_color_hover, $field_focus_bg_color_important ), ) ); } // 3.c.1. Field Text Color. $is_field_text_color_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, "{$option_name}_text_color" ); $field_text_color_values = array( 'desktop' => esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_text_color" ) ), 'tablet' => $is_field_text_color_responsive ? esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_text_color_tablet" ) ) : '', 'phone' => $is_field_text_color_responsive ? esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_text_color_phone" ) ) : '', ); $field_text_color_important = in_array( 'form_text_color', $important_list ) ? ' !important' : ''; $text_color_selector = $placeholder_option ? "{$text_color_selector}, {$placeholder_selector}" : $text_color_selector; et_pb_responsive_options()->generate_responsive_css( $field_text_color_values, $text_color_selector, 'color', $function_name, $field_text_color_important, 'color' ); // 3.c.2. Field Text Color. $field_text_color_hover = $this->get_hover_value("{$option_name}_text_color" ); if ( ! empty( $field_text_color_hover ) ) { $text_color_hover_selector = $placeholder_option ? "{$text_color_hover_selector}, {$placeholder_hover_selector}" : $text_color_hover_selector; self::set_style( $function_name, array( 'selector' => $text_color_hover_selector, 'declaration' => sprintf( 'color:%1$s%2$s;', $field_text_color_hover, $field_text_color_important ), ) ); } // 3.d.1. Field Focus Text Color. $is_field_focus_text_color_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, "{$option_name}_focus_text_color" ); $field_focus_text_color_values = array( 'desktop' => esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_focus_text_color" ) ), 'tablet' => $is_field_focus_text_color_responsive ? esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_focus_text_color_tablet" ) ) : '', 'phone' => $is_field_focus_text_color_responsive ? esc_attr( et_pb_responsive_options()->get_any_value( $this->props, "{$option_name}_focus_text_color_phone" ) ) : '', ); $text_color_focus_selector = $placeholder_option ? "{$text_color_focus_selector}, {$placeholder_focus_selector}" : $text_color_focus_selector; $field_focus_text_color_important = in_array( 'form_text_color', $important_list ) ? ' !important' : ''; et_pb_responsive_options()->generate_responsive_css( $field_focus_text_color_values, $text_color_focus_selector, 'color', $function_name, $field_focus_text_color_important, 'color' ); // 3.d.2. Field Focus Text Hover Color. $field_focus_text_color_hover = $this->get_hover_value("{$option_name}_focus_text_color" ); if ( ! empty( $field_focus_text_color_hover ) ) { $text_color_focus_hover_selector = $placeholder_option ? "{$text_color_focus_hover_selector}, {$placeholder_focus_hover_selector}" : $text_color_focus_hover_selector; self::set_style( $function_name, array( 'selector' => $text_color_focus_hover_selector, 'declaration' => sprintf( 'color:%1$s%2$s;', $field_focus_text_color_hover, $field_focus_text_color_important ), ) ); } } } function process_custom_css_fields( $function_name ) { if ( empty( $this->custom_css_fields ) ) { return false; } foreach ( $this->custom_css_fields as $slug => $option ) { $css = $this->props["custom_css_{$slug}"]; $order_class = isset( $this->main_css_element ) && count( explode( ' ', $this->main_css_element ) ) === 1 ? $selector = $this->main_css_element : '%%order_class%%'; $selector = ! empty( $option['selector'] ) ? $option['selector'] : ''; if ( false === strpos( $selector, '%%order_class%%' ) ) { if ( ! ( isset( $option['no_space_before_selector'] ) && $option['no_space_before_selector'] ) && '' !== $selector ) { $selector = " {$selector}"; } $selector = "{$order_class}{$selector}"; } if ( et_pb_responsive_options()->is_responsive_enabled( $this->props, "custom_css_{$slug}" ) ) { $responsive_values = et_pb_responsive_options()->get_property_values( $this->props, "custom_css_{$slug}" ); // Desktop mode custom CSS. if ( '' !== $css ) { self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => trim( $css ), 'media_query' => empty( $responsive_values['tablet'] ) ? null : ET_Builder_Element::get_media_query( 'min_width_981' ), ) ); } // Tablet mode custom CSS. $tablet_css = et_pb_responsive_options()->get_tablet_value( "custom_css_{$slug}", $this->props ); if ( ! empty( $tablet_css ) ) { self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => trim( $tablet_css ), 'media_query' => empty( $responsive_values['phone'] ) ? ET_Builder_Element::get_media_query( 'max_width_980' ) : ET_Builder_Element::get_media_query( '768_980' ), ) ); } // Phone mode custom CSS. $phone_css = et_pb_responsive_options()->get_phone_value( "custom_css_{$slug}", $this->props ); if ( ! empty( $phone_css ) ) { self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => trim( $phone_css ), 'media_query' => ET_Builder_Element::get_media_query( 'max_width_767' ), ) ); } } else { // Non responsive mode custom CSS. if ( '' !== $css ) { self::set_style( $function_name, array( 'selector' => $selector, 'declaration' => trim( $css ), ) ); } } // Hover mode custom CSS. if ( et_pb_hover_options()->is_enabled( "custom_css_{$slug}", $this->props ) ) { $hover_css = et_pb_hover_options()->get_value( "custom_css_{$slug}", $this->props ); if ( ! empty( $hover_css ) ) { self::set_style( $function_name, array( 'selector' => $this->add_hover_to_selectors( $selector ), 'declaration' => trim( $hover_css ), ) ); } } } } /** * Process box shadow CSS styles. * * @since 3.23 Add responsive support. Pass device attributes and make sure no duplicate styles * are rendered. * * @param string $function_name Module slug. */ function process_box_shadow( $function_name ) { /** * @var ET_Builder_Module_Field_BoxShadow $box_shadow */ $box_shadow = ET_Builder_Module_Fields_Factory::get( 'BoxShadow' ); $advanced_fields = self::$_->array_get( $this->advanced_fields, 'box_shadow', array( 'default' => array() ) ); if ( ! $advanced_fields ) { return ''; } // A module can have multiple advanced box shadow fields (i.e. default + button's box shadow) which are // generated by advanced button fields foreach ( $advanced_fields as $option_name => $option_settings ) { // Enable module to explicitly disable box shadow fields (box shadow is automatically) // added to all module by default if ( false === $option_settings ) { continue; } // Prepare attribute for getting box shadow's css declaration $declaration_args = array( 'suffix' => $option_name === 'default' ? '' : "_{$option_name}", 'important' => self::$_->array_get( $option_settings, 'css.important', false ), ); // Enable module to conditionally print box shadow styling if particular attribute(s) have specific value. // This works in 'OR' logic. Once an attribute doesn't match the value, this box shadow styling is skipped $show_if = self::$_->array_get( $option_settings, 'css.show_if', array() ); if ( ! empty( $show_if ) ) { $show_if_skip = false; foreach ( $show_if as $show_if_attr_name => $show_if_attr_value ) { $attr_value = self::$_->array_get( $this->props, $show_if_attr_name, '' ); // Skip printing this box shadow value once one of the attribute value doesn't // match with given value if ( $attr_value !== $show_if_attr_value ) { $show_if_skip = true; break; } } if ( $show_if_skip ) { continue; } } // Enable module to conditionally print box shadow styling if particular attribute(s) doesn't have // specific value. This works on 'OR' logic. Once an attribute matches the supplied value, this // box shadow styling is skipped $show_if_not = self::$_->array_get( $option_settings, 'css.show_if_not', array() ); if ( ! empty( $show_if_not ) ) { $show_if_not_skip = false; foreach ( $show_if_not as $show_if_not_attr_name => $show_if_not_attr_value ) { $attr_value = self::$_->array_get( $this->props, $show_if_not_attr_name, '' ); // Skip printing this box value once this attribute value matches the given value if ( $attr_value === $show_if_not_attr_value ) { $show_if_not_skip = true; break; } } if ( $show_if_not_skip ) { continue; } } $overlay = self::$_->array_get( $option_settings, 'css.overlay', false ); $has_video_bg = ! empty( $atts['background_video_mp4'] ) || ! empty( $atts['background_video_webm'] ); $inset = $box_shadow->is_inset( $box_shadow->get_value( $this->props, $declaration_args ) ); $inset_hover = $box_shadow->is_inset( $box_shadow->get_value( $this->props, array_merge( $declaration_args, array( 'hover' => true ) ) ) ); $selector = self::$_->array_get( $option_settings, 'css.main', '%%order_class%%' ); // Default box shadow affects module while other affects group element it belongs to (ie image, button, etc) $hover_selector = 'default' === $option_name ? $this->add_hover_to_order_class( $selector ) : $this->add_hover_to_selectors( $selector ); // Custom box shadow hover selector. $custom_hover = self::$_->array_get( $option_settings, 'css.hover', '' ); if ( '' !== $custom_hover ) { $hover_selector = $custom_hover; } // Render box shadow styles for esponsive settings. $prev_declaration = ''; foreach( et_pb_responsive_options()->get_modes() as $device ) { // Add device argument. $device_declaration_args = array_merge( $declaration_args, array( 'device' => $device ) ); // Get box-shadow styles. if ( ( $inset && 'inset' === $overlay ) || 'always' === $overlay || $has_video_bg ) { $box_shadow_style = $box_shadow->get_overlay_style( $function_name, $selector, $this->props, $device_declaration_args ); } else { $box_shadow_style = $box_shadow->get_style( $selector, $this->props, $device_declaration_args ); } // Compare current device declaration and previous declaration to avoid // duplicate rendered styles. Or don't render if current declaration is // empty string. $declaration = isset( $box_shadow_style['declaration'] ) ? $box_shadow_style['declaration'] : ''; if ( $prev_declaration === $declaration || empty( $declaration ) ) { continue; } $prev_declaration = $declaration; // Set media query for tablet and phone. if ( 'desktop' !== $device ) { $breakpoint = 'tablet' === $device ? 'max_width_980' : 'max_width_767'; $media_query = ET_Builder_Element::get_media_query( $breakpoint ); $box_shadow_style['media_query'] = $media_query; } self::set_style( $function_name, $box_shadow_style ); } if ( ( $inset_hover && 'inset' == $overlay ) || 'always' == $overlay || $has_video_bg ) { self::set_style( $function_name, $box_shadow->get_overlay_style( $function_name, $hover_selector, $this->props, array_merge( $declaration_args, array( 'hover' => true ) ) ) ); } else { self::set_style( $function_name, $box_shadow->get_style( $hover_selector, $this->props, array_merge( $declaration_args, array( 'hover' => true ) ) ) ); } } } function make_options_filterable() { if ( isset( $this->advanced_fields ) ) { $this->advanced_fields = apply_filters( "{$this->slug}_advanced_fields", $this->advanced_fields, $this->slug, $this->main_css_element ); } if ( isset( $this->custom_css_fields ) ) { $this->custom_css_fields = apply_filters( "{$this->slug}_custom_css_fields", $this->custom_css_fields, $this->slug, $this->main_css_element ); } } function disable_wptexturize( $shortcodes ) { $shortcodes[] = $this->slug; return $shortcodes; } function fix_wptexturized_script( $matches ) { return str_replace( '&', '&', $matches[0] ); } function fix_wptexturized_scripts( $content ) { return preg_replace_callback( '/<script.*?>(.*?)<\/script>/mis', array( $this, 'fix_wptexturized_script' ), $content ); } static function compare_by_priority( $a, $b ) { $a_priority = ! empty( $a['priority'] ) ? (int) $a['priority'] : self::DEFAULT_PRIORITY; $b_priority = ! empty( $b['priority'] ) ? (int) $b['priority'] : self::DEFAULT_PRIORITY; if ( isset( $a['_order_number'], $b['_order_number'] ) && ( $a_priority === $b_priority ) ) { return $a['_order_number'] - $b['_order_number']; } return $a_priority - $b_priority; } /* * Reorder toggles based on the priority with respect to manually ordered items with no priority * */ static function et_pb_order_toggles_by_priority( $toggles_array ) { if ( empty( $toggles_array ) ) { return array(); } $high_priority_toggles = array(); $low_priority_toggles = array(); $manually_ordered_toggles = array(); // fill 3 arrays based on priority foreach ( $toggles_array as $toggle_id => $toggle_data ) { if ( isset( $toggle_data['priority'] ) ) { if ( $toggle_data['priority'] < 10 ) { $high_priority_toggles[ $toggle_id ] = $toggle_data; } else { $low_priority_toggles[ $toggle_id ] = $toggle_data; } } else { // keep the original order of options without priority defined $manually_ordered_toggles[ $toggle_id ] = $toggle_data; } } // order high and low priority toggles uasort( $high_priority_toggles, array( 'self', 'compare_by_priority' ) ); uasort( $low_priority_toggles, array( 'self', 'compare_by_priority' ) ); // merge 3 arrays to get the correct order of toggles. return array_merge( $high_priority_toggles, $manually_ordered_toggles, $low_priority_toggles ); } static function compare_by_name( $a, $b ) { return strcasecmp( $a->name, $b->name ); } static function get_modules_count( $post_type ) { $parent_modules = self::get_parent_modules( $post_type ); $child_modules = self::get_child_modules( $post_type ); $overall_count = count( $parent_modules ) + count( $child_modules ); return $overall_count; } static function get_modules_js_array( $post_type ) { $modules = array(); $parent_modules = self::get_parent_modules( $post_type ); if ( ! empty( $parent_modules ) ) { /** * Sort modules alphabetically by name. */ $sorted_modules = $parent_modules; uasort( $sorted_modules, array( 'self', 'compare_by_name' ) ); foreach( $sorted_modules as $module ) { /** * Replace single and double quotes with %% and || respectively * to avoid js conflicts */ $module_name = str_replace( array( '"', '"', '"', '"' ) , '%%', $module->name ); $module_name = str_replace( array( "'", ''', ''' ) , '||', $module_name ); $modules[] = sprintf( '{ "title" : "%1$s", "label" : "%2$s"%3$s}', esc_js( $module_name ), esc_js( $module->slug ), ( isset( $module->fullwidth ) && $module->fullwidth ? ', "fullwidth_only" : "on"' : '' ) ); } } return '[' . implode( ',', $modules ) . ']'; } static function get_modules_array( $post_type = '', $include_child = false ) { $modules = array(); $module_icons = self::get_module_icons(); if ( ! empty( $post_type ) ) { $parent_modules = self::get_parent_modules( $post_type ); if ( $include_child ) { $parent_modules = array_merge( $parent_modules, self::get_child_modules( $post_type )); } if ( ! empty( $parent_modules ) ) { $sorted_modules = $parent_modules; } } else { $parent_modules = self::get_parent_modules(); if ( $include_child ) { $parent_modules = array_merge( $parent_modules, self::get_child_modules()); } if ( ! empty( $parent_modules ) ) { $all_modules = array(); foreach( $parent_modules as $post_type => $post_type_modules ) { foreach ( $post_type_modules as $module_slug => $module ) { $all_modules[ $module_slug ] = $module; } } $sorted_modules = $all_modules; } } if ( ! empty( $sorted_modules ) ) { /** * Sort modules alphabetically by name. */ uasort( $sorted_modules, array( 'self', 'compare_by_name' ) ); foreach( $sorted_modules as $module ) { /** * Replace single and double quotes with %% and || respectively * to avoid js conflicts */ $module_name = str_replace( '"', '%%', $module->name ); $module_name = str_replace( "'", '||', $module_name ); $module_name_plural = str_replace( '"', '%%', empty( $module->plural ) ? $module->name : $module->plural ); $module_name_plural = str_replace( "'", '||', $module_name_plural ); $_module = array( 'title' => esc_attr( $module_name ), 'plural' => esc_attr( $module_name_plural ), 'label' => esc_attr( $module->slug ), 'is_parent' => $module->type === 'child' ? 'off' : 'on', 'is_official_module' => $module->_is_official_module, 'vb_support' => isset( $module->vb_support ) ? $module->vb_support : 'off', ); if ( isset( $module->fullwidth ) && $module->fullwidth ) { $_module['fullwidth_only'] = 'on'; } // Get module icon character (font-icon) $icon = self::$_->array_get( $module_icons, "{$module->slug}.icon"); if ( $icon ) { $_module['icon'] = $icon; } // Get module icon svg from fetched svg content $icon_svg = self::$_->array_get( $module_icons, "{$module->slug}.icon_svg"); if ( $icon_svg ) { $_module['icon_svg'] = $icon_svg; } $modules[] = $_module; } } return $modules; } static function get_fb_unsupported_modules() { $parent_modules = self::get_parent_modules(); $unsupported_modules_array = array(); foreach( $parent_modules as $post_type => $post_type_modules ) { foreach ( $post_type_modules as $module_slug => $module ) { if ( ! isset( $module->vb_support ) || 'off' === $module->vb_support ) { $unsupported_modules_array[] = $module_slug; } } } return array_unique( $unsupported_modules_array ); } /** * Get list of modules that has rich content option * * @since 3.18 * * @return array */ static function get_has_content_modules() { return self::$has_content_modules; } /** * Returns a regex pattern that includes all parent module slugs. * * @since 3.1 Renamed from `get_parent_shortcodes()` to `get_parent_slugs_regex()` * @since 1.0 * * @param string $post_type * * @return string */ public static function get_parent_slugs_regex( $post_type = 'page' ) { $slugs = array(); $parent_modules = self::get_parent_modules( $post_type ); if ( ! empty( $parent_modules ) ) { foreach( $parent_modules as $module ) { $slugs[] = $module->slug; } } return implode( '|', $slugs ); } /** * Returns a regex pattern that includes all child module slugs. * * @since 3.1 Renamed from `get_child_shortcodes()` to `get_child_slugs_regex()` * @since 1.0 * * @param string $post_type * * @return string */ public static function get_child_slugs_regex( $post_type = 'page' ) { $slugs = array(); $child_modules = self::get_child_modules( $post_type ); if ( ! empty( $child_modules ) ) { foreach( $child_modules as $slug => $module ) { if ( ! empty( $slug ) ) { $slugs[] = $slug; } } } return implode( '|', $slugs ); } static function get_child_slugs( $post_type ) { $child_slugs = array(); $child_modules = self::get_parent_modules( $post_type ); if ( ! empty( $child_modules ) ) { foreach( $child_modules as $module ) { if ( ! empty( $module->child_slug ) ) { $child_slugs[ $module->slug ] = $module->child_slug; } } } return $child_slugs; } public static function get_raw_content_slugs( $post_type ) { $shortcodes = array(); $parent_modules = self::get_parent_modules( $post_type ); if ( ! empty( $parent_modules ) ) { foreach( $parent_modules as $module ) { if ( isset( $module->use_raw_content ) && $module->use_raw_content ) { $shortcodes[] = $module->slug; } } } $child_modules = self::get_child_modules( $post_type ); if ( ! empty( $child_modules ) ) { foreach( $child_modules as $module ) { if ( isset( $module->use_raw_content ) && $module->use_raw_content ) { $shortcodes[] = $module->slug; } } } return implode( '|', $shortcodes ); } static function get_modules_templates( $post_type, $slugs_array ) { $all_modules = self::get_parent_and_child_modules( $post_type ); $templates_array = array(); if ( empty( $slugs_array ) ) { return; } foreach ( $slugs_array as $slug ) { if ( ! isset( $all_modules[ $slug ] ) ) { return ''; } $module = $all_modules[ $slug ]; $templates_array[] = array( 'slug' => $slug, 'template' => $module->build_microtemplate(), ); } if ( ET_BUILDER_OPTIMIZE_TEMPLATES ) { $templates_array = array( 'templates' => $templates_array, 'unique' => self::$_unique_bb_keys_values, ); } return $templates_array; } static function output_templates( $post_type = '', $start_from = 0, $amount = 999 ) { $all_modules = self::get_parent_and_child_modules( $post_type ); $modules_names = array_keys( $all_modules ); $output = array(); $output['templates'] = array(); if ( ! empty( $all_modules ) ) { for ( $i = 0; $i < ET_BUILDER_AJAX_TEMPLATES_AMOUNT; $i++ ) { if ( isset( $modules_names[ $i ] ) ) { $module = $all_modules[ $modules_names[ $i ] ]; $output['templates'][ $module->slug ] = self::optimize_bb_chunk( $module->build_microtemplate() ); } else { break; } } } if ( ET_BUILDER_OPTIMIZE_TEMPLATES ) { $output['unique'] = self::$_unique_bb_keys_values; } return $output; } static function get_structure_module_slugs() { if ( ! empty( self::$structure_module_slugs ) ) { return self::$structure_module_slugs; } $structure_modules = self::get_structure_modules(); self::$structure_module_slugs = array(); foreach( $structure_modules as $structural_module ) { self::$structure_module_slugs[] = $structural_module->slug; } return self::$structure_module_slugs; } static function get_structure_modules() { if ( ! empty( self::$structure_modules ) ) { return self::$structure_modules; } $parent_modules = self::get_parent_modules( 'et_pb_layout' ); self::$structure_modules = array(); foreach ( $parent_modules as $parent_module ) { if ( isset( $parent_module->is_structure_element ) && $parent_module->is_structure_element ) { $parent_module->plural = empty( $parent_module->plural ) ? $parent_module->name : $parent_module->plural; self::$structure_modules[] = $parent_module; } } return self::$structure_modules; } /** * Get a filtered list of modules. * * @since 3.10 * * @param string $post_type Leave empty for any. * @param string $type 'parent' or 'child'. Leave empty for any. * * @return ET_Builder_Element[] */ static function get_modules( $post_type = '', $type = '' ) { $modules = array(); foreach ( self::$modules as $slug => $module ) { if ( '' !== $post_type && ! in_array( $post_type, $module->post_types ) ) { continue; } if ( '' !== $type && ! $module->type !== $type ) { continue; } $modules[ $slug ] = $module; } return $modules; } static function get_custom_post_type_fallback_modules( $type = 'parent' ) { $modules = 'child' === $type ? self::$child_modules : self::$parent_modules; // Most of the time, page module is expected to be used as disabled post type fallback if ( isset( $modules['page'] ) ) { return $modules['page']; } // Post module is also expected to be used if ( isset( $modules['post'] ) ) { return $modules['post']; } // If Divi Builder is disabled for all post types use layout modules as fallback if ( isset( $modules['et_pb_layout'] ) ) { return $modules['et_pb_layout']; } // If all else fail, use all modules return self::get_modules(); } static function get_parent_modules( $post_type = '' ) { if ( ! empty( $post_type ) ) { // We get all modules when post type is not enabled so that posts that have // had their post type support disabled still load all necessary modules. $parent_modules = ! empty( self::$parent_modules[ $post_type ] ) ? self::$parent_modules[ $post_type ] : self::get_custom_post_type_fallback_modules( 'parent' ); } else { $parent_modules = self::$parent_modules; } return apply_filters( 'et_builder_get_parent_modules', $parent_modules, $post_type ); } static function get_child_modules( $post_type = '' ) { if ( ! empty( $post_type ) ) { // We get all modules when post type is not enabled so that posts that have // had their post type support disabled still load all necessary modules. $child_modules = ! empty( self::$child_modules[ $post_type ] ) ? self::$child_modules[ $post_type ] : self::get_custom_post_type_fallback_modules( 'child' ); } else { $child_modules = self::$child_modules; } return apply_filters( 'et_builder_get_child_modules', $child_modules, $post_type ); } static function get_woocommerce_modules() { return apply_filters( 'et_builder_get_woocommerce_modules', self::$woocommerce_modules ); } /** * Get registered module icons * * @since 3.1 * * @return array */ static function get_module_icons() { /** * Filters Module Icons displayed in Add Module modals. * * @param array $module_icons Array of all registered module icons. */ $module_icons = apply_filters( 'et_builder_module_icons', self::$module_icons ); // Loop module icons foreach ( $module_icons as $key => $icons ) { if ( isset( $icons['icon_path'] ) ) { // Get svg content based on given svg's path $icon_svg = et_()->WPFS()->exists( $icons['icon_path'] ) ? et_()->WPFS()->get_contents( $icons['icon_path'] ) : false; if ( $icon_svg ) { $module_icons[ $key ]['icon_svg'] = $icon_svg; // Remove icon path attribute since it's no longer used unset( $module_icons[ $key ]['icon_path'] ); } } } return $module_icons; } /** * Get combined array of child and parent modules for provided post_type * * @since 3.1 * * @return array */ static function get_parent_and_child_modules( $post_type = '' ) { $parent_modules = self::get_parent_modules( $post_type ); $child_modules = self::get_child_modules( $post_type ); return array_merge( $parent_modules, $child_modules ); } /** * Get a module instance for provided post type by its slug. * * @since 3.10 * * @param string $slug * @param string $post_type * * @return ET_Builder_Element|null */ public static function get_module( $slug, $post_type = 'post' ) { $modules = self::get_parent_and_child_modules( $post_type ); return self::$_->array_get( $modules, $slug ); } /** * Outputs list of all module help videos array * * @since 3.1 * * @return array */ static function get_help_videos() { return self::$module_help_videos; } static function get_featured_image_background_modules( $post_type = '' ) { $parent_modules = self::get_parent_modules( $post_type ); $featured_image_background_modules = array(); foreach ( $parent_modules as $slug => $parent_module ) { if ( ! empty( $parent_module->featured_image_background ) ) { $featured_image_background_modules[] = $slug; } } /** * Filters list of modules with support of featured image as background. * * @since 3.1 * * @param array[] $featured_image_background_modules List of modules with support of featured image as background. */ return apply_filters( 'et_pb_featured_image_background_modules', $featured_image_background_modules ); } public static function get_toggles( $post_type ) { static $toggles_array = array(); if ( $toggles_array ) { return $toggles_array; } $modules = self::get_parent_and_child_modules( $post_type ); $custom_modules = array(); foreach ( $modules as $module_slug => $module ) { if ( ! $module->_is_official_module ) { $custom_modules[ $module_slug ] = $module; } foreach ( $module->settings_modal_toggles as $tab_slug => &$tab_data ) { if ( ! isset( $tab_data['toggles'] ) ) { continue; } $tab_data['toggles'] = self::et_pb_order_toggles_by_priority( $tab_data['toggles'] ); } $toggles_array[ $module_slug ] = $module->settings_modal_toggles; } if ( $custom_modules ) { // Add missing toggle definitions for any existing toggles used in custom modules foreach ( $custom_modules as $module_slug => $module ) { foreach ( $module->get_complete_fields() as $field_name => $field_info ) { $tab_slug = self::$_->array_get( $field_info, 'tab_slug' ); $tab_slug = empty( $tab_slug ) ? 'general' : $tab_slug; $toggle_slug = self::$_->array_get( $field_info, 'toggle_slug' ); if ( ! $toggle_slug || isset( $toggles_array[ $module_slug ][ $tab_slug ]['toggles'][ $toggle_slug ] ) ) { continue; } // Find existing definition foreach ( $toggles_array as $_module_slug => $tabs ) { foreach ( $tabs as $tab => $toggles ) { if ( isset( $toggles['toggles'][ $toggle_slug ] ) ) { self::$_->array_set( $toggles_array, "{$module_slug}.{$tab_slug}.toggles.{$toggle_slug}", $toggles['toggles'][ $toggle_slug ] ); $toggles_array[ $module_slug ][ $tab_slug ]['toggles'] = self::et_pb_order_toggles_by_priority( $toggles_array[ $module_slug ][ $tab_slug ]['toggles'] ); break 2; } } } // Add missing unregistered toggles to the list if ( ! isset( $toggles_array[ $module_slug ][ $tab_slug ]['toggles'][ $toggle_slug ] ) ) { if ( ! isset( $toggles_array[ $module_slug ][ $tab_slug ] ) ) { $toggles_array[ $module_slug ][ $tab_slug ] = array( 'toggles' => array( $toggle_slug ) ); } else { $toggles_array[ $module_slug ][ $tab_slug ]['toggles'][] = $toggle_slug; } } } } } return $toggles_array; } public static function get_tabs( $post_type = '' ) { $official_tabs = array( 'general' => '', 'advanced' => '', 'custom_css' => '' ); $tabs_array = array(); $modules = self::get_parent_and_child_modules( $post_type ); foreach( $modules as $module_slug => $module ) { if ( '' === $post_type ) { foreach( $module as $_module_slug => $_module ) { // Backward compatibility with custom tabs registered via `et_builder_main_tabs` filter. $bb_custom_tabs = array_diff_key( $_module->get_main_tabs(), $official_tabs ); $bb_custom_tabs_formatted = array(); // Prepare properly formatted array of tabs data foreach ( $bb_custom_tabs as $tab_id => $tab_name ) { $bb_custom_tabs_formatted[ $tab_id ] = array( 'name' => $tab_name ); } // Add BB custom tabs to all modules $tabs_array[ $_module_slug ] = $bb_custom_tabs_formatted; if ( ! isset( $_module->settings_modal_tabs ) ) { continue; } $tabs_array[ $_module_slug ] = array_merge( $tabs_array[ $_module_slug ], $_module->settings_modal_tabs ); } } else { // Backward compatibility with custom tabs registered via `et_builder_main_tabs` filter. $bb_custom_tabs = array_diff_key( $module->get_main_tabs(), $official_tabs ); $bb_custom_tabs_formatted = array(); // Prepare properly formatted array of tabs data foreach ( $bb_custom_tabs as $tab_id => $tab_name ) { $bb_custom_tabs_formatted[ $tab_id ] = array( 'name' => $tab_name ); } // Add BB custom tabs to all modules $tabs_array[ $module_slug ] = $bb_custom_tabs_formatted; if ( ! isset( $module->settings_modal_tabs ) ) { continue; } $tabs_array[ $module_slug ] = array_merge( $tabs_array[ $module_slug ], $module->settings_modal_tabs ); } } return $tabs_array; } static function get_options_categories() { $options_categories = array( 'edit_colors' => array( 'name' => esc_html__( 'Edit Colors', 'et_builder' ), ), 'edit_content' => array( 'name' => esc_html__( 'Edit Content', 'et_builder' ), ), 'edit_fonts' => array( 'name' => esc_html__( 'Edit Fonts', 'et_builder' ), ), 'edit_buttons' => array( 'name' => esc_html__( 'Edit Buttons', 'et_builder' ), ), 'edit_layout' => array( 'name' => esc_html__( 'Edit Layout', 'et_builder' ), ), 'edit_borders' => array( 'name' => esc_html__( 'Edit Borders', 'et_builder' ), ), 'edit_configuration' => array( 'name' => esc_html__( 'Edit Configuration', 'et_builder' ), ), ); $options_categories = array_merge( $options_categories, self::get_custom_options_categories() ); return $options_categories; } static function get_custom_options_categories( $post_type = '' ) { $parent_modules = self::get_parent_modules( $post_type ); $child_modules = self::get_child_modules( $post_type ); $custom_options_categories = array(); $_modules = array_merge_recursive( $parent_modules, $child_modules ); foreach( $_modules as $_module_slug => $_module ) { if ( '' === $post_type ) { foreach( $_module as $__module_slug => $__module ) { if ( ! isset( $__module->options_categories ) ) { continue; } $custom_options_categories = array_merge( $custom_options_categories, $__module->options_categories ); } } else { if ( ! isset( $_module->options_categories ) ) { continue; } $custom_options_categories = array_merge( $custom_options_categories, $_module->options_categories ); } } return $custom_options_categories; } static function get_all_fields( $post_type = '' ) { $_modules = self::get_parent_and_child_modules( $post_type ); $module_fields = array(); foreach( $_modules as $_module_slug => $_module ) { // skip modules without fb support if ( ! isset( $_module->vb_support ) || 'off' === $_module->vb_support ) { continue; } $_module->set_fields(); $_module->_add_additional_fields(); $_module->_add_custom_css_fields(); $_module->_maybe_add_defaults(); $_module->_finalize_all_fields(); foreach ( $_module->fields_unprocessed as $field_key => $field ) { // do not add the fields with 'skip' type. These fields used for rendering shortcode on Front End only if ( isset( $field['type'] ) && 'skip' === $field['type'] ) { continue; } $field['name'] = $field_key; $module_fields[ $_module_slug ][ $field_key ] = $field; } } return $module_fields; } static function get_general_fields( $post_type = '', $mode = 'all', $module_type = 'all' ) { $parent_modules = self::get_parent_modules( $post_type ); $child_modules = self::get_child_modules( $post_type ); switch ( $mode ) { case 'parent': $_modules = $parent_modules; break; case 'child': $_modules = $child_modules; break; default: $_modules = array_merge( $parent_modules, $child_modules ); break; } $module_fields = array(); foreach( $_modules as $_module_slug => $_module ) { // filter modules by slug if needed if ( 'all' !== $module_type && $module_type !== $_module_slug ) { continue; } foreach ( $_module->fields_unprocessed as $field_key => $field ) { $is_option_template = self::$option_template->is_option_template_field( $field_key ); // Do not process field template if ( ! $is_option_template && ( isset( $field['tab_slug'] ) && 'general' !== $field['tab_slug'] ) ) { continue; } // Skip if current option template isn't eligible for `advanced` tab if ( $is_option_template && ! self::$option_template->is_template_inside_tab( 'general', $field ) ) { continue; } $module_fields[ $_module_slug ][ $field_key ] = $field; } // Some module types must be separated for the Global Presets. // For example we keep all section types as `et_pb_section` however they need different Global Presets. $additional_slugs = self::$global_presets_manager->get_module_additional_slugs( $_module_slug ); foreach ( $additional_slugs as $alias ) { $module_fields[ $alias ] = $module_fields[ $_module_slug ]; } } if ( 'all' !== $module_type ) { return $module_fields[ $module_type ]; } return $module_fields; } static function get_settings_modal_tabs_fields( $post_type = '', $mode = 'all', $module_type = 'all' ) { $parent_modules = self::get_parent_modules( $post_type ); $child_modules = self::get_child_modules( $post_type ); switch ( $mode ) { case 'parent': $_modules = $parent_modules; break; case 'child': $_modules = $child_modules; break; default: $_modules = array_merge( $parent_modules, $child_modules ); break; } $module_fields = array(); foreach( $_modules as $_module_slug => $_module ) { // filter modules by slug if needed if ( 'all' !== $module_type && $module_type !== $_module_slug ) { continue; } foreach ( $_module->fields_unprocessed as $field_key => $field ) { $this_tab_slug = isset( $field['tab_slug'] ) ? $field['tab_slug'] : false; if ( ! $this_tab_slug || in_array( $this_tab_slug, array( 'general', 'advanced', 'custom_css' ) ) ) { continue; } $field['name'] = $field_key; $module_fields[ $_module_slug ][ $this_tab_slug ][ $field_key ] = $field; } } if ( 'all' !== $module_type ) { return $module_fields[ $module_type ]; } return $module_fields; } static function get_child_module_titles( $post_type ) { $child_modules = self::get_child_modules( $post_type ); $child_modules_titles = array(); $child_modules_titles_fields = array( 'advanced_setting_title_text', 'child_title_fallback_var', 'child_title_var' ); foreach( $child_modules as $_module_slug => $_module ) { foreach( $child_modules_titles_fields as $single_field ) { if ( isset( $_module->$single_field ) ) { $child_modules_titles[ $_module_slug ][ $single_field ] = $_module->$single_field ; } } } return $child_modules_titles; } static function get_advanced_fields( $post_type = '', $mode = 'all', $module_type = 'all' ) { $parent_modules = self::get_parent_modules( $post_type ); $child_modules = self::get_child_modules( $post_type ); switch ( $mode ) { case 'parent': $_modules = $parent_modules; break; case 'child': $_modules = $child_modules; break; default: $_modules = array_merge( $parent_modules, $child_modules ); break; } $module_fields = array(); foreach( $_modules as $_module_slug => $_module ) { // filter modules by slug if needed if ( 'all' !== $module_type && $module_type !== $_module_slug ) { continue; } foreach ( $_module->fields_unprocessed as $field_key => $field ) { $is_option_template = self::$option_template->is_option_template_field( $field_key ); // Do not process field template if ( ! $is_option_template && ( ! isset( $field['tab_slug'] ) || 'advanced' !== $field['tab_slug'] ) ) { continue; } // Skip if current option template isn't eligible for `advanced` tab if ( $is_option_template && ! self::$option_template->is_template_inside_tab( 'advanced', $field ) ) { continue; } if ( isset( $field['default'] ) ) { $module_fields[ $_module_slug ]['advanced_defaults'][ $field_key ] = $field['default']; } $module_fields[ $_module_slug ][ $field_key ] = $field; } if ( ! empty( $_module->advanced_fields ) ) { $module_fields[ $_module_slug ]['advanced_common'] = $_module->advanced_fields; if ( isset( $_module->advanced_fields['border']['border_styles'] ) ) { $module_fields[ $_module_slug ]['border_styles'] = array_merge( $module_fields[ $_module_slug ]['border_styles'], $_module->advanced_fields['border']['border_styles'] ); } if ( isset( $_module->advanced_fields['border']['border_radii'] ) ) { $module_fileds[ $_module_slug ]['border_radii'] = array_merge( $module_fields[ $_module_slug ]['border_radii'], $_module->advanced_fields['border']['border_radii'] ); } } // Some module types must be separated for the Global Presets. // For example we keep all section types as `et_pb_section` however they need different Global Presets. $additional_slugs = self::$global_presets_manager->get_module_additional_slugs( $_module_slug ); foreach ( $additional_slugs as $alias ) { $module_fields[ $alias ] = $module_fields[ $_module_slug ]; } } if ( 'all' !== $module_type ) { return $module_fields[ $module_type ]; } return $module_fields; } static function get_custom_css_fields( $post_type = '', $mode = 'all', $module_type = 'all' ) { $parent_modules = self::get_parent_modules( $post_type ); $child_modules = self::get_child_modules( $post_type ); switch ( $mode ) { case 'parent': $_modules = $parent_modules; break; case 'child': $_modules = $child_modules; break; default: $_modules = array_merge( $parent_modules, $child_modules ); break; } $module_fields = array(); $custom_css_unwanted_types = array( 'custom_css', 'column_settings_css', 'column_settings_css_fields', 'column_settings_custom_css' ); foreach( $_modules as $_module_slug => $_module ) { // filter modules by slug if needed if ( 'all' !== $module_type && $module_type !== $_module_slug ) { continue; } $module_fields[ $_module_slug ] = $_module->custom_css_fields; foreach ( $module_fields[ $_module_slug ] as &$item ) { $item['hover'] = self::$_->array_get( $item, 'hover', 'tabs' ); $item['mobile_options'] = self::$_->array_get( $item, 'mobile_options', true ); } // Automatically added module ID and module class fields to setting modal's CSS tab if ( ! empty( $_module->fields_unprocessed ) ) { foreach ( $_module->fields_unprocessed as $field_unprocessed_key => $field_unprocessed ) { $has_tab_slug = isset( $field_unprocessed['tab_slug'] ); $is_css_field = $has_tab_slug && 'custom_css' === $field_unprocessed['tab_slug']; $has_type = isset( $field_unprocessed['type'] ); $is_unwanted_css_field = $has_type && in_array( $field_unprocessed['type'], $custom_css_unwanted_types ); $is_template_inside_css_tab = is_string( $field_unprocessed ) && self::$option_template->is_template_inside_tab( 'custom_css', $field_unprocessed ); // Option template's template that might be rendered in custom_css tab if ( ( $is_css_field && ! $is_unwanted_css_field ) || $is_template_inside_css_tab ) { $module_fields[ $_module_slug ][ $field_unprocessed_key ] = $field_unprocessed; } } } // Some module types must be separated for the Global Presets. // For example we keep all section types as `et_pb_section` however they need different Global Presets. $additional_slugs = self::$global_presets_manager->get_module_additional_slugs( $_module_slug ); foreach ( $additional_slugs as $alias ) { $module_fields[ $alias ] = $module_fields[ $_module_slug ]; } } if ( 'all' !== $module_type ) { return $module_fields[ $module_type ]; } return $module_fields; } static function get_modules_i10n( $post_type = '', $mode = 'all', $module_type = 'all' ) { $parent_modules = self::get_parent_modules( $post_type ); $child_modules = self::get_child_modules( $post_type ); switch ( $mode ) { case 'parent': $_modules = $parent_modules; break; case 'child': $_modules = $child_modules; break; default: $_modules = array_merge( $parent_modules, $child_modules ); break; } $fields = array(); foreach( $_modules as $_module_slug => $_module ) { // filter modules by slug if needed if ( 'all' !== $module_type && $module_type !== $_module_slug ) { continue; } $fields[$_module_slug] = array( 'addNew' => $_module->add_new_child_text() ); } if ( 'all' !== $module_type ) { return $fields[ $module_type ]; } return $fields; } public static function get_modules_transitions( $post_type = '', $mode = 'all', $module_type = 'all' ) { /** * @var ET_Builder_Element[] $_modules */ $parent_modules = self::get_parent_modules( $post_type ); $child_modules = self::get_child_modules( $post_type ); $fields = array(); switch ( $mode ) { case 'parent': $_modules = $parent_modules; break; case 'child': $_modules = $child_modules; break; default: $_modules = array_merge( $parent_modules, $child_modules ); break; } foreach ( $_modules as $_module_slug => $_module ) { // filter modules by slug if needed if ( 'all' !== $module_type && $module_type !== $_module_slug ) { continue; } $fields[ $_module_slug ] = $_module->get_transition_fields_css_props(); } return $fields; } public static function get_module_items_configs( $post_type ) { $modules = self::get_parent_and_child_modules( $post_type ); $configs = array(); foreach ( $modules as $slug => $module ) { if ( isset( $module->module_items_config ) ) { $configs[ $slug ] = $module->module_items_config; } } return $configs; } static function get_module_fields( $post_type, $module ) { $_modules = self::get_parent_and_child_modules( $post_type ); if ( ! empty( $_modules[ $module ] ) ) { return $_modules[ $module ]->fields_unprocessed; } return false; } static function get_parent_module_fields( $post_type, $module ) { if ( ! empty( self::$parent_modules[ $post_type ][ $module ] ) ) { return self::$parent_modules[ $post_type ][ $module ]->get_complete_fields(); } return false; } static function get_child_module_fields( $post_type, $module ) { if ( ! empty( self::$child_modules[ $post_type ][ $module ] ) ) { return self::$child_modules[ $post_type ][ $module ]->get_complete_fields(); } return false; } static function get_parent_module_field( $post_type, $module, $field ) { $fields = self::get_parent_module_fields( $post_type, $module ); if ( ! empty( $fields[ $field ] ) ) { return $fields[ $field ]; } return false; } static function get_font_icon_fields( $post_type = '' ) { $_modules = self::get_parent_and_child_modules( $post_type ); $module_fields = array(); foreach ( $_modules as $module_name => $module ) { foreach ($module->fields_unprocessed as $module_field_name => $module_field) { if ( isset( $module_field['type'] ) && 'select_icon' === $module_field['type'] ) { $module_fields[ $module_name ][ $module_field_name ] = true; } } } return $module_fields; } /** * Retrieves credits of custom modules for VB * * @return array of credits info by module slug */ public static function get_custom_modules_credits( $post_type = '' ) { $result = array(); $modules = self::get_parent_and_child_modules( $post_type ); /** * @var $module_slug string * @var $module ET_Builder_Module */ foreach ( $modules as $module_slug => $module ) { // Include custom module credits for displaying them within VB if ( $module->_is_official_module ) { continue; } else { if ( isset( $module->module_credits ) && is_array( $module->module_credits ) ) { $result[ $module_slug ] = $module->module_credits; } } } return $result; } static function get_media_quries( $for_js=false ) { $media_queries = array( 'min_width_1405' => '@media only screen and ( min-width: 1405px )', '1100_1405' => '@media only screen and ( min-width: 1100px ) and ( max-width: 1405px)', '981_1405' => '@media only screen and ( min-width: 981px ) and ( max-width: 1405px)', '981_1100' => '@media only screen and ( min-width: 981px ) and ( max-width: 1100px )', 'min_width_981' => '@media only screen and ( min-width: 981px )', 'max_width_980' => '@media only screen and ( max-width: 980px )', '768_980' => '@media only screen and ( min-width: 768px ) and ( max-width: 980px )', 'min_width_768' => '@media only screen and ( min-width: 768px )', 'max_width_767' => '@media only screen and ( max-width: 767px )', 'max_width_479' => '@media only screen and ( max-width: 479px )', ); $media_queries['mobile'] = $media_queries['max_width_767']; $media_queries = apply_filters( 'et_builder_media_queries', $media_queries ); if ( 'for_js' === $for_js ) { $processed_queries = array(); foreach ( $media_queries as $key => $value ) { $processed_queries[] = array( $key, $value ); } } else { $processed_queries = $media_queries; } return $processed_queries; } static function set_media_queries() { self::$media_queries = self::get_media_quries(); } static function get_media_query( $name ) { if ( ! isset( self::$media_queries[ $name ] ) ) { return false; } return self::$media_queries[ $name ]; } static function get_style_key() { if ( self::is_theme_builder_layout() ) { return self::get_layout_id(); } // Use a generic key in all other cases. // For example, injector plugins that repeat a layout in a loop // need to group that CSS under the same key. return 'post'; } static function get_style_array( $internal = false, $key = 0 ) { $styles = $internal ? self::$internal_modules_styles : self::$styles; if ( 0 === $key ) { $key = self::get_style_key(); } return isset( $styles[ $key ] ) ? $styles[ $key ] : array(); } /** * Intended to be used for unit testing * * @intendedForTesting */ static function reset_styles() { self::$internal_modules_styles = array(); self::$styles = array(); self::$media_queries = array(); } static function get_style( $internal = false, $key = 0 ) { // use appropriate array depending on which styles we need $styles_array = self::get_style_array( $internal, $key ); if ( empty( $styles_array ) ) { return ''; } global $et_user_fonts_queue; $output = ''; if ( ! empty( $et_user_fonts_queue ) ) { $output .= et_builder_enqueue_user_fonts( $et_user_fonts_queue ); } $styles_by_media_queries = $styles_array; $styles_count = (int) count( $styles_by_media_queries ); $media_queries_order = array_merge( array( 'general' ), array_values( self::$media_queries ) ); // make sure styles in the array ordered by media query correctly from bigger to smaller screensize $styles_by_media_queries_sorted = array_merge( array_flip( $media_queries_order ), $styles_by_media_queries ); foreach ( $styles_by_media_queries_sorted as $media_query => $styles ) { // skip wrong values which were added during the array sorting if ( ! is_array( $styles ) ) { continue; } $media_query_output = ''; $wrap_into_media_query = 'general' !== $media_query; // sort styles by priority et_()->uasort( $styles, array( 'ET_Builder_Element', 'compare_by_priority' ) ); // get each rule in a media query foreach ( $styles as $selector => $settings ) { $media_query_output .= sprintf( '%3$s%4$s%1$s { %2$s }', $selector, $settings['declaration'], "\n", ( $wrap_into_media_query ? "\t" : '' ) ); } // All css rules that don't use media queries are assigned to the "general" key. // Wrap all non-general settings into media query. if ( $wrap_into_media_query ) { $media_query_output = sprintf( '%3$s%3$s%1$s {%2$s%3$s}', $media_query, $media_query_output, "\n" ); } $output .= $media_query_output; } return $output; } static function get_column_video_background( $args = array(), $conditional_tags = array(), $current_page = array() ) { if ( empty( $args ) ) { return false; } $formatted_args = array(); foreach ( $args as $key => $value) { $key_length = strlen( $key ); $formatted_args[ substr( $key, 0, ( $key_length - 2 ) ) ] = $value; } return self::get_video_background( $formatted_args, $conditional_tags, $current_page ); } /** * Generate video background markup. * * @since 3.23 Add support for responsive settings. * * @param array $args Background values. * @param array $conditional_tags Conditional tags. * @param array $current_page Current page info. * @return mixed Mixed background content generated as video markup. */ static function get_video_background( $args = array(), $conditional_tags = array(), $current_page = array() ) { $base_name = isset( $args['computed_variables'] ) && isset( $args['computed_variables']['base_name'] ) ? $args['computed_variables']['base_name'] : 'background'; $device = isset( $args['computed_variables'] ) && isset( $args['computed_variables']['device'] ) ? $args['computed_variables']['device'] : 'desktop'; $suffix = ! empty( $device ) && 'desktop' !== $device ? "_{$device}" : ''; $defaults = array( "{$base_name}_video_mp4{$suffix}" => '', "{$base_name}_video_webm{$suffix}" => '', "{$base_name}_video_width{$suffix}" => '', "{$base_name}_video_height{$suffix}" => '', ); $args = wp_parse_args( $args, $defaults ); if ( '' === $args["{$base_name}_video_mp4{$suffix}"] && '' === $args["{$base_name}_video_webm{$suffix}"] ) { return false; } return do_shortcode( sprintf( ' <video loop="loop" autoplay playsinline muted %3$s%4$s> %1$s %2$s </video>', ( '' !== $args["{$base_name}_video_mp4{$suffix}"] ? sprintf( '<source type="video/mp4" src="%s" />', esc_url( $args["{$base_name}_video_mp4{$suffix}"] ) ) : '' ), ( '' !== $args["{$base_name}_video_webm{$suffix}"] ? sprintf( '<source type="video/webm" src="%s" />', esc_url( $args["{$base_name}_video_webm{$suffix}"] ) ) : '' ), ( '' !== $args["{$base_name}_video_width{$suffix}"] ? sprintf( ' width="%s"', esc_attr( intval( $args["{$base_name}_video_width{$suffix}"] ) ) ) : '' ), ( '' !== $args["{$base_name}_video_height{$suffix}"] ? sprintf( ' height="%s"', esc_attr( intval( $args["{$base_name}_video_height{$suffix}"] ) ) ) : '' ) ) ); } static function clean_internal_modules_styles( $need_internal_styles = true ) { // clean the styles array self::$internal_modules_styles[ self::get_style_key() ] = array(); // set the flag to make sure new styles will be saved to the correct place self::$prepare_internal_styles = $need_internal_styles; // generate unique number to make sure module classes will be unique if shortcode is generated via ajax self::$internal_modules_counter = rand( 10000, 99999 ); } /** * Set the field dependencies based on the `show_if` or `show_if_not` key from the * field. * @param string $slug The module's slug. ie `et_pb_section` * @param string $field_id The field id. id `background_color` * @param array $field_info Associative array of the field's data. */ protected static function set_field_dependencies( $slug, $field_id, $field_info ) { // bail if the field_info is not an array. if ( ! is_array( $field_info ) || ! self::$_->array_get( $field_info, 'bb_support', true ) ) { return; } // otherwise we keep going. foreach ( array( 'show_if', 'show_if_not' ) as $dependency_type ) { if ( ! isset( $field_info[ $dependency_type ] ) ) { continue; } if ( ! self::$data_utils->is_assoc_array( $field_info[ $dependency_type ] ) ) { continue; } foreach ( $field_info[ $dependency_type ] as $dependency => $value ) { // dependency -> dependent (eg. et_pb_signup.provider.affects.first_name_field.show_if: mailchimp) $address = self::$_->esc_array( array( $slug, $dependency, 'affects', $field_id, $dependency_type ), 'esc_attr' ); self::$data_utils->array_set( self::$field_dependencies, $address, self::$_->esc_array( $value, 'esc_attr' ) ); // dependent -> dependency (eg. et_pb_signup.first_name_field.show_if.provider: mailchimp) $address = self::$_->esc_array( array( $slug, $field_id, $dependency_type, $dependency ), 'esc_attr' ); self::$data_utils->array_set( self::$field_dependencies, $address, self::$_->esc_array( $value, 'esc_attr' ) ); } } } public static function get_field_dependencies( $post_type ) { if ( self::$field_dependencies ) { return self::$field_dependencies; } $all_modules = self::get_parent_and_child_modules( $post_type ); foreach ( $all_modules as $module_slug => $module ) { // Get all the fields. $all_fields = $module->sort_fields( $module->_get_fields() ); foreach ( $all_fields as $field_id => $field_info ) { if ( isset( $field_info['type'] ) && 'composite' === $field_info['type'] ) { foreach ( $field_info['composite_structure'] as $field ) { foreach ( $field['controls'] as $control => $data ) { self::set_field_dependencies( $module_slug, $control, $data ); } } } self::set_field_dependencies( $module_slug, $field_id, $field_info ); } } return self::$field_dependencies; } static function set_style( $function_name, $style ) { $selectors = is_array( $style['selector'] ) ? $style['selector'] : array( $style['selector'] ); foreach ( $selectors as $item ) { foreach ( self::$_->sanitize_css_placeholders( $item ) as $selector ) { $selector = apply_filters( "{$function_name}_css_selector", $selector ); self::_set_style( $function_name, array_merge( $style, array( 'selector' => $selector ) ) ); } } } /** * Applies the responsive and hover style for a specified option * * @since 3.25.3 * * @param string $option * @param string $selector * @param string $css_prop */ public function generate_responsive_hover_style( $option, $selector, $css_prop ) { $responsive = et_pb_responsive_options(); $hover = et_pb_hover_options(); $values = $responsive->get_property_values( $this->props, $option ); $hover_value = $hover->get_value( $option, $this->props ); $responsive->generate_responsive_css( $values, $selector, $css_prop, $this->slug, '', 'color' ); if ( $hover_value ) { self::set_style( $this->slug, array( 'selector' => $hover->add_hover_to_selectors( $selector ), 'declaration' => "{$css_prop}: $hover_value;" ) ); } } protected static function _set_style( $function_name, $style ) { $declaration = rtrim($style['declaration']); if ( empty($declaration) ) { // Do not add empty declarations return; } $builder_post_types = et_builder_get_builder_post_types(); $allowed_post_types = apply_filters( 'et_builder_set_style_allowed_post_types', $builder_post_types ); if ( $builder_post_types !== $allowed_post_types ) { $matches = array_intersect( $allowed_post_types, array_keys( self::$_module_slugs_by_post_type ) ); $allowed = false; foreach ( $matches as $post_type ) { if ( ! isset( self::$_module_slugs_by_post_type[ $post_type ] ) ) { continue; } if ( in_array( $function_name, self::$_module_slugs_by_post_type[ $post_type ] ) ) { $allowed = true; break; } } if ( ! $allowed ) { return; } } global $et_pb_rendering_column_content; // do not process all the styles if FB enabled. Only those for modules without fb support and styles for the internal modules from Blog/Slider $main_query_post = ET_Post_Stack::get_main_post(); $main_query_post_id = null !== $main_query_post ? $main_query_post->ID : 0; $editing_current_post = et_fb_is_enabled() && self::get_layout_id() === $main_query_post_id; if ( $editing_current_post && ! in_array( $function_name, self::get_fb_unsupported_modules() ) && ! $et_pb_rendering_column_content ) { return; } $order_class_name = self::get_module_order_class( $function_name ); $selector = str_replace( '%%order_class%%', ".{$order_class_name}", $style['selector'] ); $selector = str_replace( '%order_class%', ".{$order_class_name}", $selector ); // %%parent_class%% only works if child module's slug is `parent_slug` + _item suffix. If child module slug // use different slug structure, %%parent_class%% should not be used if ( false !== strpos( $selector, '%%parent_class%%' ) ) { $parent_class = str_replace( '_item', '', $function_name ); $selector = str_replace( '%%parent_class%%', ".{$parent_class}", $selector ); } $selector = strip_tags( apply_filters( 'et_pb_set_style_selector', $selector, $function_name ) ); $selector = et_builder_maybe_wrap_css_selectors( $selector, false ); // New lines are saved as || in CSS Custom settings, remove them $declaration = preg_replace( '/(\|\|)/i', '', $declaration ); $media_query = isset( $style[ 'media_query' ] ) ? $style[ 'media_query' ] : 'general'; $internal = $et_pb_rendering_column_content && self::$prepare_internal_styles; $style_key = self::get_style_key(); $styles = self::get_style_array( $internal ); // prepare styles for internal content. Used in Blog/Slider modules if they contain Divi modules if ( isset( $styles[ $media_query ][ $selector ]['declaration'] ) ) { $styles[ $media_query ][ $selector ]['declaration'] = sprintf( '%1$s %2$s', $styles[ $media_query ][ $selector ]['declaration'], $declaration ); } else { $styles[ $media_query ][ $selector ]['declaration'] = $declaration; } if ( isset( $style['priority'] ) ) { $styles[ $media_query ][ $selector ]['priority'] = (int) $style['priority']; } if ( $internal ) { self::$internal_modules_styles[ $style_key ] = $styles; } else { self::$styles[ $style_key ] = $styles; } } static function get_module_order_class( $function_name ) { global $et_pb_rendering_column_content, $et_pb_predefined_module_index; // determine whether we need to get the internal module class or regular $get_inner_module_class = $et_pb_rendering_column_content; if ( $get_inner_module_class ) { if ( self::_get_index( array( self::INDEX_INNER_MODULE_ORDER, $function_name ) ) === -1 ) { return false; } } else { if ( self::_get_index( array( self::INDEX_MODULE_ORDER, $function_name ) ) === -1 ) { return false; } } if ( isset( $et_pb_predefined_module_index ) && $et_pb_predefined_module_index ) { $shortcode_order_num = $et_pb_predefined_module_index; } else { $shortcode_order_num = $get_inner_module_class ? self::_get_index( array( self::INDEX_INNER_MODULE_ORDER, $function_name ) ) : self::_get_index( array( self::INDEX_MODULE_ORDER, $function_name ) ); } $theme_builder_suffix = self::_get_theme_builder_order_class_suffix(); $order_class_name = sprintf( '%1$s_%2$s%3$s', $function_name, $shortcode_order_num, $theme_builder_suffix ); return $order_class_name; } static function set_order_class( $function_name ) { global $et_pb_rendering_column_content; // determine whether we need to update the internal module class or regular $process_inner_module_class = $et_pb_rendering_column_content; if ( $process_inner_module_class ) { $current_inner_index = self::_get_index( array( self::INDEX_INNER_MODULE_ORDER, $function_name ) ); self::_set_index( array( self::INDEX_INNER_MODULE_ORDER, $function_name ), $current_inner_index > -1 ? $current_inner_index + 1 : self::$internal_modules_counter ); } else { self::_set_index( array( self::INDEX_MODULE_ORDER, $function_name ), self::_get_index( array( self::INDEX_MODULE_ORDER, $function_name ) ) + 1 ); } } static function add_module_order_class( $module_class, $function_name ) { $order_class_name = self::get_module_order_class( $function_name ); return "{$module_class} {$order_class_name}"; } /** * Generate video background markup. * * @since 3.23 Add support for responsive settings. * * @param array $args Background values. * @param string $base_name Background base name. * @return string Video background string value. */ function video_background( $args = array(), $base_name = 'background' ) { $attr_prefix = "{$base_name}_"; $custom_prefix = 'background' === $base_name ? '' : "{$base_name}_"; $module_attrs = $this->props; // Default background class for each devices. $background_video_class = ''; $background_video_class_tablet = 'et_pb_section_video_bg_tablet'; $background_video_class_phone = 'et_pb_section_video_bg_phone'; $background_video_class_hover = 'et_pb_section_video_bg_hover'; // Hover and Responsive Status. $hover_enabled = self::$_->array_get( $this->props, "{$base_name}__hover_enabled", 'off' ); $is_background_hover = 'on' === $hover_enabled; $is_background_mobile = et_pb_responsive_options()->is_responsive_enabled( $this->props, $base_name ); if ( ! empty( $args ) ) { $background_video = self::get_video_background( $args ); $background_video_tablet = ''; $background_video_phone = ''; $background_video_hover = ''; $pause_outside_viewport = self::$_->array_get( $args, "{$attr_prefix}video_pause_outside_viewport", 'off' ); $allow_player_pause = self::$_->array_get( $args, "{$custom_prefix}allow_player_pause", 'off' ); } else { $background_videos = array(); // Desktop. $default_args = array( "{$attr_prefix}video_mp4" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_mp4" ), "{$attr_prefix}video_webm" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_webm" ), "{$attr_prefix}video_width" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_width", '', true ), "{$attr_prefix}video_height" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_height", '', true ), 'computed_variables' => array( 'base_name' => $base_name, ), ); // Collecting background videos. $background_videos['desktop'] = self::get_video_background( $default_args ); $module_attrs["video_{$base_name}_values"] = $background_videos; // Get video and display status. $background_video_status = et_pb_responsive_options()->get_inheritance_background_value( $module_attrs, "video_{$base_name}_values", 'desktop', $base_name, $this->fields_unprocessed ); $background_video = self::$_->array_get( $background_video_status, 'video', '' ); $background_display = self::$_->array_get( $background_video_status, 'display', '' ); // Hover. $background_video_hover = ''; $background_display_hover = ''; if ( $is_background_hover ) { $hover_args = array( "{$attr_prefix}video_mp4__hover" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_mp4__hover" ), "{$attr_prefix}video_webm__hover" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_webm__hover" ), "{$attr_prefix}video_width__hover" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_width__hover", '', true ), "{$attr_prefix}video_height__hover" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_height__hover", '', true ), 'computed_variables' => array( 'base_name' => $base_name, 'device' => '_hover', ), ); // Collecting background videos. $background_videos['hover'] = self::get_video_background( $hover_args ); $module_attrs["video_{$base_name}_values"] = $background_videos; // Get video and display status. $background_video_status_hover = et_pb_responsive_options()->get_inheritance_background_value( $module_attrs, "video_{$base_name}_values", 'hover', $base_name, $this->fields_unprocessed ); $background_video_hover = self::$_->array_get( $background_video_status_hover, 'video', '' ); $background_display_hover = self::$_->array_get( $background_video_status_hover, 'display', '' ); } // Tablet and Phone. $background_video_tablet = ''; $background_display_tablet = ''; $background_video_phone = ''; $background_display_phone = ''; if ( $is_background_mobile ) { $tablet_args = array( "{$attr_prefix}video_mp4_tablet" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_mp4_tablet" ), "{$attr_prefix}video_webm_tablet" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_webm_tablet" ), "{$attr_prefix}video_width_tablet" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_width_tablet", '', true ), "{$attr_prefix}video_height_tablet" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_height_tablet", '', true ), 'computed_variables' => array( 'base_name' => $base_name, 'device' => 'tablet', ), ); $phone_args = array( "{$attr_prefix}video_mp4_phone" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_mp4_phone" ), "{$attr_prefix}video_webm_phone" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_webm_phone" ), "{$attr_prefix}video_width_phone" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_width_phone", '', true ), "{$attr_prefix}video_height_phone" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_height_phone", '', true ), 'computed_variables' => array( 'base_name' => $base_name, 'device' => 'phone', ), ); // Collecting background videos. $background_videos['tablet'] = self::get_video_background( $tablet_args ); $background_videos['phone'] = self::get_video_background( $phone_args ); $module_attrs["video_{$base_name}_values"] = $background_videos; // Get video and display status. $background_video_status_tablet = et_pb_responsive_options()->get_inheritance_background_value( $module_attrs, "video_{$base_name}_values", 'tablet', $base_name, $this->fields_unprocessed ); $background_video_tablet = self::$_->array_get( $background_video_status_tablet, 'video', '' ); $background_display_tablet = self::$_->array_get( $background_video_status_tablet, 'display', '' ); $background_video_status_phone = et_pb_responsive_options()->get_inheritance_background_value( $module_attrs, "video_{$base_name}_values", 'phone', $base_name, $this->fields_unprocessed ); $background_video_phone = self::$_->array_get( $background_video_status_phone, 'video', '' ); $background_display_phone = self::$_->array_get( $background_video_status_phone, 'display', '' ); } // Set background video and class. Inherit is used to avoid rendering the same video. if ( '' !== $background_display_phone ) { if ( 'hide' === $background_display_phone ) { $background_video_class = 'et_pb_section_video_bg_desktop_tablet'; $background_video_class_tablet = 'et_pb_section_video_bg_tablet_only'; } else if ( 'inherit' === $background_display_phone ) { $background_video_phone = ''; } } if ( '' !== $background_display_tablet ) { if ( 'hide' === $background_display_tablet ) { $background_video_class = 'et_pb_section_video_bg_desktop_only'; } else if ( 'inherit' === $background_display_tablet ) { $background_video_tablet = ''; } } if ( '' !== $background_display_hover ) { if ( 'inherit' === $background_display_hover ) { $background_video_class .= ' et_pb_section_video_bg_hover_inherit'; $background_video_hover = ''; } } } $video_background = ''; // Desktop. if ( $background_video ) { // Video on desktop properties. $pause_outside_viewport = self::$_->array_get( $this->props, "{$attr_prefix}video_pause_outside_viewport", '' ); $allow_player_pause = self::$_->array_get( $this->props, "{$custom_prefix}allow_player_pause", 'off' ); $video_background .= sprintf( '<span class="et_pb_section_video_bg %2$s %3$s%4$s"> %1$s </span>', $background_video, $background_video_class, ( 'on' === $allow_player_pause ? ' et_pb_allow_player_pause' : '' ), ( 'off' === $pause_outside_viewport ? ' et_pb_video_play_outside_viewport' : '' ) ); } // Hover. if ( $is_background_hover ) { if ( $background_video_hover ) { // Video on hover properties. $pause_outside_viewport_hover = self::$_->array_get( $this->props, "{$attr_prefix}video_pause_outside_viewport__hover", '' ); $allow_player_pause_hover = self::$_->array_get( $this->props, "{$custom_prefix}allow_player_pause__hover", 'off' ); $video_background .= sprintf( '<span class="et_pb_section_video_bg %2$s %3$s%4$s"> %1$s </span>', $background_video_hover, $background_video_class_hover, ( 'on' === $allow_player_pause_hover ? ' et_pb_allow_player_pause' : '' ), ( 'off' === $pause_outside_viewport_hover ? ' et_pb_video_play_outside_viewport' : '' ) ); } $this->add_classname( 'et_pb_section_video_on_hover' ); } // Tablet. if ( $background_video_tablet && $is_background_mobile ) { // Video on tablet properties. $pause_outside_viewport_tablet = self::$_->array_get( $this->props, "{$attr_prefix}video_pause_outside_viewport_tablet", '' ); $allow_player_pause_tablet = self::$_->array_get( $this->props, "{$custom_prefix}allow_player_pause_tablet", 'off' ); $video_background .= sprintf( '<span class="et_pb_section_video_bg %2$s %3$s%4$s"> %1$s </span>', $background_video_tablet, $background_video_class_tablet, ( 'on' === $allow_player_pause_tablet ? ' et_pb_allow_player_pause' : '' ), ( 'off' === $pause_outside_viewport_tablet ? ' et_pb_video_play_outside_viewport' : '' ) ); } // Phone. if ( $background_video_phone && $is_background_mobile ) { // Video on phone properties. $pause_outside_viewport_phone = self::$_->array_get( $this->props, "{$attr_prefix}video_pause_outside_viewport_phone", '' ); $allow_player_pause_phone = self::$_->array_get( $this->props, "{$custom_prefix}allow_player_pause_phone", 'off' ); $video_background .= sprintf( '<span class="et_pb_section_video_bg %2$s %3$s%4$s"> %1$s </span>', $background_video_phone, $background_video_class_phone, ( 'on' === $allow_player_pause_phone ? ' et_pb_allow_player_pause' : '' ), ( 'off' === $pause_outside_viewport_phone ? ' et_pb_video_play_outside_viewport' : '' ) ); } // Added classname for module wrapper if ( '' !== $video_background ) { wp_enqueue_style( 'wp-mediaelement' ); wp_enqueue_script( 'wp-mediaelement' ); $this->add_classname( array( 'et_pb_section_video', 'et_pb_preload' ) ); } return $video_background; } function get_parallax_image_background( $base_name = 'background' ) { $attr_prefix = "{$base_name}_"; $custom_prefix = 'background' === $base_name ? '' : "{$base_name}_"; $parallax_processed = array(); $parallax_background = ''; $hover_suffix = et_pb_hover_options()->get_suffix(); $preview_modes = array( $hover_suffix, '_phone', '_tablet', '' ); // Featured Image as Background. $featured_image = ''; $featured_placement = ''; $featured_image_src = ''; if ( $this->featured_image_background ) { $featured_image = self::$_->array_get( $this->props, 'featured_image', '' ); $featured_placement = self::$_->array_get( $this->props, 'featured_placement', '' ); $featured_image_src_obj = wp_get_attachment_image_src( get_post_thumbnail_id( self::_get_main_post_id() ), 'full' ); $featured_image_src = isset( $featured_image_src_obj[0] ) ? $featured_image_src_obj[0] : ''; } foreach( $preview_modes as $suffix ) { $is_hover = $hover_suffix === $suffix; // A. Bail early if hover or responsive settings disabled on mobile/hover. if ( '' !== $suffix ) { // Ensure responsive settings is enabled on mobile. if ( ! $is_hover && ! et_pb_responsive_options()->is_responsive_enabled( $this->props, $base_name ) ) { continue; } // Ensure hover settings is enabled. if ( $is_hover && ! et_pb_hover_options()->is_enabled( $base_name, $this->props ) ) { continue; } } // Prepare preview mode. $mode = '' !== $suffix ? str_replace( '_', '', $suffix ) : 'desktop'; $mode = $is_hover ? 'hover' : $mode; // B.1. Get inherited background value. $background_image = et_pb_responsive_options()->get_inheritance_background_value( $this->props, "{$attr_prefix}image", $mode, $base_name, $this->fields_unprocessed ); $parallax = $is_hover ? et_pb_hover_options()->get_raw_value( "{$custom_prefix}parallax", $this->props ) : et_pb_responsive_options()->get_any_value( $this->props, "{$custom_prefix}parallax{$suffix}", '', true ); $parallax_method = $is_hover ? et_pb_hover_options()->get_raw_value( "{$custom_prefix}parallax_method", $this->props ) : et_pb_responsive_options()->get_any_value( $this->props, "{$custom_prefix}parallax_method{$suffix}", '', true ); // B.2. Set default value for parallax and parallax method on hover when they are empty. if ( $is_hover ) { $parallax = empty( $parallax ) ? et_pb_responsive_options()->get_any_value( $this->props, "{$custom_prefix}parallax", '', true ) : $parallax; $parallax_method = empty( $parallax_method ) ? et_pb_responsive_options()->get_any_value( $this->props, "{$custom_prefix}parallax_method", '', true ) : $parallax_method; } // B.3. Override background image with featured image if needed. if ( 'on' === $featured_image && 'background' === $featured_placement && '' !== $featured_image_src ) { $background_image = $featured_image_src; } // C.1. Parallax BG Class to inform if other modes exist. $parallax_classname = array(); if ( ( '_tablet' === $suffix || '' === $suffix ) && in_array( '_phone', $parallax_processed ) ) { $parallax_classname[] = 'et_parallax_bg_phone_exist'; } if ( '' === $suffix && in_array( '_tablet', $parallax_processed ) ) { $parallax_classname[] = 'et_parallax_bg_tablet_exist'; } if ( in_array( $hover_suffix, $parallax_processed ) ) { $parallax_classname[] = 'et_parallax_bg_hover_exist'; } // C.2. Set up parallax class and wrapper. if ( '' !== $background_image && 'on' === $parallax ) { $parallax_classname[] = 'et_parallax_bg'; if ( 'off' === $parallax_method ) { $parallax_classname[] = 'et_pb_parallax_css'; } // Parallax BG Class with suffix. if ( '' !== $suffix ) { $parallax_classname[] = "et_parallax_bg{$suffix}"; } $parallax_background .= sprintf( '<span class="et_parallax_bg_wrap"><span class="%1$s" style="background-image: url(%2$s);" ></span></span>', esc_attr( implode( ' ', $parallax_classname ) ), esc_url( $background_image ) ); // set `.et_parallax_bg_wrap` border-radius. et_set_parallax_bg_wrap_border_radius( $this->props, $this->slug, $this->main_css_element ); } // C.3. Hover parallax class. if ( '' !== $background_image && $is_hover ) { $this->add_classname( 'et_pb_section_parallax_hover' ); } array_push( $parallax_processed, $suffix ); } // Added classname for module wrapper if ( '' !== $parallax_background ) { $this->add_classname( 'et_pb_section_parallax' ); } return $parallax_background; } /** * Generate CSS Filters * Check our shortcode arguments for CSS `filter` properties. If found, set the style rules for this block. (This * function reads options set by the 'Filters' and 'Image Filters' builder menu fields.) * * @since 3.23 Add responsive setting styling processing here. * * @param string $function_name Builder module's function name (keeps the CSS rules straight) * @param string $prefix Optional string prepended to the field name (i.e., `filter_saturate` -> `child_filter_saturate`) * @param mixed $selectors Array or string containing all target DOM element(s), ID(s), and/or class(es) * * @return string Any additional CSS classes (added if filters were applied). */ function generate_css_filters( $function_name = '', $prefix = '', $selectors = array('%%order_class%%') ) { if ( '' === $function_name ) { ET_Core_Logger::error( '$function_name is required.' ); return; } // If `$selectors` is a string, convert to an array before we continue $selectors_prepared = $selectors; if ( ! is_array( $selectors ) ) { $selectors_prepared = explode( ',', et_core_intentionally_unescaped( $selectors, 'fixed_string' ) ); } $responsive_selectors = $selectors_prepared; $additional_classes = ''; // If we don't have a target selector, get out now if ( ! $selectors_prepared ) { return $additional_classes; } $hover_suffix = et_pb_hover_options()->get_suffix(); $field_suffixes = array( '', 'tablet', 'phone', $hover_suffix ); $filters_default = array(); $filters_default_fb = array(); foreach ( $field_suffixes as $suffix ) { if ( $hover_suffix === $suffix ) { $selectors_prepared = array_map( array( $this, 'add_hover_to_selectors' ), $selectors_prepared ); } // Mobile parameters. Update suffix and add media query argument for styles declaration. $device_suffix = ''; $media_query = array(); $is_mobile = in_array( $suffix, array( 'tablet', 'phone' ) ); if ( $is_mobile ) { $breakpoint = 'tablet' === $suffix ? 'max_width_980' : 'max_width_767'; $media_query = array( 'media_query' => ET_Builder_Element::get_media_query( $breakpoint ) ); // For mobile, we need to reset $suffix and use $devie_suffix instead. Later on with // empty suffix, the filter will only return desktop value and will be used as default // and will be merged with filter mobile values. $device_suffix = "_{$suffix}"; $suffix = ''; } // Some web browser glitches with filters and blend modes can be improved this way // see https://bugs.chromium.org/p/chromium/issues/detail?id=157218 for more info $backfaceVisibility = 'backface-visibility:hidden;'; $backfaceVisibilityAdded = array(); $additional_classes = ''; // Blend Mode $mix_blend_mode = self::$data_utils->array_get( $this->props, "{$prefix}mix_blend_mode", '' ); // Filters $filter = array(); $filter_names = array(); $filter_keys = array( 'hue_rotate', 'saturate', 'brightness', 'contrast', 'invert', 'sepia', 'opacity', 'blur', ); // Assign filter values and names. foreach( $filter_keys as $filter_key ) { $filter_name = "{$prefix}filter_{$filter_key}"; $filter_names[] = $filter_name; $filter[ $filter_key ] = self::$data_utils->array_get( $this->props, "{$filter_name}{$suffix}", ''); } $is_any_filter_responsive = et_pb_responsive_options()->is_any_responsive_enabled( $this->props, $filter_names ); $is_any_filter_hover_enabled = et_pb_hover_options()->is_any_hover_enabled( $this->props, $filter_names ); // For mobile, it should return any value exist if current device value is empty. if ( $is_mobile ) { // Blend Mode. $is_blend_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, "{$prefix}mix_blend_mode" ); $mix_blend_mode = $is_blend_responsive ? et_pb_responsive_options()->get_any_value( $this->props, "{$prefix}mix_blend_mode{$suffix}", '', true ) : ''; // Filters. $filters_mobile = array(); foreach( $filter as $filter_key => $filter_value ) { if ( ! et_pb_responsive_options()->is_responsive_enabled( $this->props, "{$prefix}filter_{$filter_key}" ) ) { continue; } $filters_mobile[ $filter_key ] = et_pb_responsive_options()->get_any_value( $this->props, "{$prefix}filter_{$filter_key}{$device_suffix}", '', true ); } // If any responsive settings active on filter settings, set desktop value as default. if ( $is_any_filter_responsive ) { $filters_mobile = array_merge( $filter, $filters_mobile ); } // Replace current filter values with mobile filter values. $filter = $filters_mobile; } // Remove any filters with null or default values $filter = array_filter( $filter, 'strlen' ); // Optional: CSS `mix-blend-mode` rule $mix_blend_mode_default = ET_Global_Settings::get_value( 'all_mix_blend_mode', 'default' ); if ( $mix_blend_mode && $mix_blend_mode !== $mix_blend_mode_default ) { foreach ( $selectors_prepared as $selector ) { ET_Builder_Element::set_style( $function_name, array_merge( array( 'selector' => $selector, 'declaration' => sprintf( 'mix-blend-mode: %1$s;', esc_html( $mix_blend_mode ) ) . $backfaceVisibility, ), $media_query ) ); $backfaceVisibilityAdded[] = $selector; } $additional_classes .= ' et_pb_css_mix_blend_mode'; } else if ( 'et_pb_column' === $function_name ) { // Columns need to pass through $additional_classes .= ' et_pb_css_mix_blend_mode_passthrough'; } // Optional: CSS `filter` rule if ( empty( $filter ) ) { // Since we added responsive settings, the process should not be stopped here. // It should continue until tablet and phone are checked completely. Replace // return with continue. continue; } $css_value = array(); $css_value_fb_hover = array(); foreach ( $filter as $label => $value ) { // Check against our default settings, and only append the rule if it differs // (only for default state since hover and mobile might be equal to default, // ie. no filter on hover only) if ( ET_Global_Settings::get_value( 'all_filter_' . $label, 'default' ) === $value && $hover_suffix !== $suffix && ! $is_mobile && ! ( $is_any_filter_responsive && $is_any_filter_hover_enabled ) ) { continue; } // Don't apply hover filter if it is not enabled if ( $hover_suffix === $suffix && ! et_pb_hover_options()->is_enabled( "{$prefix}filter_{$label}{$suffix}", $this->props ) ) { continue; } $value = et_sanitize_input_unit( $value, false, 'deg' ); $label_css_format = str_replace( '_', '-', $label ); // Construct string of all CSS Filter values $css_value[$label] = esc_html( "${label_css_format}(${value})" ); // Construct Visual Builder hover rules if ( ! in_array( $label, array( 'opacity', 'blur' ) ) ) { // Skip those, because they mess with VB controls $css_value_fb_hover[$label] = esc_html( "${label_css_format}(${value})" ); } } // Append our new CSS rules if ( $css_value ) { // Store the default (non-hover) filters if ( '' === $suffix ) { $filters_default = $css_value; } // Merge the hover filters onto the default filters so that filters that // have no hover option set are not removed from the CSS declaration if ( $hover_suffix === $suffix ) { $css_value = array_merge( $filters_default, $css_value ); } foreach ( $selectors_prepared as $selector ) { $backfaceVisibilityDeclaration = in_array( $selector, $backfaceVisibilityAdded ) ? '' : $backfaceVisibility; // Allow custom child filter target hover selector if ( 'child_' == $prefix && $hover_suffix === $suffix ){ $selector = self::$_->array_get( $this->advanced_fields, 'filters.child_filters_target.css.hover', $selector ); } ET_Builder_Element::set_style( $function_name, array_merge( array( 'selector' => $selector, 'declaration' => sprintf( 'filter: %1$s;', implode( ' ', $css_value ) ) . $backfaceVisibilityDeclaration, ), $media_query ) ); } $additional_classes .= ' et_pb_css_filters'; } // If we have VB hover-friendly CSS rules, we'll gather those and append them here if ( $css_value_fb_hover ) { // Store the default (non-hover) filters if ( '' === $suffix ) { $filters_default_fb = $css_value_fb_hover; } // Merge the hover filters onto the default filters so that filters that // have no hover option set are not removed from the CSS declaration if ( $hover_suffix === $suffix ) { $css_value_fb_hover = array_merge( $filters_default_fb, $css_value_fb_hover ); } foreach ( $selectors_prepared as $selector ) { $selector_hover = str_replace( '%%order_class%%', 'html:not(.et_fb_edit_enabled) #et-fb-app %%order_class%%:hover', $selector ); ET_Builder_Element::set_style( $function_name, array( 'selector' => $selector_hover, 'declaration' => esc_html( sprintf( 'filter: %1$s;', implode( ' ', $css_value_fb_hover ) ) ), ) ); } $additional_classes .= ' et_pb_css_filters_hover'; } } return $additional_classes; } /** * Convert classes array to a string. Also removes any duplicate classes * * @param array $classes A list of CSS classnames * * @return array */ function stringify_css_filter_classes( $classes ) { // Remove repeating classes $classes = array_unique( $classes ); // Transform classes to a string $classes = ' ' . implode( ' ', $classes ); return $classes; } /** * Adds a suffix at the end of the selector * E.g: add_suffix_to_selectors(':hover', '%%order_class%%% .image') >>> '%%order_class%%% .image:hover' * * @param string $suffix * @param string $selector * * @return string */ public function add_suffix_to_selectors( $suffix, $selector ) { $selectors = explode( ',', $selector ); $selectors = array_map( 'trim', $selectors ); foreach ( $selectors as &$selector ) { $selector .= $suffix; } return implode( ', ', $selectors ); } /** * Adds `:hover` in selector at the end of the selector * E.g: add_hover_to_selectors('%%order_class%%% .image') >>> '%%order_class%%% .image:hover' * * @param string $selector * * @return string * * @deprecated Use et_pb_hover_options()->add_hover_to_selectors( $selector ); */ public function add_hover_to_selectors( $selector ) { return et_pb_hover_options()->add_hover_to_selectors( $selector ); } /** * Adds `:hover` in selector at the end of the selector if $add_hover is true * otherwise returns the original selector * * @param string $selector * @param bool $add_hover * * @return string */ protected function _maybe_add_hover_to_selectors( $selector, $add_hover = false ) { return $add_hover ? et_pb_hover_options()->add_hover_to_selectors( $selector ) : $selector; } /** * Adds `:hover` in selector after `%%order_class%%` * E.g: add_hover_to_order_class('%%order_class%%% .image') >>> '%%order_class%%%:hover .image' * * @param string $selector * * @return string * * @deprecated Use et_pb_hover_options()->add_hover_to_order_class( $selector ); */ public function add_hover_to_order_class( $selector ) { return et_pb_hover_options()->add_hover_to_order_class( $selector ); } /** * Adds `:hover` to order class only if is specified, in other cse returns original selector * otherwise returns the original selector * * @param string $selector * @param bool $add_hover * * @return string */ protected function _maybe_add_hover_to_order_class( $selector, $add_hover = false ) { return $add_hover ? et_pb_hover_options()->add_hover_to_order_class( $selector ) : $selector; } /** * Convert smart quotes and & entity to their applicable characters * * @param string $text Input text * * @return string */ static function convert_smart_quotes_and_amp( $text ) { $smart_quotes = array( '“', '”', '″', '‘', '’', ''', '&', ); $replacements = array( '"', '"', '"', ''', ''', ''', '&', ); if ( 'fr_FR' === get_locale() ) { $french_smart_quotes = array( ' »', '″>', ); $french_replacements = array( '"', '">', ); $smart_quotes = array_merge( $smart_quotes, $french_smart_quotes ); $replacements = array_merge( $replacements, $french_replacements ); } $text = str_replace( $smart_quotes, $replacements, $text ); return $text; } public function process_multiple_checkboxes_field_value( $value_map, $value ) { $result = array(); $index = 0; foreach ( explode( '|', $value ) as $checkbox_value ) { if ( 'on' === $checkbox_value ) { $result[] = $value_map[ $index ]; } $index++; } return implode( '|', $result ); } /** * Adds one or more CSS classes to the module on the frontend. * * @since 3.1 * * @param string|array $to_add classname(s) to be added * @param number|bool $position position of added classname (0-based). Some class need to be placed * at exact position. i.e. .et_pb_column_{$type} on column inner */ function add_classname( $to_add, $position = false ) { if ( empty( $to_add ) ) { return; } $classname = is_array( $to_add ) ? $to_add : array( $to_add ); if ( is_numeric( $position ) ) { array_splice($this->classname, intval( $position ), 0, $classname ); } else { $this->classname = array_merge( $this->classname, $classname ); } } /** * Removes one ore more CSS classes to the module on the frontend * * @since 3.1 * * @param string|array $to_remove classname(s) to be removed */ function remove_classname( $to_remove ) { $this->classname = array_filter( $this->classname ); if ( is_string( $to_remove ) && '' !== $to_remove ) { $this->classname = array_diff( $this->classname, array( $to_remove ) ); } elseif ( is_array( $to_remove ) ) { $to_remove = array_filter( $to_remove ); $this->classname = array_diff( $this->classname, $to_remove ); } } /** * Outputs module class * * @since 3.1 * * @return string escaped class */ function module_classname( $function_name = '' ) { if ( ! in_array( $function_name, ET_Builder_Element::$uses_module_classname ) ) { // Add module slug to array of modules where `module_classname()` used ET_Builder_Element::$uses_module_classname[] = $function_name; } $module_name = str_replace( 'et_pb_', '', $this->slug ); /** * Filters module classes. * * @since 3.1 * * @param array $classname Array of classnames. * @param int $render_count Number of times render function has been executed */ $classname = (array) array_unique( apply_filters( "et_builder_{$module_name}_classes", $this->classname, $this->render_count() ) ); return implode( ' ', array_map( 'esc_attr', $classname ) ); } /** * Outputs module id * * @since 3.1 * * @param bool $include_attribute wrap module id with id attribute name or not (to be used directly on module div) * * @return string module id / module id wrapped by id attribute */ function module_id( $include_attribute = true ) { $module_id = esc_attr( $this->props['module_id'] ); $output = $include_attribute ? sprintf( ' id="%1$s"', $module_id ) : $module_id; return '' !== $module_id ? $output : ''; } /** * Helper method for rendering button markup which works compatible with advanced options' button * * @since 3.1 * * @param array $args button settings * * @return string rendered button HTML */ function render_button( $args = array() ) { // Prepare arguments $defaults = array( 'button_id' => '', 'button_classname' => array(), 'button_custom' => '', 'button_rel' => '', 'button_text' => '', 'button_text_escaped' => false, 'button_url' => '', 'custom_icon' => '', 'custom_icon_tablet' => '', 'custom_icon_phone' => '', 'display_button' => true, 'has_wrapper' => true, 'url_new_window' => '', 'multi_view_data' => '', ); $args = wp_parse_args( $args, $defaults ); // Do not proceed if display_button argument is false. if ( ! $args['display_button'] ) { return ''; } $button_text = $args['button_text_escaped'] ? $args['button_text'] : esc_html( $args['button_text'] ); // Do not proceed if button_text argument is empty and not having multi view value. if ( '' === $button_text && ! $args['multi_view_data'] ) { return ''; } // Button classname $button_classname = array( 'et_pb_button' ); if ( ( '' !== $args['custom_icon'] || '' !== $args['custom_icon_tablet'] || '' !== $args['custom_icon_phone'] ) && 'on' === $args['button_custom'] ) { $button_classname[] = 'et_pb_custom_button_icon'; } // Add multi view CSS hidden helper class when button text is empty on desktop mode. if ( '' === $button_text && $args['multi_view_data'] ) { $button_classname[] = 'et_multi_view_hidden'; } if ( ! empty( $args['button_classname'] ) ) { $button_classname = array_merge( $button_classname, $args['button_classname'] ); } // Custom icon data attribute $use_data_icon = '' !== $args['custom_icon'] && 'on' === $args['button_custom']; $data_icon = $use_data_icon ? sprintf( ' data-icon="%1$s"', esc_attr( et_pb_process_font_icon( $args['custom_icon'] ) ) ) : ''; $use_data_icon_tablet = '' !== $args['custom_icon_tablet'] && 'on' === $args['button_custom']; $data_icon_tablet = $use_data_icon_tablet ? sprintf( ' data-icon-tablet="%1$s"', esc_attr( et_pb_process_font_icon( $args['custom_icon_tablet'] ) ) ) : ''; $use_data_icon_phone = '' !== $args['custom_icon_phone'] && 'on' === $args['button_custom']; $data_icon_phone = $use_data_icon_phone ? sprintf( ' data-icon-phone="%1$s"', esc_attr( et_pb_process_font_icon( $args['custom_icon_phone'] ) ) ) : ''; // Render button return sprintf( '%7$s<a%9$s class="%5$s" href="%1$s"%3$s%4$s%6$s%10$s%11$s%12$s>%2$s</a>%8$s', esc_url( $args['button_url'] ), et_core_esc_previously( $button_text ), ( 'on' === $args['url_new_window'] ? ' target="_blank"' : '' ), et_core_esc_previously( $data_icon ), esc_attr( implode( ' ', array_unique( $button_classname ) ) ), // #5 et_core_esc_previously( $this->get_rel_attributes( $args['button_rel'] ) ), $args['has_wrapper'] ? '<div class="et_pb_button_wrapper">' : '', $args['has_wrapper'] ? '</div>' : '', '' !== $args['button_id'] ? sprintf( ' id="%1$s"', esc_attr( $args['button_id'] ) ) : '', et_core_esc_previously( $data_icon_tablet ), // #10 et_core_esc_previously( $data_icon_phone ), et_core_esc_previously( $args['multi_view_data'] ) ); } public static function is_saving_cache() { return apply_filters( 'et_builder_modules_is_saving_cache', false ); } /** * Get array of attributes which have dynamic content enabled. * * @since 3.17.2 * * @param mixed[] $attrs * * @return string[] */ protected function _get_enabled_dynamic_attributes( $attrs ) { $enabled_dynamic_attributes = isset( $attrs['_dynamic_attributes'] ) ? $attrs['_dynamic_attributes'] : ''; $enabled_dynamic_attributes = array_filter( explode( ',', $enabled_dynamic_attributes ) ); return $enabled_dynamic_attributes; } /** * Check if an attribute value is dynamic or not. * * @since 3.17.2 * * @param string $attribute * @param string $value * @param array $enabled_dynamic_attributes * * @return bool */ protected function _is_dynamic_value( $attribute, $value, $enabled_dynamic_attributes ) { if ( ! in_array( $attribute, $enabled_dynamic_attributes ) ) { return false; } return et_builder_parse_dynamic_content( $value )->is_dynamic(); } /** * Re-encode legacy dynamic content values in an attrs array. * * @since 3.20.2 * * @param string[] $attrs * @param string[] $enabled_dynamic_attributes * * @return string[] */ protected function _encode_legacy_dynamic_content( $attrs, $enabled_dynamic_attributes ) { if ( is_array( $attrs ) ) { foreach ( $attrs as $field => $value ) { $attrs[ $field ] = $this->_encode_legacy_dynamic_content_value( $field, $value, $enabled_dynamic_attributes ); } } return $attrs; } /** * Re-encode legacy dynamic content value. * * @since 3.20.2 * * @param string $field * @param string $value * * @return string */ protected function _encode_legacy_dynamic_content_value( $field, $value, $enabled_dynamic_attributes ) { if ( ! in_array( $field, $enabled_dynamic_attributes ) ) { return $value; } $json = et_builder_clean_dynamic_content( $value ); if ( preg_match( '/^@ET-DC@(.*?)@$/', $json ) ) { return $value; } return $this->_resolve_value_from_json( $field, $json, $enabled_dynamic_attributes ); } /** * Resolve a value, be it static or dynamic to a static one. * * @since 3.17.2 * * @param integer $post_id * @param string $field * @param string $value * @param string[] $enabled_dynamic_attributes * @param boolean $serialize * * @return string */ protected function _resolve_value( $post_id, $field, $value, $enabled_dynamic_attributes, $serialize ) { global $wp_query; if ( ! in_array( $field, $enabled_dynamic_attributes ) ) { return $value; } $builder_value = et_builder_parse_dynamic_content( $value ); if ( $serialize ) { return $builder_value->serialize(); } $is_blog_query = isset( $wp_query->et_pb_blog_query ) && $wp_query->et_pb_blog_query; if ( ! $is_blog_query && ! $wp_query->is_singular() ) { return $builder_value->resolve( null ); } return $builder_value->resolve( $post_id ); } /** * Resolve a value from the legacy JSON format of dynamic content. * This is essentially a migration but is implemented separately * as it needs to parse every field of every module and do it * before actual migrations are ran. * * @since 3.20.2 * * @param integer $post_id * @param string $field * @param string $value * @param string[] $enabled_dynamic_attributes * @param boolean $serialize * * @return string */ protected function _resolve_value_from_json( $field, $value, $enabled_dynamic_attributes ) { if ( ! in_array( $field, $enabled_dynamic_attributes ) ) { return $value; } $json = et_builder_clean_dynamic_content( $value ); // Replace encoded quotes. $json = str_replace( array( '“', '”', '″', "%22" ), '"', $json ); // Strip <p></p> artifacts from wpautop in before/after settings. Example: // {"dynamic":true,"content":"post_title","settings":{"before":"</p> // <h1>","after":"</h1> // <p>"}} // This is a rough solution implemented due to time constraints. $json = preg_replace( '~ ("(?:before|after)":") # $1 = Anchor to the before/after settings. (?: # Match cases where the value starts with the offending tag. <\/?p> # The root of all evil. [\r\n]+ # Whitespace follows the tag. )* (?: # Match cases where the value ends with the offending tag. ([^"]*) # $2 = The preceeding value. [\r\n]+ # Whitespace preceedes the tag. <\/?p> # The root of all evil. )* ~xi', '$1$2', $json ); // Remove line-breaks which break the json strings. $json = preg_replace( '/\r|\n/', '', $json ); $json_value = et_builder_parse_dynamic_content_json( $json ); if ( null === $json_value ) { return $value; } return $json_value->serialize(); } /** * Escape an attribute's value. * * @since 3.17.2 * * @param string $attribute * @param string $html 'limited', 'full', 'none' * @param string $predefined_value Predifined value need to escape. * * @return string */ protected function _esc_attr( $attribute, $html = 'none', $predefined_value = null ) { $html = in_array( $html, array( 'limited', 'full' ), true ) ? $html : 'none'; $raw = isset( $this->attrs_unprocessed[ $attribute ] ) ? $this->attrs_unprocessed[ $attribute ] : ''; $formatted = isset( $this->props[ $attribute ] ) ? $this->props[ $attribute ] : ''; $dynamic_attributes = $this->_get_enabled_dynamic_attributes( $this->props ); // More often than not content is not an attribute so we need to handle that special case. if ( 'content' === $attribute && ! isset( $this->attrs_unprocessed[ $attribute ] ) ) { $raw = $this->content_unprocessed; $formatted = $this->content; } if ( ! is_null( $predefined_value ) ) { $formatted = $predefined_value; } if ( ! $this->_is_dynamic_value( $attribute, $raw, $dynamic_attributes ) ) { if ( 'full' === $html ) { return $formatted; } return esc_html( $formatted ); } if ( 'limited' === $html ) { return wp_kses( $formatted, array( 'strong' => array( 'id' => array(), 'class' => array(), 'style' => array() ), 'em' => array( 'id' => array(), 'class' => array(), 'style' => array() ), 'i' => array( 'id' => array(), 'class' => array(), 'style' => array() ), ) ); } // Dynamic content values are escaped when they are resolved so we do not want to // double-escape them when using them in the frontend, for example. return et_core_esc_previously( $formatted ); } /** * Get the current TB layout ID if we are rendering one or the current post ID instead. * * @since 4.0 * * @return integer */ public static function get_layout_id() { $layout_id = self::get_theme_builder_layout_id(); $post_id = self::get_current_post_id_reverse(); return $layout_id ? $layout_id : $post_id; } /** * Get the current theme builder layout. * Returns 'default' if no layout has been started. * * @since 4.0 * * @return string */ public static function get_theme_builder_layout_type() { $count = count( self::$theme_builder_layout ); if ( $count > 0 ) { return self::$theme_builder_layout[ $count - 1 ]['type']; } return 'default'; } /** * Check if a module is rendered as normal post content or theme builder layout. * * @since 4.0 * * @return bool */ public static function is_theme_builder_layout() { return 'default' !== self::get_theme_builder_layout_type(); } /** * Get the current theme builder layout id. * Returns 0 if no layout has been started. * * @since 4.0 * * @return integer */ public static function get_theme_builder_layout_id() { $count = count( self::$theme_builder_layout ); if ( $count > 0 ) { return self::$theme_builder_layout[ $count - 1 ]['id']; } return 0; } /** * Begin a theme builder layout. * * @since 4.0 * * @param integer $layout_id * * @return void */ public static function begin_theme_builder_layout( $layout_id ) { $type = get_post_type( $layout_id ); if ( ! et_theme_builder_is_layout_post_type( $type ) ) { $type = 'default'; } self::$theme_builder_layout[] = array( 'id' => (int) $layout_id, 'type' => $type, ); } /** * End the current theme builder layout. * * @since 4.0 * * @return void */ public static function end_theme_builder_layout() { array_pop(self::$theme_builder_layout); } /** * Get the order class suffix for the current theme builder layout, if any. * * @since 4.0 * * @return string */ protected static function _get_theme_builder_order_class_suffix() { $layout_type = self::get_theme_builder_layout_type(); $type_map = array( ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE => '_tb_header', ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE => '_tb_body', ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE => '_tb_footer', ); if ( empty( $layout_type ) || ! isset( $type_map[ $layout_type ] ) ) { return ''; } return $type_map[ $layout_type ]; } protected function field_to_css_prop( $field ) { return str_replace( '_', '-', $field ); } /** * Initialize Modules Cache * * @since 3.24 */ public static function init_cache() { $cache = self::get_cache_filename(); if ( $cache && et_()->WPFS()->is_readable( $cache ) ) { // Load cache $result = @unserialize( et_()->WPFS()->get_contents( $cache ) ); if ( false !== $result ) { if ( count( $result ) < 3 ) { // Old cache format detected, delete everything et_fb_delete_builder_assets(); if ( ! file_exists ( $cache ) ) { // If cache has been successfully deleted, then init again. self::init_cache(); } return; } list ( self::$_cache, self::$_fields_unprocessed ) = $result; // Define option template variable instead of using list to avoid error that might // happen when option template file exists (theme is updated) and frontend is // accessed while static module field data hasn't been updated $cached_option_template_data = et_()->array_get( $result, '2', array() ); $cached_option_template = et_()->array_get( $result, '3', array() ); $cached_option_template_tab_slug_maps = et_()->array_get( $result, '4', array() ); // init_cache() is called really early. $template property might not be available yet if ( null === self::$option_template ) { self::$option_template = et_pb_option_template(); } // Set option template data from static cache if exist if ( is_array( $cached_option_template_data ) && ! empty( $cached_option_template_data ) ) { self::$option_template->set_data( $cached_option_template_data ); } // Set option template from static cache if exist if ( is_array( $cached_option_template ) && ! empty( $cached_option_template ) ) { self::$option_template->set_templates( $cached_option_template ); } // Set option template tab slug maps from static cache if exist if ( is_array( $cached_option_template_tab_slug_maps ) && ! empty( $cached_option_template_tab_slug_maps ) ) { self::$option_template->set_tab_slug_map( $cached_option_template_tab_slug_maps ); } // Box Shadow sets WP hooks internally so we gotta load it anyway -> #blame_george. ET_Builder_Module_Fields_Factory::get( 'BoxShadow' ); } else { // Cache couldn't be unserialized, delete the file so it will be regenerated. @unlink( $cache ); } } else if ( $cache ) { // Only save cache when a builder page is being rendered, needed because some data // (e.g. mail provider defaults) is only generated in this case, hence saving while rendering // a FE page or during AJAX call would result in cache missing data. self::$_cache = array(); add_filter( 'et_builder_modules_is_saving_cache', '__return_true' ); add_action( 'et_builder_modules_loaded', array( 'ET_Builder_Element', 'save_cache' ) ); } } /** * Get Modules cache file name. * * @param mixed $post_type When set to `false`, autodetect. * * @since 3.24 */ public static function get_cache_filename( $post_type = false ) { global $post, $et_builder_post_type; $ajax_use_cache = apply_filters( 'et_builder_ajax_use_cache', false ); if ( false === $post_type ) { if ( is_a( $post, 'WP_POST' ) ) { $post_type = $post->post_type; } else if ( $ajax_use_cache ) { $post_type = et_()->array_get( $_POST, 'et_post_type', 'page' ); } else if ( is_admin() && ! wp_doing_ajax() ) { $et_builder_post_type = $post_type = 'page'; } if ( false === $post_type ) { return false; } } $post_type = apply_filters( 'et_builder_cache_post_type', $post_type, 'modules' ); $post_type = trim( sanitize_file_name( $post_type ), '.' ); // Per language Cache due to fields data being localized. // Use user custom locale only if admin or VB/BFB $lang = is_admin() || et_fb_is_enabled() ? get_user_locale() : get_locale(); $lang = trim( sanitize_file_name( $lang ), '.' ); $prefix = 'modules'; $cache = sprintf( '%s/%s', ET_Core_PageResource::get_cache_directory(), $lang ); $files = glob( sprintf( '%s/%s-%s-*.data', $cache, $prefix, $post_type ) ); $exists = is_array( $files ) && $files; if ( $exists ) { return $files[0]; } elseif ( $ajax_use_cache ) { // Allowlisted AJAX requests aren't allowed to generate cache, only to use it. return false; } wp_mkdir_p( $cache ); // Create uniq filename $uniq = str_replace( '.', '', (string) microtime( true ) ); $file = sprintf( '%s/%s-%s-%s.data', $cache, $prefix, $post_type, $uniq ); return wp_is_writable( dirname( $file ) ) ? $file : false; } /** * Get Module cache file name's id. * * @since 3.28 * * @param mixed $post_type When set to `false`, autodetect. * * @return bool|string */ public static function get_cache_filename_id( $post_type = false ) { $filename = self::get_cache_filename( $post_type ); if ( ! is_string( $filename ) ) { return false; } preg_match( '/(?<=-)[0-9]*(?=.data)/', $filename, $matches ); return isset( $matches[0] ) ? $matches[0] : false; } public static function save_cache() { remove_filter( 'et_builder_modules_is_saving_cache', '__return_true' ); $cache = self::get_cache_filename(); if ( $cache ) { et_()->WPFS()->put_contents( $cache, serialize( array( self::$_cache, self::$_fields_unprocessed, self::$option_template->all(), self::$option_template->templates(), self::$option_template->get_tab_slug_map(), '3.0' ) ) ); } } /** * Render image element HTML * * @since 3.27.1 * * @param string $image_props Image data props key or actual image URL. * @param array $image_attrs_raw List of extra image attributes. * @param array $echo Wheter to print the image output or return it. * @param array $disable_responsive Wheter to enable the responsive image or not. * * @return string The images's HTML output. Empty string on failure. */ protected function render_image( $image_props, $image_attrs_raw = array(), $echo = true, $disable_responsive = false ) { // Bail early when the $image_props arg passed is empty. if ( ! $image_props ) { return ''; } $img_src = $image_props && is_string( $image_props ) ? self::$_->array_get( $this->props, $image_props, $image_props ) : $image_props; if ( ! $img_src ) { return ''; } if ( ! count( $image_attrs_raw ) ) { $html = sprintf( '<img src="%1$s" />', esc_url( $img_src ) ); return et_image_add_srcset_and_sizes( $html, $echo ); } $image_attrs = array(); $is_disable_responsive = $disable_responsive || ! et_is_responsive_images_enabled(); foreach ( $image_attrs_raw as $name => $value ) { // Skip src attributes key. if ( 'src' === $name ) { continue; } // Skip srcset & sizes attributes when setting is off. if ( $is_disable_responsive && in_array( $name, array( 'srcset', 'sizes' ), true ) ) { continue; } // Skip if attributes value is empty. if ( ! strlen( $value ) ) { continue; } // Format as JSON if the value is array or object. if ( is_array( $value ) || is_object( $value ) ) { $value = wp_json_encode( $value ); } // Trim extra space from attributes value. $value = trim( $value ); // Standalone attributes that act as Booleans (Numerical indexed array keys such as required, disabled, multiple). if ( is_numeric( $name ) ) { $value = et_core_esc_attr( $value, $value ); if ( ! is_wp_error( $value ) ) { $image_attrs[ $value ] = et_core_esc_previously( $value ); } } else { $value = et_core_esc_attr( $name, $value ); if ( ! is_wp_error( $value ) ) { $image_attrs[ $name ] = esc_attr( $name ) . '="' . et_core_esc_previously( $value ) . '"'; } } } $html = sprintf( '<img src="%1$s" %2$s />', esc_url( $img_src ), et_core_esc_previously( implode( ' ', $image_attrs ) ) ); if ( ! $is_disable_responsive && ! isset( $image_attrs['srcset'] ) && ! isset( $image_attrs['sizes'] ) ) { $html = et_image_add_srcset_and_sizes( $html, false ); } if ( ! $echo ) { return $html; } echo et_core_intentionally_unescaped( $html, 'html' ); } /** * Get advanced field settings exposed for layout block preview * * @since 4.3.2 * * @return array */ public static function get_layout_block_assistive_settings() { return self::$layout_block_assistive_settings; } public static function enqueue_scroll_effects_fields() { wp_localize_script( apply_filters( 'et_builder_modules_script_handle', 'et-builder-modules-script' ), 'et_pb_motion_elements', ET_Builder_Element::$_scroll_effects_fields ); } /** * Get whether the provided element content contains at least one of the * specified modules based on their slugs. * * @since 4.3.3 * * @param string $content * @param string[] $module_slugs * * @return bool */ protected static function contains( $content, $module_slugs ) { foreach ( $module_slugs as $slug ) { if ( false !== strpos( $content, '[' . $slug ) ) { return true; } } return false; } /* ================================================================================================================ * -------------------------->>> Class-level (static) deprecations begin here! <<<--------------------------------- * ================================================================================================================ */ /** * @deprecated See {@see self::get_parent_slugs_regex()} */ public static function get_parent_shortcodes( $post_type ) { $method = __METHOD__; $replacement = __CLASS__ . '::get_parent_slugs_regex()'; et_error( "You're Doing It Wrong! {$method} is deprecated. Use {$replacement} instead." ); return self::get_parent_slugs_regex( $post_type ); } /** * @deprecated See {@see self::get_child_slugs_regex()} */ public static function get_child_shortcodes( $post_type ) { $method = __METHOD__; $replacement = __CLASS__ . '::get_child_slugs_regex()'; et_error( "You're Doing It Wrong! {$method} is deprecated. Use {$replacement} instead." ); return self::get_child_slugs_regex( $post_type ); } /** * Deprecated. * * @deprecated * * @param string $post_type * @param string $mode * * @return array */ public static function get_defaults( $post_type = '', $mode = 'all' ) { et_error( "You're Doing It Wrong! " . __METHOD__ . ' is deprecated and should not be used.' ); return array(); } /** * Deprecated. * * @deprecated * * @param string $post_type * @param string $mode * * @return array */ public static function get_fields_defaults( $post_type = '', $mode = 'all' ) { et_error( "You're Doing It Wrong! " . __METHOD__ . ' is deprecated and should not be used.' ); return array(); } /** * @deprecated */ public static function get_slugs_with_children( $post_type ) { $parent_modules = self::get_parent_modules( $post_type ); $slugs = array(); foreach ( $parent_modules as $module ) { if ( ! empty( $module->child_slug ) ) { $slugs[] = sprintf( '"%1$s":"%2$s"', esc_js( $module->slug ), esc_js( $module->child_slug ) ); } } return '{' . implode( ',', $slugs ) . '}'; } /* ================================================================================================================ * ------------------------------->>> Non-static deprecations begin here! <<<-------------------------------------- * ================================================================================================================ */ /** * Determine if current request is VB Data Request by checking $_POST['action'] value * * @deprecated {@see et_builder_is_loading_vb_data()} * * @since 4.0.7 Deprecated. * * @return bool */ protected function is_loading_vb_data() { return et_builder_is_loading_data(); } /** * Determine if current request is BB Data Request by checking $_POST['action'] value * * @deprecated {@see et_builder_is_loading_bb_data()} * * @since 4.0.7 Deprecated. * * @return bool */ protected function is_loading_bb_data() { return et_builder_is_loading_data( 'bb' ); } /* NOTE: Adding a new method? New methods should be placed BEFORE deprecated methods. */ } do_action( 'et_pagebuilder_module_init' ); class ET_Builder_Module extends ET_Builder_Element {} class ET_Builder_Structure_Element extends ET_Builder_Element { public $is_structure_element = true; function wrap_settings_option( $option_output, $field, $name = '' ) { // Option template convert array field into string id; return early to prevent error if ( is_string( $field ) ) { return ''; } $field_type = ! empty( $field['type'] ) ? $field['type'] : ''; switch( $field_type ) { case 'column_settings_background' : $output = $this->generate_columns_settings_background(); $field['hover'] = 'tabs'; break; case 'column_settings_padding' : $output = $this->generate_columns_settings_padding(); break; case 'column_settings_css_fields' : $output = $this->generate_columns_settings_css_fields(); break; case 'column_settings_css' : $output = $this->generate_columns_settings_css(); break; case 'column-structure' : // column structure option is not supported in BB return ''; break; default: $depends = false; $new_depends = isset( $field['show_if'] ) || isset( $field['show_if_not'] ); if ( ! $new_depends && ( isset( $field['depends_show_if'] ) || isset( $field['depends_show_if_not'] ) ) ) { $depends = true; if ( isset( $field['depends_show_if_not'] ) ) { $depends_show_if_not = is_array( $field['depends_show_if_not'] ) ? implode( ',', $field['depends_show_if_not'] ) : $field['depends_show_if_not']; $depends_attr = sprintf( ' data-depends_show_if_not="%s"', esc_attr( $depends_show_if_not ) ); } else { $depends_attr = sprintf( ' data-depends_show_if="%s"', esc_attr( $field['depends_show_if'] ) ); } } // Overriding background color's attribute, turning it into appropriate background attributes if ( isset( $field['type'] ) && isset( $field['name' ] ) && in_array( $field['name'], array( 'background_color' ) ) ) { $field['type'] = 'background'; // Appending background class if ( isset( $field['option_class'] ) ) { $field['option_class'] .= ' et-pb-option--background'; } else { $field['option_class'] = 'et-pb-option--background'; } // Removing depends default variable which hides background color for unified background field UI $depends = false; if ( isset( $field['depends_show_if'] ) ) { unset( $field['depends_show_if'] ); } } $output = sprintf( '%6$s<div class="et-pb-option et-pb-option--%11$s%1$s%2$s%3$s%8$s%9$s%10$s%13$s"%4$s data-option_name="%12$s">%5$s</div>%7$s', ( ! empty( $field['type'] ) && 'tiny_mce' === $field['type'] ? ' et-pb-option-main-content' : '' ), $depends || $new_depends ? ' et-pb-depends' : '', ( ! empty( $field['type'] ) && 'hidden' === $field['type'] ? ' et_pb_hidden' : '' ), ( $depends ? $depends_attr : '' ), "\n\t\t\t\t" . $option_output . "\n\t\t\t", "\t", "\n\n\t\t", ( ! empty( $field['type'] ) && 'hidden' === $field['type'] ? esc_attr( sprintf( ' et-pb-option-%1$s', $field['name'] ) ) : '' ), ( ! empty( $field['option_class'] ) ? ' ' . $field['option_class'] : '' ), isset( $field['specialty_only'] ) && 'yes' === $field['specialty_only'] ? ' et-pb-specialty-only-option' : '', isset( $field['type'] ) ? esc_attr( $field['type'] ) : '', esc_attr( $field['name'] ), $new_depends ? ' et-pb-new-depends' : '' ); break; } if ( ! empty( $field['hover'] ) ) { if ( 'tabs' === $field['hover'] ) { $name = ( 'columns_background' === $name ) ? 'background_color_<%= counter %>' : $name; $this->last_hover_tab_field = $name; } $hover = $this->last_hover_tab_field; if ( $hover ) { $begin = '<div class="et-pb-option '; $pos = strpos( $output, $begin ); if ( $pos >= 0 ) { $output = substr_replace( $output, "<div data-depends_hover=\"$hover\" class=\"et-pb-option-standard et-pb-option ", $pos, strlen( $begin ) ); } } } return self::get_unique_bb_key( $output ); } function generate_column_vars_css() { $output = ''; for ( $i = 1; $i < 4; $i++ ) { $output .= sprintf( 'case %1$s : current_module_id_value = typeof et_pb_module_id_%1$s !== \'undefined\' ? et_pb_module_id_%1$s : \'\', current_module_class_value = typeof et_pb_module_class_%1$s !== \'undefined\' ? et_pb_module_class_%1$s : \'\', current_custom_css_before_value = typeof et_pb_custom_css_before_%1$s !== \'undefined\' ? et_pb_custom_css_before_%1$s : \'\', current_custom_css_main_value = typeof et_pb_custom_css_main_%1$s !== \'undefined\' ? et_pb_custom_css_main_%1$s : \'\', current_custom_css_after_value = typeof et_pb_custom_css_after_%1$s !== \'undefined\' ? et_pb_custom_css_after_%1$s : \'\'; break; ', esc_attr( $i ) ); } return $output; } function generate_column_vars_bg() { $output = ''; for ( $i = 1; $i < 4; $i++ ) { $output .= sprintf( 'case %1$s : current_value_bg = typeof et_pb_background_color_%1$s !== \'undefined\' ? et_pb_background_color_%1$s : \'\', current_value_bg_img = typeof et_pb_bg_img_%1$s !== \'undefined\' ? et_pb_bg_img_%1$s : \'\'; current_background_size_cover = typeof et_pb_background_size_%1$s !== \'undefined\' && et_pb_background_size_%1$s === \'cover\' ? \' selected="selected"\' : \'\'; current_background_size_contain = typeof et_pb_background_size_%1$s !== \'undefined\' && et_pb_background_size_%1$s === \'contain\' ? \' selected="selected"\' : \'\'; current_background_size_initial = typeof et_pb_background_size_%1$s !== \'undefined\' && et_pb_background_size_%1$s === \'initial\' ? \' selected="selected"\' : \'\'; current_background_position_topleft = typeof et_pb_background_position_%1$s !== \'undefined\' && et_pb_background_position_%1$s === \'top_left\' ? \' selected="selected"\' : \'\'; current_background_position_topcenter = typeof et_pb_background_position_%1$s !== \'undefined\' && et_pb_background_position_%1$s === \'top_center\' ? \' selected="selected"\' : \'\'; current_background_position_topright = typeof et_pb_background_position_%1$s !== \'undefined\' && et_pb_background_position_%1$s === \'top_right\' ? \' selected="selected"\' : \'\'; current_background_position_centerleft = typeof et_pb_background_position_%1$s !== \'undefined\' && et_pb_background_position_%1$s === \'center_left\' ? \' selected="selected"\' : \'\'; current_background_position_center = typeof et_pb_background_position_%1$s === \'undefined\' || et_pb_background_position_%1$s === \'center\' ? \' selected="selected"\' : \'\'; current_background_position_centerright = typeof et_pb_background_position_%1$s !== \'undefined\' && et_pb_background_position_%1$s === \'center_right\' ? \' selected="selected"\' : \'\'; current_background_position_bottomleft = typeof et_pb_background_position_%1$s !== \'undefined\' && et_pb_background_position_%1$s === \'bottom_left\' ? \' selected="selected"\' : \'\'; current_background_position_bottomcenter = typeof et_pb_background_position_%1$s !== \'undefined\' && et_pb_background_position_%1$s === \'bottom_center\' ? \' selected="selected"\' : \'\'; current_background_position_bottomright = typeof et_pb_background_position_%1$s !== \'undefined\' && et_pb_background_position_%1$s === \'bottom_right\' ? \' selected="selected"\' : \'\'; current_background_repeat_repeat = typeof et_pb_background_repeat_%1$s === \'undefined\' || et_pb_background_repeat_%1$s === \'repeat\' ? \' selected="selected"\' : \'\'; current_background_repeat_repeatx = typeof et_pb_background_repeat_%1$s !== \'undefined\' && et_pb_background_repeat_%1$s === \'repeat-x\' ? \' selected="selected"\' : \'\'; current_background_repeat_repeaty = typeof et_pb_background_repeat_%1$s !== \'undefined\' && et_pb_background_repeat_%1$s === \'repeat-y\' ? \' selected="selected"\' : \'\'; current_background_repeat_space = typeof et_pb_background_repeat_%1$s !== \'undefined\' && et_pb_background_repeat_%1$s === \'space\' ? \' selected="selected"\' : \'\'; current_background_repeat_round = typeof et_pb_background_repeat_%1$s !== \'undefined\' && et_pb_background_repeat_%1$s === \'round\' ? \' selected="selected"\' : \'\'; current_background_repeat_norepeat = typeof et_pb_background_repeat_%1$s !== \'undefined\' && et_pb_background_repeat_%1$s === \'no-repeat\' ? \' selected="selected"\' : \'\'; current_background_blend_normal = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'normal\' ? \' selected="selected"\' : \'\'; current_background_blend_multiply = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'multiply\' ? \' selected="selected"\' : \'\'; current_background_blend_screen = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'screen\' ? \' selected="selected"\' : \'\'; current_background_blend_overlay = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'overlay\' ? \' selected="selected"\' : \'\'; current_background_blend_darken = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'darken\' ? \' selected="selected"\' : \'\'; current_background_blend_lighten = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'lighten\' ? \' selected="selected"\' : \'\'; current_background_blend_colordodge = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'color-dodge\' ? \' selected="selected"\' : \'\'; current_background_blend_colorburn = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'color-burn\' ? \' selected="selected"\' : \'\'; current_background_blend_hardlight = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'hard-light\' ? \' selected="selected"\' : \'\'; current_background_blend_softlight = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'soft-light\' ? \' selected="selected"\' : \'\'; current_background_blend_difference = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'difference\' ? \' selected="selected"\' : \'\'; current_background_blend_exclusion = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'hue\' ? \' selected="selected"\' : \'\'; current_background_blend_hue = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'saturation\' ? \' selected="selected"\' : \'\'; current_background_blend_saturation = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'color\' ? \' selected="selected"\' : \'\'; current_background_blend_color = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'normal\' ? \' selected="selected"\' : \'\'; current_background_blend_luminosity = typeof et_pb_background_blend_%1$s !== \'undefined\' && et_pb_background_blend_%1$s === \'luminosity\' ? \' selected="selected"\' : \'\'; current_use_background_color_gradient = typeof et_pb_use_background_color_gradient_%1$s !== \'undefined\' && \'on\' === et_pb_use_background_color_gradient_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_start = typeof et_pb_background_color_gradient_start_%1$s !== \'undefined\' ? et_pb_background_color_gradient_start_%1$s : \'%2$s\'; current_background_color_gradient_end = typeof et_pb_background_color_gradient_end_%1$s !== \'undefined\' ? et_pb_background_color_gradient_end_%1$s : \'%3$s\'; current_background_color_gradient_type = typeof et_pb_background_color_gradient_type_%1$s !== \'undefined\' && \'radial\' === et_pb_background_color_gradient_type_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_direction = typeof et_pb_background_color_gradient_direction_%1$s !== \'undefined\' ? et_pb_background_color_gradient_direction_%1$s : \'%4$s\'; current_background_color_gradient_direction_radial_center = typeof et_pb_background_color_gradient_direction_radial_%1$s !== \'undefined\' && \'center\' === et_pb_background_color_gradient_direction_radial_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_direction_radial_top_left = typeof et_pb_background_color_gradient_direction_radial_%1$s !== \'undefined\' && \'top left\' === et_pb_background_color_gradient_direction_radial_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_direction_radial_top = typeof et_pb_background_color_gradient_direction_radial_%1$s !== \'undefined\' && \'top\' === et_pb_background_color_gradient_direction_radial_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_direction_radial_top_right = typeof et_pb_background_color_gradient_direction_radial_%1$s !== \'undefined\' && \'top right\' === et_pb_background_color_gradient_direction_radial_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_direction_radial_right = typeof et_pb_background_color_gradient_direction_radial_%1$s !== \'undefined\' && \'right\' === et_pb_background_color_gradient_direction_radial_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_direction_radial_bottom_right = typeof et_pb_background_color_gradient_direction_radial_%1$s !== \'undefined\' && \'bottom right\' === et_pb_background_color_gradient_direction_radial_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_direction_radial_bottom = typeof et_pb_background_color_gradient_direction_radial_%1$s !== \'undefined\' && \'bottom\' === et_pb_background_color_gradient_direction_radial_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_direction_radial_bottom_left = typeof et_pb_background_color_gradient_direction_radial_%1$s !== \'undefined\' && \'bottom left\' === et_pb_background_color_gradient_direction_radial_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_direction_radial_left = typeof et_pb_background_color_gradient_direction_radial_%1$s !== \'undefined\' && \'left\' === et_pb_background_color_gradient_direction_radial_%1$s ? \' selected="selected"\' : \'\'; current_background_color_gradient_start_position = typeof et_pb_background_color_gradient_start_position_%1$s !== \'undefined\' ? et_pb_background_color_gradient_start_position_%1$s : \'%5$s\'; current_background_color_gradient_end_position = typeof et_pb_background_color_gradient_end_position_%1$s !== \'undefined\' ? et_pb_background_color_gradient_end_position_%1$s : \'%6$s\'; current_background_color_gradient_overlays_image = typeof et_pb_background_color_gradient_overlays_image_%1$s !== \'undefined\' && \'on\' === et_pb_background_color_gradient_overlays_image_%1$s ? \' selected="selected"\' : \'\'; current_background_video_mp4 = typeof et_pb_background_video_mp4_%1$s !== \'undefined\' ? et_pb_background_video_mp4_%1$s : \'\'; current_background_video_webm = typeof et_pb_background_video_webm_%1$s !== \'undefined\' ? et_pb_background_video_webm_%1$s : \'\'; current_background_video_width = typeof et_pb_background_video_width_%1$s !== \'undefined\' ? et_pb_background_video_width_%1$s : \'\'; current_background_video_height = typeof et_pb_background_video_height_%1$s !== \'undefined\' ? et_pb_background_video_height_%1$s : \'\'; current_allow_played_pause = typeof et_pb_allow_player_pause_%1$s !== \'undefined\' && \'on\' === et_pb_allow_player_pause_%1$s ? \' selected="selected"\' : \'\'; current_background_video_pause_outside_viewport = typeof et_pb_background_video_pause_outside_viewport_%1$s !== \'undefined\' && \'off\' === et_pb_background_video_pause_outside_viewport_%1$s ? \' selected="selected"\' : \'\'; current_value_parallax = typeof et_pb_parallax_%1$s !== \'undefined\' && \'on\' === et_pb_parallax_%1$s ? \' selected="selected"\' : \'\'; current_value_parallax_method = typeof et_pb_parallax_method_%1$s !== \'undefined\' && \'on\' !== et_pb_parallax_method_%1$s ? \' selected="selected"\' : \'\'; break; ', esc_attr( $i ), esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_start' ) ), esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_end' ) ), esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_direction' ) ), esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_start_position' ) ), // #5 esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_end_position' ) ) ); } return $output; } function generate_column_vars_padding() { $output = ''; for ( $i = 1; $i < 4; $i++ ) { $output .= sprintf( 'case %1$s : current_value_pt = typeof et_pb_padding_top_%1$s !== \'undefined\' ? et_pb_padding_top_%1$s : \'\', current_value_pr = typeof et_pb_padding_right_%1$s !== \'undefined\' ? et_pb_padding_right_%1$s : \'\', current_value_pb = typeof et_pb_padding_bottom_%1$s !== \'undefined\' ? et_pb_padding_bottom_%1$s : \'\', current_value_pl = typeof et_pb_padding_left_%1$s !== \'undefined\' ? et_pb_padding_left_%1$s : \'\', current_value_padding_tablet = typeof et_pb_padding_%1$s_tablet !== \'undefined\' ? et_pb_padding_%1$s_tablet : \'\', current_value_padding_phone = typeof et_pb_padding_%1$s_phone !== \'undefined\' ? et_pb_padding_%1$s_phone : \'\', last_edited_padding_field = typeof et_pb_padding_%1$s_last_edited !== \'undefined\' ? et_pb_padding_%1$s_last_edited : \'\', has_tablet_padding = typeof et_pb_padding_%1$s_tablet !== \'undefined\' ? \'yes\' : \'no\', has_phone_padding = typeof et_pb_padding_%1$s_phone !== \'undefined\' ? \'yes\' : \'no\'; break; ', esc_attr( $i ) ); } return $output; } function generate_columns_settings_background() { $output = sprintf( '<%% var columns = typeof columns_layout !== \'undefined\' ? columns_layout.split(",") : [], counter = 1; _.each( columns, function ( column_type ) { var current_value_bg, current_value_bg_img, current_value_parallax, current_value_parallax_method, current_background_size_cover, current_background_size_contain, current_background_size_initial, current_background_position_topleft, current_background_position_topcenter, current_background_position_topright, current_background_position_centerleft, current_background_position_center, current_background_position_centerright, current_background_position_bottomleft, current_background_position_bottomcenter, current_background_position_bottomright, current_background_repeat_repeat, current_background_repeat_repeatx, current_background_repeat_repeaty, current_background_repeat_space, current_background_repeat_round, current_background_repeat_norepeat, current_background_blend_normal, current_background_blend_multiply, current_background_blend_screen, current_background_blend_overlay, current_background_blend_darken, current_background_blend_lighten, current_background_blend_colordodge, current_background_blend_colorburn, current_background_blend_hardlight, current_background_blend_softlight, current_background_blend_difference, current_background_blend_exclusion, current_background_blend_hue, current_background_blend_saturation, current_background_blend_color, current_background_blend_luminosity, current_use_background_color_gradient, current_background_color_gradient_start, current_background_color_gradient_end, current_background_color_gradient_type, current_background_color_gradient_direction, current_background_color_gradient_direction_radial_center, current_background_color_gradient_direction_radial_top_left, current_background_color_gradient_direction_radial_top, current_background_color_gradient_direction_radial_top_right, current_background_color_gradient_direction_radial_right, current_background_color_gradient_direction_radial_bottom_right, current_background_color_gradient_direction_radial_bottom, current_background_color_gradient_direction_radial_bottom_left, current_background_color_gradient_direction_radial_left, current_background_color_gradient_start_position, current_background_color_gradient_end_position, current_background_color_gradient_overlays_image, current_background_video_mp4, current_background_video_webm, current_background_video_width, current_background_video_height, current_allow_played_pause, current_background_video_pause_outside_viewport; switch ( counter ) { %1$s } %%>', $this->generate_column_vars_bg() ); $tab_navs = sprintf( '<ul class="et_pb_background-tab-navs"> <li> <a href="#" class="et_pb_background-tab-nav et_pb_background-tab-nav--color" data-tab="color" title="%1$s"> %5$s </a> </li><li> <a href="#" class="et_pb_background-tab-nav et_pb_background-tab-nav--gradient" data-tab="gradient" title="%2$s"> %6$s </a> </li><li> <a href="#" class="et_pb_background-tab-nav et_pb_background-tab-nav--image" data-tab="image" title="%3$s"> %7$s </a> </li><li> <a href="#" class="et_pb_background-tab-nav et_pb_background-tab-nav--video" data-tab="video" title="%4$s"> %8$s </a> </li> </ul>', et_builder_i18n( 'Color' ), esc_html__( 'Gradient', 'et_builder' ), et_builder_i18n( 'Image' ), esc_html__( 'Video', 'et_builder' ), $this->get_icon( 'background-color' ), $this->get_icon( 'background-gradient' ), $this->get_icon( 'background-image' ), $this->get_icon( 'background-video' ) ); $tab_color = sprintf( '<div class="et_pb_background-tab et_pb_background-tab--color" data-tab="color"> <div class="et_pb_background-option et_pb_background-option--background_color et-pb-option et-pb-option--background_color et-pb-option--has-preview"> <label for="et_pb_background_color">%1$s: </label> <div class="et-pb-option-container et-pb-option-container--color-alpha"> <div class="et-pb-option-preview et-pb-option-preview--empty"> <button class="et-pb-option-preview-button et-pb-option-preview-button--add"> %2$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--edit"> %3$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--delete"> %4$s </button> </div> <input id="et_pb_background_color_<%%= counter %%>" class="et-pb-color-picker-hex et-pb-color-picker-hex-alpha et-pb-color-picker-hex-has-preview" type="text" data-alpha="true" placeholder="%5$s" data-selected-value="" value="<%%= current_value_bg %%>"> </div> </div> </div>', esc_html__( 'Background Color', 'et_builder' ), $this->get_icon( 'add' ), $this->get_icon( 'setting' ), $this->get_icon( 'delete' ), esc_html__( 'Hex Value', 'et_builder' ) ); $tab_gradient = sprintf( '<div class="et_pb_background-tab et_pb_background-tab--gradient" data-tab="gradient"> <div class="et-pb-option-preview et-pb-option-preview--empty"> <button class="et-pb-option-preview-button et-pb-option-preview-button--add"> %1$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--swap"> %2$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--delete"> %3$s </button> </div> <div class="et_pb_background-option et_pb_background-option--use_background_color_gradient et_pb_background-template--use_color_gradient et-pb-option et-pb-option--use_background_color_gradient"> <label for="et_pb_use_background_color_gradient_<%%= counter %%>">%4$s: </label> <div class="et-pb-option-container et-pb-option-container--yes_no_button"> <div class="et_pb_yes_no_button_wrapper "> <div class="et_pb_yes_no_button et_pb_off_state"> <span class="et_pb_value_text et_pb_on_value">%5$s</span> <span class="et_pb_button_slider"></span> <span class="et_pb_value_text et_pb_off_value">%6$s</span> </div> <select name="et_pb_use_background_color_gradient_<%%= counter %%>" id="et_pb_use_background_color_gradient_<%%= counter %%>" class="et-pb-main-setting regular-text et-pb-affects" data-affects="background_color_gradient_start_<%%= counter %%>, background_color_gradient_end_<%%= counter %%>, background_color_gradient_start_position_<%%= counter %%>, background_color_gradient_end_position_<%%= counter %%>, background_color_gradient_type_<%%= counter %%>, background_color_gradient_overlays_image_<%%= counter %%>" data-default="off"> <option value="off">%6$s</option> <option value="on" <%%= current_use_background_color_gradient %%>>%5$s</option> </select> </div><span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_color_gradient_start et_pb_background-template--color_gradient_start et-pb-option et-pb-option--background_color_gradient_start" data-depends_show_if="on"> <label for="et_pb_background_color_gradient_start_<%%= counter %%>">%7$s: </label> <div class="et-pb-option-container et-pb-option-container--color-alpha"> <div class="wp-picker-container"> <input id="et_pb_background_color_gradient_start_<%%= counter %%>" class="et-pb-color-picker-hex et-pb-color-picker-hex-alpha et-pb-main-setting" type="text" data-alpha="true" placeholder="%8$s" data-selected-value="<%%= current_background_color_gradient_start %%>" value="<%%= current_background_color_gradient_start %%>" data-default-color="%26$s" data-default="%26$s"> </div> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_color_gradient_end et_pb_background-template--color_gradient_end et-pb-option et-pb-option--background_color_gradient_end" data-depends_show_if="on"> <label for="et_pb_background_color_gradient_end_<%%= counter %%>">%9$s: </label> <div class="et-pb-option-container et-pb-option-container--color-alpha"> <div class="wp-picker-container"> <input id="et_pb_background_color_gradient_end_<%%= counter %%>" class="et-pb-color-picker-hex et-pb-color-picker-hex-alpha et-pb-main-setting" type="text" data-alpha="true" placeholder="%8$s" data-selected-value="<%%= current_background_color_gradient_end %%>" value="<%%= current_background_color_gradient_end %%>" data-default-color="%27$s" data-default="%27$s"> </div> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_color_gradient_type et_pb_background-template--color_gradient_type et-pb-option et-pb-option--background_color_gradient_type" data-depends_show_if="on"> <label for="et_pb_background_color_gradient_type_<%%= counter %%>">%10$s: </label> <div class="et-pb-option-container et-pb-option-container--select"> <select name="et_pb_background_color_gradient_type_<%%= counter %%>" id="et_pb_background_color_gradient_type_<%%= counter %%>" class="et-pb-main-setting et-pb-affects" data-affects="background_color_gradient_direction_<%%= counter %%>, background_color_gradient_direction_radial_<%%= counter %%>" data-default="linear"> <option value="linear">%11$s</option> <option value="radial" <%%= current_background_color_gradient_type %%>>%12$s</option> </select> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_color_gradient_direction et_pb_background-template--color_gradient_direction et-pb-option et-pb-option--background_color_gradient_direction" data-depends_show_if="linear"> <label for="et_pb_background_color_gradient_direction_<%%= counter %%>">%13$s: </label> <div class="et-pb-option-container et-pb-option-container--range"> <input type="range" class="et-pb-main-setting et-pb-range et-pb-fixed-range" data-default="180" value="<%%= current_background_color_gradient_direction %%>" min="0" max="360" step="1"> <input id="et_pb_background_color_gradient_direction_<%%= counter %%>" type="text" class="regular-text et-pb-validate-unit et-pb-range-input" value="<%%= current_background_color_gradient_direction %%>" data-default="180deg"> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_color_gradient_direction_radial et_pb_background-template--color_gradient_direction_radial et-pb-option et-pb-option--background_color_gradient_direction_radial" data-depends_show_if="radial"> <label for="et_pb_background_color_gradient_direction_radial_<%%= counter %%>">%14$s: </label> <div class="et-pb-option-container et-pb-option-container--select"> <select name="et_pb_background_color_gradient_direction_radial_<%%= counter %%>" id="et_pb_background_color_gradient_direction_radial_<%%= counter %%>" class="et-pb-main-setting" data-default="center"> <option value="center" <%%= current_background_color_gradient_direction_radial_center %%>>%15$s</option> <option value="top left" <%%= current_background_color_gradient_direction_radial_top_left %%>>%16$s</option> <option value="top" <%%= current_background_color_gradient_direction_radial_top %%>>%17$s</option> <option value="top right" <%%= current_background_color_gradient_direction_radial_top_right %%>>%18$s</option> <option value="right" <%%= current_background_color_gradient_direction_radial_right %%>>%19$s</option> <option value="bottom right" <%%= current_background_color_gradient_direction_radial_bottom_right %%>>%20$s</option> <option value="bottom" <%%= current_background_color_gradient_direction_radial_bottom %%>>%21$s</option> <option value="bottom left" <%%= current_background_color_gradient_direction_radial_bottom_left %%>>%22$s</option> <option value="left" <%%= current_background_color_gradient_direction_radial_left %%>>%23$s</option> </select> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_color_gradient_start_position et_pb_background-template--color_gradient_start_position et-pb-option et-pb-option--background_color_gradient_start_position" data-depends_show_if="on"> <label for="et_pb_background_color_gradient_start_position_<%%= counter %%>">%24$s: </label> <div class="et-pb-option-container et-pb-option-container--range"> <input type="range" class="et-pb-main-setting et-pb-range et-pb-fixed-range" data-default="0" value="<%%= parseInt( current_background_color_gradient_start_position.trim() ) %%>" min="0" max="100" step="1"> <input id="et_pb_background_color_gradient_start_position_<%%= counter %%>" type="text" class="regular-text et-pb-validate-unit et-pb-range-input" value="<%%= current_background_color_gradient_start_position %%>" data-default="0%%"> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_color_gradient_end_position et_pb_background-template--color_gradient_end_position et-pb-option et-pb-option--background_color_gradient_end_position" data-depends_show_if="on"> <label for="et_pb_background_color_gradient_end_position_<%%= counter %%>">%25$s: </label> <div class="et-pb-option-container et-pb-option-container--range"> <input type="range" class="et-pb-main-setting et-pb-range et-pb-fixed-range" data-default="100" value="<%%= parseInt( current_background_color_gradient_end_position.trim() ) %%>" min="0" max="100" step="1"> <input id="et_pb_background_color_gradient_end_position_<%%= counter %%>" type="text" class="regular-text et-pb-validate-unit et-pb-range-input" value="<%%= current_background_color_gradient_end_position %%>" data-default="100%%"> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_color_gradient_overlays_image et_pb_background-template--use_color_gradient et-pb-option et-pb-option--background_color_gradient_overlays_image"> <label for="et_pb_background_color_gradient_overlays_image_<%%= counter %%>">%35$s: </label> <div class="et-pb-option-container et-pb-option-container--yes_no_button"> <div class="et_pb_yes_no_button_wrapper "> <div class="et_pb_yes_no_button et_pb_off_state"> <span class="et_pb_value_text et_pb_on_value">%5$s</span> <span class="et_pb_button_slider"></span> <span class="et_pb_value_text et_pb_off_value">%6$s</span> </div> <select name="et_pb_background_color_gradient_overlays_image_<%%= counter %%>" id="et_pb_background_color_gradient_overlays_image_<%%= counter %%>" class="et-pb-main-setting regular-text" data-depends_show_if="on" data-default="off"> <option value="off">%6$s</option> <option value="on" <%%= current_background_color_gradient_overlays_image %%>>%5$s</option> </select> </div><span class="et-pb-reset-setting"></span> </div> </div> </div>', $this->get_icon( 'add' ), $this->get_icon( 'swap' ), $this->get_icon( 'delete' ), esc_html__( 'Background Gradient', 'et_builder' ), et_builder_i18n( 'On' ), // #5 et_builder_i18n( 'Off' ), esc_html__( 'Gradient Start', 'et_builder' ), esc_html__( 'Hex Value', 'et_builder' ), esc_html__( 'Gradient End', 'et_builder' ), esc_html__( 'Gradient Type', 'et_builder' ), // #10 et_builder_i18n( 'Linear' ), et_builder_i18n( 'Radial' ), esc_html__( 'Gradient Direction', 'et_builder' ), esc_html__( 'Radial Direction', 'et_builder' ), et_builder_i18n( 'Center' ), // #15 et_builder_i18n( 'Top Left' ), et_builder_i18n( 'Top' ), et_builder_i18n( 'Top Right' ), et_builder_i18n( 'Right' ), et_builder_i18n( 'Bottom Right' ), // #20 et_builder_i18n( 'Bottom' ), et_builder_i18n( 'Bottom Left' ), et_builder_i18n( 'Left' ), esc_html__( 'Start Position', 'et_builder' ), esc_html__( 'End Position', 'et_builder' ), // #25 esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_start' ) ), esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_end' ) ), esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_type' ) ), esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_direction' ) ), esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_direction_radial' ) ), // #30 esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_start_position' ) ), esc_attr( intval( ET_Global_Settings::get_value( 'all_background_gradient_start_position' ) ) ), esc_attr( ET_Global_Settings::get_value( 'all_background_gradient_end_position' ) ), esc_attr( intval( ET_Global_Settings::get_value( 'all_background_gradient_end_position' ) ) ), esc_html__( 'Place Gradient Above Background Image', 'et_builder' ) // #35 ); $select_background_size = sprintf( '<select name="et_pb_background_size_<%%= counter %%>" id="et_pb_background_size_<%%= counter %%>" class="et-pb-main-setting" data-default="cover"> <option value="cover"<%%= current_background_size_cover %%>>%1$s</option> <option value="contain"<%%= current_background_size_contain %%>>%2$s</option> <option value="initial"<%%= current_background_size_initial %%>>%3$s</option> </select>', esc_html__( 'Cover', 'et_builder' ), esc_html__( 'Fit', 'et_builder' ), esc_html__( 'Actual Size', 'et_builder' ) ); $select_background_position = sprintf( '<select name="et_pb_background_position_<%%= counter %%>" id="et_pb_background_position_<%%= counter %%>" class="et-pb-main-setting" data-default="center"> <option value="top_left"<%%= current_background_position_topleft %%>>%1$s</option> <option value="top_center"<%%= current_background_position_topcenter %%>>%2$s</option> <option value="top_right"<%%= current_background_position_topright %%>>%3$s</option> <option value="center_left"<%%= current_background_position_centerleft %%>>%4$s</option> <option value="center"<%%= current_background_position_center %%>>%5$s</option> <option value="center_right"<%%= current_background_position_centerright %%>>%6$s</option> <option value="bottom_left"<%%= current_background_position_bottomleft %%>>%7$s</option> <option value="bottom_center"<%%= current_background_position_bottomcenter %%>>%8$s</option> <option value="bottom_right"<%%= current_background_position_bottomright %%>>%9$s</option> </select>', et_builder_i18n( 'Top Left' ), et_builder_i18n( 'Top Center' ), et_builder_i18n( 'Top Right' ), et_builder_i18n( 'Center Left' ), et_builder_i18n( 'Center' ), et_builder_i18n( 'Center Right' ), et_builder_i18n( 'Bottom Left' ), et_builder_i18n( 'Bottom Center' ), et_builder_i18n( 'Bottom Right' ) ); $select_background_repeat = sprintf( '<select name="et_pb_background_repeat_<%%= counter %%>" id="et_pb_background_repeat_<%%= counter %%>" class="et-pb-main-setting" data-default="repeat"> <option value="no-repeat"<%%= current_background_repeat_norepeat %%>>%1$s</option> <option value="repeat"<%%= current_background_repeat_repeat %%>>%2$s</option> <option value="repeat-x"<%%= current_background_repeat_repeatx %%>>%3$s</option> <option value="repeat-y"<%%= current_background_repeat_repeaty %%>>%4$s</option> <option value="space"<%%= current_background_repeat_space %%>>%5$s</option> <option value="round"<%%= current_background_repeat_round %%>>%6$s</option> </select>', esc_html__( 'No Repeat', 'et_builder' ), esc_html__( 'Repeat', 'et_builder' ), esc_html__( 'Repeat X (horizontal)', 'et_builder' ), esc_html__( 'Repeat Y (vertical)', 'et_builder' ), et_builder_i18n( 'Space' ), esc_html__( 'Round', 'et_builder' ) ); $select_background_blend = sprintf( '<select name="et_pb_background_blend_<%%= counter %%>" id="et_pb_background_blend_<%%= counter %%>" class="et-pb-main-setting" data-default="normal"> <option value="normal"<%%= current_background_blend_normal %%>>%1$s</option> <option value="multiply"<%%= current_background_blend_multiply %%>>%2$s</option> <option value="screen"<%%= current_background_blend_screen %%>>%3$s</option> <option value="overlay"<%%= current_background_blend_overlay %%>>%4$s</option> <option value="darken"<%%= current_background_blend_darken %%>>%5$s</option> <option value="lighten"<%%= current_background_blend_lighten %%>>%6$s</option> <option value="color-dodge"<%%= current_background_blend_colordodge %%>>%7$s</option> <option value="color-burn"<%%= current_background_blend_colorburn %%>>%8$s</option> <option value="hard-light"<%%= current_background_blend_hardlight %%>>%9$s</option> <option value="soft-light"<%%= current_background_blend_softlight %%>>%10$s</option> <option value="difference"<%%= current_background_blend_difference %%>>%11$s</option> <option value="exclusion"<%%= current_background_blend_exclusion %%>>%12$s</option> <option value="hue"<%%= current_background_blend_hue %%>>%13$s</option> <option value="saturation"<%%= current_background_blend_saturation %%>>%14$s</option> <option value="color"<%%= current_background_blend_color %%>>%15$s</option> <option value="luminosity"<%%= current_background_blend_luminosity %%>>%16$s</option> </select>', et_builder_i18n( 'Normal' ), et_builder_i18n( 'Multiply' ), et_builder_i18n( 'Screen' ), et_builder_i18n( 'Overlay' ), et_builder_i18n( 'Darken' ), et_builder_i18n( 'Lighten' ), et_builder_i18n( 'Color Dodge' ), et_builder_i18n( 'Color Burn' ), et_builder_i18n( 'Hard Light' ), et_builder_i18n( 'Soft Light' ), et_builder_i18n( 'Difference' ), et_builder_i18n( 'Exclusion' ), et_builder_i18n( 'Hue' ), et_builder_i18n( 'Saturation' ), et_builder_i18n( 'Color' ), et_builder_i18n( 'Luminosity' ) ); $tab_image = sprintf( '<div class="et_pb_background-tab et_pb_background-tab--image" data-tab="image"> <div class="et_pb_background-option et_pb_background-option--background_image et-pb-option et-pb-option--background_image et-pb-option--has-preview"> <label for="et_pb_bg_img_<%%= counter %%>">%1$s: </label> <div class="et-pb-option-container et-pb-option-container--upload"> <div class="et-pb-option-preview et-pb-option-preview--empty"> <button class="et-pb-option-preview-button et-pb-option-preview-button--add"> %2$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--edit"> %3$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--delete"> %4$s </button> </div> <input id="et_pb_bg_img_<%%= counter %%>" type="text" class="et-pb-main-setting regular-text et-pb-upload-field" value="<%%= current_value_bg_img %%>"> <input type="button" class="button button-upload et-pb-upload-button" value="%5$s" data-choose="%6$s" data-update="%7$s" data-type="image"> <span class="et-pb-reset-setting" style="display: none;"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--parallax et_pb_background-template--parallax et-pb-option et-pb-option--parallax"> <label for="et_pb_parallax_<%%= counter %%>">%8$s: </label> <div class="et-pb-option-container et-pb-option-container--yes_no_button"> <div class="et_pb_yes_no_button_wrapper "> <div class="et_pb_yes_no_button et_pb_off_state"> <span class="et_pb_value_text et_pb_on_value">%9$s</span> <span class="et_pb_button_slider"></span> <span class="et_pb_value_text et_pb_off_value">%10$s</span> </div> <select name="et_pb_parallax_<%%= counter %%>" id="et_pb_parallax_<%%= counter %%>" class="et-pb-main-setting regular-text et-pb-affects" data-affects="parallax_method_<%%= counter %%>, background_size_<%%= counter %%>, background_position_<%%= counter %%>, background_repeat_<%%= counter %%>, background_blend_<%%= counter %%>" data-default="off"> <option value="off">%10$s</option> <option value="on" <%%= current_value_parallax %%>>%9$s</option> </select> </div><span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--parallax_method et_pb_background-template--parallax_method et-pb-option et-pb-option--parallax_method" data-depends_show_if="on"> <label for="et_pb_parallax_method_<%%= counter %%>">%11$s: </label> <div class="et-pb-option-container et-pb-option-container--select"> <select name="et_pb_parallax_method_<%%= counter %%>" id="et_pb_parallax_method_<%%= counter %%>" class="et-pb-main-setting" data-default="on"> <option value="on">%12$s</option> <option value="off" <%%= current_value_parallax_method %%>>%13$s</option> </select> <span class="et-pb-reset-setting" style="display: none;"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_size et_pb_background-template--size et-pb-option et-pb-option--background_size" data-depends_show_if="off" data-option_name="background_size"> <label for="et_pb_background_size">%14$s:</label> <div class="et-pb-option-container et-pb-option-container--select"> %15$s </div> </div> <div class="et_pb_background-option et_pb_background-option--background_position et_pb_background-template--position et-pb-option et-pb-option--background_position" data-depends_show_if="off" data-option_name="background_position"> <label for="et_pb_background_position">%16$s:</label> <div class="et-pb-option-container et-pb-option-container--select"> %17$s </div> </div> <div class="et_pb_background-option et_pb_background-option--background_repeat et_pb_background-template--repeat et-pb-option et-pb-option--background_repeat" data-depends_show_if="off" data-option_name="background_repeat"> <label for="et_pb_background_repeat">%18$s:</label> <div class="et-pb-option-container et-pb-option-container--select"> %19$s </div> </div> <div class="et_pb_background-option et_pb_background-option--background_blend et_pb_background-template--blend et-pb-option et-pb-option--background_blend" data-depends_show_if="off" data-option_name="background_blend"> <label for="et_pb_background_blend">%20$s: </label> <div class="et-pb-option-container et-pb-option-container--select"> %21$s </div> </div> </div>', esc_html__( 'Background Image', 'et_builder' ), $this->get_icon( 'add' ), $this->get_icon( 'setting' ), $this->get_icon( 'delete' ), et_builder_i18n( 'Upload an image' ), // #5 esc_html__( 'Choose a Background Image', 'et_builder' ), esc_html__( 'Set As Background', 'et_builder' ), esc_html__( 'Use Parallax Effect', 'et_builder' ), et_builder_i18n( 'On' ), et_builder_i18n( 'Off' ), // #10 esc_html__( 'Parallax Method', 'et_builder' ), esc_html__( 'True Parallax', 'et_builder' ), esc_html__( 'CSS', 'et_builder' ), esc_html__( 'Background Image Size', 'et_builder' ), $select_background_size, // #15 esc_html__( 'Background Image Position', 'et_builder' ), $select_background_position, esc_html__( 'Background Image Repeat', 'et_builder' ), $select_background_repeat, esc_html__( 'Background Image Blend', 'et_builder' ), // #20 $select_background_blend ); $tab_video = sprintf( '<div class="et_pb_background-tab et_pb_background-tab--video" data-tab="video"> <div class="et_pb_background-option et_pb_background-option--background_video_mp4 et_pb_background-template--video_mp4 et-pb-option et-pb-option--background_video_mp4 et-pb-option--has-preview"> <label for="et_pb_background_video_mp4_<%%= counter %%>">%1$s: </label> <div class="et-pb-option-container et-pb-option-container--upload"> <div class="et-pb-option-preview et-pb-option-preview--empty"> <button class="et-pb-option-preview-button et-pb-option-preview-button--add"> %2$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--edit"> %3$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--delete"> %4$s </button> </div> <input id="et_pb_background_video_mp4_<%%= counter %%>" type="text" class="et-pb-main-setting regular-text et-pb-upload-field" value="<%%= current_background_video_mp4 %%>"> <input type="button" class="button button-upload et-pb-upload-button" value="%5$s" data-choose="%6$s" data-update="%7$s" data-type="video"> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_video_webm et_pb_background-template--video_webm et-pb-option et-pb-option--background_video_webm et-pb-option--has-preview"> <label for="et_pb_background_video_webm_<%%= counter %%>">%8$s: </label> <div class="et-pb-option-container et-pb-option-container--upload"> <div class="et-pb-option-preview et-pb-option-preview--empty"> <button class="et-pb-option-preview-button et-pb-option-preview-button--add"> %2$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--edit"> %3$s </button> <button class="et-pb-option-preview-button et-pb-option-preview-button--delete"> %4$s </button> </div> <input id="et_pb_background_video_webm_<%%= counter %%>" type="text" class="et-pb-main-setting regular-text et-pb-upload-field" value="<%%= current_background_video_webm %%>"> <input type="button" class="button button-upload et-pb-upload-button" value="%5$s" data-choose="%9$s" data-update="%7$s" data-type="video"> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_video_width et_pb_background-template--video_width et-pb-option et-pb-option--background_video_width"> <label for="et_pb_background_video_width_<%%= counter %%>">%10$s: </label> <div class="et-pb-option-container et-pb-option-container--text"> <input id="et_pb_background_video_width_<%%= counter %%>" type="text" class="regular-text et-pb-main-setting" value="<%%= current_background_video_width %%>"> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_video_height et_pb_background-template--video_height et-pb-option et-pb-option--background_video_height"> <label for="et_pb_background_video_height_<%%= counter %%>">%11$s: </label> <div class="et-pb-option-container et-pb-option-container--text"> <input id="et_pb_background_video_height_<%%= counter %%>" type="text" class="regular-text et-pb-main-setting" value="<%%= current_background_video_height %%>"> <span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--allow_player_pause et_pb_background-template--allow_player_pause et-pb-option et-pb-option--allow_player_pause"> <label for="et_pb_allow_player_pause_<%%= counter %%>">%12$s: </label> <div class="et-pb-option-container et-pb-option-container--yes_no_button"> <div class="et_pb_yes_no_button_wrapper "> <div class="et_pb_yes_no_button et_pb_off_state"> <span class="et_pb_value_text et_pb_on_value">%13$s</span> <span class="et_pb_button_slider"></span> <span class="et_pb_value_text et_pb_off_value">%14$s</span> </div> <select name="et_pb_allow_player_pause_<%%= counter %%>" id="et_pb_allow_player_pause_<%%= counter %%>" class="et-pb-main-setting regular-text" data-default="off"> <option value="off">%14$s</option> <option value="on" <%%= current_allow_played_pause %%>>%13$s</option> </select> </div><span class="et-pb-reset-setting"></span> </div> </div> <div class="et_pb_background-option et_pb_background-option--background_video_pause_outside_viewport et_pb_background-template--background_video_pause_outside_viewport et-pb-option et-pb-option--background_video_pause_outside_viewport"> <label for="et_pb_background_video_pause_outside_viewport_<%%= counter %%>">%15$s: </label> <div class="et-pb-option-container et-pb-option-container--yes_no_button"> <div class="et_pb_yes_no_button_wrapper "> <div class="et_pb_yes_no_button et_pb_off_state"> <span class="et_pb_value_text et_pb_on_value">%13$s</span> <span class="et_pb_button_slider"></span> <span class="et_pb_value_text et_pb_off_value">%14$s</span> </div> <select name="et_pb_background_video_pause_outside_viewport_<%%= counter %%>" id="et_pb_background_video_pause_outside_viewport_<%%= counter %%>" class="et-pb-main-setting regular-text" data-default="on"> <option value="on">%13$s</option> <option value="off" <%%= current_background_video_pause_outside_viewport %%>>%14$s</option> </select> </div><span class="et-pb-reset-setting"></span> </div> </div> </div>', esc_html__( 'Background Video MP4', 'et_builder' ), $this->get_icon( 'add' ), $this->get_icon( 'setting' ), $this->get_icon( 'delete' ), esc_html__( 'Upload a video', 'et_builder' ), // #5 esc_html__( 'Choose a Background Video MP4 File', 'et_builder' ), esc_html__( 'Set As Background Video', 'et_builder' ), esc_html__( 'Background Video Webm', 'et_builder' ), esc_html__( 'Choose a Background Video WEBM File', 'et_builder' ), esc_html__( 'Background Video Width', 'et_builder' ), // #10 esc_html__( 'Background Video Height', 'et_builder' ), esc_html__( 'Pause Video When Another Video Plays', 'et_builder' ), et_builder_i18n( 'On' ), et_builder_i18n( 'Off' ), esc_html__( 'Pause Video While Not In View', 'et_builder' ) // #15 ); $output .= sprintf( '<div class="et_pb_subtoggle_section"> <div class="et-pb-option-toggle-content"> <div class="et-pb-option et-pb-option--background" data-option_name="background_color_<%%= counter %%>"> <label for="et_pb_background"> %1$s <%% if ( "4_4" !== column_type ) { %%> <%%= counter + " " %%> <%% } %%> %2$s: </label> <div class="et-pb-option-container et-pb-option-container-inner et-pb-option-container--background" data-column-index="<%%= counter %%>" data-base_name="background"> %3$s %4$s %5$s %6$s %7$s </div> </div> </div> </div> <%% counter++; }); %%>', esc_html__( 'Column', 'et_builder' ), et_builder_i18n( 'Background' ), $tab_navs, $tab_color, $tab_gradient, // #5 $tab_image, $tab_video ); return $output; } function generate_columns_settings_padding() { $output = sprintf( '<%% var columns = typeof columns_layout !== \'undefined\' ? columns_layout.split(",") : [], counter = 1; _.each( columns, function ( column_type ) { var current_value_pt, current_value_pr, current_value_pb, current_value_pl, current_value_padding_tablet, current_value_padding_phone, has_tablet_padding, has_phone_padding; switch ( counter ) { %1$s } %%>', $this->generate_column_vars_padding() ); $output .= sprintf( '<div class="et_pb_subtoggle_section"> <div class="et-pb-option-toggle-content"> <div class="et-pb-option"> <label for="et_pb_padding_<%%= counter %%>"> %1$s <%% if ( "4_4" !== column_type ) { %%> <%%= counter + " " %%> <%% } %%> %2$s: </label> <div class="et-pb-option-container"> %7$s <div class="et_margin_padding"> <label> %3$s <input type="text" class="medium-text et_custom_margin et_custom_margin_top et-pb-validate-unit et_pb_setting_mobile et_pb_setting_mobile_desktop et_pb_setting_mobile_active" id="et_pb_padding_top_<%%= counter %%>" name="et_pb_padding_top_<%%= counter %%>" value="<%%= current_value_pt %%>" data-device="desktop"> <input type="text" class="medium-text et_custom_margin et_custom_margin_top et_pb_setting_mobile et_pb_setting_mobile_tablet" data-device="tablet"> <input type="text" class="medium-text et_custom_margin et_custom_margin_top et_pb_setting_mobile et_pb_setting_mobile_phone" data-device="phone"> </label> <label> %4$s <input type="text" class="medium-text et_custom_margin et_custom_margin_right et-pb-validate-unit et_pb_setting_mobile et_pb_setting_mobile_desktop et_pb_setting_mobile_active" id="et_pb_padding_right_<%%= counter %%>" name="et_pb_padding_right_<%%= counter %%>" value="<%%= current_value_pr %%>" data-device="desktop"> <input type="text" class="medium-text et_custom_margin et_custom_margin_right et_pb_setting_mobile et_pb_setting_mobile_tablet" data-device="tablet"> <input type="text" class="medium-text et_custom_margin et_custom_margin_right et_pb_setting_mobile et_pb_setting_mobile_phone" data-device="phone"> </label> <label> %5$s <input type="text" class="medium-text et_custom_margin et_custom_margin_bottom et-pb-validate-unit et_pb_setting_mobile et_pb_setting_mobile_desktop et_pb_setting_mobile_active" id="et_pb_padding_bottom_<%%= counter %%>" name="et_pb_padding_bottom_<%%= counter %%>" value="<%%= current_value_pb %%>" data-device="desktop"> <input type="text" class="medium-text et_custom_margin et_custom_margin_bottom et_pb_setting_mobile et_pb_setting_mobile_tablet" data-device="tablet"> <input type="text" class="medium-text et_custom_margin et_custom_margin_bottom et_pb_setting_mobile et_pb_setting_mobile_phone" data-device="phone"> </label> <label> %6$s <input type="text" class="medium-text et_custom_margin et_custom_margin_left et-pb-validate-unit et_pb_setting_mobile et_pb_setting_mobile_desktop et_pb_setting_mobile_active" id="et_pb_padding_left_<%%= counter %%>" name="et_pb_padding_left_<%%= counter %%>" value="<%%= current_value_pl %%>" data-device="desktop"> <input type="text" class="medium-text et_custom_margin et_custom_margin_left et_pb_setting_mobile et_pb_setting_mobile_tablet" data-device="tablet"> <input type="text" class="medium-text et_custom_margin et_custom_margin_left et_pb_setting_mobile et_pb_setting_mobile_phone" data-device="phone"> </label> <input type="hidden" class="et_custom_margin_main et_pb_setting_mobile et_pb_setting_mobile_desktop et-pb-main-setting et_pb_setting_mobile_active" value="<%%= \'\' === current_value_pt && \'\' === current_value_pr && \'\' === current_value_pb && \'\' === current_value_pl ? \'\' : current_value_pt + \'|\' + current_value_pr + \'|\' + current_value_pb + \'|\' + current_value_pl %%>" data-device="desktop"> <input type="hidden" class="et_custom_margin_main et_pb_setting_mobile et_pb_setting_mobile_tablet et-pb-main-setting" id="et_pb_padding_<%%= counter %%>_tablet" name="et_pb_padding_<%%= counter %%>_tablet" value="<%%= current_value_padding_tablet %%>" data-device="tablet" data-has_saved_value="<%%= has_tablet_padding %%>"> <input type="hidden" class="et_custom_margin_main et_pb_setting_mobile et_pb_setting_mobile_phone et-pb-main-setting" id="et_pb_padding_<%%= counter %%>_phone" name="et_pb_padding_<%%= counter %%>_phone" value="<%%= current_value_padding_phone %%>" data-device="phone" data-has_saved_value="<%%= has_phone_padding %%>"> <input id="et_pb_padding_<%%= counter %%>_last_edited" type="hidden" class="et_pb_mobile_last_edited_field" value="<%%= last_edited_padding_field %%>"> </div> <span class="et-pb-mobile-settings-toggle"></span> <span class="et-pb-reset-setting"></span> </div> </div> </div> </div> <%% counter++; }); %%>', esc_html__( 'Column', 'et_builder' ), esc_html__( 'Padding', 'et_builder' ), et_builder_i18n( 'Top' ), et_builder_i18n( 'Right' ), et_builder_i18n( 'Bottom' ), // #5 et_builder_i18n( 'Left' ), et_pb_generate_mobile_settings_tabs() // #7 ); return $output; } function generate_columns_settings_css() { $output = sprintf( '<%% var columns_css = typeof columns_layout !== \'undefined\' ? columns_layout.split(",") : [], counter_css = 1; _.each( columns_css, function ( column_type ) { var current_module_id_value, current_module_class_value, current_custom_css_before_value, current_custom_css_main_value, current_custom_css_after_value; switch ( counter_css ) { %1$s } %%> <div class="et_pb_subtoggle_section"> <div class="et-pb-option-toggle-content"> <div class="et-pb-option et-pb-option--custom_css"> <label for="et_pb_custom_css_before_<%%= counter_css %%>"> %2$s <%% if ( "4_4" !== column_type ) { %%> <%%= counter_css + " " %%> <%% } %%> %3$s:<span>.et_pb_column_<%%= \'row_inner\' === module_type ? \'inner_\' : \'\' %%><%%= typeof columns_order !== \'undefined\' && typeof columns_order[counter_css-1] !== \'undefined\' ? columns_order[counter_css-1] : \'\' %%>:before</span> </label> <div class="et-pb-option-container et-pb-custom-css-option"> <textarea id="et_pb_custom_css_before_<%%= counter_css %%>" class="et-pb-main-setting large-text coderegular-text" rows="4" cols="50"><%%= current_custom_css_before_value.replace( /\|\|/g, "\n" ) %%></textarea> </div> </div> <div class="et-pb-option et-pb-option--custom_css"> <label for="et_pb_custom_css_main_<%%= counter_css %%>"> %2$s <%% if ( "4_4" !== column_type ) { %%> <%%= counter_css + " " %%> <%% } %%> %4$s:<span>.et_pb_column_<%%= \'row_inner\' === module_type ? \'inner_\' : \'\' %%><%%= typeof columns_order !== \'undefined\' && typeof columns_order[counter_css-1] !== \'undefined\' ? columns_order[counter_css-1] : \'\' %%></span> </label> <div class="et-pb-option-container et-pb-custom-css-option"> <textarea id="et_pb_custom_css_main_<%%= counter_css %%>" class="et-pb-main-setting large-text coderegular-text" rows="4" cols="50"><%%= current_custom_css_main_value.replace( /\|\|/g, "\n" ) %%></textarea> </div> </div> <div class="et-pb-option et-pb-option--custom_css"> <label for="et_pb_custom_css_after_<%%= counter_css %%>"> %2$s <%% if ( "4_4" !== column_type ) { %%> <%%= counter_css + " " %%> <%% } %%> %5$s:<span>.et_pb_column_<%%= \'row_inner\' === module_type ? \'inner_\' : \'\' %%><%%= typeof columns_order !== \'undefined\' && typeof columns_order[counter_css-1] !== \'undefined\' ? columns_order[counter_css-1] : \'\' %%>:after</span> </label> <div class="et-pb-option-container et-pb-custom-css-option"> <textarea id="et_pb_custom_css_after_<%%= counter_css %%>" class="et-pb-main-setting large-text coderegular-text" rows="4" cols="50"><%%= current_custom_css_after_value.replace( /\|\|/g, "\n" ) %%></textarea> </div> </div> </div> </div> <%% counter_css++; }); %%>', $this->generate_column_vars_css(), esc_html__( 'Column', 'et_builder' ), et_builder_i18n( 'Before' ), et_builder_i18n( 'Main Element' ), et_builder_i18n( 'After' ) ); return $output; } function generate_columns_settings_css_fields() { $output = sprintf( '<%% var columns_css = typeof columns_layout !== \'undefined\' ? columns_layout.split(",") : [], counter_css = 1; _.each( columns_css, function ( column_type ) { var current_module_id_value, current_module_class_value; switch ( counter_css ) { %1$s } %%> <div class="et_pb_subtoggle_section"> <div class="et-pb-option-toggle-content"> <div class="et-pb-option et_pb_custom_css_regular"> <label for="et_pb_module_id_<%%= counter_css %%>"> %2$s <%% if ( "4_4" !== column_type ) { %%> <%%= counter_css + " " %%> <%% } %%> %3$s: </label> <div class="et-pb-option-container"> <input id="et_pb_module_id_<%%= counter_css %%>" type="text" class="regular-text et_pb_custom_css_regular et-pb-main-setting" value="<%%= current_module_id_value %%>"> </div> </div> <div class="et-pb-option et_pb_custom_css_regular"> <label for="et_pb_module_class_<%%= counter_css %%>"> %2$s <%% if ( "4_4" !== column_type ) { %%> <%%= counter_css + " " %%> <%% } %%> %4$s: </label> <div class="et-pb-option-container"> <input id="et_pb_module_class_<%%= counter_css %%>" type="text" class="regular-text et_pb_custom_css_regular et-pb-main-setting" value="<%%= current_module_class_value %%>"> </div> </div> </div> </div> <%% counter_css++; }); %%>', $this->generate_column_vars_css(), esc_html__( 'Column', 'et_builder' ), esc_html__( 'CSS ID', 'et_builder' ), esc_html__( 'CSS Class', 'et_builder' ) ); return $output; } }
•
Search:
•
Replace:
1
2
Function
Edit by line
Download
Information
Rename
Copy
Move
Delete
Chmod
List