You are here:  » Side Filter - Product Size


Side Filter - Product Size

Submitted by ChrisNBC on Mon, 2015-03-02 12:28 in

Hi David,

Hope you had a good weekend. I wondered if you could give me some advice re sidebar filters.....

On the site that I'm currently working on, I already have a number of custom filters and I would like to add one last filter for product size. I have added the extra filter and it all works fine. The merchants provide the size information in the feeds in a number of formats but I plan to use global filters to standardise them.

Each merchant shows each product on a single row of the feed and includes somewhere all the sizes they stock. So for example the size field for a product in one merchants feed might contain something like "34R,32L,30R,32R,38R,36R,34L" and for another stocking the same product they might only have "32R,38R,36R,34L" .

Ideally I would like to add a complete list of options to the filter (either manually or dynamically if possible) so that a single size could be selected and all products containing that size would be returned. Things are complicated further by the fact the other filters I have in place only show available filter options based on the other filters already selected....

I wondered if you could suggest if there is a simple way, I could modify the size filter so a single size could be selected and also so that only available sizes based on what's been selected in the other filters are displayed?

Thanks in advance.

Regards
Chris

Submitted by support on Mon, 2015-03-02 13:15

Hi Chris,

I've helped lots of users do this - I'll document the basic principle of the changes here, if you're not sure of course email me your modified files with the standard method of implementing your size filter in place and I'll apply the changes for you.

In search.php, you would have added the following code to implement sizeFilter:

  if ($sizeFilter)
  {
    $priceWhere .= " AND size = '".database_safe($sizeFilter)."' ";
  }

The first thing to do is to change this into a LIKE clause using the SQL wildcard character, which is the % sign:

  if ($sizeFilter)
  {
    $priceWhere .= " AND size LIKE '%".database_safe($sizeFilter)."%' ";
  }

Next, regarding the extraction of the comma separated values in the actual `size` field into individual unique values to populate the drop-down, in html/searchfilters.php, you would have added the following to implement sizeFilter in the same was as the others:

  foreach($rows1 as $row)
  {
    $selected = ($sizeFilter==$row["size"]?"selected='selected'":"");
    print "<option value='".htmlspecialchars($row["size"],ENT_QUOTES,$config_charset)."' ".$selected.">".$row["size"]."</option>";
  }

Going in to this loop, $rows1 is the result of the DISTINCT SELECT query that will at this point contain the merchant's combined comma separated sizes list, so this code needs to be preceded by a loop to process each value, explode() into individual size values, populate a new array of unique values, and finally sort. To do this, REPLACE the above as follows:

  $newRows1 = array();
  foreach($rows1 as $row)
  {
    $sizes = explode(",",$row["size"]);
    foreach($sizes as $size)
    {
      $size = trim($size);
      if ($size)
      {
        $newRows1[$size]["size"] = $size;
      }
    }
  }
  ksort($newRows1);
  $rows1 = $newRows1;
  foreach($rows1 as $row)
  {
    $selected = ($sizeFilter==$row["size"]?"selected='selected'":"");
    print "<option value='".htmlspecialchars($row["size"],ENT_QUOTES,$config_charset)."' ".$selected.">".$row["size"]."</option>";
  }

That should do the trick!

Cheers,
David.
--
PriceTapestry.com

Submitted by ChrisNBC on Mon, 2015-03-02 15:14

Hi David,

Thanks as always for your quick response. It's a really neat solution and works a treat!

Thanks again.

Best regards
Chris

Submitted by ChrisNBC on Fri, 2015-03-06 10:30

Hi David,

I just wondered if you could suggest if there is a simple way to filter the results of the product.php price table using the filters a user may have already selected on the preceding search.php page? At the moment a user might select a size on search.php and then see the results for all sizes in product price table.

Thanks in advance.

Regards
Chris

Submitted by support on Fri, 2015-03-06 11:18

Hi Chris,

You could pass sizeFilter through to the product page no problem - in includes/tapestry.php look for the following code beginning at line 67:

    if ($config_useRewrite)
    {
      return $config_baseHREF."product/".urlencode(tapestry_hyphenate($product["normalised_name"])).".html";
    }
    else
    {
      return $config_baseHREF."products.php?q=".urlencode($product["normalised_name"]);
    }

...and REPLACE with:

    global $sizeFilter;
    if ($config_useRewrite)
    {
      $retval = $config_baseHREF."product/".urlencode(tapestry_hyphenate($product["normalised_name"])).".html";
      if (isset($sizeFilter) && $sizeFilter)
      {
        $retval .= "?sizeFilter=".urlencode($sizeFilter);
      }
    }
    else
    {
      $retval = $config_baseHREF."products.php?q=".urlencode($product["normalised_name"]);
      if (isset($sizeFilter) && $sizeFilter)
      {
        $retval .= "&sizeFilter=".urlencode($sizeFilter);
      }
    }
    return $retval;

And then at the top of products.php look for the following code at line 12:

  $sql = "SELECT * FROM `".$config_databaseTablePrefix."products` WHERE normalised_name = '".database_safe($q)."'";

...and REPLACE with:

  $sql = "SELECT * FROM `".$config_databaseTablePrefix."products` WHERE normalised_name = '".database_safe($q)."'";
  if (isset($_GET["sizeFilter"]))
  {
    $sql .= " AND size LIKE '%".database_safe($_GET["sizeFilter"])."%'";
  }

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by ChrisNBC on Fri, 2015-03-06 22:52

Hi David,

Thanks as always for your super quick reply. I made the change above which works really well. Ideally, I would like to add at least one more filter variable to the code and wondered if you could possibly explain where this would need to be added in the code above.

Thanks in advance.

Regards
Chris

Submitted by support on Sat, 2015-03-07 07:40

Hi Chris,

To add an additional filter "otherFilter", for the replacement in includes/tapestry.php, where you will have added the following lines:

         $retval .= "?sizeFilter=".urlencode($sizeFilter);

and

         $retval .= "&sizeFilter=".urlencode($sizeFilter);

...REPLACE with:

         $retval .= "?sizeFilter=".urlencode($sizeFilter);
         $retval .= "&otherFilter=".urlencode($otherFilter);

and

         $retval .= "&sizeFilter=".urlencode($sizeFilter);
         $retval .= "&otherFilter=".urlencode($otherFilter);

...respectively.

And finally in products.php, where you will have added:

  if (isset($_GET["sizeFilter"]))
  {
    $sql .= " AND size LIKE '%".database_safe($_GET["sizeFilter"])."%'";
  }

....REPLACE with:

  if (isset($_GET["sizeFilter"]))
  {
    $sql .= " AND size LIKE '%".database_safe($_GET["sizeFilter"])."%'";
  }
  if (isset($_GET["otherFilter"]))
  {
    $sql .= " AND other LIKE '%".database_safe($_GET["otherFilter"])."%'";
  }

Cheers,
David.
--
PriceTapestry.com

Submitted by ChrisNBC on Mon, 2015-03-09 17:07

Hi David,

Hope you had a good weekend.

Thanks for the solution above, which I have just implemented for one additional filter. Something seems to be wrong though as the second filter appears in the URL on the Products page but with just an '=' with nothing after it...the first filter still seems to work. I have checked the changes a couple of times and am pretty sure the change is as per above...I wondered if you might have any ideas what could be going wrong?

Thanks in advance.

Regards
Chris

Submitted by support on Mon, 2015-03-09 17:21

Hello Chris,

My apologies, the global declaration for $otherFilter was missing from the modification to includes/tapestry.php.

In that file, where you would have added this new line:

    global $sizeFilter;

...REPLACE with:

    global $sizeFilter;
    global $otherFilter;

That should be all it is!

Cheers,
David.
--
PriceTapestry.com

Submitted by ChrisNBC on Thu, 2015-03-12 10:28

Hi David,

Thanks for your quick response. I made the change which resolved the issue.

I wondered if you might be able to help me with a slight variation to the size filter above...

In summary, on my site, users can go straight to a product page if they go via the featured items or related item links. This causes a problem since the price table shows all results (i.e all sizes for a product). Ideally, I would like to include the drop down size filter on the product page to allow the list to be filtered where no size filter is already applied.

I wondered if you might be able to suggest a simple way to do this?

Thanks in advance.

Regards
Chris

Submitted by support on Thu, 2015-03-12 16:38

Hello Chris,

The following should be very close - it's essentially identical to the sizeFilter code that you will now have in html/searchfilters.php, including the code to extract multiple sizes from comma separated values into a single list.

To give it a go, add the following to the top of html/prices.php to display the sizeFilter drop-down above the price comparison table:

<?php
  $sizeFilter 
= (isset($_GET["sizeFilter"])?$_GET["sizeFilter"]:"");
  
$sql1 "SELECT DISTINCT(size) FROM `".$config_databaseTablePrefix."products` WHERE normalised_name = '".database_safe($q)."' AND size <> '' ORDER BY size";
  if (
database_querySelect($sql1,$rows1))
  {
    
$newRows1 = array();
    foreach(
$rows1 as $row)
    {
      
$sizes explode(",",$row["size"]);
      foreach(
$sizes as $size)
      {
        
$size trim($size);
        if (
$size)
        {
          
$newRows1[$size]["size"] = $size;
        }
      }
    }
    
ksort($newRows1);
    
$rows1 $newRows1;
    print 
"<form method='GET' action=''>";
    print 
"<label>Size<br />";
    print 
"<select name='sizeFilter' onchange='JavaScript:this.form.submit();'>";
    print 
"<option value=''>All</option>";
    foreach(
$rows1 as $row)
    {
      
$selected = ($sizeFilter==$row["size"]?"selected='selected'":"");
      print 
"<option value='".htmlspecialchars($row["size"],ENT_QUOTES,$config_charset)."' ".$selected.">".$row["size"]."</option>";
    }
    print 
"</select>";
    print 
"</label>";
    print 
"<noscript><input type='submit' value='Apply' /></noscript>";
    print 
"</form>";
  }
?>

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by ChrisNBC on Thu, 2015-04-09 10:26

Hi David,

Hope all is going well. Thanks for the mod above which I have now had a chance to implement...it works perfectly!

Best regards
Chris

Submitted by stevebi on Tue, 2015-12-22 12:37

Hello David,

Just a verification. If I want to add the above code for gender filter should I change $size to $gender then $sizeFilter to $genderFilter and how should I change "foreach($sizes as $size)"

Thank you again

Steve

Submitted by support on Tue, 2015-12-22 13:13

Hello Steve,

I just checked the latest searchfilters.php that I have in email from you and it should be automatically creating a filter for "gender" if configured in $config_fieldset and not excluded by way of your custom $config_fieldSetNoFilters config array.

The foreach() loop in the sizeFilter code above is part of the modification to a simple filter operation to separate out comma separated size values from a single field into individual filter options so would not be required for a genderFilter - the generic code for which using standard (not multiple select) filters would be;

  $sql1 = "SELECT DISTINCT(gender) FROM `".$config_databaseTablePrefix."products` WHERE ".$where.$priceWhere." AND gender <> '' ORDER BY gender";
  if (database_querySelect($sql1,$rows1))
  {
    print "<div class='small-12 medium-2 columns'>";
    print "<label>Gender<br />";
    print "<select name='genderFilter'>";
    print "<option value=''>".translate("All")."</option>";
    foreach($rows1 as $row)
    {
      $selected = ($genderFilter==$row["gender"]?"selected='selected'":"");
      print "<option value='".htmlspecialchars($row["gender"],ENT_QUOTES,$config_charset)."' ".$selected.">".$row["gender"]."</option>";
    }
    print "</select>";
    print "</label>";
    print "</div>";
  }

Cheers,
David.
--
PriceTapestry.com

Submitted by stevebi on Tue, 2015-12-22 19:32

Thank you very much David!

Submitted by ChrisNBC on Tue, 2016-09-06 14:31

Hi David,

Hope all is going well.

I wondered if you might be able to suggest a way I could modify the code above to make the size filter refresh the contents of the price table using AJAX rather than a page reload? Currently when a user selects the filter the page refreshes which means they end up at the top of the page rather than looking at the price table.

Thanks in advance.

Best regards
Chris

Submitted by support on Thu, 2016-09-08 08:53

Hi Chris,

Please could you email me products.php and html/prices.php and I'll help you out with this, and also if you could let me know in your email whether your template is already including the jQuery library?

Cheers,
David.
--
PriceTapestry.com