| @@ -14,12 +14,10 @@ | ||
| 14 | 14 | use Elementor\Controls_Manager; |
| 15 | 15 | use WPDeveloper\BetterDocs\Editors\Elementor\Helper; |
| 16 | 16 | use Elementor\Group_Control_Border; |
| 17 | 17 | use Elementor\Group_Control_Typography; |
| 18 | -use WPDeveloper\BetterDocs\Editors\Elementor\BaseWidget; | |
| 19 | -use WPDeveloper\BetterDocs\FrontEnd\WooProductFAQ as WooFAQRenderer; | |
| 20 | 18 | |
| 21 | -class FAQ extends BaseWidget { | |
| 19 | +class FAQ extends Widget_Base { | |
| 22 | 20 | |
| 23 | 21 | public function get_name() { |
| 24 | 22 | return 'betterdocs-faq'; |
| 25 | 23 | } |
| @@ -71,34 +69,8 @@ | ||
| 71 | 69 | 'label_block' => true |
| 72 | 70 | ] |
| 73 | 71 | ); |
| 74 | 72 | |
| 75 | - if ( class_exists( 'WooCommerce' ) ) { | |
| 76 | - $this->add_control( | |
| 77 | - 'faq_taxonomy', | |
| 78 | - [ | |
| 79 | - 'label' => __( 'FAQ Type', 'betterdocs' ), | |
| 80 | - 'type' => Controls_Manager::SELECT, | |
| 81 | - 'options' => [ | |
| 82 | - 'betterdocs_faq_category' => __( 'General FAQ', 'betterdocs' ), | |
| 83 | - 'betterdocs_product_faq_category' => __( 'Product FAQ', 'betterdocs' ), | |
| 84 | - 'product_assignments' => __( 'Product Assignments', 'betterdocs' ), | |
| 85 | - ], | |
| 86 | - 'default' => 'betterdocs_faq_category', | |
| 87 | - ] | |
| 88 | - ); | |
| 89 | - | |
| 90 | - $this->add_control( | |
| 91 | - 'faq_product_assignments_note', | |
| 92 | - [ | |
| 93 | - 'type' => Controls_Manager::RAW_HTML, | |
| 94 | - 'raw' => __( 'Groups are resolved automatically per product: a per-product assignment is shown if set, otherwise the groups assigned to the product’s categories. Manage assignments on each group in FAQ Builder → WooCommerce → Product FAQ Groups.', 'betterdocs' ), | |
| 95 | - 'content_classes' => 'elementor-control-field-description', | |
| 96 | - 'condition' => [ 'faq_taxonomy' => 'product_assignments' ], | |
| 97 | - ] | |
| 98 | - ); | |
| 99 | - } | |
| 100 | - | |
| 101 | 73 | $this->add_control( |
| 102 | 74 | 'faq_layout_section', |
| 103 | 75 | [ |
| 104 | 76 | 'label' => __( 'FAQ Section', 'betterdocs' ), |
| @@ -109,120 +81,42 @@ | ||
| 109 | 81 | 'default' => __( 'Frequently Asked Questions', 'betterdocs' ) |
| 110 | 82 | ] |
| 111 | 83 | ); |
| 112 | 84 | |
| 85 | + $terms = betterdocs()->container->get( Helper::class )->get_faq_terms(); | |
| 86 | + | |
| 113 | 87 | $this->add_control( |
| 114 | - 'faq_section_title_tag', | |
| 88 | + 'select_specific_faq', | |
| 115 | 89 | [ |
| 116 | - 'label' => __( 'Section Title Tag', 'betterdocs' ), | |
| 117 | - 'type' => Controls_Manager::SELECT, | |
| 118 | - 'default' => 'h2', | |
| 119 | - 'options' => [ | |
| 120 | - 'h1' => __( 'H1', 'betterdocs' ), | |
| 121 | - 'h2' => __( 'H2', 'betterdocs' ), | |
| 122 | - 'h3' => __( 'H3', 'betterdocs' ), | |
| 123 | - 'h4' => __( 'H4', 'betterdocs' ), | |
| 124 | - 'h5' => __( 'H5', 'betterdocs' ), | |
| 125 | - 'h6' => __( 'H6', 'betterdocs' ) | |
| 90 | + 'label' => __( 'Include FAQ Groups', 'betterdocs' ), | |
| 91 | + 'label_block' => true, | |
| 92 | + 'type' => Controls_Manager::SELECT2, | |
| 93 | + 'options' => $terms, | |
| 94 | + 'multiple' => true, | |
| 95 | + 'default' => '', | |
| 96 | + 'select2options' => [ | |
| 97 | + 'placeholder' => __( 'Include FAQ Groups', 'betterdocs' ), | |
| 98 | + 'allowClear' => true | |
| 126 | 99 | ] |
| 127 | 100 | ] |
| 128 | 101 | ); |
| 129 | 102 | |
| 130 | 103 | $this->add_control( |
| 131 | - 'faq_group_title_tag', | |
| 104 | + 'exclude_specific_faq', | |
| 132 | 105 | [ |
| 133 | - 'label' => __( 'Group Title Tag', 'betterdocs' ), | |
| 134 | - 'type' => Controls_Manager::SELECT, | |
| 135 | - 'default' => 'h3', | |
| 136 | - 'options' => [ | |
| 137 | - 'h1' => __( 'H1', 'betterdocs' ), | |
| 138 | - 'h2' => __( 'H2', 'betterdocs' ), | |
| 139 | - 'h3' => __( 'H3', 'betterdocs' ), | |
| 140 | - 'h4' => __( 'H4', 'betterdocs' ), | |
| 141 | - 'h5' => __( 'H5', 'betterdocs' ), | |
| 142 | - 'h6' => __( 'H6', 'betterdocs' ) | |
| 143 | - ], | |
| 144 | - 'condition' => [ | |
| 145 | - 'faq_layout_selection' => [ 'layout-1', 'layout-2', 'layout-3' ] | |
| 106 | + 'label' => __( 'Exclude FAQ Groups', 'betterdocs' ), | |
| 107 | + 'label_block' => true, | |
| 108 | + 'type' => Controls_Manager::SELECT2, | |
| 109 | + 'options' => $terms, | |
| 110 | + 'multiple' => true, | |
| 111 | + 'default' => '', | |
| 112 | + 'select2options' => [ | |
| 113 | + 'placeholder' => __( 'Exclude FAQ Groups', 'betterdocs' ), | |
| 114 | + 'allowClear' => true | |
| 146 | 115 | ] |
| 147 | 116 | ] |
| 148 | 117 | ); |
| 149 | 118 | |
| 150 | - $terms = betterdocs()->container->get( Helper::class )->get_faq_terms(); | |
| 151 | - | |
| 152 | - // General FAQ include/exclude — shown always when WooCommerce is off, | |
| 153 | - // or conditioned on FAQ Type = General FAQ when WooCommerce is on. | |
| 154 | - $general_include_args = [ | |
| 155 | - 'label' => __( 'Include FAQ Groups', 'betterdocs' ), | |
| 156 | - 'label_block' => true, | |
| 157 | - 'type' => Controls_Manager::SELECT2, | |
| 158 | - 'options' => $terms, | |
| 159 | - 'multiple' => true, | |
| 160 | - 'default' => '', | |
| 161 | - 'select2options' => [ | |
| 162 | - 'placeholder' => __( 'Include FAQ Groups', 'betterdocs' ), | |
| 163 | - 'allowClear' => true | |
| 164 | - ] | |
| 165 | - ]; | |
| 166 | - $general_exclude_args = [ | |
| 167 | - 'label' => __( 'Exclude FAQ Groups', 'betterdocs' ), | |
| 168 | - 'label_block' => true, | |
| 169 | - 'type' => Controls_Manager::SELECT2, | |
| 170 | - 'options' => $terms, | |
| 171 | - 'multiple' => true, | |
| 172 | - 'default' => '', | |
| 173 | - 'select2options' => [ | |
| 174 | - 'placeholder' => __( 'Exclude FAQ Groups', 'betterdocs' ), | |
| 175 | - 'allowClear' => true | |
| 176 | - ] | |
| 177 | - ]; | |
| 178 | - | |
| 179 | - if ( class_exists( 'WooCommerce' ) ) { | |
| 180 | - $general_include_args['condition'] = [ 'faq_taxonomy' => 'betterdocs_faq_category' ]; | |
| 181 | - $general_exclude_args['condition'] = [ 'faq_taxonomy' => 'betterdocs_faq_category' ]; | |
| 182 | - } | |
| 183 | - | |
| 184 | - $this->add_control( 'select_specific_faq', $general_include_args ); | |
| 185 | - $this->add_control( 'exclude_specific_faq', $general_exclude_args ); | |
| 186 | - | |
| 187 | - if ( class_exists( 'WooCommerce' ) ) { | |
| 188 | - $product_terms = betterdocs()->query->get_faq_terms( [], 'betterdocs_product_faq_category' ); | |
| 189 | - | |
| 190 | - $this->add_control( | |
| 191 | - 'select_specific_product_faq', | |
| 192 | - [ | |
| 193 | - 'label' => __( 'Include Product FAQ Groups', 'betterdocs' ), | |
| 194 | - 'label_block' => true, | |
| 195 | - 'type' => Controls_Manager::SELECT2, | |
| 196 | - 'options' => $product_terms, | |
| 197 | - 'multiple' => true, | |
| 198 | - 'default' => '', | |
| 199 | - 'condition' => [ 'faq_taxonomy' => 'betterdocs_product_faq_category' ], | |
| 200 | - 'select2options' => [ | |
| 201 | - 'placeholder' => __( 'Include Product FAQ Groups', 'betterdocs' ), | |
| 202 | - 'allowClear' => true | |
| 203 | - ] | |
| 204 | - ] | |
| 205 | - ); | |
| 206 | - | |
| 207 | - $this->add_control( | |
| 208 | - 'exclude_specific_product_faq', | |
| 209 | - [ | |
| 210 | - 'label' => __( 'Exclude Product FAQ Groups', 'betterdocs' ), | |
| 211 | - 'label_block' => true, | |
| 212 | - 'type' => Controls_Manager::SELECT2, | |
| 213 | - 'options' => $product_terms, | |
| 214 | - 'multiple' => true, | |
| 215 | - 'default' => '', | |
| 216 | - 'condition' => [ 'faq_taxonomy' => 'betterdocs_product_faq_category' ], | |
| 217 | - 'select2options' => [ | |
| 218 | - 'placeholder' => __( 'Exclude Product FAQ Groups', 'betterdocs' ), | |
| 219 | - 'allowClear' => true | |
| 220 | - ] | |
| 221 | - ] | |
| 222 | - ); | |
| 223 | - } | |
| 224 | - | |
| 225 | 119 | $this->end_controls_section(); |
| 226 | 120 | |
| 227 | 121 | /** |
| 228 | 122 | * ---------------------------------------------------------- |
| @@ -319,9 +213,9 @@ | ||
| 319 | 213 | [ |
| 320 | 214 | 'label' => esc_html__( 'Title Color', 'betterdocs' ), |
| 321 | 215 | 'type' => Controls_Manager::COLOR, |
| 322 | 216 | 'selectors' => [ |
| 323 | - '{{WRAPPER}} .betterdocs-faq-wrapper .betterdocs-faq-inner-wrapper .betterdocs-faq-title .betterdocs-faq-title-tag' => 'color:{{VALUE}};' | |
| 217 | + '{{WRAPPER}} .betterdocs-faq-wrapper .betterdocs-faq-inner-wrapper .betterdocs-faq-title h2' => 'color:{{VALUE}};' | |
| 324 | 218 | ] |
| 325 | 219 | ] |
| 326 | 220 | ); |
| 327 | 221 | |
| @@ -330,9 +224,9 @@ | ||
| 330 | 224 | [ |
| 331 | 225 | 'label' => esc_html__( 'Title Hover Color', 'betterdocs' ), |
| 332 | 226 | 'type' => Controls_Manager::COLOR, |
| 333 | 227 | 'selectors' => [ |
| 334 | - '{{WRAPPER}} .betterdocs-faq-wrapper .betterdocs-faq-inner-wrapper .betterdocs-faq-title .betterdocs-faq-title-tag:hover' => 'color:{{VALUE}};' | |
| 228 | + '{{WRAPPER}} .betterdocs-faq-wrapper .betterdocs-faq-inner-wrapper .betterdocs-faq-title h2:hover' => 'color:{{VALUE}};' | |
| 335 | 229 | ] |
| 336 | 230 | ] |
| 337 | 231 | ); |
| 338 | 232 | |
| @@ -339,9 +233,9 @@ | ||
| 339 | 233 | $this->add_group_control( |
| 340 | 234 | Group_Control_Typography::get_type(), |
| 341 | 235 | [ |
| 342 | 236 | 'name' => 'faq_box_title_typography', |
| 343 | - 'selector' => '{{WRAPPER}} .betterdocs-faq-wrapper .betterdocs-faq-inner-wrapper .betterdocs-faq-title .betterdocs-faq-title-tag' | |
| 237 | + 'selector' => '{{WRAPPER}} .betterdocs-faq-wrapper .betterdocs-faq-inner-wrapper .betterdocs-faq-title h2' | |
| 344 | 238 | ] |
| 345 | 239 | ); |
| 346 | 240 | |
| 347 | 241 | $this->end_controls_section(); |
| @@ -867,49 +761,15 @@ | ||
| 867 | 761 | |
| 868 | 762 | $this->end_controls_section(); |
| 869 | 763 | } |
| 870 | 764 | |
| 871 | - protected function render_callback() { | |
| 765 | + protected function render() { | |
| 872 | 766 | $control_values = $this->get_settings_for_display(); |
| 873 | 767 | |
| 874 | - $taxonomy = sanitize_key( $control_values['faq_taxonomy'] ?? 'betterdocs_faq_category' ); | |
| 768 | + $specific_faqs = ! empty( $control_values['select_specific_faq'] ) ? implode( ',', $control_values['select_specific_faq'] ) : ''; | |
| 875 | 769 | |
| 876 | - if ( $taxonomy === 'product_assignments' ) { | |
| 877 | - if ( ElementorPlugin::instance()->editor->is_edit_mode() ) { | |
| 878 | - // Editor preview: show all product FAQ terms so the layout can be styled. | |
| 879 | - betterdocs()->views->get( | |
| 880 | - 'layouts/faq', | |
| 881 | - [ | |
| 882 | - 'enable' => true, | |
| 883 | - 'have_posts' => true, | |
| 884 | - 'layout' => $control_values['faq_layout_selection'], | |
| 885 | - 'shortcode_attr' => [ | |
| 886 | - 'group_exclude' => '', | |
| 887 | - 'groups' => '', | |
| 888 | - 'class' => 'betterdocs-faq-' . $control_values['faq_layout_selection'], | |
| 889 | - 'faq_heading' => $control_values['faq_layout_section'], | |
| 890 | - 'faq_section_title_tag' => $control_values['faq_section_title_tag'], | |
| 891 | - 'faq_group_title_tag' => $control_values['faq_group_title_tag'], | |
| 892 | - 'faq_taxonomy' => 'betterdocs_product_faq_category', | |
| 893 | - ] | |
| 894 | - ] | |
| 895 | - ); | |
| 896 | - $this->render_editor_script(); | |
| 897 | - } else { | |
| 898 | - $this->render_product_assignments( $control_values['faq_layout_selection'] ); | |
| 899 | - } | |
| 770 | + $faqs_exclude = ! empty( $control_values['exclude_specific_faq'] ) ? implode( ',', $control_values['exclude_specific_faq'] ) : ''; | |
| 900 | 771 | |
| 901 | - return; | |
| 902 | - } | |
| 903 | - | |
| 904 | - if ( $taxonomy === 'betterdocs_product_faq_category' ) { | |
| 905 | - $specific_faqs = ! empty( $control_values['select_specific_product_faq'] ) ? implode( ',', $control_values['select_specific_product_faq'] ) : ''; | |
| 906 | - $faqs_exclude = ! empty( $control_values['exclude_specific_product_faq'] ) ? implode( ',', $control_values['exclude_specific_product_faq'] ) : ''; | |
| 907 | - } else { | |
| 908 | - $specific_faqs = ! empty( $control_values['select_specific_faq'] ) ? implode( ',', $control_values['select_specific_faq'] ) : ''; | |
| 909 | - $faqs_exclude = ! empty( $control_values['exclude_specific_faq'] ) ? implode( ',', $control_values['exclude_specific_faq'] ) : ''; | |
| 910 | - } | |
| 911 | - | |
| 912 | 772 | betterdocs()->views->get( |
| 913 | 773 | 'layouts/faq', |
| 914 | 774 | [ |
| 915 | 775 | 'enable' => true, |
| @@ -915,15 +775,12 @@ | ||
| 915 | 775 | 'enable' => true, |
| 916 | 776 | 'have_posts' => true, |
| 917 | 777 | 'layout' => $control_values['faq_layout_selection'], |
| 918 | 778 | 'shortcode_attr' => [ |
| 919 | - 'group_exclude' => $faqs_exclude, | |
| 920 | - 'class' => 'betterdocs-faq-' . $control_values['faq_layout_selection'], | |
| 921 | - 'groups' => $specific_faqs, | |
| 922 | - 'faq_heading' => $control_values['faq_layout_section'], | |
| 923 | - 'faq_section_title_tag' => $control_values['faq_section_title_tag'], | |
| 924 | - 'faq_group_title_tag' => $control_values['faq_group_title_tag'], | |
| 925 | - 'faq_taxonomy' => $taxonomy | |
| 779 | + 'group_exclude' => $faqs_exclude, | |
| 780 | + 'class' => 'betterdocs-faq-' . $control_values['faq_layout_selection'], | |
| 781 | + 'groups' => $specific_faqs, | |
| 782 | + 'faq_heading' => $control_values['faq_layout_section'] | |
| 926 | 783 | ] |
| 927 | 784 | ] |
| 928 | 785 | ); |
| 929 | 786 | |
| @@ -931,69 +788,12 @@ | ||
| 931 | 788 | $this->render_editor_script(); |
| 932 | 789 | } |
| 933 | 790 | } |
| 934 | 791 | |
| 935 | - private function render_product_assignments( $layout ) { | |
| 936 | - if ( ! class_exists( 'WooCommerce' ) || ! is_product() ) { | |
| 937 | - return; | |
| 938 | - } | |
| 939 | - | |
| 940 | - // In theme-builder templates, the widget can render outside the loop, | |
| 941 | - // so get_the_ID() can be 0 — fall back to the queried product. | |
| 942 | - $product_id = get_the_ID(); | |
| 943 | - if ( ! $product_id ) { | |
| 944 | - $product_id = get_queried_object_id(); | |
| 945 | - } | |
| 946 | - if ( ! $product_id ) { | |
| 947 | - return; | |
| 948 | - } | |
| 949 | - | |
| 950 | - /** @var WooFAQRenderer $renderer */ | |
| 951 | - $renderer = betterdocs()->container->get( WooFAQRenderer::class ); | |
| 952 | - | |
| 953 | - // This widget is the explicit placement; don't also inject into the tab/summary. | |
| 954 | - $renderer->suppress_auto_placement(); | |
| 955 | - $renderer->render_for_product( $product_id, $layout ); | |
| 956 | - } | |
| 957 | - | |
| 958 | 792 | protected function render_editor_script() { |
| 959 | 793 | ?> |
| 960 | 794 | <script> |
| 961 | 795 | jQuery(document).ready(function($) { |
| 962 | - const $tabs = $(".betterdocs-faq-tab"); | |
| 963 | - const $mobileTabs = $(".betterdocs-faq-list-wrapper .betterdocs-faq-tab"); | |
| 964 | - const $contents = $(".betterdocs-faq-list-content"); | |
| 965 | - | |
| 966 | - $tabs.on("click", function () { | |
| 967 | - const termId = $(this).data("term-id"); | |
| 968 | - | |
| 969 | - // Remove active class from all tabs and hide all contents | |
| 970 | - $tabs.removeClass("active"); | |
| 971 | - $contents.hide().removeClass("active"); | |
| 972 | - | |
| 973 | - // Reset all icons to default state | |
| 974 | - $(".betterdocs-faq-iconplus").show(); | |
| 975 | - $(".betterdocs-faq-iconminus").hide(); | |
| 976 | - | |
| 977 | - // Add active class to the clicked tab and show the corresponding content | |
| 978 | - $(this).addClass("active"); | |
| 979 | - $contents.filter(`[data-term-id="${termId}"]`).show().addClass("active"); | |
| 980 | - | |
| 981 | - // Toggle icons for the active tab | |
| 982 | - $(this).find(".betterdocs-faq-iconplus").hide(); | |
| 983 | - $(this).find(".betterdocs-faq-iconminus").show(); | |
| 984 | - }); | |
| 985 | - | |
| 986 | - // Trigger click on the first tab to show the first content by default | |
| 987 | - if ($tabs.length > 0) { | |
| 988 | - $tabs.first().trigger("click").addClass("active"); | |
| 989 | - | |
| 990 | - const $mobileFirstTab = $mobileTabs.first(); | |
| 991 | - $mobileFirstTab.addClass("active"); | |
| 992 | - $mobileFirstTab.find(".betterdocs-faq-iconplus").hide(); | |
| 993 | - $mobileFirstTab.find(".betterdocs-faq-iconminus").show(); | |
| 994 | - } | |
| 995 | - | |
| 996 | 796 | $('.betterdocs-faq-post').on('click', function(e) { |
| 997 | 797 | var current_node = $(this); |
| 998 | 798 | var active_list = $('.betterdocs-faq-group.active'); |
| 999 | 799 | |