class ET_Builder_Module_Contact_Form_Item extends ET_Builder_Module {
public $additional_shortcode_slugs = array( 'et_pb_signup_custom_field' );
$this->name = esc_html__( 'Field', 'et_builder' );
$this->plural = esc_html__( 'Fields', 'et_builder' );
$this->slug = 'et_pb_contact_field';
$this->vb_support = 'on';
$this->child_title_var = 'field_id';
$this->advanced_setting_title_text = esc_html__( 'New Field', 'et_builder' );
$this->settings_text = esc_html__( 'Field Settings', 'et_builder' );
$this->main_css_element = '.et_pb_contact_form_container %%order_class%%.et_pb_contact_field';
$this->settings_modal_toggles = array(
'main_content' => et_builder_i18n( 'Text' ),
'field_options' => esc_html__( 'Field Options', 'et_builder' ),
'conditional_logic' => esc_html__( 'Conditional Logic', 'et_builder' ),
'layout' => et_builder_i18n( 'Layout' ),
$this->advanced_fields = array(
'border_radii' => sprintf( '%1$s .input, %1$s .input[type="checkbox"] + label i, %1$s .input[type="radio"] + label i', $this->main_css_element ),
'border_styles' => sprintf( '%1$s .input, %1$s .input[type="checkbox"] + label i, %1$s .input[type="radio"] + label i', $this->main_css_element ),
'important' => 'plugin_only',
'label_prefix' => esc_html__( 'Input', 'et_builder' ),
'%%order_class%% select',
'%%order_class%% textarea',
'%%order_class%% .et_pb_contact_field_options_list label > i',
'main' => '%%order_class%%',
'margin_padding' => array(
'padding' => 'p%%order_class%%',
'important' => array( 'custom_margin' ), // needed to overwrite last module margin-bottom styling
'text_orientation' => '%%order_class%% input, %%order_class%% textarea, %%order_class%% label',
// Don't add text-shadow fields since they already are via font-options
'%%order_class%% textarea',
'label' => esc_html__( 'Field', 'et_builder' ),
'background_color' => '%%order_class%% .input, %%order_class%% .input[type="checkbox"] + label i, %%order_class%% .input[type="radio"] + label i',
'main' => '%%order_class%%.et_pb_contact_field .input',
'background_color' => '%%order_class%%.et_pb_contact_field .input, %%order_class%%.et_pb_contact_field .input[type="checkbox"] + label i, %%order_class%%.et_pb_contact_field .input[type="radio"] + label i',
'background_color_hover' => '%%order_class%%.et_pb_contact_field .input:hover, %%order_class%%.et_pb_contact_field .input[type="checkbox"] + label:hover i, %%order_class%%.et_pb_contact_field .input[type="radio"] + label:hover i',
'focus_background_color' => '%%order_class%%.et_pb_contact_field .input:focus, %%order_class%%.et_pb_contact_field .input[type="checkbox"]:active + label i, %%order_class%%.et_pb_contact_field .input[type="radio"]:active + label i',
'focus_background_color_hover' => '%%order_class%%.et_pb_contact_field .input:focus:hover, %%order_class%%.et_pb_contact_field .input[type="checkbox"]:active:hover + label i, %%order_class%%.et_pb_contact_field .input[type="radio"]:active:hover + label i',
'form_text_color' => '%%order_class%%.et_pb_contact_field .input, %%order_class%%.et_pb_contact_field .input[type="checkbox"] + label, %%order_class%%.et_pb_contact_field .input[type="radio"] + label, %%order_class%%.et_pb_contact_field .input[type="checkbox"]:checked + label i:before',
'form_text_color_hover' => '%%order_class%%.et_pb_contact_field .input:hover, %%order_class%%.et_pb_contact_field .input[type="checkbox"]:hover + label,
%%order_class%%.et_pb_contact_field .input[type="radio"]:hover + label, %%order_class%%.et_pb_contact_field .input[type="checkbox"]:checked:hover + label i:before',
'focus_text_color' => '%%order_class%%.et_pb_contact_field .input:focus, %%order_class%%.et_pb_contact_field .input[type="checkbox"]:active + label,
%%order_class%%.et_pb_contact_field .input[type="radio"]:active + label, %%order_class%%.et_pb_contact_field .input[type="checkbox"]:checked:active + label i:before',
'focus_text_color_hover' => '%%order_class%%.et_pb_contact_field .input:focus:hover, %%order_class%%.et_pb_contact_field .input[type="checkbox"]:active:hover + label,
%%order_class%%.et_pb_contact_field .input[type="radio"]:active:hover + label, %%order_class%%.et_pb_contact_field .input[type="checkbox"]:checked:active:hover + label i:before',
'margin_padding' => false,
'border_styles' => false,
'%%order_class%%.et_pb_contact_field .et_pb_contact_field_options_title',
"{$this->main_css_element} .input",
"{$this->main_css_element} .input::placeholder",
"{$this->main_css_element} .input::-webkit-input-placeholder",
"{$this->main_css_element} .input::-moz-placeholder",
"{$this->main_css_element} .input:-ms-input-placeholder",
"{$this->main_css_element} .input[type=checkbox] + label",
"{$this->main_css_element} .input[type=radio] + label",
'important' => 'plugin_only',
'%%order_class%% input[type=text]',
'%%order_class%% input[type=email]',
'%%order_class%% textarea',
'%%order_class%%[data-type=checkbox]',
'%%order_class%%[data-type=radio]',
'%%order_class%%[data-type=select]',
'%%order_class%%[data-type=select] select',
'link_url' => esc_html__( 'Link URL', 'et_builder' ),
'link_text' => esc_html__( 'Link Text', 'et_builder' ),
'link_cancel' => esc_html__( 'Discard Changes', 'et_builder' ),
'link_save' => esc_html__( 'Save Changes', 'et_builder' ),
'link_settings' => esc_html__( 'Option Link', 'et_builder' ),
'label' => esc_html__( 'Field ID', 'et_builder' ),
'description' => esc_html__( 'Define the unique ID of this field. You should use only English characters without special characters and spaces.', 'et_builder' ),
'toggle_slug' => 'main_content',
'default_on_front' => '',
'option_category' => 'basic_option',
'label' => et_builder_i18n( 'Title' ),
'description' => esc_html__( 'Here you can define the content that will be placed within the current tab.', 'et_builder' ),
'toggle_slug' => 'main_content',
'default_on_front' => esc_html__( 'New Field', 'et_builder' ),
'option_category' => 'basic_option',
'mobile_options' => true,
'label' => esc_html__( 'Type', 'et_builder' ),
'option_category' => 'basic_option',
'input' => esc_html__( 'Input Field', 'et_builder' ),
'email' => esc_html__( 'Email Field', 'et_builder' ),
'text' => esc_html__( 'Textarea', 'et_builder' ),
'checkbox' => esc_html__( 'Checkboxes', 'et_builder' ),
'radio' => esc_html__( 'Radio Buttons', 'et_builder' ),
'select' => esc_html__( 'Select Dropdown', 'et_builder' ),
'description' => esc_html__( 'Choose the type of field', 'et_builder' ),
'toggle_slug' => 'field_options',
'checkbox_checked' => array(
'label' => esc_html__( 'Checked By Default', 'et_builder' ),
'description' => esc_html__( 'If enabled, the check mark will be automatically selected for the visitor. They can still deselected it.', 'et_builder' ),
'option_category' => 'layout',
'depends_show_if' => 'checkbox',
'toggle_slug' => 'field_options',
'checkbox_options' => array(
'label' => esc_html__( 'Options', 'et_builder' ),
'type' => 'sortable_list',
'option_category' => 'basic_option',
'depends_show_if' => 'checkbox',
'toggle_slug' => 'field_options',
'right_actions' => 'move|link|copy|delete',
'radio_options' => array(
'label' => esc_html__( 'Options', 'et_builder' ),
'type' => 'sortable_list',
'option_category' => 'basic_option',
'depends_show_if' => 'radio',
'toggle_slug' => 'field_options',
'right_actions' => 'move|link|copy|delete',
'select_options' => array(
'label' => esc_html__( 'Options', 'et_builder' ),
'type' => 'sortable_list',
'option_category' => 'basic_option',
'depends_show_if' => 'select',
'toggle_slug' => 'field_options',
'label' => esc_html__( 'Minimum Length', 'et_builder' ),
'description' => esc_html__( 'Leave at 0 to remove restriction', 'et_builder' ),
'range_settings' => array(
'option_category' => 'basic_option',
'depends_show_if' => 'input',
'toggle_slug' => 'field_options',
'label' => esc_html__( 'Maximum Length', 'et_builder' ),
'description' => esc_html__( 'Leave at 0 to remove restriction', 'et_builder' ),
'range_settings' => array(
'option_category' => 'basic_option',
'depends_show_if' => 'input',
'toggle_slug' => 'field_options',
'allowed_symbols' => array(
'label' => esc_html__( 'Allowed Symbols', 'et_builder' ),
'all' => esc_html__( 'All', 'et_builder' ),
'letters' => esc_html__( 'Letters Only (A-Z)', 'et_builder' ),
'numbers' => esc_html__( 'Numbers Only (0-9)', 'et_builder' ),
'alphanumeric' => esc_html__( 'Alphanumeric Only (A-Z, 0-9)', 'et_builder' ),
'option_category' => 'basic_option',
'depends_show_if' => 'input',
'toggle_slug' => 'field_options',
'required_mark' => array(
'label' => esc_html__( 'Required Field', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'on' => et_builder_i18n( 'Yes' ),
'off' => et_builder_i18n( 'No' ),
'description' => esc_html__( 'Define whether the field should be required or optional', 'et_builder' ),
'toggle_slug' => 'field_options',
'fullwidth_field' => array(
'label' => esc_html__( 'Make Fullwidth', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'layout',
'on' => et_builder_i18n( 'Yes' ),
'off' => et_builder_i18n( 'No' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'layout',
'description' => esc_html__( 'If enabled, the field will take 100% of the width of the content area, otherwise it will take 50%', 'et_builder' ),
'default_on_front' => 'off',
'conditional_logic' => array(
'label' => esc_html__( 'Enable', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'layout',
'on' => et_builder_i18n( 'Yes' ),
'off' => et_builder_i18n( 'No' ),
'conditional_logic_rules',
'conditional_logic_relation',
'description' => et_get_safe_localization( __( 'Enabling conditional logic makes this field only visible when any or all of the rules below are fulfilled<br><strong>Note:</strong> Only fields with an unique and non-empty field ID can be used', 'et_builder' ) ),
'toggle_slug' => 'conditional_logic',
'conditional_logic_relation' => array(
'label' => esc_html__( 'Relation', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'layout',
'on' => esc_html__( 'All', 'et_builder' ),
'off' => esc_html__( 'Any', 'et_builder' ),
'button_options' => array(
'button_type' => 'equal',
'depends_show_if' => 'on',
'description' => esc_html__( 'Choose whether any or all of the rules should be fulfilled', 'et_builder' ),
'toggle_slug' => 'conditional_logic',
'conditional_logic_rules' => array(
'label' => esc_html__( 'Rules', 'et_builder' ),
'type' => 'conditional_logic',
'option_category' => 'layout',
'depends_show_if' => 'on',
'toggle_slug' => 'conditional_logic',
public function get_transition_fields_css_props() {
$fields = parent::get_transition_fields_css_props();
$fields['form_field_background_color'] = array(
'%%order_class%%.et_pb_contact_field .input',
'%%order_class%%.et_pb_contact_field .input + label:hover i',
* Renders the module output.
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
public function render( $attrs, $content, $render_slug ) {
global $et_pb_half_width_counter, $et_pb_contact_form_num;
et_core_nonce_verified_previously();
$multi_view = et_pb_multi_view_options( $this );
$field_title = $this->props['field_title'];
$field_type = $this->props['field_type'];
$field_id = $this->props['field_id'];
$required_mark = $this->props['required_mark'];
$fullwidth_field = $this->props['fullwidth_field'];
$form_field_text_color = $this->props['form_field_text_color'];
$checkbox_checked = $this->props['checkbox_checked'];
$checkbox_options = $this->props['checkbox_options'];
$radio_options = $this->props['radio_options'];
$select_options = $this->props['select_options'];
$min_length = $this->props['min_length'];
$max_length = $this->props['max_length'];
$conditional_logic = $this->props['conditional_logic'];
$conditional_logic_relation = $this->props['conditional_logic_relation'];
$conditional_logic_rules = $this->props['conditional_logic_rules'];
$allowed_symbols = $this->props['allowed_symbols'];
$render_count = $this->render_count();
$current_module_num = null === $et_pb_contact_form_num ? 0 : intval( $et_pb_contact_form_num ) + 1;
$field_text_color_hover = $this->get_hover_value( 'form_field_text_color' );
$field_text_color_values = et_pb_responsive_options()->get_property_values( $this->props, 'form_field_text_color' );
$field_focus_text_color_hover = $this->get_hover_value( 'form_field_focus_text_color' );
$field_focus_text_color_values = et_pb_responsive_options()->get_property_values( $this->props, 'form_field_focus_text_color' );
if ( '' === $field_id ) {
$field_id = sprintf( 'field_%d_%d', $et_pb_contact_form_num, $render_count );
if ( 'et_pb_signup_custom_field' === $render_slug ) {
$this->add_classname( 'et_pb_newsletter_field' );
$field_id = strtolower( $field_id );
$video_background = $this->video_background();
$parallax_image_background = $this->get_parallax_image_background();
$et_pb_half_width_counter = ! isset( $et_pb_half_width_counter ) ? 0 : $et_pb_half_width_counter;
// count fields to add the et_pb_contact_field_last properly
if ( 'off' === $fullwidth_field ) {
$et_pb_half_width_counter++;
$et_pb_half_width_counter = 0;
// Form Field Text Color - Radio Checked.
$field_text_color_important = et_builder_has_limitation( 'force_use_global_important' ) ? ' !important' : '';
et_pb_responsive_options()->generate_responsive_css( $field_text_color_values, '%%order_class%%.et_pb_contact_field .input[type="radio"]:checked + label i:before', 'background-color', $render_slug, $field_text_color_important, 'color' );
if ( et_builder_is_hover_enabled( 'form_field_text_color', $this->props ) ) {
ET_Builder_Element::set_style(
'selector' => '%%order_class%%.et_pb_contact_field .input[type="radio"]:checked:hover + label i:before',
'declaration' => sprintf(
'background-color: %1$s%2$s;',
esc_html( $field_text_color_hover ),
$field_text_color_important
// Form Field Text Color on Focus - Radio Checked.
et_pb_responsive_options()->generate_responsive_css( $field_focus_text_color_values, '%%order_class%%.et_pb_contact_field .input[type="radio"]:checked:active + label i:before', 'background-color', $render_slug, $field_text_color_important, 'color' );
if ( et_builder_is_hover_enabled( 'form_field_focus_text_color', $this->props ) ) {
ET_Builder_Element::set_style(
'selector' => '%%order_class%%.et_pb_contact_field .input[type="radio"]:checked:active:hover + label i:before',
'declaration' => sprintf(
'background-color: %1$s%2$s;',
esc_html( $field_focus_text_color_hover ),
$field_text_color_important
$min_length = intval( $min_length );
$max_length = intval( $max_length );
if ( in_array( $allowed_symbols, array( 'letters', 'numbers', 'alphanumeric' ) ) ) {
switch ( $allowed_symbols ) {
$symbols_pattern = '[A-Z|a-z|\s-]';
$title = __( 'Only letters allowed.', 'et_builder' );
$symbols_pattern = '[0-9\s-]';
$title = __( 'Only numbers allowed.', 'et_builder' );
$symbols_pattern = '[\w\s-]';
$title = __( 'Only letters and numbers allowed.', 'et_builder' );
if ( 0 !== $min_length && 0 !== $max_length ) {
$max_length = max( $min_length, $max_length );
$min_length = min( $min_length, $max_length );
$max_length_attr = sprintf(