Post by dvfd9 » Tue Apr 08, 2008 11:40 am

hi all, first off i would like to say OpenCart is amazing.  I've been reading a lot, and like many of you felt the need to mod the existing code to achieve what I feel is best for my store.

I've read a lot about sub-menu's all of which don't support the "ordering" feature as provided in the Admin feature.  I'd like to thank tmcguire for his mod, as it got me to get mine working the way i wanted.

I've found a way to do this in a fashion that may or may not be coding etiquette (as it add's another query) but preserves the Admin Sorting feature, if the sub-categories had a separate table then this wouldn't be an issue as all the categories share the same sort_order field.

This code was not tested for sub-sub-categories (categories 2 levels or more deep) but it does work for those that would like the sort method for 1 category, i'm sure it could be modified to do such however I didn't spend the time doing so.

first: backup the following files in case something goes wrong

"your store path"/catalog/template/default/css/default.css (adjust this path accordingly with how you setup your template)
"your store path"/catalog/extension/module/category.php
"your store path"/catalog/template/default/module/category.tpl


in file:

"your store path"/catalog/template/default/css/default.css


find css tag that looks like:

Code: Select all

.box .category a {
	padding: 0px 0px 0px 10px;
	display: block;
	font-size:14px;
	font-weight:bold;
	text-decoration: none;
	margin-bottom: 8px;
}
add this after it:

Code: Select all

.box .subcategory a{
	background: url('../image/bullet_1.png') no-repeat 15px 4px;
	padding: 0px 0px 0px 25px;
	display: block;
	font-size:11px;
	font-weight:bold;
	text-decoration: none;
	margin-bottom: 8px;
}
^

adjust the css for however you want the text to look like

Next,


in file:

"your store path"/catalog/extension/module/category.php



find:

Code: Select all

			$results = $database->getRows("select c.category_id, cd.name from category c left join category_description cd on (c.category_id = cd.category_id) where parent_id = '0' and language_id = '" . (int)$language->getId() . "' order by c.sort_order");

    		foreach ($results as $result) {
      			$category_data[] = array(
       				'name' => $result['name'],
        			'href' => $url->href('category', false, array('path' => $result['category_id']))
          		);
			}
change to:

Code: Select all

			$results = $database->getRows("select c.category_id, cd.name from category c left join category_description cd on (c.category_id = cd.category_id) where parent_id = '0' and language_id = '" . (int)$language->getId() . "' order by c.sort_order");

    		foreach ($results as $result) {
      			$category_data[] = array(
				'catid' => $result['category_id'],
       				'name' => $result['name'],
        			'href' => $url->href('category', false, array('path' => $result['category_id']))
          		);
			}

				$subcategory_data = array();
				
				$results = $database->getRows("select c.category_id, c.parent_id, cd.name from category c left join category_description cd on (c.category_id = cd.category_id) where c.parent_id != 0 and language_id = '" . (int)$language->getId() . "' order by c.sort_order");
				
        		foreach ($results as $result) {
          			$subcategory_data[] = array(
						'parid' => $result['parent_id'],
            			'name'  => $result['name'],
            			'href' => $url->href('category', false, array('path' => $result['category_id']))
      			);
				}
		    $view->set('subcategories', $subcategory_data);
Next,

in the file

"your store path"/catalog/template/default/module/category.tpl:


find :

Code: Select all

<div class="category">
    <?php foreach ($categories as $category) { ?>
    <a href="<?php echo $category['href']; ?>"><?php echo $category['name']; ?></a>
    <?php } ?>
  </div>
change to:

Code: Select all

    <?php foreach ($categories as $category) { ?>
      <div class="category"><a href="<?php echo $category['href']; ?>"><?php echo $category['name']; ?></a> </div>
	<?php foreach ($subcategories as $subcategory) { ?>
    <?php if  ($category['catid'] == $subcategory['parid']){ ?>
    <div class="subcategory"><a href="<?php echo $subcategory['href']; ?>"><?php echo $subcategory['name']; ?></a></div>
    <?php } ?>
    <?php } ?>
	    <?php } ?>
  
Last edited by dvfd9 on Tue Apr 08, 2008 12:32 pm, edited 1 time in total.

Newbie

Posts

Joined
Mon Apr 07, 2008 2:43 am

Post by trippy » Fri May 09, 2008 10:53 pm

Thanks dvfd9!!
:)

New member

Posts

Joined
Sun Dec 16, 2007 5:12 pm

Post by imike24 » Tue Jun 10, 2008 3:43 pm


Newbie

Posts

Joined
Tue Jun 10, 2008 3:41 pm

Post by rigo » Thu Aug 07, 2008 4:41 am

thanks Work perfect :D

Newbie

Posts

Joined
Mon Jan 21, 2008 11:53 pm

Post by Qphoria » Thu Aug 07, 2008 4:50 am

Good work :)

Heh, looks like I overlooked a lot of other people doing this same thing.

I did mine a bit different to allow dynamic leveling (for subn-th power categories). You can see a demo here

It's about 80% complete now. I'm a bit of a stickler for best practices, until I realize I don't know them and just call it a day :)
Last edited by Qphoria on Fri Aug 08, 2008 5:15 am, edited 1 time in total.

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am

Post by JNeuhoff » Thu Aug 07, 2008 4:33 pm

I did mine similarly, tho a bit different to allow dynamic leveling (for subn-th power categories). You can see a demo here.
There is still a bug in the way you expand sub-categories in your system:

When I click on 'Sub Cat 1A' it opens up all the sub-categories of 'Sub Cat 1B'.

There is always the danger of having too many DB queries involved in this kind of server-side, session-based stroage of tree states.
To improve performance, only one DB query should be done for the session, getting all categories and storing them in a server-side session cache.

Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig


User avatar
Guru Member
Online

Posts

Joined
Wed Dec 05, 2007 3:38 am


Post by Qphoria » Thu Aug 07, 2008 6:37 pm

JNeuhoff wrote:
I did mine similarly, tho a bit different to allow dynamic leveling (for subn-th power categories). You can see a demo here.
There is still a bug in the way you expand sub-categories in your system:

When I click on 'Sub Cat 1A' it opens up all the sub-categories of 'Sub Cat 1B'.

There is always the danger of having too many DB queries involved in this kind of server-side, session-based stroage of tree states.
To improve performance, only one DB query should be done for the session, getting all categories and storing them in a server-side session cache.
I am aware of the Sub Cat 1A thing.. actually the subcat does belong to 1A, but it is just displaying it under 1B. I am also aware of the multiple queries thing, which is why i mention in my thread that I am rewriting it to use 1 query total, instead of a 1 per level.

That is why I say it is only 80% done  ;)

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am

Post by bruce » Thu Aug 07, 2008 7:14 pm

If you guys are interested then have a look at my first posts  :D which were related to category sorting. The solution uses an opensource tree control and it may be useful for your solution Qphoria since it starts with a single query to get all categories and sub-categories.

Active Member

Posts

Joined
Wed Dec 12, 2007 2:26 pm

Post by Qphoria » Fri Aug 08, 2008 5:00 am

Now its complete, dynamic levels and all:
http://forum.opencart.com/index.php/top ... ml#msg7440

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am

Post by Qphoria » Thu Aug 14, 2008 11:01 pm

bruce wrote: If you guys are interested then have a look at my first posts  :D which were related to category sorting. The solution uses an opensource tree control and it may be useful for your solution Qphoria since it starts with a single query to get all categories and sub-categories.
I assume you are referring to this thread where you use Tree class to sort by sort order. I actually already have something self contained using usort that I was working on but I can only get it to sort the first level categories, but the sort order for the subcategories is still out of order.

I was hoping your tree method would help but after trying it, it seems that it too only does the first level category sorting.

I guess I'll have to get creative and figure out another way
Last edited by Qphoria on Thu Aug 14, 2008 11:03 pm, edited 1 time in total.

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am

Post by bruce » Thu Aug 14, 2008 11:08 pm

No, it does unlimited levels. The following examples show it all off and should give you a good start.

catalog/extensiont/module/category.php

Code: Select all

<?php

//  The following comment appears at each modified location.
//  Changes to support sort order in Category drop down list.
require_once('Tree.php');
require_once('Tree/Factory/List.php');
//

class ModuleCategory extends Controller
{
	function fetch()
	{
		$config   =& $this->locator->get('config');
		$database =& $this->locator->get('database');
		$language =& $this->locator->get('language');
		$url      =& $this->locator->get('url');

		if ($config->get('category_status'))
		{
			$language->load('extension/module/category.php');

			$view = $this->locator->create('template');

    		$view->set('heading_title', $language->get('heading_title'));

    		$category_data = array();
            $list_data = array();

            $results = $database->getRows("select c.category_id, cd.name, c.parent_id, c.path, c.sort_order from category c left join category_description cd on (c.category_id = cd.category_id) where cd.language_id = '" . (int)$language->getId() . "' order by c.path");
    		foreach ($results as $result)
    		{
                $list_data[] = $result['path'];
      			$category_data[$result['category_id']] = array(
       				'name' => $result['name'],
        			'href' => $url->href('category', false, array('path' => $result['path'])),
                    'sort_order' => (int)$result['sort_order'],
                    'indent' => (count(explode('_', $result['path'])) - 1)
      			);
    		}

            $new_category_data = array();

			// If we get no data, there is no need to sort with the tree.
            if ($list_data)
            {
	            $rit = new Tree_Factory_List($list_data, '_');
	            $tree = Tree::factory($rit);
	            $tree->nodes->traverse('setTags', $category_data);
	            $tree->usortNodes('cmp');
	            $flatList = $tree->nodes->getFlatList();
	            foreach ($flatList as $node)
	            {
	                $tag = $node->getTag();
	                $new_category_data[] = $tag;
	            }
			}
    		$view->set('categories', $new_category_data);

			return $view->fetch('module/category.tpl');
		}
  	}
}

//  Changes to support sort order in Category drop down list.
function setTags($node, $data)
{
    $tag =  $data[$node->getTag()];
    $node->setTag($tag);
}
function cmp($first, $second)
{
   $ret = 0;

   if ( isset( $first) && isset($second) )
    {
        $a =$first->getTag();
        $b = $second->getTag();

        if ($a['sort_order'] < $b['sort_order']) $ret = -1;
        if ($a['sort_order'] > $b['sort_order']) $ret = 1;
    }

    return $ret;
}

?>
and catalog\template\default\extension\module\category.tpl

Code: Select all

<!-- A more complex indent example,
     using unordered lists.
     -->
<div class="box">
	<div class="heading"><?php echo $heading_title; ?></div>
	<div class="category" >
	<ul>
		<?php
		$prev_level = 0;
		foreach ($categories as $category)
		{
			$level = $category['indent'];
			if ($prev_level < $level)
			{  ?>
				<ul><li><a href="<?php echo $category['href']; ?>" ><?php htmlEcho( $category['name']);?></a>
<?php		}
			elseif ($prev_level > $level)
			{  ?>
				</li></ul></li><li><a href="<?php echo $category['href']; ?>" ><?php htmlEcho( $category['name']);?></a>
<?php		}
			else
			{  ?>
				<li><a href="<?php echo $category['href']; ?>" ><?php htmlEcho( $category['name']);?></a>
<?php		}
			$prev_level = $level;
		}  ?>
		</ul>
	</div>
</div>

Active Member

Posts

Joined
Wed Dec 12, 2007 2:26 pm

Post by Qphoria » Thu Aug 14, 2008 11:42 pm

Hmm.. still only sorting the Main Categories, not the subs.

The order I entered my cats and subs was like this
Electronics (sort 1)
-- Gadgets (sort 2)
-- USB      (sort 1)
-- Test     (sort 0)
Cellphones (sort 0)
-- Accessories (sort 0)
But they should display like this:
Cellphones (sort 0)
-- Accessories (sort 0)
Electronics (sort 1)
-- Test     (sort 0)
-- USB      (sort 1)
-- Gadgets (sort 2)
Instead, only the main level sorts, and the sublevels stay in the inserted order like this:
Cellphones (sort 0)usortNodes('cmp');

There is no function called usortNodes in the Tree package.

So I just changed it to:
usort($tree->nodes->nodes, "cmp");
which uses the callback cmp function you have in the category.php file at the bottom.
and changed the $nodes variable to public

I think the end result is the same.
Last edited by Qphoria on Thu Aug 14, 2008 11:48 pm, edited 1 time in total.

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am

Post by bruce » Thu Aug 14, 2008 11:47 pm

That function is part of the tree code which I have attached here.

Active Member

Posts

Joined
Wed Dec 12, 2007 2:26 pm

Post by Qphoria » Thu Aug 14, 2008 11:49 pm

bruce wrote: That function is part of the tree code which I have attached here.
you must have a newer version. I got 2.0 from phpguru.com and it didnt have it in there. I'll try that

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am

Post by Qphoria » Thu Aug 14, 2008 11:51 pm

Ah yes.. that's better. Thx!

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am

Post by bruce » Thu Aug 14, 2008 11:56 pm

I just had a look at that function and find that it is something that I added it to my version of the tree package for just this purpose. My memory is fading  :D

Anyway, happy to help.

Active Member

Posts

Joined
Wed Dec 12, 2007 2:26 pm

Post by Qphoria » Fri Aug 15, 2008 11:30 am

Alright! I've "Hybrided" my "relevant subcategories" with the sort_order stuff from your "show all subcategories". It's perfect!
Thx so much for your help.

Update info found here.
Download update found here.

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am
Who is online

Users browsing this forum: No registered users and 3 guests