Advanced AJAX Product Filters - Version 1.0.4

Version Description

  • Enhancement - SEO friendly urls with possibility for users to share/bookmark their search. Will be shortened in future
  • Enhancement - Option added to turn SEO friendly urls on/off. Off by default as this is first version of this feature
  • Enhancement - Option to turn filters on/off globally
  • Enhancement - Option to take control over (default) sorting function, make it AJAXy and work with filters
  • Fix - Sorting remain correct after using filters. Sorting wasn't counted before
  • Fix - If there are 2 or more sliders they are not working correctly.
  • Fix - Values in slider was converted to float even when value ia not a price.
  • Fix - If there are 2 or more values for attribute it was not validated when used in slider.
Download this release

Release Info

Developer dholovnia
Plugin Icon wp plugin Advanced AJAX Product Filters
Version 1.0.4
Comparing to
See all releases

Code changes from version 1.0.3.5 to 1.0.4

css/widget.css DELETED
@@ -1,204 +0,0 @@
1
- ul.products{
2
- position: relative;
3
- min-height: 500px;
4
- }
5
-
6
- ul.products.hide_products li{
7
- visibility: hidden;
8
- height: 20px;
9
- }
10
-
11
- .berocket_aapf_widget input[type="checkbox"] {
12
- position: absolute;
13
- left: -9999px;
14
- }
15
-
16
- .berocket_aapf_widget input[type="checkbox"] + label:before {
17
- content: "";
18
- display: inline-block;
19
- width: 14px;
20
- height: 14px;
21
- background: url('../images/sprite.png') no-repeat;
22
- cursor: pointer;
23
- }
24
-
25
- .berocket_aapf_widget input[type="checkbox"]:checked + label:before {
26
- background-position: -14px 0;
27
- }
28
-
29
- .berocket_aapf_widget input[type="radio"] {
30
- position: absolute;
31
- left: -9999px;
32
- }
33
-
34
- .berocket_aapf_widget input[type="radio"] + label:before {
35
- content: "";
36
- display: inline-block;
37
- width: 14px;
38
- height: 14px;
39
- background: url('../images/sprite_radio.png') no-repeat;
40
- }
41
-
42
- .berocket_aapf_widget input[type="radio"]:checked + label:before {
43
- background-position: -14px 0;
44
- }
45
-
46
- .berocket_aapf_widget-title{
47
- margin-bottom: 5px;
48
- font-size: 14px;
49
- }
50
-
51
- ul.berocket_aapf_widget{
52
- margin-bottom: 30px;
53
- }
54
-
55
- ul.berocket_aapf_widget li{
56
- list-style-type: none;
57
- padding-left: 0;
58
- }
59
-
60
- ul.berocket_aapf_widget li > span{
61
- display: block;
62
- cursor: pointer;
63
- height: 20px;
64
- }
65
-
66
- ul.berocket_aapf_widget li > span:hover{
67
- color: #000000;
68
- }
69
-
70
- .berocket_aapf_widget_loading{
71
- position: absolute;
72
- top: 0;
73
- left: 0;
74
- right: 0;
75
- bottom: 0;
76
- background: white url('../images/ajax-loader.gif') no-repeat center center;
77
- z-index: 10000;
78
- }
79
-
80
- .no-products{
81
- font-size: 26px;
82
- font-weight: bold;
83
- line-height: 6em;
84
- text-align: center;
85
- }
86
-
87
- span.product-size{
88
- color: #777;
89
- display: block;
90
- text-align: center;
91
- }
92
-
93
- .berocket_aapf_widget li.slider span.left, .berocket_aapf_widget li.slider span.right{
94
- height: 40px;
95
- float: left;
96
- font-size: 12px;
97
- }
98
-
99
- .berocket_aapf_widget li.slider span.left input, .berocket_aapf_widget li.slider span.right input{
100
- border: 1px solid #E8E8E8;
101
- font-size: 13px;
102
- font-style: italic;
103
- padding: 4px 9px;
104
- text-align: right;
105
- width: 40px;
106
- background: white;
107
- }
108
-
109
- .berocket_aapf_widget li.slider{
110
- width: 80%;
111
- }
112
-
113
- .berocket_aapf_widget li.slider span.right{
114
- float: right;
115
- }
116
-
117
- .berocket_aapf_widget li.slider span.slide{
118
- clear: both;
119
- height: auto;
120
- }
121
-
122
- .berocket_filter_slider.ui-widget-content, .berocket_filter_price_slider.ui-widget-content{
123
- background: none repeat scroll 0 0 #b0b5b9;
124
- border: 0 none;
125
- border-radius: 0;
126
- height: 4px;
127
- padding: 0;
128
- }
129
-
130
- .berocket_filter_slider.ui-widget-content .ui-slider-range, .berocket_filter_price_slider.ui-widget-content .ui-slider-range{
131
- background: none repeat scroll 0 0 #000000;
132
- }
133
-
134
- .berocket_filter_slider.ui-widget-content .ui-slider-handle, .berocket_filter_price_slider.ui-widget-content .ui-slider-handle{
135
- background: url("../images/handler.png") no-repeat scroll center center / cover transparent;
136
- width: 12px;
137
- height: 12px;
138
- border: 0;
139
- top: -4px;
140
- }
141
-
142
- .ui-slider {
143
- position: relative;
144
- text-align: left;
145
- }
146
- .ui-slider .ui-slider-handle {
147
- position: absolute;
148
- z-index: 2;
149
- width: 1.2em;
150
- height: 1.2em;
151
- cursor: pointer;
152
- -ms-touch-action: none;
153
- touch-action: none;
154
- }
155
- .ui-slider .ui-slider-range {
156
- position: absolute;
157
- z-index: 1;
158
- font-size: .7em;
159
- display: block;
160
- border: 0;
161
- background-position: 0 0;
162
- }
163
- .ui-slider.ui-state-disabled .ui-slider-handle,
164
- .ui-slider.ui-state-disabled .ui-slider-range {
165
- filter: inherit;
166
- }
167
-
168
- .ui-slider-horizontal {
169
- height: .8em;
170
- }
171
- .ui-slider-horizontal .ui-slider-handle {
172
- top: -.3em;
173
- margin-left: -.6em;
174
- }
175
- .ui-slider-horizontal .ui-slider-range {
176
- top: 0;
177
- height: 100%;
178
- }
179
- .ui-slider-horizontal .ui-slider-range-min {
180
- left: 0;
181
- }
182
- .ui-slider-horizontal .ui-slider-range-max {
183
- right: 0;
184
- }
185
-
186
- .ui-slider-vertical {
187
- width: .8em;
188
- height: 100px;
189
- }
190
- .ui-slider-vertical .ui-slider-handle {
191
- left: -.3em;
192
- margin-left: 0;
193
- margin-bottom: -.6em;
194
- }
195
- .ui-slider-vertical .ui-slider-range {
196
- left: 0;
197
- width: 100%;
198
- }
199
- .ui-slider-vertical .ui-slider-range-min {
200
- bottom: 0;
201
- }
202
- .ui-slider-vertical .ui-slider-range-max {
203
- top: 0;
204
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
css/widget.min.css ADDED
@@ -0,0 +1 @@
 
1
+ ul.products{position:relative;min-height:500px}ul.products.hide_products li{visibility:hidden;height:20px}.berocket_aapf_widget input[type="checkbox"]{position:absolute;left:-9999px}.berocket_aapf_widget input[type="checkbox"] + label:before{content:"";display:inline-block;width:14px;height:14px;background:url(../images/sprite.png) no-repeat;cursor:pointer}.berocket_aapf_widget input[type="checkbox"]:checked + label:before{background-position:-14px 0}.berocket_aapf_widget input[type="radio"]{position:absolute;left:-9999px}.berocket_aapf_widget input[type="radio"] + label:before{content:"";display:inline-block;width:14px;height:14px;background:url(../images/sprite_radio.png) no-repeat}.berocket_aapf_widget input[type="radio"]:checked + label:before{background-position:-14px 0}.berocket_aapf_widget-title{margin-bottom:5px;font-size:14px}ul.berocket_aapf_widget{margin-bottom:30px}ul.berocket_aapf_widget li{list-style-type:none;padding-left:0}ul.berocket_aapf_widget li > span{display:block;cursor:pointer;height:20px}ul.berocket_aapf_widget li > span:hover{color:#000}.berocket_aapf_widget_loading{position:absolute;top:0;left:0;right:0;bottom:0;background:#fff url(../images/ajax-loader.gif) no-repeat center center;z-index:10000}.no-products{font-size:26px;font-weight:700;line-height:6em;text-align:center}span.product-size{color:#777;display:block;text-align:center}.berocket_aapf_widget li.slider span.left,.berocket_aapf_widget li.slider span.right{height:40px;float:left;font-size:12px}.berocket_aapf_widget li.slider span.left input,.berocket_aapf_widget li.slider span.right input{border:1px solid #E8E8E8;font-size:13px;font-style:italic;padding:4px 9px;text-align:right;width:40px;background:#fff}.berocket_aapf_widget li.slider{width:80%}.berocket_aapf_widget li.slider span.right{float:right}.berocket_aapf_widget li.slider span.slide{clear:both;height:auto}.berocket_filter_slider.ui-widget-content,.berocket_filter_price_slider.ui-widget-content{background:none repeat scroll 0 0 #b0b5b9;border:0 none;border-radius:0;height:4px;padding:0}.berocket_filter_slider.ui-widget-content .ui-slider-range,.berocket_filter_price_slider.ui-widget-content .ui-slider-range{background:none repeat scroll 0 0 #000}.berocket_filter_slider.ui-widget-content .ui-slider-handle,.berocket_filter_price_slider.ui-widget-content .ui-slider-handle{background:url(../images/handler.png) no-repeat scroll center center / cover transparent;width:12px;height:12px;border:0;top:-4px}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:pointer;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}
includes/functions.php CHANGED
@@ -5,3 +5,161 @@ if( ! function_exists( 'br_get_template_part' ) ){
5
  BeRocket_AAPF::br_get_template_part( $name );
6
  }
7
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  BeRocket_AAPF::br_get_template_part( $name );
6
  }
7
  }
8
+
9
+ if( ! function_exists( 'br_aapf_get_attributes' ) ) {
10
+ function br_aapf_get_attributes() {
11
+ $attribute_taxonomies = wc_get_attribute_taxonomies();
12
+ $attributes = array();
13
+
14
+ if ( $attribute_taxonomies ) {
15
+ foreach ( $attribute_taxonomies as $tax ) {
16
+ $attributes[ wc_attribute_taxonomy_name( $tax->attribute_name ) ] = $tax->attribute_label;
17
+ }
18
+ }
19
+
20
+ return apply_filters( 'berocket_aapf_get_attributes', $attributes );
21
+ }
22
+ }
23
+
24
+ if( ! function_exists( 'br_parse_order_by' ) ){
25
+ function br_aapf_parse_order_by( &$args ){
26
+ $orderby = $_POST['orderby'];
27
+ $order = "ASK";
28
+ if( @ preg_match( "/-/", $orderby ) ){
29
+ list( $orderby, $order ) = explode( "-", $orderby );
30
+ }
31
+
32
+ if( @ $orderby and @ $order ) {
33
+
34
+ // Get ordering from query string unless defined
35
+ $orderby = strtolower( $orderby );
36
+ $order = strtoupper( $order );
37
+
38
+ // default - menu_order
39
+ $args['orderby'] = 'menu_order title';
40
+ $args['order'] = $order == 'DESC' ? 'DESC' : 'ASC';
41
+
42
+ switch ( $orderby ) {
43
+ case 'rand' :
44
+ $args['orderby'] = 'rand';
45
+ break;
46
+ case 'date' :
47
+ $args['orderby'] = 'date';
48
+ $args['order'] = $order == 'ASC' ? 'ASC' : 'DESC';
49
+ break;
50
+ case 'price' :
51
+ $args['orderby'] = 'meta_value_num';
52
+ $args['order'] = $order == 'DESC' ? 'DESC' : 'ASC';
53
+ $args['meta_key'] = '_price';
54
+ break;
55
+ case 'popularity' :
56
+ $args['meta_key'] = 'total_sales';
57
+
58
+ // Sorting handled later though a hook
59
+ add_filter( 'posts_clauses', array( 'WC_Query', 'order_by_popularity_post_clauses' ) );
60
+ break;
61
+ case 'rating' :
62
+ // Sorting handled later though a hook
63
+ add_filter( 'posts_clauses', array( 'WC_Query', 'order_by_rating_post_clauses' ) );
64
+ break;
65
+ case 'title' :
66
+ $args['orderby'] = 'title';
67
+ $args['order'] = $order == 'DESC' ? 'DESC' : 'ASC';
68
+ break;
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ if( ! function_exists( 'br_aapf_args_parser' ) ){
75
+ function br_aapf_args_parser( $args = array() ) {
76
+ $attributes_terms = $tax_query = array();
77
+ $attributes = apply_filters( 'berocket_aapf_listener_get_attributes', br_aapf_get_attributes() );
78
+
79
+ if ( @$attributes ) {
80
+ foreach ( $attributes as $k => $v ) {
81
+ $terms = get_terms( array( $k ), $args = array( 'orderby' => 'name', 'order' => 'ASC' ) );
82
+ if ( $terms ) {
83
+ foreach ( $terms as $term ) {
84
+ $attributes_terms[ $k ][ $term->term_id ] = $term->slug;
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ if ( @$_POST['terms'] ) {
91
+ foreach ( $_POST['terms'] as $t ) {
92
+ $taxonomies[ $t[0] ][] = $attributes_terms[ $t[0] ][ $t[1] ];
93
+ $taxonomies_operator[ $t[0] ] = $t[2];
94
+ }
95
+ }
96
+
97
+ $taxonomies = apply_filters( 'berocket_aapf_listener_taxonomies', @$taxonomies );
98
+ $taxonomies_operator = apply_filters( 'berocket_aapf_listener_taxonomies_operator', @$taxonomies_operator );
99
+
100
+ if ( @$taxonomies ) {
101
+ $tax_query['relation'] = 'AND';
102
+ if ( $taxonomies ) {
103
+ foreach ( $taxonomies as $k => $v ) {
104
+ if ( $taxonomies_operator[ $k ] == 'AND' ) {
105
+ $op = 'AND';
106
+ } else {
107
+ $op = 'IN';
108
+ }
109
+
110
+ $tax_query[] = array(
111
+ 'taxonomy' => $k,
112
+ 'field' => 'slug',
113
+ 'terms' => $v,
114
+ 'operator' => $op
115
+ );
116
+ }
117
+ }
118
+ }
119
+
120
+ if ( @$_POST['product_cat'] and $_POST['product_cat'] != '-1' ) {
121
+ $tax_query[] = array(
122
+ 'taxonomy' => 'product_cat',
123
+ 'field' => 'slug',
124
+ 'terms' => strip_tags( $_POST['product_cat'] ),
125
+ 'operator' => 'IN'
126
+ );
127
+ }
128
+
129
+ $args['tax_query'] = $tax_query;
130
+ $args['post_type'] = 'product';
131
+
132
+ if ( @ $_POST['orderby'] ) {
133
+ br_aapf_parse_order_by( $args );
134
+ }
135
+
136
+ return $args;
137
+ }
138
+ }
139
+
140
+ if( ! function_exists( 'br_aapf_args_converter' ) ) {
141
+ function br_aapf_args_converter() {
142
+ if ( preg_match( "~\|~", $_GET['filters'] ) ) {
143
+ $filters = explode( "|", $_GET['filters'] );
144
+ } else {
145
+ $filters[0] = $_GET['filters'];
146
+ }
147
+
148
+ foreach ( $filters as $filter ) {
149
+ list( $attribute, $value ) = explode( "=", $filter );
150
+
151
+ if ( $attribute == 'price' ) {
152
+ $_POST['price'] = explode( "^", $value );
153
+ } elseif ( $attribute == 'order' ) {
154
+ $_GET['orderby'] = $value;
155
+ } else {
156
+ $term_or_limit = explode( "^", $value );
157
+ if ( $term_or_limit[1] == 'OR' or $term_or_limit[1] == 'AND' ) {
158
+ $_POST['terms'][] = array( "pa_" . $attribute, $term_or_limit[0], $term_or_limit[1] );
159
+ } else {
160
+ $_POST['limits'][] = array( "pa_" . $attribute, $term_or_limit[0], $term_or_limit[1] );
161
+ }
162
+ }
163
+ }
164
+ }
165
+ }
includes/widget.php CHANGED
@@ -29,6 +29,8 @@ class BeRocket_AAPF_Widget extends WP_Widget {
29
 
30
  /* Create the widget. */
31
  $this->WP_Widget( 'berocket_aapf_widget', 'AJAX Product Filters', $widget_ops, $control_ops );
 
 
32
  }
33
 
34
  /**
@@ -39,12 +41,16 @@ class BeRocket_AAPF_Widget extends WP_Widget {
39
  */
40
  function widget( $args, $instance ) {
41
  if( !is_shop() and !is_product_category() ) return;
42
- global $wp_query;
 
 
 
 
43
 
44
  wp_register_style( 'berocket_aapf_widget-style', plugins_url( '../css/widget.min.css', __FILE__ ) );
45
  wp_enqueue_style( 'berocket_aapf_widget-style' );
46
 
47
- /* custom scrollbar */
48
  wp_enqueue_script( 'berocket_aapf_widget-scroll-script', plugins_url( '../js/custom-scrollbar/jquery.mCustomScrollbar.concat.min.js', __FILE__ ), array( 'jquery' ) );
49
  wp_register_style( 'berocket_aapf_widget-scroll-style', plugins_url( '../js/custom-scrollbar/jquery.mCustomScrollbar.min.css', __FILE__ ) );
50
  wp_enqueue_style( 'berocket_aapf_widget-scroll-style' );
@@ -54,9 +60,7 @@ class BeRocket_AAPF_Widget extends WP_Widget {
54
  wp_enqueue_script( 'berocket_aapf_widget-script', plugins_url( '../js/widget.min.js', __FILE__ ), array( 'jquery' ) );
55
  wp_enqueue_script( 'berocket_aapf_widget-hack-script', plugins_url( '../js/mobiles.min.js', __FILE__ ), array( 'jquery' ) );
56
 
57
- $br_options = apply_filters( 'berocket_aapf_listener_br_options', get_option('br_filters_options') );
58
-
59
- $wp_query_product_cat = '-1';
60
  if ( @ $wp_query->query['product_cat'] ) {
61
  $wp_query_product_cat = explode( "/", $wp_query->query['product_cat'] );
62
  $wp_query_product_cat = $wp_query_product_cat[ count( $wp_query_product_cat ) - 1 ];
@@ -64,13 +68,23 @@ class BeRocket_AAPF_Widget extends WP_Widget {
64
 
65
  if( ! $br_options['products_holder_id'] ) $br_options['products_holder_id'] = 'ul.products';
66
 
 
 
 
 
 
 
67
  wp_localize_script(
68
  'berocket_aapf_widget-script',
69
  'the_ajax_script',
70
  array(
 
71
  'ajaxurl' => admin_url( 'admin-ajax.php' ),
72
  'product_cat' => $wp_query_product_cat,
73
- 'products_holder_id' => $br_options['products_holder_id']
 
 
 
74
  )
75
  );
76
 
@@ -172,8 +186,11 @@ class BeRocket_AAPF_Widget extends WP_Widget {
172
  }
173
  }
174
  $id = rand( 0, time() );
175
- $slider_class = 'berocket_filter_price_slider';
176
  $main_class .= ' price';
 
 
 
177
  }else{
178
  if( $terms ) {
179
  foreach ( $terms as $term ) {
@@ -188,11 +205,29 @@ class BeRocket_AAPF_Widget extends WP_Widget {
188
  $id = $term->taxonomy;
189
  }
190
 
191
- set_query_var( 'id', $id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  set_query_var( 'main_class', $main_class );
193
  set_query_var( 'slider_class', $slider_class );
194
- set_query_var( 'min', number_format(floor($min), 2, '.', '') );
195
- set_query_var( 'max', number_format(ceil($max), 2, '.', '') );
196
  }
197
 
198
  br_get_template_part( $type );
@@ -324,7 +359,7 @@ class BeRocket_AAPF_Widget extends WP_Widget {
324
  $defaults = apply_filters( 'berocket_aapf_form_defaults', $defaults );
325
 
326
  $instance = wp_parse_args( (array) $instance, $defaults );
327
- $attributes = $this->get_attributes();
328
  $categories = self::get_product_categories( @ json_decode( $instance['product_cat'] ) );
329
 
330
  include AAPF_TEMPLATE_PATH . "admin.php";
@@ -334,66 +369,13 @@ class BeRocket_AAPF_Widget extends WP_Widget {
334
  * Widget ajax listener
335
  */
336
  public static function listener(){
337
- $attributes_terms = $tax_query = array();
338
 
339
  add_filter( 'post_class', array( __CLASS__, 'add_product_class' ) );
340
-
341
- $attributes = apply_filters( 'berocket_aapf_listener_get_attributes', self::get_attributes() );
342
- if( @$attributes ) {
343
- foreach ( $attributes as $k => $v ) {
344
- $terms = get_terms( array( $k ), $args = array( 'orderby' => 'name', 'order' => 'ASC' ) );
345
- if( $terms ) {
346
- foreach ( $terms as $term ) {
347
- $attributes_terms[ $k ][ $term->term_id ] = $term->slug;
348
- }
349
- }
350
- }
351
- }
352
-
353
- if( @$_POST['terms'] ){
354
- foreach( $_POST['terms'] as $t ){
355
- $taxonomies[$t[0]][] = $attributes_terms[$t[0]][$t[1]];
356
- $taxonomies_operator[$t[0]] = $t[2];
357
- }
358
- }
359
-
360
- $taxonomies = apply_filters( 'berocket_aapf_listener_taxonomies', @$taxonomies );
361
- $taxonomies_operator = apply_filters( 'berocket_aapf_listener_taxonomies_operator', @$taxonomies_operator );
362
-
363
- if( @$taxonomies ){
364
- $tax_query['relation'] = 'AND';
365
- if( $taxonomies ) {
366
- foreach ( $taxonomies as $k => $v ) {
367
- if ( $taxonomies_operator[ $k ] == 'AND' ) {
368
- $op = 'AND';
369
- } else {
370
- $op = 'IN';
371
- }
372
-
373
- $tax_query[] = array(
374
- 'taxonomy' => $k,
375
- 'field' => 'slug',
376
- 'terms' => $v,
377
- 'operator' => $op
378
- );
379
- }
380
- }
381
- }
382
-
383
- if( @$_POST['product_cat'] and $_POST['product_cat'] != '-1' )
384
- $tax_query[] = array(
385
- 'taxonomy' => 'product_cat',
386
- 'field' => 'slug',
387
- 'terms' => strip_tags( $_POST['product_cat'] ),
388
- 'operator' => 'IN'
389
- );
390
-
391
- $args = array( 'tax_query' => $tax_query, 'posts_per_page' => 9, 'post_type' => 'product' );
392
 
393
  $args = apply_filters( 'berocket_aapf_listener_wp_query_args', $args );
394
 
395
  $query = new WP_Query( $args );
396
- $br_options = apply_filters( 'berocket_aapf_listener_br_options', get_option('br_filters_options') );
397
  $has_products = false;
398
 
399
  if( $query->have_posts() ){
@@ -405,8 +387,22 @@ class BeRocket_AAPF_Widget extends WP_Widget {
405
  if( @$_POST['limits'] ){
406
  foreach( $_POST['limits'] as $l ){
407
  $attr = $product->get_attribute( $l[0] );
408
- if( $attr < $l[1] or $attr > $l[2] )
409
- continue 2;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
  }
411
  }
412
 
@@ -426,19 +422,6 @@ class BeRocket_AAPF_Widget extends WP_Widget {
426
  }
427
  die();
428
  }
429
-
430
- public static function get_attributes(){
431
- $attribute_taxonomies = wc_get_attribute_taxonomies();
432
- $attributes = array();
433
-
434
- if ( $attribute_taxonomies ) {
435
- foreach ( $attribute_taxonomies as $tax ) {
436
- $attributes[ wc_attribute_taxonomy_name( $tax->attribute_name ) ] = $tax->attribute_label;
437
- }
438
- }
439
-
440
- return apply_filters( 'berocket_aapf_get_attributes', $attributes );
441
- }
442
 
443
  function get_product_categories( $current_product_cat = '' ) {
444
  $args = array(
29
 
30
  /* Create the widget. */
31
  $this->WP_Widget( 'berocket_aapf_widget', 'AJAX Product Filters', $widget_ops, $control_ops );
32
+
33
+ add_filter( 'berocket_aapf_listener_wp_query_args', 'br_aapf_args_parser' );
34
  }
35
 
36
  /**
41
  */
42
  function widget( $args, $instance ) {
43
  if( !is_shop() and !is_product_category() ) return;
44
+
45
+ $br_options = apply_filters( 'berocket_aapf_listener_br_options', get_option('br_filters_options') );
46
+ if( @ $br_options['filters_turn_off'] ) return;
47
+
48
+ global $wp_query, $wp;
49
 
50
  wp_register_style( 'berocket_aapf_widget-style', plugins_url( '../css/widget.min.css', __FILE__ ) );
51
  wp_enqueue_style( 'berocket_aapf_widget-style' );
52
 
53
+ /* custom scrollbar */
54
  wp_enqueue_script( 'berocket_aapf_widget-scroll-script', plugins_url( '../js/custom-scrollbar/jquery.mCustomScrollbar.concat.min.js', __FILE__ ), array( 'jquery' ) );
55
  wp_register_style( 'berocket_aapf_widget-scroll-style', plugins_url( '../js/custom-scrollbar/jquery.mCustomScrollbar.min.css', __FILE__ ) );
56
  wp_enqueue_style( 'berocket_aapf_widget-scroll-style' );
60
  wp_enqueue_script( 'berocket_aapf_widget-script', plugins_url( '../js/widget.min.js', __FILE__ ), array( 'jquery' ) );
61
  wp_enqueue_script( 'berocket_aapf_widget-hack-script', plugins_url( '../js/mobiles.min.js', __FILE__ ), array( 'jquery' ) );
62
 
63
+ $wp_query_product_cat = '-1';
 
 
64
  if ( @ $wp_query->query['product_cat'] ) {
65
  $wp_query_product_cat = explode( "/", $wp_query->query['product_cat'] );
66
  $wp_query_product_cat = $wp_query_product_cat[ count( $wp_query_product_cat ) - 1 ];
68
 
69
  if( ! $br_options['products_holder_id'] ) $br_options['products_holder_id'] = 'ul.products';
70
 
71
+ if( $_POST['terms'] ){
72
+ $post_temrs = @ json_encode( $_POST['terms'] );
73
+ }else{
74
+ $post_temrs = "[]";
75
+ }
76
+
77
  wp_localize_script(
78
  'berocket_aapf_widget-script',
79
  'the_ajax_script',
80
  array(
81
+ 'current_page_url' => home_url( $wp->request ),
82
  'ajaxurl' => admin_url( 'admin-ajax.php' ),
83
  'product_cat' => $wp_query_product_cat,
84
+ 'products_holder_id' => $br_options['products_holder_id'],
85
+ 'control_sorting' => $br_options['control_sorting'],
86
+ 'seo_friendly_urls' => $br_options['seo_friendly_urls'],
87
+ 'berocket_aapf_widget_product_filters' => $post_temrs
88
  )
89
  );
90
 
186
  }
187
  }
188
  $id = rand( 0, time() );
189
+ $slider_class .= ' berocket_filter_price_slider';
190
  $main_class .= ' price';
191
+
192
+ $min = number_format( floor( $min ), 2, '.', '' );
193
+ $max = number_format( ceil( $max ), 2, '.', '' );
194
  }else{
195
  if( $terms ) {
196
  foreach ( $terms as $term ) {
205
  $id = $term->taxonomy;
206
  }
207
 
208
+ $slider_value1 = $min;
209
+ $slider_value2 = $max;
210
+
211
+ if( $attribute == 'price' and $_POST['price'] ){
212
+ $slider_value1 = $_POST['price'][0];
213
+ $slider_value2 = $_POST['price'][1];
214
+ }
215
+ if( $attribute != 'price' and $_POST['limits'] ){
216
+ foreach( $_POST['limits'] as $p_limit ){
217
+ if( $p_limit[0] == $attribute ){
218
+ $slider_value1 = $p_limit[1];
219
+ $slider_value2 = $p_limit[2];
220
+ }
221
+ }
222
+ }
223
+
224
+ set_query_var( 'slider_value1', $slider_value1 );
225
+ set_query_var( 'slider_value2', $slider_value2 );
226
+ set_query_var( 'filter_slider_id', $id );
227
  set_query_var( 'main_class', $main_class );
228
  set_query_var( 'slider_class', $slider_class );
229
+ set_query_var( 'min', $min );
230
+ set_query_var( 'max', $max );
231
  }
232
 
233
  br_get_template_part( $type );
359
  $defaults = apply_filters( 'berocket_aapf_form_defaults', $defaults );
360
 
361
  $instance = wp_parse_args( (array) $instance, $defaults );
362
+ $attributes = br_aapf_get_attributes();
363
  $categories = self::get_product_categories( @ json_decode( $instance['product_cat'] ) );
364
 
365
  include AAPF_TEMPLATE_PATH . "admin.php";
369
  * Widget ajax listener
370
  */
371
  public static function listener(){
372
+ $br_options = apply_filters( 'berocket_aapf_listener_br_options', get_option('br_filters_options') );
373
 
374
  add_filter( 'post_class', array( __CLASS__, 'add_product_class' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
 
376
  $args = apply_filters( 'berocket_aapf_listener_wp_query_args', $args );
377
 
378
  $query = new WP_Query( $args );
 
379
  $has_products = false;
380
 
381
  if( $query->have_posts() ){
387
  if( @$_POST['limits'] ){
388
  foreach( $_POST['limits'] as $l ){
389
  $attr = $product->get_attribute( $l[0] );
390
+
391
+ if( preg_match( "~(, )~", $attr ) ){
392
+ $attr = explode( ",", $attr );
393
+ $continue = true;
394
+ foreach( $attr as $attr_single ){
395
+ $attr_single = trim( $attr_single );
396
+ if( $attr_single >= $l[1] and $attr_single <= $l[2] ){
397
+ $continue = false;
398
+ break;
399
+ }
400
+ }
401
+ if( $continue ) continue 2;
402
+ }else{
403
+ if( $attr < $l[1] or $attr > $l[2] )
404
+ continue 2;
405
+ }
406
  }
407
  }
408
 
422
  }
423
  die();
424
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
425
 
426
  function get_product_categories( $current_product_cat = '' ) {
427
  $args = array(
js/hack.js DELETED
@@ -1,145 +0,0 @@
1
- /*!
2
- * jQuery UI Touch Punch 0.2.3
3
- *
4
- * Copyright 2011–2014, Dave Furfero
5
- * Dual licensed under the MIT or GPL Version 2 licenses.
6
- *
7
- * Depends:
8
- * jquery.ui.widget.js
9
- * jquery.ui.mouse.js
10
- */
11
- (function ($) {
12
- // Detect touch support
13
- $.support.touch = 'ontouchend' in document;
14
- // Ignore browsers without touch support
15
- if (!$.support.touch) {
16
- return;
17
- }
18
- var mouseProto = $.ui.mouse.prototype,
19
- _mouseInit = mouseProto._mouseInit,
20
- _mouseDestroy = mouseProto._mouseDestroy,
21
- touchHandled;
22
-
23
- /**
24
- * Simulate a mouse event based on a corresponding touch event
25
- * @param {Object} event A touch event
26
- * @param {String} simulatedType The corresponding mouse event
27
- */
28
- function simulateMouseEvent(event, simulatedType) {
29
- // Ignore multi-touch events
30
- if (event.originalEvent.touches.length > 1) {
31
- return;
32
- }
33
- event.preventDefault();
34
- var touch = event.originalEvent.changedTouches[0],
35
- simulatedEvent = document.createEvent('MouseEvents');
36
- // Initialize the simulated mouse event using the touch event's coordinates
37
- simulatedEvent.initMouseEvent(
38
- simulatedType, // type
39
- true, // bubbles
40
- true, // cancelable
41
- window, // view
42
- 1, // detail
43
- touch.screenX, // screenX
44
- touch.screenY, // screenY
45
- touch.clientX, // clientX
46
- touch.clientY, // clientY
47
- false, // ctrlKey
48
- false, // altKey
49
- false, // shiftKey
50
- false, // metaKey
51
- 0, // button
52
- null // relatedTarget
53
- );
54
- // Dispatch the simulated event to the target element
55
- event.target.dispatchEvent(simulatedEvent);
56
- }
57
-
58
- /**
59
- * Handle the jQuery UI widget's touchstart events
60
- * @param {Object} event The widget element's touchstart event
61
- */
62
- mouseProto._touchStart = function (event) {
63
- var self = this;
64
- // Ignore the event if another widget is already being handled
65
- if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {
66
- return;
67
- }
68
- // Set the flag to prevent other widgets from inheriting the touch event
69
- touchHandled = true;
70
- // Track movement to determine if interaction was a click
71
- self._touchMoved = false;
72
- // Simulate the mouseover event
73
- simulateMouseEvent(event, 'mouseover');
74
- // Simulate the mousemove event
75
- simulateMouseEvent(event, 'mousemove');
76
- // Simulate the mousedown event
77
- simulateMouseEvent(event, 'mousedown');
78
- };
79
- /**
80
- * Handle the jQuery UI widget's touchmove events
81
- * @param {Object} event The document's touchmove event
82
- */
83
- mouseProto._touchMove = function (event) {
84
- // Ignore event if not handled
85
- if (!touchHandled) {
86
- return;
87
- }
88
- // Interaction was not a click
89
- this._touchMoved = true;
90
- // Simulate the mousemove event
91
- simulateMouseEvent(event, 'mousemove');
92
- };
93
- /**
94
- * Handle the jQuery UI widget's touchend events
95
- * @param {Object} event The document's touchend event
96
- */
97
- mouseProto._touchEnd = function (event) {
98
- // Ignore event if not handled
99
- if (!touchHandled) {
100
- return;
101
- }
102
- // Simulate the mouseup event
103
- simulateMouseEvent(event, 'mouseup');
104
- // Simulate the mouseout event
105
- simulateMouseEvent(event, 'mouseout');
106
- // If the touch interaction did not move, it should trigger a click
107
- if (!this._touchMoved) {
108
- // Simulate the click event
109
- simulateMouseEvent(event, 'click');
110
- }
111
- // Unset the flag to allow other widgets to inherit the touch event
112
- touchHandled = false;
113
- };
114
- /**
115
- * A duck punch of the $.ui.mouse _mouseInit method to support touch events.
116
- * This method extends the widget with bound touch event handlers that
117
- * translate touch events to mouse events and pass them to the widget's
118
- * original mouse event handling methods.
119
- */
120
- mouseProto._mouseInit = function () {
121
- var self = this;
122
- // Delegate the touch handlers to the widget's element
123
- self.element.bind({
124
- touchstart: $.proxy(self, '_touchStart'),
125
- touchmove: $.proxy(self, '_touchMove'),
126
- touchend: $.proxy(self, '_touchEnd')
127
- });
128
- // Call the original $.ui.mouse init method
129
- _mouseInit.call(self);
130
- };
131
- /**
132
- * Remove the touch event handlers
133
- */
134
- mouseProto._mouseDestroy = function () {
135
- var self = this;
136
- // Delegate the touch handlers to the widget's element
137
- self.element.unbind({
138
- touchstart: $.proxy(self, '_touchStart'),
139
- touchmove: $.proxy(self, '_touchMove'),
140
- touchend: $.proxy(self, '_touchEnd')
141
- });
142
- // Call the original $.ui.mouse destroy method
143
- _mouseDestroy.call(self);
144
- };
145
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/widget.js DELETED
@@ -1,108 +0,0 @@
1
- (function ($){
2
- $(document).ready(function (){
3
-
4
- var berocket_aapf_widget_product_filters = [],
5
- berocket_aapf_widget_product_limits = [],
6
- berocket_aapf_widget_product_price_limit = [];
7
- function updateProducts( $el ){
8
- $('ul.products').addClass('hide_products').append('<div class="berocket_aapf_widget_loading" />');
9
-
10
- if( $el ){
11
- $li = $el.parent().parent();
12
- if( $el.is("select") ) $li = $el.find("option:selected");
13
- taxonomy = $li.data('taxonomy');
14
- term_id = $li.data('term_id');
15
- operator = $li.data('operator');
16
-
17
- if( $el.is("select") ){
18
- $(berocket_aapf_widget_product_filters).each(function (i, o) {
19
- if (o[0] == taxonomy) {
20
- berocket_aapf_widget_product_filters.splice(i, 1);
21
- }
22
- });
23
- if( $li.val() )
24
- berocket_aapf_widget_product_filters[berocket_aapf_widget_product_filters.length] = [taxonomy, term_id, operator];
25
- }else {
26
- if ($el.is(':checked') || $el.is(':selected')) {
27
- berocket_aapf_widget_product_filters[berocket_aapf_widget_product_filters.length] = [taxonomy, term_id, operator];
28
- } else {
29
- $(berocket_aapf_widget_product_filters).each(function (i, o) {
30
- if (o[0] == taxonomy && o[1] == term_id) {
31
- berocket_aapf_widget_product_filters.splice(i, 1);
32
- }
33
- });
34
- }
35
- }
36
- }
37
-
38
- $t = $('.berocket_filter_slider');
39
- if( $t.hasClass('berocket_filter_slider') ){
40
- $t.each(function (i,o){
41
- val1 = $('#'+$(o).data('fields_1')).val();
42
- val2 = $('#'+$(o).data('fields_2')).val();
43
- berocket_aapf_widget_product_limits[berocket_aapf_widget_product_limits.length] = [$(o).data('taxonomy'), val1, val2];
44
- });
45
- }
46
- $d = $('.berocket_filter_price_slider');
47
- if( $d.hasClass('berocket_filter_price_slider') ){
48
- val1 = $('#'+$d.data('fields_1')).val();
49
- val2 = $('#'+$d.data('fields_2')).val();
50
- berocket_aapf_widget_product_price_limit = [val1, val2];
51
- }
52
-
53
- $.post( the_ajax_script.ajaxurl, { terms: berocket_aapf_widget_product_filters, price: berocket_aapf_widget_product_price_limit, limits: berocket_aapf_widget_product_limits, product_cat: the_ajax_script.product_cat, action: 'berocket_aapf_listener' }, function (data){
54
- $('ul.products').html(data).removeClass('hide_products');
55
- $('.berocket_aapf_widget_loading').remove();
56
- })
57
- }
58
-
59
- $('.berocket_aapf_widget').on("change", "input, select", function(){
60
- updateProducts( $(this) );
61
- });
62
-
63
- $( ".berocket_filter_slider" ).each(function (i,o){
64
- $(o).slider({
65
- range: true,
66
- min: $(o).data('min')>>0,
67
- max: $(o).data('max')>>0,
68
- values: [$(o).data('min')>>0,$(o).data('max')>>0],
69
- slide: function( event, ui ) {
70
- $o = $(ui.handle).parents('div.berocket_filter_slider');
71
-
72
- $( '#'+$o.data('fields_1') ).val( ui.values[0] );
73
- $( '#'+$o.data('fields_2') ).val( ui.values[1] );
74
- },
75
- stop: function(){
76
- updateProducts( false );
77
- }
78
- });
79
- });
80
-
81
- $( ".berocket_filter_price_slider" ).each(function (i,o){
82
- $(o).slider({
83
- range: true,
84
- min: $(o).data('min')>>0,
85
- max: $(o).data('max')>>0,
86
- values: [$(o).data('min')>>0,$(o).data('max')>>0],
87
- slide: function( event, ui ) {
88
- $o = $(ui.handle).parents('div.berocket_filter_price_slider');
89
-
90
- $( '#'+$o.data('fields_1') ).val( ui.values[0].toFixed(2) );
91
- $( '#'+$o.data('fields_2') ).val( ui.values[1].toFixed(2) );
92
- },
93
- stop: function( event, ui ){
94
- updateProducts( false );
95
- }
96
- });
97
- });
98
-
99
- $(".berocket_aapf_widget_height_control").each(function (i,o){
100
- $(o).mCustomScrollbar({
101
- axis: "xy",
102
- theme: $(o).data('scroll_theme'),
103
- scrollInertia: 300
104
- });
105
- })
106
-
107
- });
108
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/widget.min.js CHANGED
@@ -1,2 +1,2 @@
1
  /* http://dean.edwards.name/packer/ */
2
- eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(4($){$(S).T(4(){U c=[],j=[],w=[];4 k(b){$(l.A).V(\'B\').W(\'<x X="C" />\');5(b){$8=b.D().D();5(b.m("y"))$8=b.Y("Z:E");7=$8.3(\'7\');h=$8.3(\'h\');n=$8.3(\'n\');5(b.m("y")){$(c).9(4(i,o){5(o[0]==7){c.F(i,1)}});5($8.6())c[c.z]=[7,h,n]}G{5(b.m(\':10\')||b.m(\':E\')){c[c.z]=[7,h,n]}G{$(c).9(4(i,o){5(o[0]==7&&o[1]==h){c.F(i,1)}})}}}$t=$(\'.p\');5($t.H(\'p\')){$t.9(4(i,o){q=$(\'#\'+$(o).3(\'r\')).6();s=$(\'#\'+$(o).3(\'u\')).6();j[j.z]=[$(o).3(\'7\'),q,s]})}$d=$(\'.v\');5($d.H(\'v\')){q=$(\'#\'+$d.3(\'r\')).6();s=$(\'#\'+$d.3(\'u\')).6();w=[q,s]}$.11(l.12,{13:c,14:w,15:j,I:l.I,16:\'17\'},4(a){$(l.A).18(a).19(\'B\');$(\'.C\').1a()})}$(\'.1b\').1c("1d","1e, y",4(){k($(1f))});$(".p").9(4(i,o){$(o).J({K:L,e:$(o).3(\'e\')>>0,f:$(o).3(\'f\')>>0,g:[$(o).3(\'e\')>>0,$(o).3(\'f\')>>0],M:4(a,b){$o=$(b.N).O(\'x.p\');$(\'#\'+$o.3(\'r\')).6(b.g[0]);$(\'#\'+$o.3(\'u\')).6(b.g[1])},P:4(){k(Q)}})});$(".v").9(4(i,o){$(o).J({K:L,e:$(o).3(\'e\')>>0,f:$(o).3(\'f\')>>0,g:[$(o).3(\'e\')>>0,$(o).3(\'f\')>>0],M:4(a,b){$o=$(b.N).O(\'x.v\');$(\'#\'+$o.3(\'r\')).6(b.g[0].R(2));$(\'#\'+$o.3(\'u\')).6(b.g[1].R(2))},P:4(a,b){k(Q)}})});$(".1g").9(4(i,o){$(o).1h({1i:"1j",1k:$(o).3(\'1l\'),1m:1n})})})})(1o);',62,87,'|||data|function|if|val|taxonomy|li|each|||||min|max|values|term_id||berocket_aapf_widget_product_limits|updateProducts|the_ajax_script|is|operator||berocket_filter_slider|val1|fields_1|val2||fields_2|berocket_filter_price_slider|berocket_aapf_widget_product_price_limit|div|select|length|products_holder_id|hide_products|berocket_aapf_widget_loading|parent|selected|splice|else|hasClass|product_cat|slider|range|true|slide|handle|parents|stop|false|toFixed|document|ready|var|addClass|append|class|find|option|checked|post|ajaxurl|terms|price|limits|action|berocket_aapf_listener|html|removeClass|remove|berocket_aapf_widget|on|change|input|this|berocket_aapf_widget_height_control|mCustomScrollbar|axis|xy|theme|scroll_theme|scrollInertia|300|jQuery'.split('|'),0,{}))
1
  /* http://dean.edwards.name/packer/ */
2
+ eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(5($){$(18).19(5(){E d=1a.1b(8.1c),m=[],s=[];5 u(b){$(8.N).1d(\'O\').1e(\'<P 1f="Q" />\');4(b){$j=b.R().R();4(b.v("n"))$j=b.1g("S:T");g=$j.6(\'g\');p=$j.6(\'p\');w=$j.6(\'w\');4(b.v("n")){$(d).f(5(i,o){4(o[0]==g){d.U(i,1)}});4($j.k())d[d.9]=[g,p,w]}x{4(b.v(\':1h\')||b.v(\':T\')){d[d.9]=[g,p,w]}x{$(d).f(5(i,o){4(o[0]==g&&o[1]==p){d.U(i,1)}})}}}m=[];s=[];$t=$(\'.y\');4($t.F(\'y\')){$t.f(5(i,o){z=$(\'#\'+$(o).6(\'V\')).k();A=$(\'#\'+$(o).6(\'W\')).k();4(z!=$(o).6(\'B\')||A!=$(o).6(\'C\')){4($(o).F(\'G\')){s=[z,A]}x{m[m.9]=[$(o).6(\'g\'),z,A]}}})}H={I:d,e:s,J:m,q:8.q,1i:\'1j\',l:$(\'.K-L n.l\').k()};4(8.1k&&\'D\'X 1l&&\'Y\'X D){Z(H)}$.1m(8.1n,H,5(a){$(8.N).1o(a).1p(\'O\');$(\'.Q\').1q()})}5 Z(a){7=[];r=\'\';4(a.l&&$(\'.K-L n.l S:1r\').1s(\'1t\')!=a.l){7[7.9]=\'1u=\'+a.l}4(a.q&&a.q>0){7[7.9]=\'1v=\'+a.q}4(a.e){$M=$(\'.G\');4(a.e[0]&&a.e[1]&&(a.e[0]!=$M.6(\'B\')||a.e[1]!=$M.6(\'C\'))){7[7.9]=\'e=\'+a.e[0]+\'^\'+a.e[1]}}4(a.J){$(a.J).f(5(i,o){7[7.9]=o[0].10(3)+\'=\'+o[1]+\'^\'+o[2]})}4(a.I){$(a.I).f(5(i,o){7[7.9]=o[0].10(3)+\'=\'+o[1]+\'^\'+o[2]})}E b=\'\';4(7.9){$(7).f(5(i,o){4(r)r+="|";r+=o});b=8.11+"?1w="+r}x{b=8.11}E c={12:"13"};D.Y(c,"12 13",b);D.1x=b}$(\'.1y\').14("1z","1A, n",5(){u($(1B))});$(".y").f(5(i,o){$(o).1C({1D:1E,B:$(o).6(\'B\')>>0,C:$(o).6(\'C\')>>0,15:[$(o).6(\'1F\')>>0,$(o).6(\'1G\')>>0],1H:5(a,b){$o=$(b.1I).1J(\'P.y\');h=b.15;4($(o).F(\'G\')){h[0]=h[0].16(2);h[1]=h[1].16(2)}$(\'#\'+$o.6(\'V\')).k(h[0]);$(\'#\'+$o.6(\'W\')).k(h[1])},1K:5(){u(17)}})});$(".1L").f(5(i,o){$(o).1M({1N:"1O",1P:$(o).6(\'1Q\'),1R:1S})});4(8.1T){$(\'.K-L\').14(\'1U\',5(a){a.1V();u(17)})}})})(1W);',62,121,'||||if|function|data|uri_request_array|the_ajax_script|length|||||price|each|taxonomy|vals||li|val|orderby|berocket_aapf_widget_product_limits|select||term_id|product_cat|uri_request|berocket_aapf_widget_product_price_limit||updateProducts|is|operator|else|berocket_filter_slider|val1|val2|min|max|history|var|hasClass|berocket_filter_price_slider|args|terms|limits|woocommerce|ordering|price_obj|products_holder_id|hide_products|div|berocket_aapf_widget_loading|parent|option|selected|splice|fields_1|fields_2|in|pushState|updateLocation|substring|current_page_url|BeRocket|Rules|on|values|toFixed|false|document|ready|JSON|parse|berocket_aapf_widget_product_filters|addClass|append|class|find|checked|action|berocket_aapf_listener|seo_friendly_urls|window|post|ajaxurl|html|removeClass|remove|first|attr|value|order|pcategory|filters|pathname|berocket_aapf_widget|change|input|this|slider|range|true|value1|value2|slide|handle|parents|stop|berocket_aapf_widget_height_control|mCustomScrollbar|axis|xy|theme|scroll_theme|scrollInertia|300|control_sorting|submit|preventDefault|jQuery'.split('|'),0,{}))
readme.txt CHANGED
@@ -5,7 +5,7 @@ Donate link: http://berocket.com
5
  Tags: filters, product filters, ajax product filters, advanced product filters, woocommerce filters, woocommerce product filters, woocommerce ajax product filters
6
  Requires at least: 3.9
7
  Tested up to: 4.1
8
- Stable tag: 1.0.3.5
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -20,12 +20,15 @@ WooCommerce AJAX Filters - advanced AJAX product filters plugin for WooCommerce.
20
  * No reloading, only ajax
21
  * Slider, radio or checkbox
22
  * No spamming with widgets in admin, 1 widget - multiple instances
 
23
  * Filter visibility by product category. Different categories pages = different ( + global ) filters. One shop for everything
 
24
  * Filter box height limit with scroll themes
25
  * Working great with custom widget area
26
  * Unlimited filters by product attributes
27
 
28
-
 
29
 
30
  = How It Works: =
31
 
@@ -62,16 +65,6 @@ WooCommerce AJAX Filters - advanced AJAX product filters plugin for WooCommerce.
62
 
63
 
64
 
65
- = Next Release ( 1.1.0 ) =
66
-
67
- = Features: =
68
- * New type Image. Admin can upload image to select and deselect before/instead of text
69
- * Option to add icons before/after option text
70
- * Option to take control over (default) sorting function, make it AJAXy and work with filters
71
- * Add filters and actions for other developers to make it easier extending plugin. Please don't edit plugin directly
72
- I'm updating it almost daily =)
73
-
74
-
75
  == Installation ==
76
 
77
  1. Install WooCommerce AJAX Filters either via the WordPress.org plugin directory, or by uploading the files to your server
@@ -88,8 +81,19 @@ WooCommerce AJAX Filters - advanced AJAX product filters plugin for WooCommerce.
88
 
89
  == Changelog ==
90
 
91
- = 1.0.3.5 =
92
- * Enhancement/Fix - Option to set selector for products holder is added. Now you control where data will returned to
 
 
 
 
 
 
 
 
 
 
 
93
 
94
  = 1.0.3.3 =
95
  * Enhancement/Fix - Showing products and options now depending on woocommerce_hide_out_of_stock_items option
5
  Tags: filters, product filters, ajax product filters, advanced product filters, woocommerce filters, woocommerce product filters, woocommerce ajax product filters
6
  Requires at least: 3.9
7
  Tested up to: 4.1
8
+ Stable tag: 1.0.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
20
  * No reloading, only ajax
21
  * Slider, radio or checkbox
22
  * No spamming with widgets in admin, 1 widget - multiple instances
23
+ * SEO friendly urls
24
  * Filter visibility by product category. Different categories pages = different ( + global ) filters. One shop for everything
25
+ * Can take control over sorting select to make it AJAXy
26
  * Filter box height limit with scroll themes
27
  * Working great with custom widget area
28
  * Unlimited filters by product attributes
29
 
30
+ = Demo =
31
+ http://woocommerce-product-filter.berocket.com
32
 
33
  = How It Works: =
34
 
65
 
66
 
67
 
 
 
 
 
 
 
 
 
 
 
68
  == Installation ==
69
 
70
  1. Install WooCommerce AJAX Filters either via the WordPress.org plugin directory, or by uploading the files to your server
81
 
82
  == Changelog ==
83
 
84
+ = 1.0.4 =
85
+ * Enhancement - SEO friendly urls with possibility for users to share/bookmark their search. Will be shortened in future
86
+ * Enhancement - Option added to turn SEO friendly urls on/off. Off by default as this is first version of this feature
87
+ * Enhancement - Option to turn filters on/off globally
88
+ * Enhancement - Option to take control over (default) sorting function, make it AJAXy and work with filters
89
+ * Fix - Sorting remain correct after using filters. Sorting wasn't counted before
90
+ * Fix - If there are 2 or more sliders they are not working correctly.
91
+ * Fix - Values in slider was converted to float even when value ia not a price.
92
+ * Fix - If there are 2 or more values for attribute it was not validated when used in slider.
93
+
94
+ = 1.0.3.6 =
95
+ * Fix - Removed actions that provide warning messages
96
+ * Enhancement - Actions and filters inside plugin
97
 
98
  = 1.0.3.3 =
99
  * Enhancement/Fix - Showing products and options now depending on woocommerce_hide_out_of_stock_items option
templates/admin-settings.php CHANGED
@@ -34,7 +34,21 @@
34
  <th scope="row">Sorting control</th>
35
  <td>
36
  <input name="br_filters_options[control_sorting]" type='checkbox' value='1' <?php if( @$options['control_sorting'] ) echo "checked='checked'";?>/>
37
- <span style="color:#666666;margin-left:2px;">Take control over WooCommerce's sorting selectbox? ( not working yet )</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  </td>
39
  </tr>
40
  </table>
34
  <th scope="row">Sorting control</th>
35
  <td>
36
  <input name="br_filters_options[control_sorting]" type='checkbox' value='1' <?php if( @$options['control_sorting'] ) echo "checked='checked'";?>/>
37
+ <span style="color:#666666;margin-left:2px;">Take control over WooCommerce's sorting selectbox?</span>
38
+ </td>
39
+ </tr>
40
+ <tr>
41
+ <th scope="row">SEO friendly urls</th>
42
+ <td>
43
+ <input name="br_filters_options[seo_friendly_urls]" type='checkbox' value='1' <?php if( @$options['seo_friendly_urls'] ) echo "checked='checked'";?>/>
44
+ <span style="color:#666666;margin-left:2px;">If this option is on url will be changed when filter is selected/changed</span>
45
+ </td>
46
+ </tr>
47
+ <tr>
48
+ <th scope="row">Turn all filters off</th>
49
+ <td>
50
+ <input name="br_filters_options[filters_turn_off]" type='checkbox' value='1' <?php if( @$options['filters_turn_off'] ) echo "checked='checked'";?>/>
51
+ <span style="color:#666666;margin-left:2px;">If you want to hide filters without losing current configuration just turn them off</span>
52
  </td>
53
  </tr>
54
  </table>
templates/checkbox.php CHANGED
@@ -12,7 +12,17 @@
12
  <?php foreach( $terms as $term ):?>
13
  <li data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'>
14
  <span>
15
- <input type='checkbox' id='radio_<?=$term->term_id?>' /><label for='radio_<?=$term->term_id?>'> <?=$term->name?></label>
 
 
 
 
 
 
 
 
 
 
16
  </span>
17
  </li>
18
  <?php endforeach; ?>
12
  <?php foreach( $terms as $term ):?>
13
  <li data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'>
14
  <span>
15
+ <input type='checkbox' id='radio_<?=$term->term_id?>'
16
+ <?php
17
+ if( $_POST['terms'] ){
18
+ foreach( $_POST['terms'] as $p_term ){
19
+ if( $p_term[0] == $term->taxonomy and $term->term_id == $p_term[1] ){
20
+ echo ' checked="checked"';
21
+ break;
22
+ }
23
+ }
24
+ }
25
+ ?> /><label for='radio_<?=$term->term_id?>'> <?=$term->name?></label>
26
  </span>
27
  </li>
28
  <?php endforeach; ?>
templates/radio.php CHANGED
@@ -1,7 +1,17 @@
1
  <?php foreach( $terms as $term ): ?>
2
  <li data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'>
3
  <span>
4
- <input type='radio' id='radio_<?=$term->term_id?>' name='radio_<?=$term->taxonomy?>_<?=$x?>' /><label for='radio_<?=$term->term_id?>'> <?=$term->name?></label>
 
 
 
 
 
 
 
 
 
 
5
  </span>
6
  </li>
7
  <?php endforeach; ?>
1
  <?php foreach( $terms as $term ): ?>
2
  <li data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'>
3
  <span>
4
+ <input type='radio' id='radio_<?=$term->term_id?>' name='radio_<?=$term->taxonomy?>_<?=$x?>'
5
+ <?php
6
+ if( $_POST['terms'] ){
7
+ foreach( $_POST['terms'] as $p_term ){
8
+ if( $p_term[0] == $term->taxonomy and $term->term_id == $p_term[1] ){
9
+ echo ' checked="checked"';
10
+ break;
11
+ }
12
+ }
13
+ }
14
+ ?> /><label for='radio_<?=$term->term_id?>'> <?=$term->name?></label>
15
  </span>
16
  </li>
17
  <?php endforeach; ?>
templates/select.php CHANGED
@@ -3,7 +3,18 @@
3
  <select>
4
  <option data-taxonomy='<?=$terms[0]->taxonomy?>' value=''>Any</option>
5
  <?php foreach( $terms as $term ): ?>
6
- <option data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>' data-operator='<?=$operator?>'><?=$term->name?></option>
 
 
 
 
 
 
 
 
 
 
 
7
  <?php endforeach; ?>
8
  </select>
9
  </span>
3
  <select>
4
  <option data-taxonomy='<?=$terms[0]->taxonomy?>' value=''>Any</option>
5
  <?php foreach( $terms as $term ): ?>
6
+ <option data-term_id='<?=$term->term_id?>' data-taxonomy='<?=$term->taxonomy?>'
7
+ <?php
8
+ if( $_POST['terms'] ){
9
+ foreach( $_POST['terms'] as $p_term ){
10
+ if( $p_term[0] == $term->taxonomy and $term->term_id == $p_term[1] ){
11
+ echo ' selected="selected"';
12
+ break;
13
+ }
14
+ }
15
+ }
16
+ ?>
17
+ data-operator='<?=$operator?>'><?=$term->name?></option>
18
  <?php endforeach; ?>
19
  </select>
20
  </span>
templates/slider.php CHANGED
@@ -1,11 +1,12 @@
 
1
  <li class='<?=$main_class?>'>
2
  <span class='left'>
3
- <input type='text' disabled id='text_<?=$id?>_1' value='<?=$min?>' /><label for='text_<?=$id?>_1'>
4
  </span>
5
  <span class='right'>
6
- <input type='text' disabled id='text_<?=$id?>_2' value='<?=$max?>' /><label for='text_<?=$id?>_2'>
7
  </span>
8
  <span class='slide'>
9
- <div class='<?=$slider_class?>' data-taxonomy='<?=$id?>' data-min='<?=$min?>' data-max='<?=$max?>' data-fields_1='text_<?=$id?>_1' data-fields_2='text_<?=$id?>_2'></div>
10
  </span>
11
  </li>
1
+ <?php $unique = rand( 0, time() ); ?>
2
  <li class='<?=$main_class?>'>
3
  <span class='left'>
4
+ <input type='text' disabled id='text_<?=$filter_slider_id . $unique?>_1' value='<?=$slider_value1?>' /><label for='text_<?=$filter_slider_id . $unique?>_1'>
5
  </span>
6
  <span class='right'>
7
+ <input type='text' disabled id='text_<?=$filter_slider_id . $unique?>_2' value='<?=$slider_value2?>' /><label for='text_<?=$filter_slider_id . $unique?>_2'>
8
  </span>
9
  <span class='slide'>
10
+ <div class='<?=$slider_class?>' data-taxonomy='<?=$filter_slider_id?>' data-min='<?=$min?>' data-max='<?=$max?>' data-value1='<?=$slider_value1?>' data-value2='<?=$slider_value2?>' data-fields_1='text_<?=$filter_slider_id . $unique?>_1' data-fields_2='text_<?=$filter_slider_id . $unique?>_2'></div>
11
  </span>
12
  </li>
woocommerce-filters.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Advanced AJAX Product Filters for WooCommerce
4
  Plugin URI: http://berocket.com/wp-plugins/product-filters
5
  Description: Advanced AJAX Product Filters for WooCommerce
6
- Version: 1.0.3.6
7
  Author: BeRocket
8
  Author URI: http://berocket.com
9
  */
@@ -23,7 +23,9 @@ class BeRocket_AAPF {
23
  "no_products_message" => "There are no products meeting your criteria",
24
  "no_products_class" => "",
25
  "control_sorting" => "0",
26
- "products_holder_id" => "ul.products"
 
 
27
  );
28
 
29
  function __construct(){
@@ -32,6 +34,11 @@ class BeRocket_AAPF {
32
 
33
  add_action( 'admin_menu', array( __CLASS__, 'br_add_options_page' ) );
34
  add_action( 'admin_init', array( __CLASS__, 'register_br_options' ) );
 
 
 
 
 
35
  }
36
 
37
  public static function br_add_options_page(){
@@ -42,6 +49,36 @@ class BeRocket_AAPF {
42
  include AAPF_TEMPLATE_PATH . "admin-settings.php";
43
  }
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  /**
46
  * Get template part (for templates like the slider).
47
  *
3
  Plugin Name: Advanced AJAX Product Filters for WooCommerce
4
  Plugin URI: http://berocket.com/wp-plugins/product-filters
5
  Description: Advanced AJAX Product Filters for WooCommerce
6
+ Version: 1.0.4
7
  Author: BeRocket
8
  Author URI: http://berocket.com
9
  */
23
  "no_products_message" => "There are no products meeting your criteria",
24
  "no_products_class" => "",
25
  "control_sorting" => "0",
26
+ "products_holder_id" => "ul.products",
27
+ "filters_turn_off" => "0",
28
+ "seo_friendly_urls" => "0"
29
  );
30
 
31
  function __construct(){
34
 
35
  add_action( 'admin_menu', array( __CLASS__, 'br_add_options_page' ) );
36
  add_action( 'admin_init', array( __CLASS__, 'register_br_options' ) );
37
+
38
+ if( @ $_GET['filters'] and ! @ defined( 'DOING_AJAX' ) ) {
39
+ br_aapf_args_converter();
40
+ add_filter( 'pre_get_posts', array( __CLASS__, 'apply_user_filters' ) );
41
+ }
42
  }
43
 
44
  public static function br_add_options_page(){
49
  include AAPF_TEMPLATE_PATH . "admin-settings.php";
50
  }
51
 
52
+ public static function apply_user_filters( $query ){
53
+ if( $query->is_main_query() and ( $query->get( 'post_type' ) == 'product' or $query->get( 'product_cat' ) ) ){
54
+ $args = br_aapf_args_parser();
55
+
56
+ if( $_POST['price'] ){
57
+ $_GET['min_price'] = $_POST['price'][0];
58
+ $_GET['max_price'] = $_POST['price'][1];
59
+
60
+ add_filter( 'loop_shop_post_in', array( 'WC_QUERY', 'price_filter' ) );
61
+ }
62
+
63
+ if( $args['meta_key'] ){
64
+ $query->set( 'meta_key', $args['meta_key'] );
65
+ }
66
+ if( $args['tax_query'] ) {
67
+ $query->set( 'tax_query', $args['tax_query'] );
68
+ }
69
+ if( $args['fields'] ) {
70
+ $query->set( 'fields', $args['fields'] );
71
+ }
72
+ if( $args['where'] ) {
73
+ $query->set( 'where', $args['where'] );
74
+ }
75
+ if( $args['join'] ) {
76
+ $query->set( 'join', $args['join'] );
77
+ }
78
+ }
79
+ return $query;
80
+ }
81
+
82
  /**
83
  * Get template part (for templates like the slider).
84
  *