Pagination + sorting tweaks, new active filters widget, sort both directions for price, fix for #coenfail. Closes #771.

This commit is contained in:
Mike Jolley 2012-10-14 13:06:37 +01:00
parent 37e8a193a0
commit 596c408c27
14 changed files with 401 additions and 86 deletions

File diff suppressed because one or more lines are too long

View File

@ -383,7 +383,7 @@ span.onsale {
/* Product loops */
.products ul, ul.products {
margin: 0 0 14px;
margin: 0 0 1em;
padding: 0;
list-style:none outside;
clear:both;
@ -472,8 +472,50 @@ ul.products {
}
}
.woocommerce_result_count {
float: left;
margin: 0 0 1em;
}
.woocommerce_ordering {
margin-bottom: 2em;
margin: 0 0 1em;
float: right;
select {
vertical-align: top;
}
}
nav.woocommerce_pagination, #content nav.woocommerce_pagination {
text-align: center;
ul {
display: inline-block;
white-space: nowrap;
clear: both;
border: 1px solid darken( @secondary, 10 );
border-right: 0;
margin: 1px;
li {
border-right: 1px solid darken( @secondary, 10 );
padding: 0;
margin: 0;
float: left;
display: inline;
overflow: hidden;
a, span {
margin: 0;
text-decoration: none;
padding: 0;
line-height: 1em;
font-size: 1em;
font-weight: normal;
padding: .5em;
min-width: 1em;
display: block;
}
span.current, a:hover, a:focus {
background: @secondary;
color: darken( @secondary, 40 );
}
}
}
}
/* =Buttons
@ -1403,37 +1445,64 @@ ul.digital-downloads {
/* =Layered Nav Widget
-------------------------------------------------------------- */
.widget_layered_nav ul {
margin: 0;
padding: 0;
border: 0;
list-style:none outside;
li {
.clearfix();
padding: 0 0 1px;
list-style:none;
a, span {
.widget_layered_nav {
ul {
margin: 0;
padding: 0;
border: 0;
list-style:none outside;
li {
.clearfix();
padding: 0 0 1px;
list-style:none;
a, span {
padding: 1px 0;
float:left;
}
}
li.chosen {
a {
padding: 0 6px 0 18px;
border: 1px solid @tertiary;
background: @tertiary url(../images/cross_white.png) no-repeat 6px center;
.inset_box_shadow(0, 1px, 1px, rgba(255,255,255,0.5));
color: @tertiarytext;
.border_radius(3px);
}
}
small.count {
float: right;
margin-left: 6px;
font-size: 1em;
padding: 1px 0;
float:left;
color: @subtext;
}
}
li.chosen {
a {
padding: 0 6px 0 18px;
border: 1px solid @tertiary;
background: @tertiary url(../images/cross_white.png) no-repeat 6px center;
.inset_box_shadow(0, 1px, 1px, rgba(255,255,255,0.5));
color: @tertiarytext;
.border_radius(3px);
}
.widget_layered_nav_filters {
ul {
margin: 0;
padding: 0;
border: 0;
list-style:none outside;
overflow: hidden;
zoom: 1;
li {
float: left;
padding: 0 1px 1px 0;
list-style:none;
a {
padding: 0 6px 0 18px;
border: 1px solid @tertiary;
background: @tertiary url(../images/cross_white.png) no-repeat 6px center;
.inset_box_shadow(0, 1px, 1px, rgba(255,255,255,0.5));
color: @tertiarytext;
.border_radius(3px);
float: left;
}
}
}
small.count {
float: right;
margin-left: 6px;
font-size: 1em;
padding: 1px 0;
color: @subtext;
}
}
/* =Price Filter Widget

View File

@ -324,6 +324,11 @@ class WC_Query {
$order = 'asc';
$meta_key = '_price';
break;
case 'high_price' :
$orderby = 'meta_value_num';
$order = 'desc';
$meta_key = '_price';
break;
case 'title' :
$orderby = 'title';
$order = 'asc';

View File

@ -173,8 +173,10 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woothemes/wooc
* Feature - Added lost password shortcode / email notification (thanks Max Rice).
* Feature - Simplified permalink/base settings now found in Settings > Permalinks.
* Feature - Support more permalink structures (from http://codex.wordpress.org/Using_Permalinks)
* Feature - Added option to resend order emails, checkboxes select which one
* Feature - Added option to resend order emails, checkboxes select which one.
* Feature - New layered nav current filters widget. This lists active filters from all layered nav for de-selection.
* Templating - Revised pagination, sorting areas (sorting is now above products, numbered pagination below) and added a result count.
* Templating - email-order-items.php change get_downloadable_file_url() to get_downloadable_file_urls() to support multiple files.
* Templating - loop-end and start for product loops, allow changing the UL's used by default to something else.
@ -210,6 +212,7 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woothemes/wooc
* Localization - Localized shortcode button.
* Localization - Norwegian translation by frilyd.
* Localization - Italian update by Giuseppe-Mazzapica.
* Localization - Korean translate by Woo Jin Koh
* Many other refactors, minor fixes and tweaks!
= 1.6.5.2 - 12/09/2012 =

View File

@ -6,7 +6,7 @@
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 1.6.4
* @version 1.7.0
*/
get_header('shop'); ?>
@ -49,7 +49,16 @@ get_header('shop'); ?>
<?php if ( have_posts() ) : ?>
<?php do_action('woocommerce_before_shop_loop'); ?>
<?php
/**
* woocommerce_pagination hook
*
* @hooked woocommerce_pagination - 10
* @hooked woocommerce_result_count - 20
* @hooked woocommerce_catalog_ordering - 30
*/
do_action( 'woocommerce_before_shop_loop' );
?>
<?php woocommerce_product_loop_start(); ?>
@ -63,7 +72,7 @@ get_header('shop'); ?>
<?php woocommerce_product_loop_end(); ?>
<?php do_action('woocommerce_after_shop_loop'); ?>
<?php do_action( 'woocommerce_after_shop_loop' ); ?>
<?php else : ?>
@ -75,8 +84,6 @@ get_header('shop'); ?>
<?php endif; ?>
<div class="clear"></div>
<?php
/**
* woocommerce_pagination hook

View File

@ -1,20 +1,29 @@
<?php
/**
* Pagination
* Pagination - Show numbered pagination for catalog pages.
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 1.6.4
* @version 1.7.0
*/
global $wp_query;
if ( $wp_query->max_num_pages <= 1 )
return;
?>
<?php if ( $wp_query->max_num_pages > 1 ) : ?>
<div class="navigation">
<div class="nav-next"><?php next_posts_link( __( 'Next <span class="meta-nav">&rarr;</span>', 'woocommerce' ) ); ?></div>
<div class="nav-previous"><?php previous_posts_link( __( '<span class="meta-nav">&larr;</span> Previous', 'woocommerce' ) ); ?></div>
</div>
<?php endif; ?>
<nav class="woocommerce_pagination">
<?php
echo paginate_links( apply_filters( 'woocommerce_pagination_args', array(
'base' => str_replace( 999999999, '%#%', get_pagenum_link( 999999999 ) ),
'format' => '',
'current' => max( 1, get_query_var('paged') ),
'total' => $wp_query->max_num_pages,
'prev_text' => '&larr;',
'next_text' => '&rarr;',
'type' => 'list',
'end_size' => 3,
'mid_size' => 3
) ) );
?>
</nav>

View File

@ -0,0 +1,29 @@
<?php
/**
* Result Count
*
* Shows text: Showing x - x of x results
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 1.7
*/
global $woocommerce, $wp_query;
if ( ! woocommerce_products_will_display() )
return;
?>
<p class="woocommerce_result_count">
<?php
$paged = max( 1, $wp_query->get( 'paged' ) );
$per_page = $wp_query->get( 'posts_per_page' );
$max = $wp_query->found_posts;
$first = ( $per_page * $paged ) - $per_page + 1;
$last = $wp_query->get( 'posts_per_page' ) * $paged;
if ( $last > $max )
$last = $max;
printf( __( 'Showing %s - %s of %s results', 'woocommerce' ), $first, $last, $max );
?>
</p>

View File

@ -7,19 +7,23 @@
* @version 1.7
*/
global $woocommerce;
if ( ! woocommerce_products_will_display() )
return;
?>
<form class="woocommerce_ordering" method="POST">
<form class="woocommerce_ordering" method="post">
<select name="sort" class="orderby">
<?php
$catalog_orderby = apply_filters('woocommerce_catalog_orderby', array(
'menu_order' => __('Default sorting', 'woocommerce'),
'title' => __('Sort alphabetically', 'woocommerce'),
'date' => __('Sort by most recent', 'woocommerce'),
'price' => __('Sort by price', 'woocommerce')
));
$catalog_orderby = apply_filters( 'woocommerce_catalog_orderby', array(
'menu_order' => __( 'Default sorting', 'woocommerce' ),
'title' => __( 'Sort alphabetically', 'woocommerce' ),
'date' => __( 'Sort by most recent', 'woocommerce' ),
'price' => __( 'Sort by price - low to high', 'woocommerce' ),
'high_price' => __( 'Sort by price - high to low', 'woocommerce' )
) );
foreach ( $catalog_orderby as $id => $name )
echo '<option value="' . $id . '" ' . selected( $woocommerce->session->orderby, $id, false ) . '>' . $name . '</option>';
?>
</select>
</form>
</form>

View File

@ -23,6 +23,7 @@ function woocommerce_register_widgets() {
register_widget('WooCommerce_Widget_Product_Tag_Cloud');
register_widget('WooCommerce_Widget_Cart');
register_widget('WooCommerce_Widget_Layered_Nav');
register_widget('WooCommerce_Widget_Layered_Nav_Filters');
register_widget('WooCommerce_Widget_Price_Filter');
register_widget('WooCommerce_Widget_Product_Search');
register_widget('WooCommerce_Widget_Top_Rated_Products');
@ -39,6 +40,7 @@ add_action('widgets_init', 'woocommerce_register_widgets');
include_once('widget-cart.php');
include_once('widget-featured_products.php');
include_once('widget-layered_nav.php');
include_once('widget-layered_nav_filters.php');
include_once('widget-price_filter.php');
include_once('widget-product_categories.php');
include_once('widget-product_search.php');

View File

@ -0,0 +1,106 @@
<?php
/**
* Layered Navigation Fitlers Widget
*
* @author WooThemes
* @category Widgets
* @package WooCommerce/Widgets
* @version 1.7.0
* @extends WP_Widget
*/
class WooCommerce_Widget_Layered_Nav_Filters extends WP_Widget {
var $woo_widget_cssclass;
var $woo_widget_description;
var $woo_widget_idbase;
var $woo_widget_name;
/**
* constructor
*
* @access public
* @return void
*/
function WooCommerce_Widget_Layered_Nav_Filters() {
/* Widget variable settings. */
$this->woo_widget_cssclass = 'widget_layered_nav_filters';
$this->woo_widget_description = __( 'Shows active layered nav filters so users can see and deactivate them.', 'woocommerce' );
$this->woo_widget_idbase = 'woocommerce_layered_nav_filters';
$this->woo_widget_name = __( 'WooCommerce Layered Nav Filters', 'woocommerce' );
/* Widget settings. */
$widget_ops = array( 'classname' => $this->woo_widget_cssclass, 'description' => $this->woo_widget_description );
/* Create the widget. */
$this->WP_Widget( 'woocommerce_layered_nav_filters', $this->woo_widget_name, $widget_ops );
}
/**
* widget function.
*
* @see WP_Widget
* @access public
* @param array $args
* @param array $instance
* @return void
*/
function widget( $args, $instance ) {
global $_chosen_attributes, $woocommerce, $_attributes_array;
extract( $args );
if ( ! is_post_type_archive( 'product' ) && ! is_tax( array_merge( $_attributes_array, array( 'product_cat', 'product_tag' ) ) ) )
return;
$current_term = $_attributes_array && is_tax( $_attributes_array ) ? get_queried_object()->term_id : '';
$current_tax = $_attributes_array && is_tax( $_attributes_array ) ? get_queried_object()->taxonomy : '';
$title = __( 'Active filters', 'woocommerce' );
//$title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base );
// Price
$post_min = isset( $woocommerce->session->min_price ) ? $woocommerce->session->min_price : 0;
$post_max = isset( $woocommerce->session->max_price ) ? $woocommerce->session->max_price : 0;
if ( count( $_chosen_attributes ) > 0 || $post_min > 0 || $post_max > 0 ) {
echo $before_widget . $before_title . $title . $after_title;
echo "<ul>";
// Attributes
foreach ( $_chosen_attributes as $taxonomy => $data ) {
foreach ( $data['terms'] as $term_id ) {
$term = get_term( $term_id, $taxonomy );
$taxonomy_filter = str_replace( 'pa_', '', $taxonomy );
$current_filter = ! empty( $_GET[ 'filter_' . $taxonomy_filter ] ) ? $_GET[ 'filter_' . $taxonomy_filter ] : '';
$new_filter = array_map( 'absint', explode( ',', $current_filter ) );
$new_filter = array_diff( $new_filter, array( $term_id ) );
$link = remove_query_arg( 'filter_' . $taxonomy_filter );
if ( sizeof( $new_filter ) > 0 )
$link = add_query_arg( 'filter_' . $taxonomy_filter, implode( ',', $new_filter ), $link );
echo '<li><a title="' . __( 'Remove filter', 'woocommerce' ) . '" href="' . $link . '">' . $term->name . '</a></li>';
}
}
if ( $post_min ) {
$link = remove_query_arg( 'min_price' );
echo '<li><a title="' . __( 'Remove filter', 'woocommerce' ) . '" href="' . $link . '">' . __( 'Min', 'woocommerce' ) . ' ' . woocommerce_price( $post_min ) . '</a></li>';
}
if ( $post_max ) {
$link = remove_query_arg( 'max_price' );
echo '<li><a title="' . __( 'Remove filter', 'woocommerce' ) . '" href="' . $link . '">' . __( 'Max', 'woocommerce' ) . ' ' . woocommerce_price( $post_max ) . '</a></li>';
}
echo "</ul>";
echo $after_widget;
}
}
}

View File

@ -332,6 +332,20 @@ if ( ! function_exists( 'is_ajax' ) ) {
return ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest' ) ? true : false;
}
}
if ( ! function_exists( 'is_filtered' ) ) {
/**
* is_filtered - Returns true when filtering products using layered nav or price sliders.
*
* @access public
* @return bool
*/
function is_filtered() {
global $_chosen_attributes;
return ( sizeof( $_chosen_attributes ) > 0 || ( isset( $_GET['max_price'] ) && isset( $_GET['min_price'] ) ) ) ? true : false;
}
}
/**
@ -1660,24 +1674,25 @@ function woocommerce_manual_category_count( $terms, $taxonomy ) {
$do_count = array( 'visible', 'catalog' );
$do_not_count = array( 'search', 'hidden' );
$term = get_term( $term_id, 'product_cat' );
$counted_ids = get_option( 'wc_prod_cat_counts' );
$counted_ids[ $term->term_id ] = ( isset( $counted_ids[ $term->term_id ] ) && ! is_array( $counted_ids[ $term->term_id ] ) ) ? array() : $counted_ids[ $term->term_id ];
if ( ! is_array( $counted_ids ) )
$counted_ids = array();
$counted_ids[ $term_id ] = ( empty( $counted_ids[ $term_id ] ) || ! is_array( $counted_ids[ $term_id ] ) ) ? array() : $counted_ids[ $term_id ];
if ( in_array( $_POST['_visibility'], $do_count ) ) {
if ( ! empty( $counted_ids[ $term->term_id ] ) ) {
if ( ! in_array( $_POST['post_ID'], $counted_ids[ $term->term_id ] ) ) {
array_push( $counted_ids[ $term->term_id ], absint( $_POST['post_ID'] ) );
if ( ! empty( $counted_ids[ $term_id ] ) ) {
if ( ! in_array( $_POST['post_ID'], $counted_ids[ $term_id ] ) ) {
array_push( $counted_ids[ $term_id ], absint( $_POST['post_ID'] ) );
update_option( 'wc_prod_cat_counts', $counted_ids );
}
} else {
$counted_ids[ $term->term_id ] = array( absint( $_POST['post_ID'] ) );
$counted_ids[ $term_id ] = array( absint( $_POST['post_ID'] ) );
update_option( 'wc_prod_cat_counts', $counted_ids );
}
} elseif ( in_array( $_POST['_visibility'], $do_not_count ) ) {
if ( in_array( $_POST['post_ID'], $counted_ids[ $term->term_id ] ) ) {
if ( ( $key = array_search( $_POST['post_ID'], $counted_ids[ $term->term_id ] ) ) !== false ) {
unset( $counted_ids[ $term->term_id ][ $key ] );
if ( in_array( $_POST['post_ID'], $counted_ids[ $term_id ] ) ) {
if ( ( $key = array_search( $_POST['post_ID'], $counted_ids[ $term_id ] ) ) !== false ) {
unset( $counted_ids[ $term_id ][ $key ] );
update_option( 'wc_prod_cat_counts', $counted_ids );
}
}

View File

@ -59,11 +59,21 @@ if ( ! is_admin() || defined('DOING_AJAX') ) {
* Products Loop
*
* @see woocommerce_show_messages()
* @see woocommerce_result_count()
* @see woocommerce_catalog_ordering()
*/
add_action( 'woocommerce_before_shop_loop', 'woocommerce_show_messages', 10 );
add_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
add_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );
/**
* Product Loop Items
*
* @see woocommerce_show_messages()
* @see woocommerce_template_loop_add_to_cart()
* @see woocommerce_template_loop_product_thumbnail()
* @see woocommerce_template_loop_price()
*/
add_action( 'woocommerce_before_shop_loop', 'woocommerce_show_messages', 10 );
add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
add_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
@ -144,10 +154,8 @@ if ( ! is_admin() || defined('DOING_AJAX') ) {
* Pagination in loop-shop
*
* @see woocommerce_pagination()
* @see woocommerce_catalog_ordering()
*/
add_action( 'woocommerce_pagination', 'woocommerce_pagination', 10 );
add_action( 'woocommerce_pagination', 'woocommerce_catalog_ordering', 20 );
/**
* Product page tabs

View File

@ -390,17 +390,17 @@ if ( ! function_exists( 'woocommerce_get_product_thumbnail' ) ) {
}
}
if ( ! function_exists( 'woocommerce_pagination' ) ) {
if ( ! function_exists( 'woocommerce_result_count' ) ) {
/**
* Output the pagination.
* Output the result count text (Showing x - x of x results).
*
* @access public
* @subpackage Loop
* @return void
*/
function woocommerce_pagination() {
woocommerce_get_template( 'loop/pagination.php' );
function woocommerce_result_count() {
woocommerce_get_template( 'loop/result-count.php' );
}
}
@ -423,6 +423,20 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
}
}
if ( ! function_exists( 'woocommerce_pagination' ) ) {
/**
* Output the pagination.
*
* @access public
* @subpackage Loop
* @return void
*/
function woocommerce_pagination() {
woocommerce_get_template( 'loop/pagination.php' );
}
}
/** Single Product ********************************************************/
if ( ! function_exists( 'woocommerce_show_product_images' ) ) {
@ -959,6 +973,57 @@ if ( ! function_exists( 'woocommerce_checkout_coupon_form' ) ) {
}
}
if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
/**
* Check if we will be showing products or not (and not subcats only)
*
* @access public
* @subpackage Loop
* @return void
*/
function woocommerce_products_will_display() {
global $woocommerce, $wpdb;
if ( ! is_product_category() && ! is_shop() )
return false;
if ( is_search() || is_filtered() || is_paged() )
return true;
if ( get_option( 'woocommerce_hide_products_when_showing_subcategories' ) == 'no' )
return true;
if ( is_product_category() && get_option( 'woocommerce_show_subcategories' ) == 'no' )
return true;
if ( is_shop() && get_option( 'woocommerce_shop_show_subcategories' ) == 'no' )
return true;
$term = get_queried_object();
$parent_id = empty( $term->term_id ) ? 0 : $term->term_id;
$has_children = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent = %d", $parent_id ) );
if ( $has_children ) {
// Check terms have products inside
$children = array();
foreach ( $has_children as $term ) {
$children = array_merge( $children, get_term_children( $term, 'product_cat' ) );
$children[] = $term;
}
$objects = get_objects_in_term( $children, 'product_cat' );
if ( sizeof( $objects ) > 0 ) {
return false;
} else {
return true;
}
} else {
return true;
}
}
}
if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
/**
@ -969,7 +1034,7 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
* @return void
*/
function woocommerce_product_subcategories( $args = array() ) {
global $woocommerce, $wp_query, $_chosen_attributes;
global $woocommerce, $wp_query;
$defaults = array(
'before' => '',
@ -984,27 +1049,20 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
// Main query only
if ( ! is_main_query() && ! $force_display ) return;
// Don't show when filtering
if ( sizeof( $_chosen_attributes ) > 0 || ( isset( $_GET['max_price'] ) && isset( $_GET['min_price'] ) ) ) return;
// Don't show when filtering, searching or when on page > 1 and ensure we're on a product archive
if ( is_search() || is_filtered() || is_paged() || ( ! is_product_category() && ! is_shop() ) ) return;
// Don't show when searching or when on page > 1 and ensure we're on a product archive
if ( is_search() || is_paged() || ( ! is_product_category() && ! is_shop() ) ) return;
// Check cateogries are enabled
// Check categories are enabled
if ( is_product_category() && get_option( 'woocommerce_show_subcategories' ) == 'no' ) return;
if ( is_shop() && get_option( 'woocommerce_shop_show_subcategories' ) == 'no' ) return;
// Find the category + category parent, if applicable
if ( $product_cat_slug = get_query_var( 'product_cat' ) ) {
$product_cat = get_term_by( 'slug', $product_cat_slug, 'product_cat' );
$product_category_parent = $product_cat->term_id;
} else {
$product_category_parent = 0;
}
$term = get_queried_object();
$parent_id = empty( $term->term_id ) ? 0 : $term->term_id;
// NOTE: using child_of instead of parent - this is not ideal but due to a WP bug ( http://core.trac.wordpress.org/ticket/15626 ) pad_counts won't work
$args = array(
'child_of' => $product_category_parent,
'child_of' => $parent_id,
'menu_order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
@ -1019,7 +1077,7 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
foreach ( $product_categories as $category ) {
if ( $category->parent != $product_category_parent )
if ( $category->parent != $parent_id )
continue;
if ( ! $product_category_found ) {

View File

@ -638,7 +638,7 @@ class Woocommerce {
$product_permalink = empty( $permalinks['product_base'] ) ? _x( 'product', 'slug', 'woocommerce' ) : $permalinks['product_base'];
if ( $product_permalink )
$rewrite = array( 'slug' => untrailingslashit( $product_permalink ), 'with_front' => false );
$rewrite = array( 'slug' => untrailingslashit( $product_permalink ), 'with_front' => false, 'feeds' => true );
else
$rewrite = false;