Advanced AJAX Product Filters - Version 1.0.4.1

Version Description

  • Enhancement - Adding AJAX for pagination.
  • Enhancement - Adding PushState for pagination.
  • Enhancement/Fix - Pagination wasn't updating when filters used.
  • Enhancement/Fix - Text with amount of results (Eg "Showing all 2 results") wasn't updating after filters applied
  • Enhancement/Fix - When choosing Slider in admin Operator became hidden
  • Fix - All sliders except price wasn't working with SEO url
  • Fix - When changing attribute to/from price in admin all filters jumping
  • Fix - After filter applied all products was showed. Even those with Draft status.
Download this release

Release Info

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

Code changes from version 1.0.4 to 1.0.4.1

includes/functions.php CHANGED
@@ -1,13 +1,26 @@
1
  <?php
2
 
 
3
  if( ! function_exists( 'br_get_template_part' ) ){
4
- function br_get_template_part( $name = '' ){
 
 
 
 
 
 
 
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
 
@@ -22,7 +35,12 @@ if( ! function_exists( 'br_aapf_get_attributes' ) ) {
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 ) ){
@@ -72,7 +90,14 @@ if( ! function_exists( 'br_parse_order_by' ) ){
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
 
@@ -138,7 +163,10 @@ if( ! function_exists( 'br_aapf_args_parser' ) ){
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 {
1
  <?php
2
 
3
+
4
  if( ! function_exists( 'br_get_template_part' ) ){
5
+ /**
6
+ * Public function to get plugin's template
7
+ *
8
+ * @param string $name Template name to search for
9
+ *
10
+ * @return void
11
+ */
12
+ function br_get_template_part( $name = '' ){
13
  BeRocket_AAPF::br_get_template_part( $name );
14
  }
15
  }
16
 
17
  if( ! function_exists( 'br_aapf_get_attributes' ) ) {
18
+ /**
19
+ * Get all possible woocommerce attribute taxonomies
20
+ *
21
+ * @return mixed|void
22
+ */
23
+ function br_aapf_get_attributes() {
24
  $attribute_taxonomies = wc_get_attribute_taxonomies();
25
  $attributes = array();
26
 
35
  }
36
 
37
  if( ! function_exists( 'br_parse_order_by' ) ){
38
+ /**
39
+ * br_aapf_parse_order_by - parsing order by data and saving to $args array that was passed into
40
+ *
41
+ * @param $args
42
+ */
43
+ function br_aapf_parse_order_by( &$args ){
44
  $orderby = $_POST['orderby'];
45
  $order = "ASK";
46
  if( @ preg_match( "/-/", $orderby ) ){
90
  }
91
 
92
  if( ! function_exists( 'br_aapf_args_parser' ) ){
93
+ /**
94
+ * br_aapf_args_parser - extend $args based on passed filters
95
+ *
96
+ * @param array $args
97
+ *
98
+ * @return array
99
+ */
100
+ function br_aapf_args_parser( $args = array() ) {
101
  $attributes_terms = $tax_query = array();
102
  $attributes = apply_filters( 'berocket_aapf_listener_get_attributes', br_aapf_get_attributes() );
103
 
163
  }
164
 
165
  if( ! function_exists( 'br_aapf_args_converter' ) ) {
166
+ /**
167
+ * convert args-url to normal filters
168
+ */
169
+ function br_aapf_args_converter() {
170
  if ( preg_match( "~\|~", $_GET['filters'] ) ) {
171
  $filters = explode( "|", $_GET['filters'] );
172
  } else {
includes/widget.php CHANGED
@@ -78,7 +78,7 @@ class BeRocket_AAPF_Widget extends WP_Widget {
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'],
@@ -369,57 +369,56 @@ class BeRocket_AAPF_Widget extends WP_Widget {
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() ){
382
- while( $query->have_posts() ){
383
- $query->the_post();
384
- $product = new WC_Product($query->post);
385
- $product_price = $product->get_price();
386
-
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
-
409
- if( @$_POST['price'] ){
410
- if( $product_price < $_POST['price'][0] or $product_price > $_POST['price'][1] )
411
- continue;
412
- }
413
 
414
- $has_products = true;
 
 
 
 
 
 
 
 
415
  woocommerce_get_template_part( 'content', 'product' );
416
  }
417
  wp_reset_postdata();
418
- }
419
-
420
- if( ! $has_products ){
421
  echo apply_filters( 'berocket_aapf_listener_no_products_message', "<div class='no-products" . ( ( $br_options['no_products_class'] ) ? ' '.$br_options['no_products_class'] : '' ) . "'>" . $br_options['no_products_message'] . "</div>" );
422
  }
 
 
 
 
 
423
  die();
424
  }
425
 
@@ -442,4 +441,74 @@ class BeRocket_AAPF_Widget extends WP_Widget {
442
  $classes[] = 'product';
443
  return apply_filters( 'berocket_aapf_add_product_class', $classes );
444
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  }
78
  'berocket_aapf_widget-script',
79
  'the_ajax_script',
80
  array(
81
+ 'current_page_url' => preg_replace( "~paged?/[0-9]+/?~", "", 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'],
369
  * Widget ajax listener
370
  */
371
  public static function listener(){
372
+ global $wp_query, $wp_rewrite;
373
  $br_options = apply_filters( 'berocket_aapf_listener_br_options', get_option('br_filters_options') );
374
 
375
  add_filter( 'post_class', array( __CLASS__, 'add_product_class' ) );
376
+ add_filter( 'woocommerce_pagination_args', array( __CLASS__, 'pagination_args' ) );
377
 
378
  $args = apply_filters( 'berocket_aapf_listener_wp_query_args', $args );
379
 
380
+ $args['post__in'] = BeRocket_AAPF::limits_filter( array() );
381
+ $args['post__in'] = BeRocket_AAPF::price_filter( $args['post__in'] );
382
+ $args['post_status'] = 'publish';
383
+
384
+ add_filter( 'posts_where', array( 'WC_QUERY', 'exclude_protected_products' ) );
385
+
386
+ // here we get max products to know if current page is not too big
387
+ $wp_query = new WP_Query( $args );
388
+
389
+ if ( $wp_rewrite->using_permalinks() and preg_match( "~/page/([0-9]+)~", $_POST['location'], $mathces ) ) {
390
+ $args['paged'] = min( $mathces[1], $wp_query->max_num_pages );
391
+ $wp_query = new WP_Query( $args );
392
+ } elseif( preg_match( "~paged?=([0-9]+)~", $_POST['location'], $mathces ) ) {
393
+ $args['paged'] = min( $mathces[1], $wp_query->max_num_pages );
394
+ $wp_query = new WP_Query( $args );
395
+ }
396
+
397
+ ob_start();
398
+ woocommerce_result_count();
399
+ $_RESPONSE['results_num_html'] = apply_filters( 'berocket_aapf_listener_results_num_text', ob_get_contents() );
400
+ ob_end_clean();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
 
402
+ ob_start();
403
+ woocommerce_pagination();
404
+ $_RESPONSE['pagination_html'] = apply_filters( 'berocket_aapf_listener_pagination_html', ob_get_contents() );
405
+ ob_end_clean();
406
+
407
+ ob_start();
408
+ if ( $wp_query->have_posts() ) {
409
+ while ( $wp_query->have_posts() ) {
410
+ $wp_query->the_post();
411
  woocommerce_get_template_part( 'content', 'product' );
412
  }
413
  wp_reset_postdata();
414
+ } else {
 
 
415
  echo apply_filters( 'berocket_aapf_listener_no_products_message', "<div class='no-products" . ( ( $br_options['no_products_class'] ) ? ' '.$br_options['no_products_class'] : '' ) . "'>" . $br_options['no_products_message'] . "</div>" );
416
  }
417
+ $_RESPONSE['products'] = ob_get_contents();
418
+ ob_end_clean();
419
+
420
+ echo json_encode( $_RESPONSE );
421
+
422
  die();
423
  }
424
 
441
  $classes[] = 'product';
442
  return apply_filters( 'berocket_aapf_add_product_class', $classes );
443
  }
444
+
445
+ public static function pagination_args( $args = array() ) {
446
+ $args['base'] = str_replace( 999999999, '%#%', self::get_pagenum_link( 999999999 ) );
447
+ return $args;
448
+ }
449
+
450
+ // 99% copy of WordPress' get_pagenum_link.
451
+ public static function get_pagenum_link($pagenum = 1, $escape = true ) {
452
+ global $wp_rewrite;
453
+
454
+ $pagenum = (int) $pagenum;
455
+
456
+ $request = remove_query_arg( 'paged', preg_replace( "~".home_url()."~", "", $_POST['location'] ) );
457
+
458
+ $home_root = parse_url(home_url());
459
+ $home_root = ( isset($home_root['path']) ) ? $home_root['path'] : '';
460
+ $home_root = preg_quote( $home_root, '|' );
461
+
462
+ $request = preg_replace('|^'. $home_root . '|i', '', $request);
463
+ $request = preg_replace('|^/+|', '', $request);
464
+
465
+ if ( !$wp_rewrite->using_permalinks() ) {
466
+ $base = trailingslashit( get_bloginfo( 'url' ) );
467
+
468
+ if ( $pagenum > 1 ) {
469
+ $result = add_query_arg( 'paged', $pagenum, $base . $request );
470
+ } else {
471
+ $result = $base . $request;
472
+ }
473
+ } else {
474
+ $qs_regex = '|\?.*?$|';
475
+ preg_match( $qs_regex, $request, $qs_match );
476
+
477
+ if ( !empty( $qs_match[0] ) ) {
478
+ $query_string = $qs_match[0];
479
+ $request = preg_replace( $qs_regex, '', $request );
480
+ } else {
481
+ $query_string = '';
482
+ }
483
+
484
+ $request = preg_replace( "|$wp_rewrite->pagination_base/\d+/?$|", '', $request);
485
+ $request = preg_replace( '|^' . preg_quote( $wp_rewrite->index, '|' ) . '|i', '', $request);
486
+ $request = ltrim($request, '/');
487
+
488
+ $base = trailingslashit( get_bloginfo( 'url' ) );
489
+
490
+ if ( $wp_rewrite->using_index_permalinks() && ( $pagenum > 1 || '' != $request ) )
491
+ $base .= $wp_rewrite->index . '/';
492
+
493
+ if ( $pagenum > 1 ) {
494
+ $request = ( ( !empty( $request ) ) ? trailingslashit( $request ) : $request ) . user_trailingslashit( $wp_rewrite->pagination_base . "/" . $pagenum, 'paged' );
495
+ }
496
+
497
+ $result = $base . $request . $query_string;
498
+ }
499
+
500
+ /**
501
+ * Filter the page number link for the current request.
502
+ *
503
+ * @since 2.5.0
504
+ *
505
+ * @param string $result The page number link.
506
+ */
507
+ $result = apply_filters( 'get_pagenum_link', $result );
508
+
509
+ if ( $escape )
510
+ return esc_url( $result );
511
+ else
512
+ return esc_url_raw( $result );
513
+ }
514
  }
js/admin.js CHANGED
@@ -2,12 +2,22 @@
2
  $(document).ready(function () {
3
 
4
  $(document).on('change', '.berocket_aapf_widget_admin_attribute_select', function () {
 
5
  if ($(this).val() == 'price') {
6
- $('.berocket_aapf_widget_admin_type_select').html('<option value="slider">Slider</option>');
7
- $('.berocket_aapf_widget_admin_operator_select').parent().parent().hide(0);
8
  } else {
9
- $('.berocket_aapf_widget_admin_type_select').html('<option value="checkbox">Checkbox</option><option value="radio">Radio</option><option value="select">Select</option><option value="slider">Slider</option>');
10
- $('.berocket_aapf_widget_admin_operator_select').parent().parent().show(0);
 
 
 
 
 
 
 
 
 
11
  }
12
  });
13
 
2
  $(document).ready(function () {
3
 
4
  $(document).on('change', '.berocket_aapf_widget_admin_attribute_select', function () {
5
+ $parent = $(this).parents('form');
6
  if ($(this).val() == 'price') {
7
+ $('.berocket_aapf_widget_admin_type_select', $parent).html('<option value="slider">Slider</option>');
8
+ $('.berocket_aapf_widget_admin_operator_select', $parent).parent().parent().hide(0);
9
  } else {
10
+ $('.berocket_aapf_widget_admin_type_select', $parent).html('<option value="checkbox">Checkbox</option><option value="radio">Radio</option><option value="select">Select</option><option value="slider">Slider</option>');
11
+ $('.berocket_aapf_widget_admin_operator_select', $parent).parent().parent().show(0);
12
+ }
13
+ });
14
+
15
+ $(document).on('change', '.berocket_aapf_widget_admin_type_select', function () {
16
+ $parent = $(this).parents('form');
17
+ if ($(this).val() == 'slider') {
18
+ $('.berocket_aapf_widget_admin_operator_select', $parent).parent().parent().hide(0);
19
+ } else {
20
+ $('.berocket_aapf_widget_admin_operator_select', $parent).parent().parent().show(0);
21
  }
22
  });
23
 
js/widget.min.js CHANGED
@@ -1,2 +1 @@
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,{}))
1
+ 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($){$(1w).1x(5(){U d=1y.1z(j.1A),A=[],J=[],K=1;4($(\'.7-f\').B(\'.7-f\')){K=C($(\'.7-f .x\').L());4(K<1)K=1}5 D(b){$(j.16).1B(\'17\').1C(\'<18 19="1a" />\');4(b){$s=b.1b().1b();4(b.M("E"))$s=b.1D("1c:1d");u=$s.6(\'u\');F=$s.6(\'F\');N=$s.6(\'N\');4(b.M("E")){$(d).n(5(i,o){4(o[0]==u){d.1e(i,1)}});4($s.y())d[d.k]=[u,F,N]}v{4(b.M(\':1E\')||b.M(\':1d\')){d[d.k]=[u,F,N]}v{$(d).n(5(i,o){4(o[0]==u&&o[1]==F){d.1e(i,1)}})}}}A=[];J=[];$t=$(\'.O\');4($t.B(\'O\')){$t.n(5(i,o){P=$(\'#\'+$(o).6(\'1f\')).y();Q=$(\'#\'+$(o).6(\'1g\')).y();4(P!=$(o).6(\'R\')||Q!=$(o).6(\'S\')){4($(o).B(\'V\')){J=[P,Q]}v{A[A.k]=[$(o).6(\'u\'),P,Q]}}})}4($(\'.7-f\').B(\'.7-f\')){$(\'.7-f 1F.p-1h s a\')}l={W:d,m:J,X:A,G:j.G,1G:\'1H\',z:$(\'.7-Y E.z\').y()};4(j.1I&&\'T\'1i 1J&&\'1j\'1i T){1k(l);l.g=g.H}v{l.g=j.1l;8=$(\'.7-f I.x\').L();4(q=g.H.r(/.+\\/p\\/([0-9]+).+/,"$1")){4(!C(8)){8=q}l.g=l.g.r(/\\/?/,"")+"/p/"+8+"/"}v 4(q=g.H.r(/.+1m?=([0-9]+).+/,"$1")){4(!C(8)){8=q}l.g=l.g.r(/\\/?/,"")+"?p="+8+""}}$.1K(j.1L,l,5(a){$(\'.7-1M-1N\').1n(a.1O);$(\'.7-f\').Z();$(j.16).1o(a.1P).1n(a.1Q).1p(\'17\');$(\'.1a\').Z();10()},"1R")}5 1k(a){e=[];h=\'\';4(a.z&&$(\'.7-Y E.z 1c:1S\').1T(\'1U\')!=a.z){e[e.k]=\'1V=\'+a.z}4(a.G&&a.G>0){e[e.k]=\'1W=\'+a.G}4(a.m){$11=$(\'.V\');4(a.m[0]&&a.m[1]&&(a.m[0]!=$11.6(\'R\')||a.m[1]!=$11.6(\'S\'))){e[e.k]=\'m=\'+a.m[0]+\'^\'+a.m[1]}}4(a.X){$(a.X).n(5(i,o){e[e.k]=o[0].1q(3)+\'=\'+o[1]+\'^\'+o[2]})}4(a.W){$(a.W).n(5(i,o){e[e.k]=o[0].1q(3)+\'=\'+o[1]+\'^\'+o[2]})}U b=j.1l;4(e.k){$(e).n(5(i,o){4(h)h+="|";h+=o})}8=$(\'.7-f I.x\').L();4(q=g.H.r(/.+\\/p\\/([0-9]+).+/,"$1")){4(!C(8)){8=q}b=b.r(/\\/?$/,"")+"/p/"+8+"/";4(h){b=b+"?12="+h}}v 4(q=g.H.r(/.+1m?=([0-9]+).+/,"$1")){4(!C(8)){8=q}b=b.r(/\\/?$/,"")+"?p="+8+"";4(h){b=b+"&12="+h}}v{4(h){b=b+"?12="+h}}U c={1r:"1s"};T.1j(c,"1r 1s",b);T.1X=b}5 10(){$(\'.7-f\').13(\'1Y\',\'a\',5(a){a.1t();$(\'.7-f I.x\').1p(\'x\');$(14).1o("<I 19=\'p-1h x\'>"+$(14).L()+"</I>").Z();D(15)})}$(\'.1Z\').13("20","21, E",5(){D($(14))});$(".O").n(5(i,o){$(o).22({23:24,R:$(o).6(\'R\')>>0,S:$(o).6(\'S\')>>0,1u:[$(o).6(\'25\')>>0,$(o).6(\'26\')>>0],27:5(a,b){$o=$(b.28).29(\'18.O\');w=b.1u;4($(o).B(\'V\')){w[0]=w[0].1v(2);w[1]=w[1].1v(2)}$(\'#\'+$o.6(\'1f\')).y(w[0]);$(\'#\'+$o.6(\'1g\')).y(w[1])},2a:5(){D(15)}})});$(".2b").n(5(i,o){$(o).2c({2d:"2e",2f:$(o).6(\'2g\'),2h:2i})});4(j.2j){$(\'.7-Y\').13(\'2k\',5(a){a.1t();D(15)})}10()})})(2l);',62,146,'||||if|function|data|woocommerce|cur_page||||||uri_request_array|pagination|location|uri_request||the_ajax_script|length|args|price|each||page|prev_page|replace|li||taxonomy|else|vals|current|val|orderby|berocket_aapf_widget_product_limits|hasClass|parseInt|updateProducts|select|term_id|product_cat|href|span|berocket_aapf_widget_product_price_limit|woocommerce_pagination_page|text|is|operator|berocket_filter_slider|val1|val2|min|max|history|var|berocket_filter_price_slider|terms|limits|ordering|remove|pagin_action_init|price_obj|filters|on|this|false|products_holder_id|hide_products|div|class|berocket_aapf_widget_loading|parent|option|selected|splice|fields_1|fields_2|numbers|in|pushState|updateLocation|current_page_url|paged|html|after|removeClass|substring|BeRocket|Rules|preventDefault|values|toFixed|document|ready|JSON|parse|berocket_aapf_widget_product_filters|addClass|append|find|checked|ul|action|berocket_aapf_listener|seo_friendly_urls|window|post|ajaxurl|result|count|results_num_html|pagination_html|products|json|first|attr|value|order|pcategory|pathname|click|berocket_aapf_widget|change|input|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|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.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -17,15 +17,15 @@ WooCommerce AJAX Filters - advanced AJAX product filters plugin for WooCommerce.
17
 
18
  = Features: =
19
 
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
@@ -81,6 +81,16 @@ http://woocommerce-product-filter.berocket.com
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
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.1
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
17
 
18
  = Features: =
19
 
20
+ * AJAX Filters, Pagination and Sorting!
21
+ * Unlimited Filters
22
+ * Multiple User Interface Elements
23
+ * SEO Friendly Urls ( with HTML5 PushState )
24
+ * Filter Visibility By Product Category And Globals.
 
25
  * Filter box height limit with scroll themes
26
  * Working great with custom widget area
27
+ * Drag and Drop Filter Building
28
+ * And More...
29
 
30
  = Demo =
31
  http://woocommerce-product-filter.berocket.com
81
 
82
  == Changelog ==
83
 
84
+ = 1.0.4.1 =
85
+ * Enhancement - Adding AJAX for pagination.
86
+ * Enhancement - Adding PushState for pagination.
87
+ * Enhancement/Fix - Pagination wasn't updating when filters used.
88
+ * Enhancement/Fix - Text with amount of results (Eg "Showing all 2 results") wasn't updating after filters applied
89
+ * Enhancement/Fix - When choosing Slider in admin Operator became hidden
90
+ * Fix - All sliders except price wasn't working with SEO url
91
+ * Fix - When changing attribute to/from price in admin all filters jumping
92
+ * Fix - After filter applied all products was showed. Even those with Draft status.
93
+
94
  = 1.0.4 =
95
  * Enhancement - SEO friendly urls with possibility for users to share/bookmark their search. Will be shortened in future
96
  * Enhancement - Option added to turn SEO friendly urls on/off. Off by default as this is first version of this feature
templates/admin.php CHANGED
@@ -24,7 +24,7 @@
24
  </select>
25
  </label>
26
  </p>
27
- <p <?php if ( $instance['attribute'] == 'price' ) echo " style='display: none;'"; ?> >
28
  <label>Operator:
29
  <select id="<?php echo $this->get_field_id( 'operator' ); ?>" name="<?php echo $this->get_field_name( 'operator' ); ?>" class="berocket_aapf_widget_admin_operator_select">
30
  <option <?php if ($instance['operator'] == 'AND') echo 'selected'; ?> value="AND">AND</option>
24
  </select>
25
  </label>
26
  </p>
27
+ <p <?php if ( $instance['attribute'] == 'price' or $instance['type'] == 'slider' ) echo " style='display: none;'"; ?> >
28
  <label>Operator:
29
  <select id="<?php echo $this->get_field_id( 'operator' ); ?>" name="<?php echo $this->get_field_name( 'operator' ); ?>" class="berocket_aapf_widget_admin_operator_select">
30
  <option <?php if ($instance['operator'] == 'AND') echo 'selected'; ?> value="AND">AND</option>
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.4
7
  Author: BeRocket
8
  Author URI: http://berocket.com
9
  */
@@ -50,33 +50,106 @@ class BeRocket_AAPF {
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
  /**
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.1
7
  Author: BeRocket
8
  Author URI: http://berocket.com
9
  */
50
  }
51
 
52
  public static function apply_user_filters( $query ){
 
 
53
 
54
+ if( $query->is_main_query() and
55
+ ( $query->get( 'post_type' ) == 'product' or $query->get( 'product_cat' ) )
56
+ or
57
+ $query->is_page() && 'page' == get_option( 'show_on_front' ) && $query->get('page_id') == wc_get_page_id('shop')
58
+ ){
59
+ $args = br_aapf_args_parser();
60
 
61
+ if( @ $_POST['price'] ){
62
+ list( $_GET['min_price'], $_GET['max_price'] ) = $_POST['price'];
63
  add_filter( 'loop_shop_post_in', array( 'WC_QUERY', 'price_filter' ) );
64
  }
65
 
66
+ if ( @ $_POST['limits'] ) {
67
+ add_filter( 'loop_shop_post_in', array( __CLASS__, 'limits_filter' ) );
68
  }
69
+
70
+ $args_fields = array( 'meta_key', 'tax_query', 'fields', 'where', 'join', 'meta_query' );
71
+ foreach( $args_fields as $args_field ){
72
+ if( @ $args[$args_field] ){
73
+ $query->set( $args_field, $args[$args_field] );
74
+ }
75
  }
76
+ }
77
+
78
+ return $query;
79
+ }
80
+
81
+ public static function limits_filter( $filtered_posts ){
82
+ global $wpdb;
83
+
84
+ if ( $_POST['limits'] ) {
85
+ $matched_products = array();
86
+
87
+ foreach ( $_POST['limits'] as $v ) {
88
+ $matched_products_query = $wpdb->get_results( $wpdb->prepare("
89
+ SELECT DISTINCT ID, post_parent, post_type FROM $wpdb->posts
90
+ INNER JOIN $wpdb->term_relationships as tr ON ID = tr.object_id
91
+ INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
92
+ INNER JOIN $wpdb->terms as t ON t.term_id = tt.term_id
93
+ WHERE post_type IN ( 'product', 'product_variation' ) AND post_status = 'publish'
94
+ AND tt.taxonomy = %s AND t.slug BETWEEN %d AND %d
95
+ ", $v[0], $v[1], $v[2] ), OBJECT_K );
96
+
97
+ if ( $matched_products_query ) {
98
+ foreach ( $matched_products_query as $product ) {
99
+ if ( $product->post_type == 'product' )
100
+ $matched_products[] = $product->ID;
101
+ if ( $product->post_parent > 0 && ! in_array( $product->post_parent, $matched_products ) )
102
+ $matched_products[] = $product->post_parent;
103
+ }
104
+ }
105
  }
106
+
107
+ $matched_products = array_unique( $matched_products );
108
+
109
+ // Filter the id's
110
+ if ( sizeof( $filtered_posts ) == 0) {
111
+ $filtered_posts = $matched_products;
112
+ } else {
113
+ $filtered_posts = array_intersect( $filtered_posts, $matched_products );
114
  }
115
+ }
116
+
117
+ return (array) $filtered_posts;
118
+ }
119
+
120
+ public static function price_filter( $filtered_posts ){
121
+ global $wpdb;
122
+
123
+ if ( $_POST['price'] ) {
124
+ $matched_products = array();
125
+ $min = floatval( $_POST['price'][0] );
126
+ $max = floatval( $_POST['price'][1] );
127
+
128
+ $matched_products_query = apply_filters( 'woocommerce_price_filter_results', $wpdb->get_results( $wpdb->prepare("
129
+ SELECT DISTINCT ID, post_parent, post_type FROM $wpdb->posts
130
+ INNER JOIN $wpdb->postmeta ON ID = post_id
131
+ WHERE post_type IN ( 'product', 'product_variation' ) AND post_status = 'publish' AND meta_key = %s AND meta_value BETWEEN %d AND %d
132
+ ", '_price', $min, $max ), OBJECT_K ), $min, $max );
133
+
134
+ if ( $matched_products_query ) {
135
+ foreach ( $matched_products_query as $product ) {
136
+ if ( $product->post_type == 'product' )
137
+ $matched_products[] = $product->ID;
138
+ if ( $product->post_parent > 0 && ! in_array( $product->post_parent, $matched_products ) )
139
+ $matched_products[] = $product->post_parent;
140
+ }
141
  }
142
+
143
+ // Filter the id's
144
+ if ( sizeof( $filtered_posts ) == 0) {
145
+ $filtered_posts = $matched_products;
146
+ } else {
147
+ $filtered_posts = array_intersect( $filtered_posts, $matched_products );
148
+ }
149
+
150
  }
151
+
152
+ return (array) $filtered_posts;
153
  }
154
 
155
  /**