# 22. Hiển thị chuyên mục ra ngoài trang shop (ok)

![](/files/-MTxjO59xZjBpjHFa_z6)

C:\xampp\htdocs\test\wp-content\plugins\plugin-name\includes\class-wpf-form\_ct.php

```
<?php
class WPF_Form_CT {
  protected $plugin_name;
  protected $version;
  protected $themplate_id = false;
  public function __construct($plugin_name, $version, $themplate_id = false) {
    $this->plugin_name  = $plugin_name;
    $this->version      = $version;
    $this->themplate_id = $themplate_id;
  }
  public function form() {
    $sort_cmb  = array_merge(WPF_Utils_CT::get_wc_attributes(), WPF_Utils_CT::get_default_fields());
    $languages = array(
      'en' => array(
        'name'     => '',
        'selected' => true,
      ),
    );
    natcasesort($sort_cmb);
    $layout = $data = array();
    if (!empty($this->themplate_id)) {
      $option = WPF_Options_CT::get_option($this->plugin_name, $this->version);
      $forms = $option->get();
      if (!empty($forms[$this->themplate_id])) {
        $layout = $forms[$this->themplate_id];
        $data = $layout['data'];
        $layout = $layout['layout'];
      }
    }
    $this->add_fields($data);
    ?>
      <input type="hidden" value="" name="layout" id="wpf_ct_layout" />
      <input type="hidden" value="<?php echo $this->themplate_id ?>" id="wpf_ct_themplate_id" name="themplate_id" />
      <div class="wpf_ct_back_builder">
        <div class="wpf_ct_back_module_panel">
          <?php foreach ($sort_cmb as $type => $name): ?>
            <div <?php if (!empty($layout[$type])): ?>style="display:none;"<?php endif; ?> data-type="<?php echo $type ?>" id="wpf_ct_cmb_<?php echo $type ?>" class="wpf_ct_back_module"> 
              <?php $this->module($type, $name, array(), $languages); ?>
            </div>
          <?php endforeach; ?>
        </div>
        <div class="wpf_ct_back_row_content" id="wpf_ct_module_content">  
          <div class="wpf_ct_module_holder">
            <div class="wpf_empty_holder_text"><?php _e('Drop module here', 'wpf') ?></div>
            <?php if (!empty($layout)): ?>
              <?php foreach ($layout as $type => $module): ?>
                <?php
                  if (empty($sort_cmb[$type])) continue;
                  $name = $sort_cmb[$type];
                ?>
                <div data-type="<?php echo $type ?>" class="wpf_ct_back_module wpf_dragged">
                  <?php $this->module($type, $name, $module, $languages); ?>
                </div>
              <?php endforeach; ?>
            <?php endif; ?>
          </div>
        </div>
      </div>
    <?php
  }
  private function module($type, $name, array $module = array(), array $languages = array()) {
    ?>
      <strong class="wpf_ct_module_name"><?php echo $name ?></strong>
      <div class="wpf_ct_back_module_top">
        <div class="wpf_left">
          <span class="wpf_back_active_module_title"><?php echo $name ?></span>
        </div>
        <div class="wpf_right">
          <a href="#" class="wpf_ct_module_btn wpf_ct_toggle_module"></a>
          <a href="#" class="wpf_ct_module_btn wpf_ct_delete_module"></a>
        </div>
      </div>
      <div class="wpf_ct_active_module">
        <div data-type="<?php echo $type ?>" class="wpf_ct_back_active_module_content">    
          <?php WPF_Utils_CT::module_multi_text($type, $module, $languages, 'field_title', __('Field Title', 'wpf_ct')); ?>
          <div class="wpf_ct_back_active_module_row wpf_ct_back_active_module_hide_field">
            <div class="wpf_ct_back_active_module_label">&nbsp;</div>
            <div class="wpf_ct_back_active_module_input">
              <label>
                <input id="wpf_ct_<?php echo $type ?>[hide_field]" type="checkbox" name="[<?php echo $type ?>][hide_field]" value="1" <?php if (!empty($module['hide_field'])): ?>checked="checked"<?php endif; ?>  />
                <?php _e('Hide field title', 'wpf') ?>
              </label>
            </div>
          </div>
          <?php if (has_action('wpf_template_' . $type)): ?>
            <?php 
              do_action('wpf_template_' . $type, $this->themplate_id, $module)
            ?>
          <?php else: ?>
            <?php $this->get_main_fields($type, $name, $module) ?>
          <?php endif; ?>
        </div>
      </div>
    <?php
  }
  private function add_fields($data = array()) {
    $layouts = array(
      'vertical' => __('Vertical Layout', 'wpf'),
      'horizontal' => __('Horizontal Layout', 'wpf')
    );
    $pagination = array(
        'pagination' => __('Standard Pagination', 'wpf'),
        'infinity_auto' => __('Infinite Scroll', 'wpf'),
        'infinity' => __('Load More', 'wpf')
    );
    ?>
      <div class="wpf_ct_lightbox_row">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_name"><?php _e('Form Title', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <input id="wpf_ct_name" class="wpf_towidth" type="text" value="<?php echo !empty($data['name']) ? $data['name'] : '' ?>" name="name" />
        </div>
      </div>
      <div class="wpf_ct_lightbox_row ">
        <div class="wpf_ct_lightbox_label"><?php _e('Layout', 'wpf'); ?></div>
        <div class="wpf_ct_lightbox_input wpf_ct_grid wpf_ct_changed">
          <?php foreach ($layouts as $id => $ch): ?>
            <input id="wpf_ct_<?php echo $id ?>" type="radio" value="<?php echo $id; ?>" name="type" <?php if ((!$data && $id === 'vertical' ) || ( isset($data['type']) && $data['type'] == $id )): ?>checked="checked"<?php endif; ?>/>
            <label title="<?php echo $ch ?>" for="wpf_ct_<?php echo $id ?>" class="wpf_ct_grid_<?php echo $id; ?>"></label>
          <?php endforeach; ?>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_empty_fields"><?php _e('Empty Fields', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <input <?php if ((!isset($data['empty']) && empty($data)) || !empty($data['empty'])): ?>checked="checked"<?php endif; ?> type="checkbox" name="empty" value="1" id="wpf_ct_empty_fields"/>
          <label for="wpf_ct_empty_fields"><?php _e('Do not show field if empty', 'wpf') ?></label>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_sort_fields"><?php _e('Product Sorting', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <input <?php if (!empty($data['sort'])): ?>checked="checked"<?php endif; ?> type="checkbox" name="sort" value="1" id="wpf_ct_sort_fields"/>
          <label for="wpf_ct_sort_fields"><?php _e('Hide product sorting', 'wpf') ?></label>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_result_fields"><?php _e('Product Count', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <input <?php if (!empty($data['result'])): ?>checked="checked"<?php endif; ?>  type="checkbox" name="result" value="1" id="wpf_ct_result_fields"/>
          <label for="wpf_ct_result_fields"><?php _e('Hide result product count', 'wpf') ?></label>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_out_of_stock_fields"><?php _e('Out of Stock', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <input <?php if (!empty($data['out_of_stock'])): ?>checked="checked"<?php endif; ?> type="checkbox" name="out_of_stock" value="1" id="wpf_ct_out_of_stock_fields"/>
          <label for="wpf_ct_out_of_stock_fields"><?php _e('Do not show out of stock products', 'wpf') ?></label>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row wpf_ct_changed">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_pagination_fields"><?php _e('Pagination', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <input <?php if (!empty($data['pagination'])): ?>checked="checked"<?php endif; ?> type="checkbox" name="pagination" value="1" id="wpf_ct_pagination_fields"/>
          <label for="wpf_ct_pagination_fields"><?php _e('Hide Pagination', 'wpf') ?></label>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row wpf_infinity wpf_ct_changed">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_pagination_type_fields"><?php _e('Pagination Option', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <?php foreach ($pagination as $k => $v): ?>
            <label for="wpf_ct_<?php echo $k ?>_type_fields">
              <input <?php if ((isset($data['pagination_type']) && $data['pagination_type'] === $k) || (empty($data['pagination_type']) && $k === 'pagination')): ?>checked="checked"<?php endif; ?> type="radio" name="pagination_type" value="<?php echo $k ?>" id="wpf_ct_<?php echo $k ?>_type_fields"/><?php echo $v ?>
            </label>
          <?php endforeach; ?>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row wpf_infinity_buffer">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_pagination_type_fields">&nbsp;</label></div>
        <div class="wpf_ct_lightbox_input">
          <input type="text" name="infinitybuffer" value="<?php echo! empty( $data['infinitybuffer'] ) ? esc_attr( $data['infinitybuffer'] ) : '' ?>" id="wpf_ct_infinity_buffer_fields" /> <?php _e( 'Infinite scroll trigger point (px)' ) ?><br><small><?php _e( 'Default is 300, higher number means infinite scroll will trigger earlier.' ) ?></small>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_posts_per_page_fields"><?php _e('Products Per Page', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
            <input type="text" name="posts_per_page" value="<?php echo!empty($data['posts_per_page']) ? intval($data['posts_per_page']) : '' ?>" id="wpf_ct_posts_per_page_fields"/>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_group_fields"><?php _e('Toggle Field Groups', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <input <?php if (!empty($data['group'])): ?>checked="checked"<?php endif; ?> type="checkbox" name="group" value="1" id="wpf_ct_group_fields"/>
          <label for="wpf_ct_group_fields"><?php _e('Allow field groups toggle-able', 'wpf') ?></label>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row wpf_result_page_wrapper">
        <div class="wpf_ct_lightbox_label"><label><?php _e('Reset Button', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <ul>
            <li>
              <input id="wpf_ct_bottom_reset_button" type="radio" value="bottom" name="reset_button" <?php if ( !empty( $data['reset_button'] ) && 'bottom' === $data['reset_button'] ): ?>checked="checked"<?php endif; ?>>
              <label for="wpf_ct_bottom_reset_button"><?php _e( 'Add reset button at bottom', 'wpf' ); ?></label>
            </li>
            <li>
              <input id="wpf_ct_group_reset_button" type="radio" value="group" name="reset_button" <?php if ( !empty( $data['reset_button'] ) && 'group' === $data['reset_button'] ): ?>checked="checked"<?php endif; ?>>
              <label for="wpf_ct_group_reset_button"><?php _e( 'Add reset button at every field group', 'wpf' ); ?></label>
            </li>
            <li>
              <input id="wpf_ct_no_reset_button" type="radio" value="no" name="reset_button" <?php if ( empty( $data['reset_button'] ) || (!empty( $data['reset_button'] ) && 'no' === $data['reset_button']) ): ?>checked="checked"<?php endif; ?>>
              <label for="wpf_ct_no_reset_button"><?php _e( 'No reset button', 'wpf' ); ?></label>
            </li>
          </ul>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row ">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_clear_label"><?php _e('Reset Label', 'wpf'); ?></label></div>
        <?php  
          $get_all_languages = [
            'en' => [
              'name'     => '',
              'selected' => true,
            ],
          ];
        ?>
        <div class="wpf_ct_lightbox_input"><?php WPF_Utils_CT::module_language_tabs( 'clear_label', $data, $get_all_languages, null, 'text', __('Reset', 'wpf'), true ); ?>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_scroll_fields"><?php _e('Scroll To Result', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <input <?php if (!empty($data['scroll'])): ?>checked="checked"<?php endif; ?> type="checkbox" name="scroll" value="1" id="wpf_ct_scroll_fields"/>
          <label for="wpf_ct_scroll_fields"><?php _e('Yes', 'wpf') ?></label>
        </div>
      </div>
      <?php
        $relations = array(
          'and' => __('AND', 'wpf'),
          'or' => __('OR', 'wpf')
        );
      ?>
      <div class="wpf_ct_lightbox_row">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_tax_relation_or"><?php _e('Logical Relationship Between Taxonomies', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <?php foreach ($relations as $k => $v): ?>
            <label for="wpf_ct_tax_relation_<?php echo $k ?>">
              <input <?php if (isset($data['tax_relation']) && $data['tax_relation'] === $k || (!isset($data['tax_relation']) && $k === 'or')): ?>checked="checked"<?php endif; ?> type="radio" name="tax_relation" value="<?php echo $k ?>" id="wpf_ct_tax_relation_<?php echo $k ?>"/>
              <?php echo $v ?>
            </label>
          <?php endforeach; ?>
        </div>
      </div>
      <?php
        $pages = get_posts(array(
          'post_type' => 'page',
          'post_status' => 'publish',
          'numberposts' => -1,
          'orderby' => 'post_title',
          'order' => 'ASC'
        ));
        $result_types = array(
          'same_page' => __('Show results on the same page', 'wpf'),
          'diff_page' => __('Show results on a different page', 'wpf')
        )
      ?>
      <div class="wpf_ct_lightbox_row wpf_result_page_wrapper wpf_changed">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_result_page"><?php _e('Result Page Template', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <ul>
            <?php foreach ($result_types as $id => $ch): ?>
            <li>
              <input id="wpf_ct_<?php echo $id ?>" type="radio" value="<?php echo $id; ?>" name="result_type" <?php if ((!$data && $id === 'same_page' ) || ( isset($data['result_type']) && $data['result_type'] == $id )): ?>checked="checked"<?php endif; ?>/>
              <label for="wpf_ct_<?php echo $id ?>"><?php echo $ch ?></label>
            </li>
            <?php endforeach; ?>
            <li class ="wpf_result_page_select">
              <input id="wpf_ct_show_form_in_results" type="checkbox" value="show_form_in_results" name="show_form_in_results" <?php if (isset($data['show_form_in_results'])): ?> checked="checked"<?php endif; ?>/>
              <label for="wpf_ct_show_form_in_results"><?php _e('Show product filter form on search result page.', 'wpf') ?></label>
            </li>
          </ul>
          <div class="wpf_result_page_select">
            <div class="wpf_custom_select">
              <select name="page" id="wpf_ct_result_page">
                <?php if (!empty($pages)): ?>
                  <?php foreach ($pages as $p): ?>
                    <option <?php if (!empty($data['page']) && $data['page'] == $p->ID): ?>selected="selected"<?php endif; ?> value="<?php echo $p->ID ?>"><?php echo $p->post_title ?></option>
                  <?php endforeach; ?>
                <?php endif; ?>
              </select>
            </div><br>
            <label for="wpf_ct_result_page"><?php _e('The result page must have archive products displaying (it will swap the existing products with the result products).', 'wpf') ?></label>
          </div>
        </div>
      </div>
      <div class="wpf_ct_lightbox_row ">
        <div class="wpf_ct_lightbox_label"><label for="wpf_ct_no_found_message"><?php _e('No Products Found Message', 'wpf'); ?></label></div>
        <div class="wpf_ct_lightbox_input">
          <?php WPF_Utils_CT::module_language_tabs( 'no_found_message', $data, $get_all_languages, null, 'text', __('No products were found matching your selection.', 'wpf'), true ); ?>
        </div>
      </div>
    <?php
  }
  public function public_themplate(array $template, $page_id, array $request = array()) {
    WPF_Public_CT::get_instance()->enqueue_assets();
    if (empty($template['layout'])) {
        return '';
    }
    $lang = 'en';
    $layout = $template['layout'];
    $sort_cmb = array_merge(WPF_Utils_CT::get_wc_attributes(), WPF_Utils_CT::get_default_fields());
    $is_horizontal = $template['data']['type'] === 'horizontal';
    $is_group = !empty($template['data']['group']) || $is_horizontal;
    $page = get_permalink($template['data']['page']);
    $is_result_page = (!empty($template['data']['result_type']) && $template['data']['result_type'] === 'same_page') || get_the_ID() == $template['data']['page'];
    $scroll = !empty($template['data']['scroll']);
    $reset_btn = !empty($template['data']['reset_button']) ? $template['data']['reset_button'] : 'no';
    $no_found_message = ! empty( $template['data']['no_found_message'] ) ? WPF_Utils_CT::get_label( $template['data']['no_found_message'] ) : '';
    if ( empty( $no_found_message ) ) {
      $no_found_message = __( 'No products were found matching your selection.', 'wpf' );
    }
    $reset = ! empty( $template['data']['clear_label'] ) ? WPF_Utils_CT::get_label( $template['data']['clear_label'] ) : '';
    if ( empty( $reset ) ) {
      $reset = __( 'Clear', 'wpf' );
    }
    $infinitybuffer = ! empty( $template['data']['infinitybuffer'] ) ? $template['data']['infinitybuffer'] : 300;
    if('group' === $reset_btn){
        $non_groups = array('submit','instock','onsale');
    }
    $clasess = array('wpf_ct_form', 'wpf_ct_form_' . $this->themplate_id);
    if ($scroll) {
        $clasess[] = 'wpf_ct_form_scroll';
    }
    if (!isset($layout['submit'])) {
        $clasess[] = 'wpf_ct_submit_on_change';
    }
    ob_start();
    if ( is_product_category() || is_product_tag() ) {
    $post_id=get_queried_object();
    $post_id='c_'.$post_id->term_id;
    }else{
    $post_id=get_the_ID();
    }
    $shop_page = WPF_Utils_CT::get_shop_page_url();
    if ( ! (
      is_post_type_archive( 'product' ) || is_page() || is_tax( array( 'product_cat', 'product_tag' ) ) ) ) {
      /* assume there's no loop to display the results in, post the data to the Shop page instead */
      $action = $shop_page;
      $is_result_page = false;
    } else if ( ! $is_result_page ) {
      /* Result Page option is set to a different page */
      $action = $page;
    } else {
      $action = get_pagenum_link( 1, false );
    }
    if ( $is_result_page ) {
      $clasess[] = 'wpf_ct_form_ajax';
    }
    $wpf_parameters = array();
    if ( ! empty( $_GET ) ) {
      foreach ( $_GET as $key => $value ) {
        if ( substr( $key, 0, 3 ) === 'wpf' ) {
          $wpf_parameters[] = $key;
        }
      }
    }
    $action = remove_query_arg( $wpf_ct_parameters, $action );
        ?>
        <form
          data-post-id="<?php echo $post_id; ?>"
          data-slug="<?php echo $this->themplate_id ?>"
          action="<?php echo esc_attr( $action ); ?>"
          data-shop="<?php echo esc_attr( $shop_page ); ?>"
          method="get"
          class="<?php echo implode(' ', $clasess) ?>"
          style="visibility: hidden;"
          data-infinitybuffer="<?php echo esc_attr( $infinitybuffer ); ?>"
        >
          <input type="hidden" name="wpf_ct" value="<?php echo $this->themplate_id ?>" />
          <input type="hidden" name="orderby" value="" />
          <input type="hidden" name="wpf_ct_cols" value="" />
          <input type="hidden" name="wpf_ct_page" value="1" />
          <?php if ( ! empty( $_GET['s'] ) ) : ?>
            <input type="hidden" value="<?php echo sanitize_text_field( $_GET['s'] ); ?>" name="s" />
          <?php endif; ?>
          <div class="wpf_ct_items_wrapper wpf_ct_layout_<?php echo $template['data']['type'] ?><?php if ($is_group): ?> wpf_ct_items_grouped<?php endif; ?>">
              <?php foreach ($layout as $type => $module): ?>
                  <?php if (!empty($sort_cmb[$type])): ?>
                    <?php ob_start(); ?>
                    <?php if (has_action('wpf_ct_public_template_' . $type)): ?>
                    <?php do_action('wpf_ct_public_template_' . $type, $module, $this->themplate_id, $template['data'], $sort_cmb[$type], $this->themplate_id, $request, $lang) ?>
                  <?php else: ?>
                    <?php $this->get_public_fields($type, $module, $template['data'], $request, $lang) ?>
                  <?php endif; ?>
                  <?php
                    $view = trim(ob_get_contents());
                    ob_end_clean();
                  ?>
                      <?php if ($view || empty($template['data']['empty'])): ?>
                          <div class="wpf_ct_item wpf_ct_item_<?php echo $type ?>">
                              <?php if ($type !== 'submit' && ($is_horizontal || empty($module['hide_field']))): ?>
                                  <label class="wpf_item_name" for="wpf_ct_<?php echo $this->themplate_id ?>_item_<?php echo $type ?>"><?php echo WPF_Utils_CT::get_field_name($module, $sort_cmb[$type]) ?></label>
                              <?php endif; ?>
                              <?php if ($is_group && $type !== 'submit'): ?><div class="wpf_ct_items_group"><?php endif; ?>
                              <?php echo $view ?>
                <?php if('group' === $reset_btn && !in_array($type,$non_groups) ): ?>
                                      <div class="wpf_ct_reset_btn"><input type="reset" value="<?php echo esc_attr( $reset ); ?>"/></div>
                <?php endif; ?>
                              <?php if ($is_group && $type !== 'submit'): ?></div><?php endif; ?>
                          </div>
                      <?php endif; ?>
                  <?php endif; ?>
              <?php endforeach; ?>
          </div>
          <?php if('bottom' === $reset_btn): ?>
            <div class="wpf_ct_reset_btn"><input type="reset" value="<?php echo esc_attr( $reset ) ?>"/></div>
          <?php endif; ?>
          <div class="wpf-no-products-found" style="display: none;">
            <p class="woocommerce-info"><?php echo esc_html( $no_found_message ); ?></p>
          </div>
        </form>
      <?php
      $content = ob_get_contents();
      ob_end_clean();
      return $content;
    }
    protected function get_main_fields($type, $name, $module = array()) {
      switch ($type):
        case 'sku':
          break;
        default:
           $order = array(
            'term_order' => __('Custom Ordering', 'wpf'),
            'name' => __('Name', 'wpf'),
            'count' => __('Count', 'wpf'),
            'id' => __('ID', 'wpf'),
          );
          $orderby = array(
            'asc' => __('Ascending', 'wpf'),
            'desc' => __('Descending', 'wpf')
          );
          $display = array(
            'checkbox' => __('Checkbox', 'wpf'),
            'link' => __('Links', 'wpf'),
            'radio' => __('Radio', 'wpf'),
            'dropdown' => __('Dropdown', 'wpf'),
            'multiselect' => __('Multi Select', 'wpf'),
          );
          $logic = array(
            'or' => __('OR', 'wpf'),
            'and' => __('AND', 'wpf')
          );
          $include_children = array(
            'yes' => __('Yes', 'wpf'),
            'no' => __('No', 'wpf')
          );
        ?>
        <div class="wpf_ct_back_active_module_row">
          <div class="wpf_ct_back_active_module_label">
            <label for="wpf_ct_<?php echo $type ?>[count]"><?php _e('Product Count', 'wpf') ?></label>
          </div>
          <div class="wpf_ct_back_active_module_input">
            <label>
              <input id="wpf_ct_<?php echo $type ?>[count]" type="checkbox" name="[<?php echo $type ?>][count]" value="1" <?php if (!empty($module['count']) || !$module): ?>checked="checked"<?php endif; ?>  />
              <?php _e('Show product counts', 'wpf') ?>
            </label>
          </div>
        </div>
        <?php if ($type === 'wpf_ct_cat' || $type === 'wpf_ct_tag'): ?>
          <?php if ($type === 'wpf_ct_cat'): ?>
            <div class="wpf_ct_back_active_module_row">
              <div class="wpf_ct_back_active_module_label">
                <label for="wpf_ct_<?php echo $type ?>[hierachy]"><?php _e('Category Hierarchy', 'wpf') ?></label>
              </div>
              <div class="wpf_ct_back_active_module_input">
                <label>
                  <input id="wpf_ct_<?php echo $type ?>[hierachy]" type="checkbox" name="[<?php echo $type ?>][hierachy]" value="1" <?php if (!empty($module['hierachy'])): ?>checked="checked"<?php endif; ?>  />
                  <?php _e('Show category hierarchy', 'wpf') ?>
                </label>
              </div>
            </div>
            <div class="wpf_ct_back_active_module_row">
                <div class="wpf_ct_back_active_module_label">
                    <label for="wpf_ct_<?php echo $type ?>[include]"><?php _e('Include Children ', 'wpf') ?></label>
                </div>
                <div class="wpf_ct_back_active_module_input">
                    <?php foreach ($include_children as $k => $v): ?>
                        <label>
                            <input type="radio" name="[<?php echo $type ?>][include]" value="<?php echo $k ?>" <?php if ((isset($module['include']) && $module['include'] === $k) || (!isset($module['include']) && $k === 'yes')): ?>checked="checked"<?php endif; ?>  />
                            <?php echo $v ?>
                        </label>
                    <?php endforeach; ?>
                </div>
            </div>
          <?php endif; ?>
        <?php endif; ?>
        <div class="wpf_ct_back_active_module_row">
          <div class="wpf_ct_back_active_module_label">
            <label><?php _e('Display as', 'wpf') ?></label>
          </div>
          <div class="wpf_ct_back_active_module_input wpf_ct_display_as wpf_ct_changed">
            <?php foreach ($display as $k => $v): ?>
              <label>
                <input type="radio" name="[<?php echo $type ?>][show_as]" value="<?php echo $k ?>" <?php if ((isset($module['show_as']) && $module['show_as'] === $k) || (!isset($module['show_as']) && $k === 'checkbox')): ?>checked="checked"<?php endif; ?>  />
                <?php echo $v ?>
              </label>
            <?php endforeach; ?>
          </div>
        </div>
        <div class="wpf_ct_back_active_module_row">
          <div class="wpf_ct_back_active_module_label">
            <label><?php _e('Logic', 'wpf') ?></label>
          </div>
          <div class="wpf_ct_back_active_module_input wpf_ct_logic">
            <?php foreach ($logic as $k => $v): ?>
              <label>
                <input type="radio" name="[<?php echo $type ?>][logic]" value="<?php echo $k ?>" <?php if ((isset($module['logic']) && $module['logic'] === $k) || (!isset($module['logic']) && $k === 'or')): ?>checked="checked"<?php endif; ?>  />
                <?php echo $v ?>
              </label>
            <?php endforeach; ?>
          </div>
        </div>
        <div class="wpf_ct_back_active_module_row">
          <div class="wpf_ct_back_active_module_label">
            <label for="wpf_ct_<?php echo $type ?>[order]"><?php _e('Order', 'wpf') ?></label>
          </div>
          <div class="wpf_ct_back_active_module_input">
            <div class="wpf_ct_custom_select wpf_ct_order wpf_ct_changed">
              <select name="[<?php echo $type ?>][order]">
                <?php foreach ($order as $k => $v): if('term_order'===$k && !in_array($type,array('wpf_ct_cat','wpf_ct_tag'))) continue; ?>
                  <option <?php if (!empty($module['order']) && $module['order'] === $k): ?>selected="selected"<?php endif; ?> value="<?php echo $k ?>"><?php echo $v ?></option>
                <?php endforeach; ?>
              </select>
            </div>
            <div class="wpf_ct_custom_select wpf_ct_orderby">
              <select name="[<?php echo $type ?>][orderby]">
                <?php foreach ($orderby as $k => $v): ?>
                  <option <?php if (!empty($module['orderby']) && $module['orderby'] === $k): ?>selected="selected"<?php endif; ?> value="<?php echo $k ?>"><?php echo $v ?></option>
                <?php endforeach; ?>
              </select>
            </div>
          </div>
        </div>
        <?php
          $display = array(
            'horizontal' => __('Horizontal', 'wpf'),
            'vertical' => __('Vertical', 'wpf'),
            'columns' => __('Columns', 'wpf'),
          );
        ?>
        <div class="wpf_ct_back_active_module_row">
          <div class="wpf_ct_back_active_module_label">
            <label for="wpf_ct_<?php echo $type ?>[display]"><?php _e('Layout', 'wpf') ?></label>
          </div>
          <div class="wpf_ct_back_active_module_input">
            <?php foreach ($display as $k => $v): ?>
              <label>
                <input id="wpf_ct_<?php echo $type ?>[display_<?php echo $k ?>]" type="radio" value="<?php echo $k ?>" name="[<?php echo $type ?>][display]" <?php if ((!isset($module['display']) && $k === 'horizontal') || (isset($module['display']) && $module['display'] === $k)): ?>checked="checked"<?php endif; ?>  />
                <?php echo $v ?>
                <?php if ($k === 'columns'): ?>
                  <div class="wpf_ct_custom_select">
                    <select name="[<?php echo $type ?>][column]">
                      <?php for ($i = 2; $i < 4; ++$i): ?>
                        <option value="<?php echo $i ?>" <?php if (isset($module['column']) && $module['column'] == $i): ?>selected="selected"<?php endif; ?>><?php echo $i ?></option>
                      <?php endfor; ?>
                    </select>
                  </div>
                <?php endif; ?>
              </label>
            <?php endforeach; ?>
          </div>
        </div>
        <?php self::show_color_icons($type, $name, $module); ?>
        <?php if (in_array($type, array('wpf_ct_cat', 'wpf_ct_tag'))) : ?>
          <div class="wpf_ct_back_active_module_row">
            <div class="wpf_ct_back_active_module_label">
              <label for="wpf_ct_<?php echo $type ?>[include_cat]"><?php echo $type === 'wpf_ct_cat' ? __('Include Categories', 'wpf_ct') : __('Include Tags', 'wpf'); ?></label>
            </div>
            <div class="wpf_ct_back_active_module_input">
              <label>
                <input id="wpf_ct_<?php echo $type ?>[include_cat]" type="text" name="[<?php echo $type ?>][include_cat]" value="<?php echo!empty($module['include_cat']) ? $module['include_cat'] : ''; ?>">
                <br>
                <?php if ($type === 'wpf_ct_cat') : ?>
                    <?php _e('Enter category ID numbers to include only (eg. 2, 4, 12)', 'wpf'); ?>
                <?php else: ?>
                    <?php _e('Enter tag ID numbers to include only (eg. 2, 4, 12)', 'wpf') ?>
                <?php endif; ?>
              </label>
            </div>
          </div>
          <div class="wpf_ct_back_active_module_row">
            <div class="wpf_ct_back_active_module_label">
              <label for="wpf_ct_<?php echo $type ?>[exclude_cat]"><?php echo $type === 'wpf_ct_cat' ? __('Exclude Categories', 'wpf') : __('Exclude Tags', 'wpf'); ?></label>
            </div>
            <div class="wpf_ct_back_active_module_input">
              <label>
                <input id="wpf_ct_<?php echo $type ?>[exclude_cat]" type="text" name="[<?php echo $type ?>][exclude_cat]" value="<?php echo!empty($module['exclude_cat']) ? $module['exclude_cat'] : ''; ?>">
                <br>
                <?php if ($type === 'wpf_ct_cat') : ?>
                  <?php _e('Enter category ID numbers to exclude (eg. 2, 4, 12)', 'wpf'); ?>
                <?php else: ?>
                  <?php _e('Enter tag ID numbers to exclude (eg. 2, 4, 12)', 'wpf') ?>
                <?php endif; ?>
              </label>
            </div>
          </div>
        <?php endif; ?>
          <div class="wpf_ct_back_active_module_row wpf_ct_show_all_block">
            <div class="wpf_ct_back_active_module_label">
              <label for="wpf_ct_<?php echo $type ?>[show_all]"><?php _e( 'Show "All" option', 'wpf' ); ?></label>
            </div>
            <div class="wpf_ct_back_active_module_input">
              <label>
                <input id="wpf_ct_<?php echo $type ?>[show_all]" type="checkbox" name="[<?php echo $type ?>][show_all]" value="1" <?php if ( ! empty( $module['show_all'] ) ) : ?>checked="checked"<?php endif; ?> />
                <?php _e( 'Show option to list all terms', 'wpf' ) ?>
              </label>
            </div>
          </div>
        <?php break; ?>
      <?php endswitch; ?>
      <?php
    }
    private static function show_color_icons($type, $name, $module = array()) {
        if ($type === 'wpf_ct_cat') {
          $name = __('categories', 'wpf');
        }
        $get_all_languages = [
          'en' => [
            'name'     => '',
            'selected' => true,
          ],
        ];
      ?>
      <?php $categories = get_terms($type === 'wpf_ct_cat' || $type === 'wpf_ct_tag' ? str_replace('wpf_ct', 'product', $type) : $type, array('hide_empty' => false)); ?>
      <?php if (!empty($categories)): ?>
        <?php $languages = $get_all_languages; ?>
        <div class="wpf_ct_back_active_module_row wpf_ct_icons_block">
          <div class="wpf_ct_back_active_module_label">
            <label for="wpf_ct_<?php echo $type ?>[color]"><?php _e('Color Icons', 'wpf') ?></label>
          </div>
          <div class="wpf_ct_back_active_module_input wpf_ct_show_icons wpf_ct_changed">
            <label>
              <input id="wpf_ct_<?php echo $type ?>[color]" type="checkbox" name="[<?php echo $type ?>][color]" value="1" <?php if (!empty($module['color'])): ?>checked="checked"<?php endif; ?>  />
              <?php printf(__('Display %s as color icons', 'wpf'), $name) ?>
            </label>
            <div class="wpf_items_container">
              <label>
                <input id="wpf_ct_<?php echo $type ?>[tooltip]" type="checkbox" name="[<?php echo $type ?>][tooltip]" value="1" <?php if (!empty($module['tooltip'])): ?>checked="checked"<?php endif; ?>  />
                <?php _e('Display tooltip on icon hover', 'wpf'); ?>
              </label>
              <ul class="wpf_tax_items">
                <?php foreach ($categories as $cat): ?>
                  <li class="clearfix">
                    <div class="wpf_color_wrapper">
                      <label class="wpf_color_name" for="wpf_ct_<?php echo $type ?>_<?php echo $cat->term_id ?>_color"><?php echo $cat->name ?></label>
                    </div>
                    <div class="wpf_color_options_wrap">
                      <label class="wpf_color_wrap" for="wpf_ct_<?php echo $type ?>_<?php echo $cat->term_id ?>_color_bg">
                        <span><?php _e('Background', 'wpf') ?></span>
                        <input class="wpf_color_picker" type="text" id="wpf_ct_<?php echo $type ?>_<?php echo $cat->term_id ?>_color_bg" name="[<?php echo $type ?>][color_bg_<?php echo $cat->term_id ?>]" <?php if (!empty($module['color_bg_' . $cat->term_id])): ?>data-value="<?php echo $module['color_bg_' . $cat->term_id] ?>"<?php endif; ?> />
                      </label>
                      <label class="wpf_color_wrap" for="wpf_ct_<?php echo $type ?>_<?php echo $cat->term_id ?>_color_text">
                        <span><?php _e('Text Color', 'wpf') ?></span>
                        <input class="wpf_color_picker" type="text" id="wpf_ct_<?php echo $type ?>_<?php echo $cat->term_id ?>_color_text" name="[<?php echo $type ?>][color_text_<?php echo $cat->term_id ?>]" <?php if (!empty($module['color_text_' . $cat->term_id])): ?>data-value="<?php echo $module['color_text_' . $cat->term_id] ?>"<?php endif; ?> />
                      </label>
                      <label class="wpf_color_wrap wpf_color_text" for="wpf_ct_<?php echo $type ?>_text_<?php echo $cat->term_id ?>">
                        <span><?php _e('Icon Text', 'wpf') ?></span>
                        <?php WPF_Utils_CT::module_language_tabs($type, $module, $languages, 'text_' . $cat->term_id); ?>
                      </label>
                      <label class="wpf_color_wrap wpf_background_image <?php if (!empty($module['image_bg_' . $cat->term_id])): ?> has-image <?php endif;?>" for="wpf_ct_<?php echo $type ?>_<?php echo $cat->term_id ?>_image_bg">
                        <span><?php _e('Background Image', 'wpf') ?></span>
                        <input class="" type="text" id="wpf_ct_<?php echo $type ?>_<?php echo $cat->term_id ?>_image_bg"
                             name="[<?php echo $type ?>][image_bg_<?php echo $cat->term_id ?>]"
                             name="wpf_<?php echo $type ?>_<?php echo $cat->term_id ?>_image_bg"
                             <?php if (!empty($module['image_bg_' . $cat->term_id])): ?>value="<?php echo $module['image_bg_' . $cat->term_id] ?>"<?php endif; ?> />
                        <button class="open_media_uploader_image button-link "><?php esc_attr_e( 'Select Image', 'wpf' ); ?></button>
                        <div class="image-area">
                          <img class="preview-image-wraper" src="<?php echo $module['image_bg_' . $cat->term_id] ?>" alt="">
                          <i class="remove-background ti-close"></i>
                        </div>
                      </label>
                    </div>
                  </li>
                <?php endforeach; ?>
              </ul>
              <input type="checkbox" id="wpf_ct_<?php echo $type ?>_hide" name="[<?php echo $type ?>][hide]" value="1" <?php if (!empty($module['hide'])): ?>checked="checked"<?php endif; ?>/>
              <label for="wpf_ct_<?php echo $type ?>_hide">
                <?php printf(__('Hide original %s labels', 'wpf'), $name) ?>
              </label>
            </div>
          </div>
        </div>
      <?php endif; ?>
      <?php
    }
    public function save_themplate(array $post) {
    $result = false;
    if (!empty($post['layout'])) {
      $option = WPF_Options_CT::get_option($this->plugin_name, $this->version);
      if (empty($post['name'])) {
        $post['name'] = uniqid($this->plugin_name . '_');
      }
      $themplate_id = !empty($post['themplate_id']) ? $post['themplate_id'] : $option->unique_name($post['name']);
      $data = $option->get();
      $layout = stripslashes_deep($post['layout']);
      if (empty($data[$themplate_id])) {
        $data[$themplate_id] = array();
      }
      $data[$themplate_id]['layout'] = json_decode($layout, true);
      $data[$themplate_id]['data'] = array();
      $_keys = array( 'name', 'empty', 'group','reset_button', 'type', 'page', 'sort', 'pagination', 'posts_per_page', 'result', 'out_of_stock', 'scroll', 'result_type', 'tax_relation', 'pagination_type', 'no_found_message', 'infinitybuffer', 'clear_label' );
      foreach ($_keys as $k) {
        if (!empty($post[$k])) {
          $data[$themplate_id]['data'][$k] = $post[$k];
        }
      }
      $data[$themplate_id]['data']['date'] = current_time('timestamp');
      $data = apply_filters('wpf_ct_template_save', $data, $themplate_id);
      $option->set($data);
      $result = array(
        'id' => $themplate_id,
        'status' => '1',
        'text' => __('Template successfully updated', 'wpf')
      );
    }
    return $result;
  }
  protected function get_public_fields($type, array $args, array $data, array $request = array(), $lang = false) {
    $wpf = WPF_Public_CT::get_instance();
    $value = array();
    if (!empty($request[$type])) {
      $value = $request[$type];
    }
    switch ($type):
    case 'title':
    case 'sku':
      if ( ! wp_script_is( 'jquery-ui-autocomplete' ) ) {
        wp_enqueue_style($this->plugin_name . 'ui-css');
      }
    ?>
    <div class="wpf_autocomplete">
      <input type="text" autocomplete="off" name="<?php echo WPF_Utils_CT::strtolower(WPF_Utils::get_field_name($args, $type)); ?>" value="<?php echo $value ? esc_attr($value) : '' ?>" />
      <span class="wpf-search-wait"></span>
    </div>
    <?php
    break;
    case 'instock':
    case 'onsale':
      $show = true;
      if (!empty($data['empty'])) {
        $query_args = array(
          'post_type' => array('product'),
          'post_status' => 'publish',
          'posts_per_page' => 1
        );
        if ($type === 'onsale') {
        $query_args['meta_query'] = array(array(
          'relation' => 'OR',
          array(// Simple products type
            'key' => '_sale_price',
            'value' => 0,
            'compare' => '>',
            'type' => 'NUMERIC'
          ),
          array(// Variable products type
            'key' => '_min_variation_sale_price',
            'value' => 0,
            'compare' => '>',
            'type' => 'NUMERIC'
          )
        ));
        } else {
          $query_args['meta_query'] = array(array(
            'key' => '_stock_status',
            'value' => 'instock',
            'compare' => '=',
          ));
        }
        $meta_query = new WP_Query($query_args);
        $show = $meta_query->have_posts();
        wp_reset_postdata();
      if ( $type === 'instock' && ! empty( $data['out_of_stock'] ) ) {
        $value = 1;
      }
    }
    ?>  
    <?php if ( $show ) : ?>
      <div class="wpf_<?php echo $type ?>_wrapp">
        <input 
          type="checkbox"
          id="wpf_<?php echo $this->themplate_id ?>_item_<?php echo $type ?>"
          <?php if ( ! empty( $value ) ) : ?>checked="checked"<?php endif; ?>
          name="<?php echo WPF_Utils_CT::strtolower(WPF_Utils_CT::get_field_name($args, $type)); ?>"
          value="1"
        />
      </div>
    <?php endif; ?>
    <?php
    break;
    case 'submit':
    ?>
      <button type="submit" class="wpf_search_button"><?php echo WPF_Utils_CT::get_field_name($args, __('Search', 'wpf')) ?></button>
    <?php
    break;
    case 'price':
    $price_type = !empty($args['price_type']) ? $args['price_type'] : 'slider';
    $name = WPF_Utils_CT::strtolower(WPF_Utils_CT::get_field_name($args, $type));
    if ($price_type === 'slider') {
      list( $min, $max ) = $this->get_min_max_price();
      if ( empty( $max ) ) {
        return;
      }
      if ( ! wp_script_is( 'jquery-ui-slider' ) ) {
        wp_enqueue_style( $this->plugin_name . 'ui-css' );
      }
      $step = ($min >= 0 && $min < 1 && ceil($max) <=1)? 0.1 : 1;
      if (isset($args['step'])){
        $step = $args['step'];
      }
      $from = isset($value['from']) && is_numeric($value['from']) ? floor($value['from']) : '';
      $to = isset($value['to']) && is_numeric($value['to']) ? ceil($value['to']) : '';
      if (empty($min)) {
        $min = 0;
      }
      $min = floor($min);
      /* products are not filtered by price, set $from and $to to empty to prevent unnecessary meta query */
      if ( $from === $min && $to === $max ) {
        $from = '';
        $to = '';
      }
    ?>
    <div data-max="<?php echo ceil($max) ?>" data-min="<?php echo $min ?>" data-step="<?php echo $step;?>" class="wpf_slider"></div>
    <div class="wpf-slider-label">
      <?php echo str_replace( '0', '<span class="wpf-price-min">' . ( empty( $from ) ? $min : $from ) . '</span>', WPF_Utils_CT::format_price( 0 ) ); ?>
      -
      <?php echo str_replace( '0', '<span class="wpf-price-max">' . ( empty( $to ) ? $max : $to ) . '</span>', WPF_Utils_CT::format_price( 0 ) ); ?>
    </div>
    <input type="hidden" name="<?php echo $name ?>-from" value="<?php echo $from ?>" class="wpf_price_from" />
    <input type="hidden" name="<?php echo $name ?>-to" value="<?php echo $to ?>" class="wpf_price_to" />
    <?php
    } elseif (!empty($args['from'])) {
      $selected = isset($value['from']) && is_numeric($value['from']) ? floor($value['from']) : '';
      $selected.='-';
      $selected.= isset($value['to']) && is_numeric($value['to']) ? ceil($value['to']) : '';
      if ($selected === '-') {
        $selected = false;
      }
    ?>
    <ul class="wpf_price_range">
      <li>
        <input <?php if (!$selected): ?> checked="checked"<?php endif; ?> id="wpf_<?php echo $this->themplate_id ?>_item_<?php echo $type ?>_all" type="radio" name="<?php echo $name ?>" value=""/>
        <label for="wpf_<?php echo $this->themplate_id ?>_item_<?php echo $type ?>_all"><?php _e('All', 'wpf') ?></label>
      </li>
      <?php 
      foreach ( (array) $args['from'] as $i => $v): ?>
      <?php
        $from = floor($v);
        $to = (array) $args['to'];
        $to = ! empty( $to[ $i ] ) ? ceil( $to[ $i ] ) : '';
        $orig_v = $from . '-' . $to;
      ?>
      <li>
        <input <?php if ($selected === $orig_v): ?> checked="checked"<?php endif; ?> id="wpf_<?php echo $this->themplate_id ?>_item_<?php echo $type ?>_<?php echo $i ?>" type="radio" name="<?php echo $name ?>" value="<?php echo $orig_v ?>"/>
        <label for="wpf_<?php echo $this->themplate_id ?>_item_<?php echo $type ?>_<?php echo $i ?>"><?php echo WPF_Utils_CT::format_price($from) ?> - <?php echo WPF_Utils_CT::format_price($to) ?></label>
      </li>
      <?php endforeach; ?>
    </ul>
    <?php
      }
    ?>
    <?php break; ?>
    <?php
    default:
    $args['show_as'] = !empty($args['show_as']) ? $args['show_as'] : 'link';
    $link = $args['show_as'] === 'link';
    $hierarchy = !empty($args['hierachy']);
    $color = !$link && !empty($args['color']);
    $hide_text = !$link && !$hierarchy && $color && !empty($args['hide']);
    $column = $args['display'] === 'columns' ? (!empty($args['column']) ? $args['column'] : 1) : false;
    $q = array(
      'hide_empty' => !$hierarchy && !empty($data['empty']),
      'hierarchical' => $hierarchy,
      'pad_counts' => $hierarchy
    );
    if ($args['order'] !== 'term_order') {
      $q['orderby'] = $args['order'];
      $q['order'] = $args['orderby'];
    }
    if (!empty($args['include_cat'])) {
      $q['include'] = array_map('trim', explode(',', $args['include_cat']));
    }
    if (!empty($args['exclude_cat'])) {
      $q['exclude'] = array_map('trim', explode(',', $args['exclude_cat']));
    }
    $categories = get_terms(str_replace('wpf_ct_', 'product_', $type), $q);
    if ($hierarchy) {
      $cats = array();
      foreach ($categories as $c) {
        if (!isset($cats[$c->parent])) {
          $cats[$c->parent] = array();
        }
        $cats[$c->parent][] = $c;
      }
    } else {
      $cats = $categories;
    }
    unset($categories);
    $selected = null;
    if (($type === 'wpf_cat' && is_product_category()) || ($type === 'wpf_tag' && is_product_tag())) {
      global $wp_query;
      $cat = $wp_query->get_queried_object();
      if (is_object($cat) && !empty($cat->slug)) {
        if (empty($value)) {
          $value = array();
          $value[] = $cat->slug;
        } elseif ( $type === 'wpf_tag' ) {
          $value = explode(',', $value);
          $value[] = $cat->slug;
          $selected = $cat->slug;
        }
      }
    }
    $is_dropdown = 'dropdown' === $args['show_as'] || 'multiselect' === $args['show_as'];
    if ($is_dropdown) {
      $args['color'] = false;
      wp_enqueue_style( $this->plugin_name . '-select' );
    }
    ?>
    <?php if (!empty($cats)): ?>
      <?php if ($is_dropdown): ?>
        <select  name="<?php echo WPF_Utils_CT::strtolower(WPF_Utils_CT::get_field_name($args, $type)); ?><?php if ('multiselect' === $args['show_as']): ?>[]<?php endif; ?>" <?php if ('multiselect' === $args['show_as']): ?>multiple="multiple" <?php if ($selected && ($type === 'wpf_cat' || $type === 'wpf_tag')): ?>data-selected="<?php echo $selected ?>" <?php endif; ?><?php endif; ?>class="wpf_ct_dropdown">
        <?php else: ?>
          <ul class="<?php if ($link): ?>wpf_ct_links <?php endif; ?><?php if (!$hierarchy): ?>wpf_ct_column_<?php echo $args['display'] ?><?php if ($column): ?> wpf_ct_column_<?php echo $column ?><?php endif; ?><?php else: ?>wpf_ct_hierachy<?php endif; ?><?php if ($color): ?> wpf_ct_color_icons<?php endif; ?><?php if ($hide_text): ?> wpf_ct_hide_text<?php endif; ?>">
          <?php endif; ?>
          <?php if (!empty($args['hierachy'])): ?>
            <?php $this->category_walker($cats[0], $cats, $type, $args, $value, !empty($data['empty']), $lang); ?>
          <?php else: ?>
            <?php $this->category_walker($cats, array(), $type, $args, $value, !empty($data['empty']), $lang); ?>
          <?php endif; ?>
          <?php if ($is_dropdown): ?>
        </select>
        <?php else: ?>
        </ul>
      <?php endif; ?>
    <?php endif; ?>
    <?php break; ?>
    <?php endswitch; ?>
    <?php
  }
  private function category_walker($items, $cats = array(), $type, array $args = array(), $value, $hide_empty = true, $lang, $i = 1) {
        // echo '<pre>';
        //     echo 'ggggggggg';
        //     var_export($items);
        // echo '</pre>';
        $hierarchy = !empty($args['hierachy']);
        $color = !empty($args['color']);
        $hide_text = !$hierarchy && $color && !empty($args['hide']);
        $show_count = !empty($args['count']);
        $value = empty($value) ? array() : (!is_array($value) ? explode(',', $value) : $value);
        static $product_count = false;
        $name = WPF_Utils_CT::strtolower( WPF_Utils_CT::get_field_name( $args, $type ) );
        $name = urldecode( $name );
        if ($product_count === false && $show_count) {
            $product_count = WPF_Utils_CT::count_posts( 'product' );
        }
        ++$i;
        if ( 2 === $i && ! empty( $args['show_all'] ) ) :
            ?>
            <?php if ('radio' === $args['show_as']):
            $term_id = isset($cats->term_id)? $cats->term_id : '';
            ?>
                <li class="<?php echo $name, '_option_all'; ?>">
                    <input <?php if (empty($value)): ?>checked="checked"<?php endif; ?> id="<?php echo $name, '_option_all'; ?>" type="radio" name="<?php echo $name; ?>[]" value="" />
                    <label <?php if (($color && !empty($args['color_bg_' . $term_id])) || !empty($args['image_bg_' . $term_id])): ?>
                            style="
                            <?php if (!empty($args['image_bg_' . $term_id])):?>background-image: url(<?php echo $args['image_bg_' . $term_id] ?>);background-size: cover;<?php endif;?>
                            <?php if (!empty($args['color_bg_' . $term_id])):?>background-color:<?php echo $args['color_bg_' . $term_id]?>; <?php endif; ?>
                            <?php if (!empty($args['color_text_' . $term_id])): ?> color:<?php echo $args['color_text_' . $term_id] ?>;<?php endif; ?>"
                          <?php endif; ?>
                            for="wpf_<?php echo $this->themplate_id ?>_<?php echo $term_id ?>">
                    <label <?php if ($color): ?> class="wpf-label-option-all"<?php endif; ?> for="<?php echo $name, '_option_all'; ?>">
                        <?php _e('All', 'wpf'); ?>
                    </label>
                    <?php if ($show_count): ?>
                        <span class="wpf_item_count"><?php echo $product_count; ?></span>
                    <?php endif; ?>
                </li>
            <?php elseif ('dropdown' === $args['show_as']): ?>
                <option value="">
                    <?php _e('All', 'wpf'); ?>
                    <?php if ($show_count): ?>
                        &nbsp;(<?php echo $product_count; ?>)
                    <?php endif; ?>
                </option>
            <?php elseif (strpos($type, 'pa_') === 0 && 'link' === $args['show_as']): ?>
                <li class="<?php echo $name; ?>">
                    <a class="wpf_pa_link" href="javascript:void(0)">
                        <input <?php if (!$value): ?>checked="checked"<?php endif; ?> type="radio" value="" name="<?php echo $name ?>" />
                        <span><?php _e('All', 'wpf'); ?></span>
                    </a>
                    <?php if ($show_count): ?>
                        <span class="wpf_item_count"><?php echo $product_count; ?></span>
                    <?php endif; ?>
                </li>
            <?php endif; ?>
        <?php endif; ?>
        <?php foreach ( $items as $cat ) :
        $cat->slug = urldecode( $cat->slug ); // make slug readable, required for multilingual websites
        $read_only = '';
        if ( is_product_category() || is_product_tag() ) {
          $query_object = get_queried_object();
          if ( $cat->taxonomy === $query_object->taxonomy && $query_object->slug === $cat->slug ) {
            $read_only = 'readonly="readonly"';
          }
        }
        ?>
            <?php if ($hide_empty && $cat->count === 0): ?>
                <?php continue; ?>
            <?php endif; ?>
            <?php if ('dropdown' === $args['show_as'] || 'multiselect' === $args['show_as']): ?>
                <option<?php if ( in_array( $cat->slug, $value, true ) ) : ?> selected="selected"<?php endif; ?> value="<?php echo $cat->slug ?>">
                    <?php
                    if ($hierarchy && $i > 2) {
                        echo str_repeat('&nbsp;', ($i - 2) * 3);
                    }
                    ?>
                    <?php echo $cat->name; ?>
                    <?php if ($show_count): ?> &nbsp;(<?php echo $cat->count ?>)<?php endif; ?>
                </option>
                <?php if ($hierarchy && !empty($cats[$cat->term_id])): ?>
                    <?php $this->category_walker($cats[$cat->term_id], $cats, $type, $args, $value, $hide_empty, $lang, $i); ?>
                <?php endif; ?>
            <?php else: ?>
                <li class="<?php echo "wpf_{$cat->taxonomy}_{$cat->term_id}"; ?>">
                    <?php if ('link' === $args['show_as']): ?>
                        <?php if (strpos($type, 'pa_') !== 0 && in_array( $cat->slug, $value, true ) ): ?>
                            <span class="wpf_selected"><?php echo $cat->name ?></span>
                        <?php else: ?>
                            <?php if (strpos($type, 'pa_') === 0): ?>
                                <a class="wpf_pa_link" href="<?php echo get_term_link($cat->term_id, $cat->taxonomy); ?>">
                                    <input <?php echo $read_only; ?> <?php if (in_array($cat->slug, $value,true)): ?>checked="checked"<?php endif; ?> type="radio" value="<?php echo $cat->slug ?>" name="<?php echo $name ?>" />
                                    <span><?php echo $cat->name ?></span>
                                </a>
                            <?php else: ?>
                                <a href="<?php echo get_term_link($cat->term_id, $cat->taxonomy); ?>">
                                    <?php echo $cat->name ?>
                                </a>
                            <?php endif; ?>
                        <?php endif; ?>
                    <?php else: ?>
                        <?php
                        $show_label = $color && (!$hide_text || !empty($args['text_' . $cat->term_id][$lang]));
                        $label = $show_label && !empty($args['text_' . $cat->term_id][$lang]) ? WPF_Utils_CT::get_label($args['text_' . $cat->term_id]) : $cat->name;
                        $color_bg = !empty($args['color_bg_' . $cat->term_id])?$args['color_bg_' . $cat->term_id]:'';
                        $color_text=!empty($args['color_text_' . $cat->term_id])?$args['color_text_' . $cat->term_id]:'';
                        $image_bg=!empty($args['image_bg_' . $cat->term_id])?$args['image_bg_' . $cat->term_id]:'';
                        ?>
                        <input <?php echo $read_only; ?> <?php if ( in_array( $cat->slug, $value, true ) ): ?>checked="checked"<?php endif; ?> id="wpf_<?php echo $this->themplate_id ?>_<?php echo $cat->term_id ?>" type="<?php echo $args['show_as'] ?>" name="<?php echo $name; ?>[]" value="<?php echo $cat->slug ?>" />
                        <label <?php if (($color && ! empty( $color_bg ) ) || ! empty( $image_bg ) ) : ?>
                                style="
                                    <?php if ( ! empty( $image_bg ) ) : ?>background-image: url(<?php echo $image_bg ?>);background-size: cover;<?php endif;?>
                                    <?php if ( ! empty( $color_bg ) ) : ?>background-color:<?php echo $color_bg; ?>; <?php endif;?>
                                    <?php if ( ! empty( $color_text ) ) : ?> color:<?php echo $color_text ?>;<?php endif; ?>"
                               <?php endif; ?>
                                for="wpf_<?php echo $this->themplate_id ?>_<?php echo $cat->term_id ?>">
                            <?php if ($show_label || !$color): ?><?php echo $label ?><?php else: ?><i></i><?php endif; ?>
                            <?php if(!empty($args['tooltip'])): ?>
                            <span class="wpf_tooltip"><?php echo $label ?></span>
                            <?php endif; ?>
                        </label>
                    <?php endif; ?>
                    <?php if ($show_count): ?><span class="wpf_item_count"><?php echo $cat->count ?></span><?php endif; ?>
                    <?php if ($hierarchy && !empty($cats[$cat->term_id])): ?>
                        <ul class="wpf_submenu wpf_level_<?php echo $i ?>">
                            <?php $this->category_walker($cats[$cat->term_id], $cats, $type, $args, $value, $hide_empty, $lang, $i); ?>
                        </ul>
                    <?php endif; ?>
                </li>
            <?php endif; ?>
        <?php endforeach; ?>
        <?php
    }
}
?>
```

C:\xampp\htdocs\test\wp-content\plugins\plugin-name\public\js\wpf-public\_ct.js

```
(function ($) {
    'use strict';
    var in_scroll = false;
	var infinitybuffer = 300; /* how soon wpf will load the next set of products. Higher number means sooner */
    function triggerEvent(a, b) {
        var c;
        document.createEvent ? (c = document.createEvent("HTMLEvents"), c.initEvent(b, !0, !0)) : document.createEventObject && (c = document.createEventObject(), c.eventType = b), c.eventName = b, a.dispatchEvent ? a.dispatchEvent(c) : a.fireEvent && htmlEvents["on" + b] ? a.fireEvent("on" + c.eventType, c) : a[b] ? a[b]() : a["on" + b] && a["on" + b]()
    }
	/**
	 * Loads a script file if test() parameter passes, then calls callback()
	 *
	 * @param src string
	 * @param test function to check whether script needs to be loaded
	 * @param callback function
	 */
	var load_script = function( src, test, callback ) {
		if (test && test() === true) {
			if (callback) {
				callback();
			}
			return;
		}
		const s = document.createElement('script');
		s.setAttribute('async', 'async');
		s.onload = function () {
			if (callback) {
				callback();
			}
			const key = this.getAttribute('id');
		};
		document.head.appendChild(s);
		s.setAttribute('src', src);
	};
	/**
	 * load multiple script files, then calls callback() when all are loaded
	 *
	 * @param scripts array multidimensional
	 * @param callback function
	 */
	var load_scripts = function( scripts, callback ) {
		if ( scripts.length === 0 ) {
			callback();
			return;
		}
		load_script( scripts[0][0], scripts[0][1], function() {
			scripts.shift();
			load_scripts( scripts, callback );
		} );
	};
	var load_slider = function( callback ) {
		var jquery_path = wpf.includes_url + 'js/jquery/';
		var scripts = [
			[ jquery_path + 'ui/core.min.js', function() { return typeof $.ui === 'object' } ],
			[ jquery_path + 'ui/mouse.min.js', function() { return typeof $.ui.mouse === 'function' } ],
			[ jquery_path + 'jquery.ui.touch-punch.js', function() { return ! ( 'ontouchstart' in window ); } ],
			[ jquery_path + 'ui/slider.min.js', function() { return typeof $.ui.slider === 'function' } ]
		];
		/* compatibility with WP 5.5.3 or lower */
		if ( wpf.load_jquery_ui_widget ) {
			scripts.unshift( [ jquery_path + 'ui/widget.min.js', function() { return typeof $.widget === 'function' } ] );
		}
		load_scripts( scripts, function() {
			callback();
		} );
	};
    var InitSlider = function ( container ) {
		if ( ! $.fn.slider ) {
			return;
		}
		$( '.wpf_slider', container ).each(function () {
			var $wrap = $(this).closest('.wpf_item'),
				$min = $wrap.find('.wpf_price_from'),
				$max = $wrap.find('.wpf_price_to'),
				$min_val = parseInt($(this).data('min')),
				$max_val = parseInt($(this).data('max')),
				step = parseFloat($(this).data('step')),
				$form = $wrap.closest('form'),
				$v1 = parseInt($min.val()),
				$v2 = parseInt($max.val());
			var $label_min = $wrap.find( '.wpf-price-min' ),
				$label_max = $wrap.find( '.wpf-price-max' );
			// check for valid numbers in data-min and data-max
			if ($min_val === parseInt($min_val, 10) && $max_val === parseInt($max_val, 10)) {
				$v1 = $v1 ? $v1 : $min_val;
				$v2 = $v2 ? $v2 : $max_val;
				$(this).slider({
					range: true,
					min: $min_val,
					step: isNaN(step) || step <= 0 ? 1 : step,
					max: $max_val,
					values: [$v1, $v2],
					slide: function (event, ui) {
						$label_min.text( ui.values[ 0 ] );
						$label_max.text( ui.values[ 1 ] );
					},
					stop: function (event, ui) {
						$min.val(ui.values[ 0 ]);
						$max.val(ui.values[ 1 ]);
						if ($form.hasClass('wpf_submit_on_change')) {
							$form.trigger( 'submit' );
						}
					}
				});
				$(this).slider().on('slidechange',function(event,ui){
					$(ui.handle).find('.wpf_tooltip_amount').html(ui.value);
				});
			}
		});
    };
    var InitGroupToggle = function ( container ) {
        $( 'body' ).off( 'click.wpfGroupToggle' ).on( 'click.wpfGroupToggle', '.wpf_grouped_label', function (e) {
            var $wrap = $(this).next('.wpf_items_group'),
				$this = $(this);
			e.preventDefault();
			if ($wrap.is(':visible')) {
				$wrap.slideUp(function () {
					$this.addClass('wpf_grouped_close');
				});
			}
			else {
				$wrap.slideDown(function () {
					$this.removeClass('wpf_grouped_close');
				});
			}
        });
		$( '.wpf_items_grouped:not(.wpf_layout_horizontal) .wpf_item_name', container ).each( function() {
			if ( $( this ).closest( '.wpf_item_onsale, .wpf_item_instock' ).length ) {
				return;
			}
			$( this ).addClass( 'wpf_grouped_label' ).trigger( 'click' );
		} );
    };
	var getProductsContainer = function( context = null ) {
		var $container = $( '.wpf-search-container', context ).first();
		if ( $container.length === 0 ) {
			$container = $( '.wc-products.loops-wrapper', context ).parent(); // Themify Builder WooCommerce
			if ( $container.length === 0 ) {
				$container = $( '.woocommerce ul.products', context ).parent();
				if ( $container.length === 0 ) {
					$container = $( 'ul.products', context ).parent();
					if ( $container.length === 0 ) {
						$container = $( '.post', context ).first();
					}
				}
			}
		}
		return $container.first().addClass( 'wpf-search-container' );
	};
    var InitSubmit = function () {
        var masonryData, isMasonry;
        $( 'body' ).off( 'submit.wpfForm' ).on( 'submit.wpfForm', '.wpf_ct_form', function (e) {
            e.preventDefault();
            var $form = $(this),
				$container = getProductsContainer(),
				data = $form.serializeArray(),
				result = {};
            for (var i in data) {
                if ( data[i].value.trim() ) {
                    var name = data[i].name.replace('[]', '');
                    if (!result[name]) {
                        result[name] = data[i].value;
                    }
                    else {
                        result[name] += ',' + data[i].value;
                    }
                }
            }
            if (in_scroll) {
               result['append'] = 1;
            }
            $form.find('input[name="wpf_page"]').val('');
            // Save isotope data if masonry is enabled
			if ( $container.length ) {
				const productsWrap = $container[0].getElementsByClassName('products');
				masonryData = masonryData || $( '.products', $container ).data( 'isotope' ) || (typeof Isotope === 'function' && productsWrap.length>0 && Isotope.data( productsWrap[0] ));
				isMasonry = isMasonry || typeof masonryData === 'object' && 'options' in masonryData;
			}
			if ( $form.hasClass( 'wpf_form_ajax' ) && ! $container.length ) {
				/**
				 * result is supposed to display on the same page, but there's no loop to display it;
				 * post the data to Shop page
				 */
				$form.removeClass( 'wpf_form_ajax' ).attr( 'action', $form.attr( 'data-shop' ) );
			}
			var currentUrl = new URL( $form.prop( 'action' ) );
			for ( const i in result ) {
				currentUrl.searchParams.set( i, result[ i ] );
			}
            if ( ! $form.hasClass( 'wpf_form_ajax' ) ) {
				window.location = currentUrl.toString();
				return false;
            }
            $.ajax({
                url: currentUrl.toString(),
                type: 'GET',
                beforeSend: function () {
                    document.body.classList.add( 'wpf_loading' );
                    $form.addClass( 'wpf-search-submit' );
                    $container.addClass( 'wpf-container-wait' );
                },
                complete: function () {
					document.body.classList.remove( 'wpf_loading' );
                    $form.removeClass( 'wpf-search-submit' );
                    $container.removeClass( 'wpf-container-wait' );
                },
                success: function (resp) {
                    if (resp) {
                        history.replaceState({}, null, currentUrl.toString() );
                        var scrollTo = $container,
                            products=null,
                            containerClass = $('.products', $container).attr('class'),
                            $resp = $( resp ),
							$resp_container = getProductsContainer( $resp );
                        $container.data('slug', $form.data('slug'));
                        $.event.trigger( 'wpf_ajax_before_replace' );
                        if ( in_scroll ) {
                            products = $resp_container.find('.product');
                            products.addClass('wpf_transient_product')
								.removeClass( 'first last' ); // remove grid classes
                            $( '.products', $container ).first().append( products );
							var columns = containerClass.match( /columns-(\d)/ );
							/* add proper "first" & "last" classes to the products */
							if ( columns !== null ) {
								columns = parseInt( columns[1] );
								$( '.products', $container ).first()
									.find( '.product:nth-child(' + columns + 'n+1)' ).addClass( 'first' )
									.end().find( '.product:nth-child(' + columns + 'n)' ).addClass( 'last' );
							}
                            var scroll = $resp.find('.wpf_infinity a');
                            if(scroll.length > 0){
                                $('.wpf_infinity a',$container).data({
                                    current : scroll.data('current'),
                                    max : scroll.data('max')
                                });
                            }
                            $container.removeClass('wpf-infnitiy-scroll');
                            scrollTo = products.first();
                            delete result['append'];
                            setTimeout(function(){
                                in_scroll = false;
                            },200);
                        } else {
							// remove existing pagination links
							$( '.wpf-pagination' ).remove();
							if ( $resp_container.find( '.product' ).length ) {
								$container.empty().append( $resp_container.removeAttr( 'class' ) );
								wpfInit( $container );
							} else {
								// 404, no products matching the selection found
								$container.empty().append( $form.find( '.wpf-no-products-found' ).clone().show() );
							}
                        }
                        if( isMasonry && $.fn.isotope ) {
							if ( typeof masonryData['appended'] === 'function' && products !== null ) {
								masonryData.appended( products );
							}
                        } else if ($form.hasClass('wpf_form_scroll')) {
                            ToScroll(scrollTo);
                        }
						if ( products !== null ) {
							products.addClass('wpf_transient_end_product');
						}
                        if ( window.wp !== undefined && window.wp.mediaelement !== undefined ) {
                            window.wp.mediaelement.initialize();
                        }
                        $.event.trigger( 'wpf_ajax_success' );
                        triggerEvent(window, 'resize');
                    }
                }
            });
        });
    };
    var ToScroll = function ($container) {
        if ($container.length > 0) {
            $('html,body').animate({
                scrollTop: $container.offset().top - $('#wpadminbar').outerHeight(true) - 10
            }, 1000);
        }
    };
	var infinityEl = $(); /* element to check scroll off of */
    var infinity = function (e, click) {
		if ( ! infinityEl.length ) {
			infinityEl = getProductsContainer();
		}
		if ( ! in_scroll && (
			click
			|| ( window.scrollY > infinityEl.offset().top + infinityEl.outerHeight() - infinitybuffer ) // scroll past the products container
			|| ( ( window.innerHeight + window.pageYOffset ) >= document.body.offsetHeight ) // reach bottom of the page
		) ) {
            var container = $('.wpf-search-container'),
				scroll = $('.wpf_infinity a', container),
				$form = $('.wpf_ct_form_' + container.data('slug'));
            if ( ! $form.length ) {
				$form = $( '.wpf_ct_form:first' );
			}
            if ( $form.length ) {
                var current = scroll.data('current');
                if (current <= scroll.data('max')) {
                    $form.find('input[name="wpf_page"]').val(current);
                    in_scroll = true;
                    if (!click) {
                        container.addClass('wpf-infnitiy-scroll');
                    }
                    $form.trigger( 'submit' );
                    if (((current + 1) > scroll.data('max'))) {
                        $('.wpf_infinity').remove();
                        if (!click) {
                            $(this).off('scroll', infinity);
                        }
                    }
                }
            }
        }
    };
    var InitPagination = function () {
        function find_page_number(element) {
            var $page = parseInt(element.text());
            if ( ! $page ) {
                $page = parseInt(element.closest('.woocommerce-pagination,.pagenav').find('.current').text());
                if (element.hasClass('next')) {
                    ++$page;
                } else {
                    --$page;
                }
                var pattern = new RegExp( '(?<=paged=)[^\b\s\=]+' );
                if( ! $page && pattern.test( element.attr( 'href' ) ) ) {
                        $page = element.attr( 'href' ).match( pattern )[0];
                }
            }
            return $page;
        }
        if ($('.wpf_infinity_auto').length > 0) {
            $('#load-more').remove();
            $(window).off('scroll', infinity).on('scroll', infinity);
        }
        else if ($('.wpf_infinity').length > 0) {
			$('.wpf_infinity').closest('.wpf-hide-pagination').removeClass('wpf-hide-pagination');
            $('#load-more').remove();
            $( 'body' ).off( 'click.wpfInfinity' ).on( 'click.wpfInfinity', '.wpf_infinity a', function (e) {
                e.preventDefault();
                e.stopPropagation();
                infinity(e, 1);
            });
        }
        else {
            $( 'body' ).off( 'click.wpfPagination' ).on( 'click.wpfPagination', '.wpf-pagination a,.woocommerce-pagination a', function (e) {
                if("1" == new URL(window.location.href).searchParams.get("wpf")){
                    var $slug = $(this).closest('.wpf-search-container').data('slug'),
                        $form = $('.wpf_ct_form_' + $slug);
                    if ($form.length > 0 && $form.find('input[name="wpf_page"]').length > 0) {
                        e.preventDefault();
                        $form.find('input[name="wpf_page"]').val(find_page_number($(this)));
                        $form.trigger( 'submit' );
                    }
                }
            });
        }
    };
	/* decode HTML entities */
	var decodeEntities = function( string ) {
		var textarea = document.createElement( 'textarea' );
		textarea.innerHTML = string;
		return textarea.innerText;
	}
	var isValidUrl = function( string ) {
		try {
			new URL(string);
		} catch (_) {
			return false;  
		}
		return true;
	}
	/**
	 * Loads jQuery UI AutoComplete library and calls callback()
	 */
	var load_autocomplete = function( callback ) {
		var jquery_ui_path = wpf.includes_url + 'js/jquery/ui/';
		var scripts = [
			[ jquery_ui_path + 'core.min.js', function() { return typeof $.ui === 'object' } ],
			[ jquery_ui_path + 'position.min.js', function() { return typeof $.ui.position === 'object' } ],
			[ jquery_ui_path + 'menu.min.js', function() { return typeof $.ui.menu === 'function'; } ],
			[ jquery_ui_path + 'autocomplete.min.js', function() { return typeof $.ui.autocomplete === 'function' } ]
		];
		/* compatibility with WP 5.5.3 or lower */
		if ( wpf.load_jquery_ui_widget ) {
			scripts.unshift( [ jquery_ui_path + 'widget.min.js', function() { return typeof $.widget === 'function' } ] );
		}
		load_scripts( scripts, function() {
			callback();
		} );
	};
    var InitAutoComplete = function ( container ) {
		if ( ! $.fn.autocomplete ) {
			return;
		}
        var cache = [];
        $( '.wpf_autocomplete input', container ).each(function () {
            var $this = $(this),
                    $key = $this.closest('.wpf_item_sku').length > 0 ? 'sku' : 'title',
                    $spinner = $this.next('.wpf-search-wait'),
                    $form = $this.closest('form'),
                    $submit = $form.hasClass('wpf_submit_on_change');
            cache[$key] = [];
            $(this).autocomplete({
                minLength: 0,
                classes: {
                    "ui-autocomplete": "highlight"
                },
                source: function (request, response) {
                    var term = $.trim(request.term);
                    if ($submit && term.length === 0 && request.term.length === 0) {
                        $form.trigger( 'submit' );
                    }
                    if (term.length < 1) {
                        return;
                    }
                    request.term = term;
                    term = term.toLowerCase();
                    if (term in cache[$key]) {
                        response(cache[$key][ term ]);
                        return;
                    }
                    $spinner.show();
                    request.key = $key;
                    request.action = 'wpf_autocomplete';
                    $.post(
                            wpf.ajaxurl,
                            request,
                            function (data, status, xhr) {
                                $spinner.hide();
								for ( const i in data ) {
									data[ i ]['label'] = decodeEntities( data[ i ]['label'] );
								}
                                cache[$key][ term ] = data;
                                response(data);
                        },'json');
                },
                select: function (event, ui) {
					if ( isValidUrl( ui.item.value ) ) {
						window.location = ui.item.value;
					} else {
						$this.val( ui.item.value );
						if ($submit) {
							$form.trigger( 'submit' );
						}
					}
                    return false;
                }
            })
            .on( 'focus', function () {
                if ( $this.val().trim().length > 0) {
                    $(this).autocomplete("search");
                }
            })
            .autocomplete("widget").addClass("wpf_ui_autocomplete");
            ;
        });
    };
    var InitOrder = function () {
        function Order(val, obj) {
            var $slug = obj.closest('.wpf-search-container').data('slug'),
                    $form = $('.wpf_ct_form_' + $slug);
            if ($form.length > 0 && $form.find('input[name="orderby"]').length > 0) {
                $form.find('input[name="orderby"]').val(val);
                $form.trigger( 'submit' );
            }
        }
        $('.wpf-search-container').on('form.woocommerce-ordering', 'submit', function (e) {
            e.preventDefault();
            Order($(this).find('select').val(), $(this));
        }).on('select.orderby', 'change', function (e) {
            Order($(this).val(), $(this));
        });
        if (!$('.wpf-search-container').data('slug')) {
            $('.wpf-search-container').data('slug', $('.wpf_ct_form').last().data('slug'));
        }
    };
    var InitChange = function ( container ) {
        if ( $( '.wpf_submit_on_change', container ).length > 0) {
            $( '.wpf_submit_on_change', container ).each(function () {
                var $form = $(this);
                $form.find('input[type!="text"],select').on( 'change', function (e) {
                    if( $(this).attr("name") == 'price' && $(this).is(":checked") ) {
                        $(".wpf_price_range label").removeClass("active");
						$(this).next("label").addClass("active");
                    }
                    $form.trigger( 'submit' );
                });
                $form.find('.wpf_pa_link').on( 'click', function (e) {
                    e.preventDefault();
                    $(this).find('input').prop('checked', true).trigger('change');
                });
            });
        }
    };
    var InitTabs = function ( container ) {
        var $horizontal = $( '.wpf_layout_horizontal', container );
        if ($horizontal.length > 0) {
            InitTabsWidth($horizontal);
            $horizontal.find('.wpf_item:not(.wpf_item_onsale):not(.wpf_item_instock)').hover(
                function () {
                    $(this).children('.wpf_items_group').stop().fadeIn();
                },
                function () {
                    var $this = $(this);
                    if ($this.closest('.wpf-search-submit').length === 0) {
                        var hover = true;
                        $( '.wpf_ui_autocomplete', container ).each(function () {
                            if ($(this).is(':hover')) {
                                hover = false;
                                return false;
                            }
                        });
                        if (hover) {
                            $this.children('.wpf_items_group').stop().fadeOut();
                        }
                    }
                }
            );
            if(navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/)){
                $horizontal.find('.wpf_item:not(.wpf_item_onsale):not(.wpf_item_instock) .wpf_item_name').click(function(){
                    var $parent = $(this).parent(),
                        isVisible = $parent.children('.wpf_items_group').is(':visible'),
                        touched = $parent.hasClass('wpf_touched');
                    if(isVisible && !touched){
                        $parent.addClass('wpf_touch_tap');
                        $parent.trigger('mouseleave');
                    }else if(!isVisible && !touched){
                        $parent.removeClass('wpf_touch_tap');
                        $parent.trigger('mouseenter');
                        $parent.removeClass('wpf_touched');
                    }else if(touched){
                        $parent.removeClass('wpf_touched');
                    }
                });
            }
            var interval;
            $(window).resize(function (e) {
                if (!e.isTrigger) {
                    clearTimeout(interval);
                    interval = setTimeout(function () {
                        InitTabsWidth($horizontal);
                    }, 500);
                }
            });
        }
    };
    var InitTabsWidth = function ($groups) {
        $groups.each(function () {
			var $group = $( this );
            var $items = $group.find('.wpf_items_group'),
                    $middle = Math.ceil($items.length / 2),
                    last = $items.last().closest('.wpf_item'),
                    max = last.offset().left;
            $items.each(function () {
                var p = $(this).closest('.wpf_item');
                if (max < p.offset().left) {
                    last = p;
                    max = p.offset().left;
                }
            });
            var $firstPos = $items.first().closest('.wpf_item').offset().left - 2,
                    $lastPos = max + last.outerWidth(true);
            last = null;
            max = null;
            $items.each(function (i) {
				var parent_item = $(this).closest('.wpf_item'),
						left = parent_item.offset().left;
				if ( screen.width > 1000 ) {
					$( this ).css( 'left', '' );
					if (i + 1 >= $middle) {
						$(this).removeClass('wpf_left_tab').addClass('wpf_right_tab').outerWidth(Math.round(left + parent_item.width() - $firstPos));
					}
					else {
						$(this).removeClass('wpf_right_tab').addClass('wpf_left_tab').outerWidth(Math.round($lastPos - left));
					}
				} else {
					$(this).removeClass('wpf_right_tab').addClass('wpf_left_tab').outerWidth( Math.round( $group.width() ) ).css( 'left', ( left - $group.offset().left ) * -1 );
				}
            });
        });
    };
	/**
	 * Loads Select2 library and calls callback()
	 */
	var load_select2 = function( callback ) {
		load_script( wpf.url + 'js/select2.min.js', function() {
			return typeof $.fn.select2 === 'function';
		}, function() {
			callback();
		} );
	};
    var initSelect = function( container ) {
       if ( ! $.fn.select2 ) {
		   return;
	   }
        function clear(el,selected){
            var text = el.find('[value="'+selected+'"]').text();
            el.next('.select2').find('[title="'+text+'"]').addClass('wpf_disabled');
        }
        $( '.wpf_ct_form', container ).find('select').each(function(){
            var el = $(this),
                is_multi = el.prop('multiple'),
                selected =  is_multi?el.data('selected'):false;
            el.select2({
                dir: wpf.rtl ? 'rtl' : 'ltr',
                minimumResultsForSearch: 10,
                dropdownCssClass: 'wpf_selectbox',
                allowClear: !selected && is_multi,
                placeholder:is_multi?'':false
            });
            if(selected && is_multi){
                clear(el,selected);
                el.on('change',function(e){
                    clear(el,selected);
                });
            }
        });
    };
    var initReset = function( container ) {
		$( '.wpf_reset_btn', container ).each( function() {
           this.addEventListener( 'click',function (e) {
                e.preventDefault();
                var target = e.target,
                    area = target.closest('.wpf_item');
                area = null === area ? target.closest('.wpf_ct_form'):area;
                var inputs = area.querySelectorAll('input,select');
                for (var k = inputs.length-1; k>=0; k--) {
					if ( inputs[ k ].hasAttribute( 'readonly' ) ) {
						continue;
					}
                    if(inputs[k].tagName === 'INPUT'){
                        switch (inputs[k].type) {
                            case 'text':
                                inputs[k].value = '';
                                break;
                            case 'radio':
                            case 'checkbox':
                                inputs[k].checked = false;
                        }
                    }else{
                        inputs[k].selectedIndex = 0;
                        $(inputs[k]).val(null).trigger('change');
                    }
                }
                $(area).find('.wpf_slider').each(function () {
                    var $slider = $(this),
                        min = $slider.data('min'),
                        max = $slider.data('max');
                    $slider.siblings( ".wpf_price_from" ).val(min);
                    $slider.siblings( ".wpf_price_to" ).val(max);
					// update labels
					$slider.closest( '.wpf_item' ).find( '.wpf-price-min' ).text( min )
						.end().find( '.wpf-price-max' ).text( max );
                    $slider.slider("values", 0, min);
                    $slider.slider("values", 1, max);
                });
                $(target.closest('.wpf_ct_form')).trigger( 'submit' );
            })
		} );
    };
	var InitPagination2 = function( context ) {
		if ( window.location.href.includes( 'wpf=' ) ) { // when WPF filter is applied
			/* remove pagination links not added by WPF */
			const container = context.hasClass( 'wpf-search-container' ) ? context : context.find( '.wpf-search-container' );
			$( '.woocommerce-pagination', container ).each( function() {
				if ( ! $( this ).closest( '.wpf-pagination' ).length ) {
					$( this ).remove();
				}
			} );
		}
		$( '.wpf-pagination', context ).each( function() {
			$( this ).insertAfter( $( this ).parent() );
		} );
	}
	var wpfInit = function( container ) {
		container = container || $( 'body' );
		$( '.wpf_ct_form', container ).css( 'visibility', 'visible' );
		InitTabs( container );
		InitGroupToggle( container );
		if ( $( '.wpf_ct_form', container ).find( 'select' ).length ) {
			load_select2( function() {
				initSelect( container );
			} );
		}
		if ( $( '.wpf_slider', container ).length ) {
			load_slider( function() {
				InitSlider( container );
			} );
		}
		infinitybuffer = $( '.wpf_ct_form' ).data( 'infinitybuffer' );
		InitPagination();
		InitOrder();
		InitChange( container );
		if ( $( '.wpf_autocomplete input', container ).length ) {
			load_autocomplete( function() {
				InitAutoComplete( container );
			} );
		}
		InitSubmit();
		initReset( container );
		InitPagination2( container );
	}
    $(document).ready(function () {
        if ($('.wpf_ct_form').length > 0) {
            $('body').addClass( 'woocommerce' );
            // Check for compatibility with Divi & Elementor
            var grid,
                diviConatainer = document.querySelector('.et_pb_module.et_pb_shop .woocommerce'),
                elementorConatainer = document.querySelector('.elementor-element.elementor-wc-products');
            if(null !== diviConatainer){
                diviConatainer.className += ' wpf-search-container';
                // Set Divi column
				var products = diviConatainer.querySelector( 'ul.products' );
				if ( products ) {
					grid = products.className.match(/columns-(\d+)/);
				}
            }else if(null !== elementorConatainer){
                elementorConatainer.className += ' wpf-search-container';
                // Set elementor column
                grid = elementorConatainer.querySelector('ul.products').className.match(/columns-(\d+)/);
            }else{
                // Try to get wc-products grid
                var container = document.querySelector('.wc-products');
                if(null!==container){
                    grid = container.className.match(/grid(\d+)/);
                }else{
                    container = document.querySelector('.woocommerce > .products');
                    if(null!==container){
                        grid = container.className.match(/columns-(\d+)/);
                        grid = null !== grid ? grid : container.parentElement.className.match(/columns-(\d+)/);
                    }
                }
            }
            if(null !== grid && undefined != grid){
                document.querySelector('[name="wpf_cols"]').value = grid[1];
            }
			wpfInit();
        }
    });
}(jQuery));
```

C:\xampp\htdocs\test\wp-content\plugins\plugin-name\public\class-wpf-public\_ct.php

```
public function register_assets() {
    global $wp_version;
    $plugin_url = plugin_dir_url( __FILE__ );
    $translation_ = array(
      'ajaxurl' => admin_url( 'admin-ajax.php' ),
      'url' => trailingslashit( $plugin_url ),
      'ver' => $this->version,
      'rtl' => is_rtl(),
      'includes_url' => trailingslashit( includes_url() ),
      'load_jquery_ui_widget' => version_compare( $wp_version, '5.6', '<' ),
    );
    wp_register_style( $this->plugin_name . '-select', $plugin_url . 'css/select2.min.css', false, $this->version, false );
    wp_register_script( $this->plugin_name, $plugin_url . 'js/wpf-public_ct.js', array( 'jquery' ), $this->version, false );
    wp_localize_script( $this->plugin_name, 'wpf_ct', $translation_ );
    wp_register_style( $this->plugin_name . 'ui-css', $plugin_url . 'css/jquery-ui/jquery-ui.min.css', false, $this->version, false );
    wp_register_style( $this->plugin_name, $plugin_url . 'css/wpf-public.css', array(), $this->version, 'all' );
  }
```

{% file src="/files/-MTxkH66jukO37vQo4ab" %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://learnphp.gitbook.io/learnphp/wordpress-advand/22.-hien-thi-chuyen-muc-ra-ngoai-trang-shop-ok.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
