CMenu and multi-level nested menu

Hi there,

I copied code from CMenu class reference to my webapp. The only thing I changed was to remove ‘visible’ property for last menu item (‘Login’) so it would be displayed everytime. So the code is:


                        $this->widget('zii.widgets.CMenu', array(

                            'items'=>array(

                                array('label'=>'Home', 'url'=>array('site/index')),

                                array('label'=>'Products', 'url'=>array('product/index'), 'items'=>array(

                                    array('label'=>'New Arrivals', 'url'=>array('product/new', 'tag'=>'new')),

                                    array('label'=>'Most Popular', 'url'=>array('product/index', 'tag'=>'popular')),

                                )),

                                array('label'=>'Login', 'url'=>array('site/login')),

                            ),

                        ));

What I actually see in IE and FF is posted as attachement and pasted below:

888

CMenu_IE.png

889

CMenu_FF.png

Three questions:

  1. Has anyone got any idea why ‘Login’ position is not being displayed?

  2. Am I missing something or doing something wrong? Is this what Yii understands as ‘multi-level’, ‘nested’ menu. I was more than sure that with using nested-feature I will see a really multi-level menu like in every desktop applicaiton and on many websites. I.e. (according to above code) only ‘Home’, ‘Products’ and ‘Login’ positions would be seen and positions ‘New Arrivals’ and ‘Most Popular’ would only be displayed when user would hover mouse pointer over ‘Products’ menu item.

  3. Why do I see ‘New Arrivals’ and ‘Most Popular’ positioned like it would belong to ‘Home’ if in fact they belong to ‘Products’. The same, if I make this menu structure a bit more complicated to four-level menu:


                        $this->widget('zii.widgets.CMenu', array(

                            'items'=>array(

                                array('label'=>'Home', 'url'=>array('site/index')),

                                array('label'=>'Products', 'url'=>array('product/index'), 'items'=>array(

                                    array('label'=>'New Arrivals', 'url'=>array('product/new')),

                                    array('label'=>'Most Popular', 'url'=>array('product/index')),

                                    array('label'=>'Another', 'url'=>array('product/index'), 'items'=>array(

                                        array('label'=>'Level 3 One', 'url'=>array('product/new')),

                                        array('label'=>'Level 3 Two', 'url'=>array('product/index')),

                                        array('label'=>'Level 3 Three', 'url'=>array('product/index'), 'items'=>array(

                                            array('label'=>'Level 4 One', 'url'=>array('product/new')),

                                            array('label'=>'Level 4 Two', 'url'=>array('product/index')),

                                        )),

                                    )),

                                )),

                                array('label'=>'Login', 'url'=>array('site/login')),

                            ),

                        ));

I see ‘Level 3 One’ positioned like it would belong to ‘New Arrivals’, why in fact it belongs to ‘Another’ and Level 4 One’ like belonging to ‘Level 3 One’ when it actually belongs to ‘Level 3 Three’.

Each menu item is displayed spearatelly, positioned in some hard to understand by me matter. I completely can’t see where actually generated menu structure is relevand to menu structure in code? Can someone explain me, why CMenu class does not generates menu layout in the way as (in my opinion) logic would advise. I.e. see following two attachements.

Simple menu, relevant to first example of code above:

890

DelphiMenu_Simple.png

Complex menu, relevant to second example of code above:

891

DelphiMenu_Complex.png

Finally, if what I see on my webpage (first two attachements) is not an effect of a mistake by me or some other error and if this is what it meant to be (i.e. CMenu should generate menu this way - IMHO completely unusable) can some one tell me is there any other solution or way to build a menu on website that would at least be close or similar to one seen in desktop application (third and fourth attachement) or on many, many webpages?

With kind regards,

Trejder

Hi man!

Check this Yii Extension: MBMenu

It looks ok,

Your code isn’t bad, it is properly done. I have tested it. Maybe your styles? or layer widths?

Hi Antonio,

Well… taking into account that this one was tested on pure yii demo app generated via yiic webapp then I’m begining to believe that for a reason beyond my imagination someone thought / decided that it should be like this!

Is there anyone there, who was able to produce really multi-level menu with only CMenu without need to use some extra extensions like Antonio proposed?

BTW, mbmenu looks perfect! :)

Thanks man,

I was able to use CMenu but taking advantage of its rendering:

a) got the plugin jqueryslidemenu

B) registered teh files my code





$cs->registerCssFile($cssUrl.'jqueryslidemenu.css');

$cs->registerCoreScript('jquery');

	

$cs->registerScriptFiles(array(

		$jsUrl . 'jqueryslidemenu.js'

	));




c) created the menu using the widget





// check how findSubMenuTypeItems returns a sub-menu 


 <div id="myslidemenu" class="jqueryslidemenu">

      	<?php $this->widget('zii.widgets.CMenu',array(

      		'activeCssClass'=>'current',

			'items'=>array(

				array('label'=>'MAIN', 'url'=>array('site/index')),

				array('label'=>'ANOTHER MENU', 'url'=>array('property/index', 'for'=>Property::FOR_SALE),'items'=>Type::model()->findSubMenuTypeItems()),

				array('label'=>'ANOTHER MENU', 'url'=>array('property/index', 'for'=>Property::FOR_RENT), 'items'=>Type::model()->findSubMenuTypeItems(false)),

				array('label'=>'ANOTHER MENU', 'url'=>array('site/page',array('view'=>'about'))),

				array('label'=>'ANOTHER MENU', 'url'=>array('site/page', array('view'=>'contact')))

			),

		)); ?>

        <br style="clear: left" />

      </div>



d) I changed the styles and voilá! my own sliding menu… Wish I knew how to upload the result because it is quite good…

Good luck man!

This tutorial may help you

Creating a database driven hierarchical structure with cmenu and superfish

Quite good, heh? This one looks perfect! :)

I think you can post a new article on Yii Cookbook to publish it.

I’m uploading along with this post a zipped yii demoapp with included jqueryslidemenu. Hope someone will take a use of it.

897

jqueryslidemenu.zip

Thanks, again Antonio!

Not a problem my friend… always a pleasure… Happy to help

Btw, I will do as you said and will post a cookbook article with your demo files if you allow me to use them.

Here is updated jqueryslidemenu example with using paths to image files as global variables - as Antonio proposed in this post.

One must edit layout file -> jqueryslidemenu/protected/views/layouts/main.php to change downImagePath and rightImagePath variables.

908

jqueryslidemenu.zip

It is worth noting here, however, that jqueryslidemenu hasn’t got feature of differenting with special CSS class top-level menu item whos sub menu is currently selected. It also has some minor graphic bugs when using menu items having two or more lines.

If one needs such feature should rather look after MBMenu, you proposed earlier.

Here is Yii sample application with mentioned MBMenu used in place of original menu introduced by Yii.

909

mbmenu.zip

It is worth to note that MBMenu has some problems (menu drawing and handling bugs) when one is using menu with more than two sub levels. See ‘Test’ menu in attached example or try to reproduce this problem on your own site with using below code:


	<div id="mbmenu">

		<?php $this->widget('application.extensions.mbmenu.MbMenu',array

		(

			'items'=>array

			(

				array('label'=>'Home', 'url'=>array('/site/index')),

				array('label'=>'About', 'url'=>array('/site/page', 'view'=>'about')),

				array('label'=>'Contact', 'url'=>array('/site/contact'), 'items'=>array

				(

					array('label'=>'A Sub in Contact'),

					array('label'=>'Very, very long menu item caption test...'),

				)),

				array('label'=>'Test', 'items'=>array

				(

					array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),

					array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!Yii::app()->user->isGuest),

					array('label'=>'Another very, very long menu item caption test...', 'items'=>array

					(

						array('label'=>'Sub Sub 1', 'url'=>array('/site/page', 'view'=>'about')),

						array('label'=>'Sub Sub 2', 'url'=>array('/site/page', 'view'=>'about')),

						array('label'=>'Sub Sub 2', 'url'=>array('/site/page', 'view'=>'about'), 'items'=>array

						(

							array('label'=>'Sub Sub Sub 1', 'url'=>array('/site/page', 'view'=>'about')),

							array('label'=>'Sub Sub Sub 2', 'url'=>array('/site/page', 'view'=>'about'), 'items'=>array

							(

								array('label'=>'Sub Sub Sub Sub 1', 'url'=>array('/site/page', 'view'=>'about')),

								array('label'=>'Sub Sub Sub Sub 2', 'url'=>array('/site/page', 'view'=>'about'))

							)),

						)),

					)),

				)),

			),

	    )); ?>

	</div>

Menu items for third, fourth and more levels is being incorrectly drawn (no top border) and all sublevels are being displayed at once when hovering mouse over second level menu item containing sub-level items.

MBMenu correctly handles menu items with two line captions and has some minor drawing issues with three or more lines in menu item captions.

I’m reopening this discussion to ask if someone heard about professional menu system similar to below attachment, that would allow to build either standard page menu or popup menu with images on the left, multi-line captions (title + description) and grouping of menu items with line separators?

Example of multi-line menu popups from Microsoft SharePoint 2010:

931

sh2k10_multiline_popup.png

Could you please post Type::model()->findSubMenuTypeItems

Hi Trejder

thank you for your jqueryslidemenu and MBMenu examples.

I have a problem with jqueryslidemenu: it does not show drop down images, and sub menus are not rendered at all :(

I also have another problem with both of examples: I just want to make menus center aligned (by putting “text-align: center;” in corresponding css file), but simply they don’t change

thenks in advance

Hi arash,

About first problem - I can’t help you. I’m not using jqueryslidemenu at all as I found it not enough useful for my projects. I don’t remember right know why (maybe for the reasons, you mentioned) but since very beginning of my first project done in Yii I started to use MBMenu and then migrated this idea to my other projects. Maybe there are better menu systems for Yii out there, but for me personally MBMenu is enough good and in my private opinion it is far better than jqueryslidemenu.

About second problem - make sure that you delete whole contents of assets folder after you do any change in any extension CSS or JS source files. Yii works the way that it does not checks if any of published files (that is styles and JavaScript code put into assetes folder) has changed. It only checks, if destination folder (an assets subfolder) exist and that is path and last modification date of folder holding source CSS or JS files. In other words, if you do some change in any of source files of any extension but folder containing them will not have changed path or modification date, any changes made to these files will not be re-published. You have to delete subloder of assets folder to force Yii to recreate it with new (changed) files. It is a common mistake to modify extension source CSS and JS files.

After you modify these files, you should also - when refreshing page - press Ctrl+F5 (in Firefox) or Shift+F5 (in Internet Explorer) or any combination that is bind in your browser to force it to reload CSS and JS files from website (even if it is localhost), not from browser’s local cache.

This rule does not comply to extension PHP files as those are being parsed by PHP, not browser and are always used in newest versions.

If you are aware of above situation, you are deleting assets folder after each modification to source CSS files and you still doesn’t see effect, you’re expecting to see, than you have to install/use Firebug extension (in Firefox) or use Developer Tools (in Internet Explorer) or any other debug-tool in your browser to carefully analyse, how your CSS styoes are treated to where possible they are for example overwritten, which maybe source to your problem.

Cheers,

Trejder

Hi Trejder,

Thank you so much for your very helpful advices

searching awhile, I decided to use jquery ui menu (which is in development to be part of 1.9 version).

maybe I could post a Yii sample application containing JUI menu (after I created it).

Best regards

Arash

Excellent idea! Any piece of code or example is welcome here, even if it is most obvious. Since for some beginners an obvious things might not be so obvious. My opinion is that you should go ahead and publish example, if you write it and test it, it is working.

ok, now in attached file you can find an extension containing a multi-level nested menu package. I used CMenu and JUI menu and menubar as base of this work.

for using it, you can copy the extracted folder into your yii extension folder, and use the package just like the Yii’s CMenu.

for example in your main layout file add:




		 $this->widget('ext.jui-menu.JUIMenu', array(

		     'items'=>array(

		         array('label'=>'link1', 'url'=>array('#'), 'items'=>array(

		             array('label'=>'sublink11', 'url'=>array('#')),

		             array('label'=>'sublink12','url'=>array('#')),

		             array('label'=>'sublink13', 'url'=>array('#'), 'items'=>array(

 		             array('label'=>'sublink131', 'url'=>array('#')),

		             array('label'=>'sublink132', 'url'=>array('#')),

		             

		             )),

		             array('label'=>'sublink14', 'url'=>array('#')),

		         )),

		         array('label'=>'link2', 'url'=>array('#'), 'items'=>array(

		             array('label'=>'sublink21', 'url'=>array('#')),

		             array('label'=>'sublink22','url'=>array('#')),

		             array('label'=>'sublink23', 'url'=>array('#')),

		             array('label'=>'sublink24 'url'=>array('#')),

		         )),

		     ),

		  ));	



Hi, arash,

Sorry for replying after a month, but I was quite a busy.

Thanks for your support with this extension and a piece of example code. But either I’m missing something, or it is not working, as it suppose to work.

I’ve put your extension into brand new, autogenerated Yii application and replaced original menu with a code you provided. When I hover my mouse on a top-menu item, a submenu opens, but it is empty. Submenu items are only visible, if I hover them. If I move mouse pointer to another menu item, previous one dissipaters and a white, empty are replaces it. And – if I hover mouse pointer out of the menu at all, it does not disappears. It remains on the screen since first use of menu till page reload.

I don’t know what is wrong, but currently it seems to be pretty not usable.

Cheers,

Trejder

Hi trejder

I’m sorry to for the same reason :)

the problem with submenu items(i guess) is about their css coloring(almost same colours for fonts and background).

because the jquery-ui menu is not matured yet, I decided to use one of the css menus from here

thank you for your feedback and sorry for incomplete menu

best regards

arash

Well… These looks quite very nice! A good piece of work.

Now, it would be nice to have them as Yii’s extension.

Thanks for posting this!

Cheers,

Trejder

I did it, you can find it here

it’s my first extension, so please comment on extension page whatever you think can make extension better

best regards

arash