Guest Posted February 19, 2007 Share Posted February 19, 2007 I've searched high and low for something like this to no avail. If someone knows of a contrib that does this already, please, please let me know. By default if you select a manufacturer, all of the categories with products by that manufacturer get inserted into a single drop-down. So if you have more than one level of categories/sub-categories, it gets hard to navigate. And if there are 2 or more sub-categories with the same name, it's down right frustrating. What I want/am trying to do: Each level of categories gets its own drop-down. The 1st drop-down will be the root categories, the 2nd will be root's sub-categories, the 3rd with be the sub-categories sub-categories, and so on. I've managed to get a working solution but it's pretty slow, I'm still learning php :P. The 1st drop-down is populated on page load, the rest are populated as previous drop-downs are selected using javascript. The amount of drop-downs is determined by the maximum level of categories/sub-categories. So if your store has 3 levels of categories, there will be 3 drop-downs, one for each level. When a category is selected that doesn't have any more sub-categories, it selects that category as the filter_id and submits the form. I moved this into a separate module named mfg_categories.php in the modules folder so it would be easier to work with. In the /catalog/index.php file (Backup the original), I replaced: // optional Product List Filter if (PRODUCT_LIST_FILTER > 0) { if (isset($HTTP_GET_VARS['manufacturers_id'])) { $filterlist_sql = "select distinct c.categories_id as id, cd.categories_name as name from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c, " . TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . " cd where p.products_status = '1' and p.products_id = p2c.products_id and p2c.categories_id = c.categories_id and p2c.categories_id = cd.categories_id and cd.language_id = '" . (int)$languages_id . "' and p.manufacturers_id = '" . (int)$HTTP_GET_VARS['manufacturers_id'] . "' order by cd.categories_name"; } else { $filterlist_sql= "select distinct m.manufacturers_id as id, m.manufacturers_name as name from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c, " . TABLE_MANUFACTURERS . " m where p.products_status = '1' and p.manufacturers_id = m.manufacturers_id and p.products_id = p2c.products_id and p2c.categories_id = '" . (int)$current_category_id . "' order by m.manufacturers_name"; } $filterlist_query = tep_db_query($filterlist_sql); if (tep_db_num_rows($filterlist_query) > 1) { echo ' <td align="center" class="main">' . tep_draw_form('filter', FILENAME_DEFAULT, 'get') . TEXT_SHOW . ' '; if (isset($HTTP_GET_VARS['manufacturers_id'])) { echo tep_draw_hidden_field('manufacturers_id', $HTTP_GET_VARS['manufacturers_id']); $options = array(array('id' => '', 'text' => TEXT_ALL_CATEGORIES)); } else { echo tep_draw_hidden_field('cPath', $cPath); $options = array(array('id' => '', 'text' => TEXT_ALL_MANUFACTURERS)); } echo tep_draw_hidden_field('sort', $HTTP_GET_VARS['sort']); while ($filterlist = tep_db_fetch_array($filterlist_query)) { $options[] = array('id' => $filterlist['id'], 'text' => $filterlist['name']); } echo tep_draw_pull_down_menu('filter_id', $options, (isset($HTTP_GET_VARS['filter_id']) ? $HTTP_GET_VARS['filter_id'] : ''), 'onchange="this.form.submit()"'); echo '</form></td>' . "\n"; } } with: // optional Product List Filter if (PRODUCT_LIST_FILTER > 0) { // MODIFY START // IS CATEGORIES DROPDOWN if (isset($HTTP_GET_VARS['manufacturers_id'])) { include(DIR_WS_MODULES . 'mfg_categories.php'); } // IS MANUFACTURERS DROPDOWN else { $filterlist_sql= "select distinct m.manufacturers_id as id, m.manufacturers_name as name from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c, " . TABLE_MANUFACTURERS . " m where p.products_status = '1' and p.manufacturers_id = m.manufacturers_id and p.products_id = p2c.products_id and p2c.categories_id = '" . (int)$current_category_id . "' order by m.manufacturers_name"; $filterlist_query = tep_db_query($filterlist_sql); if (tep_db_num_rows($filterlist_query) > 1) { echo ' <td align="center" class="main" width="33%">' . tep_draw_form('filter', FILENAME_DEFAULT, 'get') . TEXT_SHOW . ' '; echo tep_draw_hidden_field('cPath', $cPath); $options = array(array('id' => '', 'text' => TEXT_ALL_MANUFACTURERS)); echo tep_draw_hidden_field('sort', $HTTP_GET_VARS['sort']); while ($filterlist = tep_db_fetch_array($filterlist_query)) { $options[] = array('id' => $filterlist['id'], 'text' => $filterlist['name']); } echo tep_draw_pull_down_menu('filter_id', $options, (isset($HTTP_GET_VARS['filter_id']) ? $HTTP_GET_VARS['filter_id'] : ''), 'onchange="this.form.submit()"'); echo '</form></td>' . "\n"; } else { echo ' <td align="center" class="main" width="33%"> </td>'; } } // MODIFY STOP } // PRODUCT_LIST FILTER END That just separates the categories drop-down from the manufacturers drop-down. By default they both use the same drop-down. Download mfg_categories-02-19-07.php.txt And rename it to mfg_categories.php and put it in the /catalog/includes/modules folder. I would appreciate any help on this, I have been working on this for far too long. My .bak files are getting out of hand. Thanks in advance. Quote Link to comment Share on other sites More sharing options...
Guest Posted February 23, 2007 Share Posted February 23, 2007 Ok, I took this back to the drawing board. The one above took like 10-20 sec to load. This revised one takes 2 seconds to load. Also the last one had problems with redirecting if a drop-down only contained a single category, that is fixed. I'm pretty pleased with it now, if you would like to modify/use it, help yourself. It probably could use a little more tweaking, but work perfectly and it much faster. mfg_categories.php.txt updated: 02-23-07 <?php /* $Id: mfg_categories.php,v 0.9 2007/02/23 12:00:00 hpdl Exp $ osCommerce, Open Source E-Commerce Solutions http://www.oscommerce.com Copyright (c) 2003 osCommerce Released under the GNU General Public License By default when a customer selects to show products from a specific manufacturer, all the categories containing products by that manufacturer are displayed into a single drop-down box. This contribution displays multiple category drop-downs, one for each level of categories. */ define('FILTER_DROP_DOWN_DEVIDER', ' ›› '); define('FILTER_DEFAULT_TEXT', 'All Categories'); define('FILTER_DEFAULT_TEXT_NEXT', 'Choose Here Now'); define('FILTER_DEFAULT_TEXT_INACTIVE', '------'); $filterlist_sql = "select distinct c.categories_id as id, cd.categories_name as name, c.parent_id as parent_id from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c, " . TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . " cd where p.products_status = '1' and p.products_id = p2c.products_id and p2c.categories_id = c.categories_id and p2c.categories_id = cd.categories_id and cd.language_id = '" . (int)$languages_id . "' and p.manufacturers_id = '" . (int)$HTTP_GET_VARS['manufacturers_id'] . "' and c.categories_id = cd.categories_id order by c.parent_id, c.sort_order, cd.categories_name"; $filterlist_query = tep_db_query($filterlist_sql); if (tep_db_num_rows($filterlist_query) > 1) { echo ' <td align="left" class="main" width="100%" colspan="3">' . tep_draw_form('filter', FILENAME_DEFAULT, 'get') . TEXT_SHOW . ' '; $options = ''; $num_max_cats = 0; $category_options = array(); while ($filterlist = tep_db_fetch_array($filterlist_query)) { $filter_id = $filterlist['id']; $categories = array(); tep_get_parent_categories($categories, $filter_id); $categories = array_reverse($categories); $categories[] = $filter_id; //add this category to the end for ($i=0, $n=sizeof($categories); $i<$n; ++$i) { //FILTER_MAX_LEVELS //sizeof($categories) if (tep_not_null($categories[($i+1)]) && !in_arrayr($categories[($i+1)], $category_options)) { if ($i == 0 && !in_arrayr($categories[$i], $category_main)) { $category_options_name = tep_get_cat_name($categories[$i]); $category_main[] = array('id' => $categories[$i], 'text' => $category_options_name); $category_options_name = tep_get_cat_name($categories[($i+1)]); $category_options[$categories[$i]][] = array('id' => $categories[($i+1)], 'text' => $category_options_name); } else { $category_options_name = tep_get_cat_name($categories[($i+1)]); $category_options[$categories[$i]][] = array('id' => $categories[($i+1)], 'text' => $category_options_name); } $category_options[$categories[$i]] = tep_sort_array_names($category_options[$categories[$i]]); } if (($i+1) > $num_max_cats) $num_max_cats = ($i+1); } } while (list ($key, $val) = each ($category_options)) { $this_level_option_names = ''; $this_level_option_values = ''; foreach($category_options[$key] as $key2 => $val2) { $this_level_option_names .= '"' . $val2['text'] . '",'; $this_level_option_values .= $val2['id'] . ','; } $this_level_option_names = substr_replace($this_level_option_names,"",-1); $this_level_option_values = substr_replace($this_level_option_values,"",-1); if (sizeof($category_options[$key]) == 1) { //add this for single category javascript redirect $this_level_option_names = $this_level_option_names . ',""'; $this_level_option_values = $this_level_option_values . ',-1'; } $options .= 'optionsArray[' . $key . '] = new Array(' . $this_level_option_names . ')' . "\n"; $options .= 'valuesArray[' . $key . '] = new Array(' . $this_level_option_values . ')' . "\n"; } $category_main = tep_sort_array_names($category_main); array_unshift($category_main, array('id' => '', 'text' => FILTER_DEFAULT_TEXT)); //DRAW THE FIRST MAIN DROP DOWN echo tep_draw_pull_down_menu('Menu', $category_main, '', 'onChange="updateOptions(0,this.options[this.selectedIndex].value);"'); $default_text = array(array('id' => '', 'text' => FILTER_DEFAULT_TEXT_INACTIVE)); // DRAW THE REST OF THE DROP DOWNS - start at 1, 0 is already drawn for ($i=1, $n=$num_max_cats; $i<$n; ++$i) { $menu_number = $i; echo FILTER_DROP_DOWN_DEVIDER; echo tep_draw_pull_down_menu('Menu', $default_text, '', 'onChange="updateOptions(' . $menu_number . ',this.options[this.selectedIndex].value);"'); } //DRAW DEFAULT HIDDEN FIELDS echo tep_draw_hidden_field('sort', $HTTP_GET_VARS['sort']); echo tep_draw_hidden_field('manufacturers_id', $HTTP_GET_VARS['manufacturers_id']); echo tep_draw_hidden_field('filter_id', '', 'value=""'); echo '</form></td>' . "\n"; } else { // NOTHING TO DISPLAY echo ' <td align="center" class="main" width="100%" colspan="3"> </td>'; } // ############################### // # FUNCTIONS START // ############################### function in_arrayr($needle, $haystack) { if (is_array($haystack)) { foreach ($haystack as $v) { if ($needle == $v) return true; elseif (is_array($v)) { if (in_arrayr($needle, $v) === true) return true; } } } return false; } function tep_sort_array_names($array) { if (is_array($array)) { foreach($array as $key => $val) { $array_id[$key] = $val['id']; $array_name[$key] = $val['text']; } array_multisort($array_name, SORT_ASC, $array); } return $array; } function tep_get_cat_name($category_id) { global $languages_id; $cName = ''; $category_sql = ("select distinct cd.categories_name from " . TABLE_CATEGORIES_DESCRIPTION . " cd where cd.categories_id = '" . (int)$category_id . "' and cd.language_id = '" . (int)$languages_id . "'"); $category_query = tep_db_query($category_sql); while ($category = tep_db_fetch_array($category_query)) { $cName = $category['categories_name']; } return $cName; } // ############################### // # FUNCTIONS STOP // ############################### ?> <script> <!-- /* ########### START CASCADING DROP DOWNS SCRIPT ########### */ // Do Not Edit These Variables var _F=document.filter; var formMenu=_F.Menu; var defaultFirst="<?php echo FILTER_DEFAULT_TEXT_NEXT; ?>"; var defaultNone="<?php echo FILTER_DEFAULT_TEXT_INACTIVE; ?>"; var optionsArray = new Array; var valuesArray = new Array; var arr; var varr; //This is the Option Array that will build your options <?php echo $options; ?> //Do Not Edit Below Here - This is the actual function. function updateOptions(menu,array) { arr = optionsArray[array]; varr = valuesArray[array]; if (varr==undefined && array!=0) { document.filter.filter_id.value = array; document.filter.submit(); } else { var current = formMenu[menu + 1].options.length; var nextMenu = menu + 1; var allMenus = formMenu.length for (var j=current;j>0;j--) { formMenu[menu + 1].options[j] = null; } for (int=nextMenu;int<allMenus;int++) { for (var y=formMenu[int].options.length;y>0;y--) { formMenu[int].options[y] = null; } formMenu[int].options[0].text=defaultNone; } for (var i=0;i<arr.length;i++) { if (varr[i]!=-1) { formMenu[menu + 1].options[formMenu[menu + 1].options.length] = new Option(arr[i],varr[i]); } } formMenu[menu + 1].options[0].text=defaultFirst; } } /* ########### END CASCADING DROP DOWNS SCRIPT ########### */ --> </script> </tr> <tr> <td align="center" class="main" width="33%"></td> Quote Link to comment Share on other sites More sharing options...
OG-Designs Posted June 13, 2007 Share Posted June 13, 2007 You my sir, are a MIND READER. With over 3000 products this type of tool/mod becomes extremely usefull. Thank you for sharing this Awesome contribution. Works like a dream on Current Version: osCMax v2.0 RC3 LIKE A DREAM!!!! Quote Link to comment Share on other sites More sharing options...
sychosyd_28 Posted July 12, 2007 Share Posted July 12, 2007 This is a beautiful thing you've done here, friend. Installed, working great. Quote Link to comment Share on other sites More sharing options...
1trackmind Posted September 1, 2007 Share Posted September 1, 2007 (edited) This is a beautiful thing you've done here, friend. Installed, working great. Using RC1 / MySql 4.1... Dropdown will show on manufactuer page and show categories. When Category is selected, results are blank. Is there a variable that needs to be changed or initiated? This is the URL from after selecting the 1st category in the respective manufacturer: /osc/catalog/index.php?Menu=3&Menu=&Menu=&sort=2a&manufacturers_id=4&filter_id=3 -------------------Update Files need to be defined? Searching for locations to edit now. Edited September 1, 2007 by 1trackmind Quote Link to comment Share on other sites More sharing options...
1trackmind Posted September 1, 2007 Share Posted September 1, 2007 Using RC1 / MySql 4.1... Dropdown will show on manufactuer page and show categories. When Category is selected, results are blank. Is there a variable that needs to be changed or initiated? This is the URL from after selecting the 1st category in the respective manufacturer: /osc/catalog/index.php?Menu=3&Menu=&Menu=&sort=2a&manufacturers_id=4&filter_id=3 -------------------Update Files need to be defined? Searching for locations to edit now. Still Not Working... Is there a way to debug? Quote Link to comment Share on other sites More sharing options...
1trackmind Posted September 1, 2007 Share Posted September 1, 2007 (edited) Getting an Object Expected Error in IE on the mfg_categories.php 02-23-07. ----- Update This is where I am at--- The mfg_categories.php 02-19-07 works** The mfg_categories.php 02-23-07 Does not work. **The orignial mfg_categories.php works when the Products from the Same Manufacturer have the Same Amount of Categories and/or Subcategories Only. <<<<I think this was addressed in the 02-23-07 page?>>>> Using PHP 5 / Mysql 4.1 Edited September 1, 2007 by 1trackmind Quote Link to comment Share on other sites More sharing options...
abuelo_12 Posted November 28, 2007 Share Posted November 28, 2007 I have the same problem and have not been able to figure out what the problem is. it is driving me crazy .... anyone help!! Quote Link to comment Share on other sites More sharing options...
abuelo_12 Posted November 29, 2007 Share Posted November 29, 2007 I have finally figure it out why :D :D . Here is what you need to change. 1. go to /includes/modules/mfg_categories.php 2. on about line 60 include this reset($category_options); like so ... this is the original code while (list ($key, $val) = each ($category_options)) { $this_level_option_names = ''; $this_level_option_values = ''; foreach($category_options[$key] as $key2 => $val2) { $this_level_option_names .= '"' . $val2['text'] . '",'; $this_level_option_values .= $val2['id'] . ','; } $this_level_option_names = substr_replace($this_level_option_names,"",-1); $this_level_option_values = substr_replace($this_level_option_values,"",-1); if (sizeof($category_options[$key]) == 1) { //add this for single category javascript redirect $this_level_option_names = $this_level_option_names . ',""'; $this_level_option_values = $this_level_option_values . ',-1'; } $options .= 'optionsArray[' . $key . '] = new Array(' . $this_level_option_names . ')' . "\n"; $options .= 'valuesArray[' . $key . '] = new Array(' . $this_level_option_values . ')' . "\n"; } now replace with this reset($category_options); while (list ($key, $val) = each ($category_options)) { $this_level_option_names = ''; $this_level_option_values = ''; foreach($category_options[$key] as $key2 => $val2) { $this_level_option_names .= '"' . $val2['text'] . '",'; $this_level_option_values .= $val2['id'] . ','; } $this_level_option_names = substr_replace($this_level_option_names,"",-1); $this_level_option_values = substr_replace($this_level_option_values,"",-1); if (sizeof($category_options[$key]) == 1) { //add this for single category javascript redirect $this_level_option_names = $this_level_option_names . ',""'; $this_level_option_values = $this_level_option_values . ',-1'; } $options .= 'optionsArray[' . $key . '] = new Array(' . $this_level_option_names . ')' . "\n"; $options .= 'valuesArray[' . $key . '] = new Array(' . $this_level_option_values . ')' . "\n"; } The problem was that some servers will think that the array $category_options has already been traversed and it is at the end. with this you force it to be at the beginning every time hope this helps. Quote Link to comment Share on other sites More sharing options...
western Posted December 17, 2007 Share Posted December 17, 2007 (edited) The problem was that some servers will think that the array $category_options has already been traversed and it is at the end. with this you force it to be at the beginning every timehope this helps. :thumbsup: Hi, grat code, do you think i can do the same with customers? :-" I Mean, find customers searching them and ordering them by work they do, city in wich they live, and so on. Can you give to me any suggestions? To me will be really useful . :lol: I think I've just to put in your code different tables for the queries. Ist't right? Thank you for your help! Western Edited December 17, 2007 by western Quote Link to comment Share on other sites More sharing options...
horsewhip Posted January 9, 2008 Share Posted January 9, 2008 I am having a hard time with this one...it keeps telling me that the first parameter of array_unshift needs to be an array??? I thought it already was? $category_main = tep_sort_array_names($category_main); array_unshift($category_main, array('id' => '', 'text' => FILTER_DEFAULT_TEXT)); Quote Link to comment Share on other sites More sharing options...
millend Posted February 22, 2008 Share Posted February 22, 2008 (edited) PLEASE PLEASE PLEASE is there any chance of getting a complete package/contribution on this...(installation/help etc)? I've played around with it for a while now and "no go"... "no how"... but then again, I am not that good in PHP, so nothing surprising there... Or it seems the orig. contrib. is done by MFG? Searched addons for MFG and found nothing of the sort, the preson exists, but not the contrib. Any help, towards the final solution as seen couple of posts before me in the small .gif would be most appreciated...! using 2.2 MS2 Thnks guys, Sten Edited February 22, 2008 by millend Quote Link to comment Share on other sites More sharing options...
Tasawer Posted April 5, 2008 Share Posted April 5, 2008 HI uscetech, This contribution is one the best contributions I have added to my site. Thanks for the great effort. I was wondering if you could guide to to make some modifications. 1. as each category is selected, I wish the category name to be displayed or at least retained in the drop-down box 2. when a manufacturer is selected, all products for this manufacturer are displayed. I wish not to display any products until the final category is selected. I hope you will be able to guide me in this project. Regards Quote Link to comment Share on other sites More sharing options...
aftabn10 Posted April 14, 2008 Share Posted April 14, 2008 HI uscetech, This contribution is one the best contributions I have added to my site. Thanks for the great effort. I was wondering if you could guide to to make some modifications. 1. as each category is selected, I wish the category name to be displayed or at least retained in the drop-down box 2. when a manufacturer is selected, all products for this manufacturer are displayed. I wish not to display any products until the final category is selected. I hope you will be able to guide me in this project. Regards Hi, Does any1 have a working example of this tool? Quote Link to comment Share on other sites More sharing options...
USKeyser Posted May 4, 2008 Share Posted May 4, 2008 I love this contribution. As far as I can tell it's the only thing I've found that allows you to properly display a category drop-down menu when viewing a manufacturer's page. It's much better than the default drop-down, which seems to simply list all categories and subcategories in alphabetical order. I've had a couple problems with it so far though. One problem is that if there are no subcategories within the parent category, the parent category doesn't show up in the drop-down. The other issue is I would like the sub-categories to be ordered by the sort order specified in the admin page (sort_order in the "categories" sql table). Currently it seems it's only alphabetical. You can see my site at BFAFoodservice.com. It's still under construction and we're not exactly live yet. I am relatively new to php programming, so any help would be appreciated. Thanks, Brian Quote Link to comment Share on other sites More sharing options...
Johnatan Posted November 8, 2008 Share Posted November 8, 2008 I need help and each word is welcome. Is there any possibility to don't reset category fields after the latest category was pick out?! The main problem is because script doesn't remember which 1st category was choose. I need help indeed. Thanks in advance here is the code //DRAW THE FIRST MAIN DROP DOWN echo tep_draw_pull_down_menu('Menu', $category_main, '', 'onChange="updateOptions(0,this.options[this.selectedIndex].value);"'); $default_text = array(array('id' => '', 'text' => FILTER_DEFAULT_TEXT_INACTIVE)); // DRAW THE REST OF THE DROP DOWNS - start at 1, 0 is already drawn for ($i=1, $n=$num_max_cats; $i<$n; ++$i) { $menu_number = $i; echo FILTER_DROP_DOWN_DEVIDER; echo tep_draw_pull_down_menu('Menu', $default_text, '', 'onChange="updateOptions(' . $menu_number . ',this.options[this.selectedIndex].value);"'); } //DRAW DEFAULT HIDDEN FIELDS echo tep_draw_hidden_field('sort', $HTTP_GET_VARS['sort']); echo tep_draw_hidden_field('manufacturers_id', $HTTP_GET_VARS['manufacturers_id']); echo tep_draw_hidden_field('filter_id', '', 'value=""'); echo '</form></td>' . "\n"; Quote Link to comment Share on other sites More sharing options...
abcooke Posted March 24, 2009 Share Posted March 24, 2009 Hi everyone, did this script develop into a full contrib? Keep getting this error: TEXT_SHOW Warning: in_array() [function.in-array]: Wrong datatype for second argument in /home/nas04l/c/**********/user/htdocs/test.php on line 327 Quote Link to comment Share on other sites More sharing options...
Henry Blake Posted November 10, 2010 Share Posted November 10, 2010 Hi everyone, did this script develop into a full contrib? Keep getting this error: TEXT_SHOW Warning: in_array() [function.in-array]: Wrong datatype for second argument in /home/nas04l/c/**********/user/htdocs/test.php on line 327 Any one get this to work for 2.2? im getting the same array warning.... any help would be useful. Or Another way to list products in a drop down by category? Cheers Henry Quote Link to comment Share on other sites More sharing options...
DaMixa Posted October 28, 2011 Share Posted October 28, 2011 Any news on this mod? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.