Jump to content


Photo

MarkupSimpleNavigation

Module

  • Please log in to reply
177 replies to this topic

#1 Soma

Soma

    Hero Member

  • Moderators
  • 3,207 posts
  • 1761

  • LocationSH, Switzerland

Posted 08 March 2012 - 04:57 PM

Markup Simple Navigation Module

While there was a lot of people asking how to make navigation, and there were many examples around already (apeisa, ryan...) I took the chance to sit down 2-3 hours to make a simple navigation module. It has even some options you can control some aspects of the output.

Installation:

1. Put this module's folder "MarkupSimpleNavigation" into your /site/modules folder.
2. Go to your module Install page and click "Check for new modules". It will appear under the section Markup. Click "install" button. Done.

Technically you don't even need to install it, after the first load call ( $modules->get("MarkupSimpleNavigation") ) it will install automaticly on first request if it isn't already. But it feels better. However, it will not be "autoloaded" by Processwire unless you load it in one of your php templates.
 

 

Documentation:
https://github.com/s...aster/README.md

 

Modules Repository processwire.com

mods.pw/u

 

Download on github

https://github.com/s...impleNavigation


 


@somartist | modules created | support me, flattr my work flattr.com


#2 alanfluff

alanfluff

    Sr. Member

  • Members
  • PipPipPipPip
  • 405 posts
  • 118

  • LocationOttawa, Canada

Posted 08 March 2012 - 05:44 PM

Thanks Soma! I'm going to check this out. Cheers, -Alan

#3 ryan

ryan

    Hero Member

  • Administrators
  • 5,780 posts
  • 3124

  • LocationAtlanta, GA

Posted 08 March 2012 - 06:49 PM

Great module Soma! Thanks for making this and posting.

The only thing I wonder is why make it an autoload module? This is one that is meant for on-demand use, so it doesn't technically need to be an autoload module. Though I agree it does make for a nicer API call:

echo treeMenu->render(...); 
// vs. 
echo $modules->get('MarkupSimpleNavigation')->render(...); 

But I'm just thinking that if every module took this approach, PW wouldn't run as efficiently, or could even run out of memory. But I love this module either way. :)

#4 Soma

Soma

    Hero Member

  • Moderators
  • 3,207 posts
  • 1761

  • LocationSH, Switzerland

Posted 08 March 2012 - 07:03 PM

I just implemented a new option to prepend the rootpage to the navigation.

echo $treeMenu->render( array('show_root' => true) );


Thanks Ryan! Yes I wasn't sure if that makes sense, now as you're saying it... So could I make it so that it isn't autoload and load it once before the call, and then you would have the $treeMenu->render variable? Like



$treeMenu = $modules->get('MarkupSimpleNavigation');
echo $treeMenu->render();

I will change it I think, as it's better performancewise.


EDIT: Just commited new version and updated first post and readme.

@somartist | modules created | support me, flattr my work flattr.com


#5 ryan

ryan

    Hero Member

  • Administrators
  • 5,780 posts
  • 3124

  • LocationAtlanta, GA

Posted 08 March 2012 - 08:23 PM

Thanks Soma, this is a great module and a recurring need--I think it will be helpful to a lot of people, including myself. Nice work with the good documentation too.

#6 MarcC

MarcC

    Sr. Member

  • Members
  • PipPipPipPip
  • 255 posts
  • 63

  • LocationCalifornia

Posted 08 March 2012 - 11:28 PM

Very helpful! Thanks Soma, I'm excited to try it. BTW, is there a way to exclude items from the menu? Maybe I missed something...

I'm a freelance, processwire-using web designer based in california. work site | personal site | visuals


#7 Soma

Soma

    Hero Member

  • Moderators
  • 3,207 posts
  • 1761

  • LocationSH, Switzerland

Posted 09 March 2012 - 03:02 AM

Very helpful! Thanks Soma, I'm excited to try it. BTW, is there a way to exclude items from the menu? Maybe I missed something...


Thanks Marc! Well not with the module, usually you make the pages you don't want to appear status "hidden".

BTW. I just commited a new update and added support for max level. You can now use 'max_levels' => 2.

@somartist | modules created | support me, flattr my work flattr.com


#8 alanfluff

alanfluff

    Sr. Member

  • Members
  • PipPipPipPip
  • 405 posts
  • 118

  • LocationOttawa, Canada

Posted 09 March 2012 - 06:55 AM

Soma / anyone,

This is off-topic really but as a newb to PW (and github), my desktop github client shows the github version is now updated, I just looked in the forum but couldn't find a post to tell me the preferred method for updating a module.


Is it a case of just getting the latest version and overwriting the contents of the folder the module is in locally? Or doI need to disable the module first? Or something different?

Thanks for any help, cheers, -Alan

#9 Soma

Soma

    Hero Member

  • Moderators
  • 3,207 posts
  • 1761

  • LocationSH, Switzerland

Posted 09 March 2012 - 07:05 AM

Soma / anyone,

This is off-topic really but as a newb to PW (and github), my desktop github client shows the github version is now updated, I just looked in the forum but couldn't find a post to tell me the preferred method for updating a module.


Is it a case of just getting the latest version and overwriting the contents of the folder the module is in locally? Or doI need to disable the module first? Or something different?

Thanks for any help, cheers, -Alan


You are save to just replace the files. No need to uninstall, as it doesn't install something or depend on something.

Although because it was at first "autoload" and I changed that, you should check in the db table "modules" if the col "flags" of this module is set to 1 and not 3. If it's at 3 it you can just change it manually to 1.

@somartist | modules created | support me, flattr my work flattr.com


#10 SiNNuT

SiNNuT

    Sr. Member

  • Members
  • PipPipPipPip
  • 367 posts
  • 232

Posted 09 March 2012 - 07:31 AM

Ho Soma, awesome stuff! Can't wait to play a bit with this module.

I think there is an error in the opening post and docs on github:
The call under basic usage should be
$treeMenu = $modules->get("MarkupSimpleNavigation"); // load the module
instead of
$treeMenu = $modules->get("SimpleMarkupNavigation"); // load the module


#11 Soma

Soma

    Hero Member

  • Moderators
  • 3,207 posts
  • 1761

  • LocationSH, Switzerland

Posted 09 March 2012 - 07:38 AM

Nice catch! Thanks sinnut, will update.

@somartist | modules created | support me, flattr my work flattr.com


#12 alanfluff

alanfluff

    Sr. Member

  • Members
  • PipPipPipPip
  • 405 posts
  • 118

  • LocationOttawa, Canada

Posted 09 March 2012 - 07:47 AM

You are safe to just replace the files. No need to uninstall, as it doesn't install something or depend on something.

Although because it was at first "autoload" and I changed that, you should check in the db table "modules" if the col "flags" of this module is set to 1 and not 3. If it's at 3 it you can just change it manually to 1.


Thanks Soma!

#13 Pete

Pete

    Administrator

  • Administrators
  • 1,756 posts
  • 658

  • LocationChester, England

Posted 09 March 2012 - 08:01 AM

I like this module as it reminds me of WayFinder for MODx - definitely one of the most useful tools I used to use for getting a site up and running quickly.

#14 tnt

tnt

    Newbie

  • Members
  • Pip
  • 4 posts
  • 0

Posted 09 March 2012 - 10:19 AM

Another MODx defector! ;-) (well, actually I'm building my first ProcessWire site at the mo and I'm liking it so far, so it might become my CMS of choice!)

This is typical though... I just adapted (don't really know PHP to do it on my own!) a script for multilevel navigation and this comes out!!! At least I learnt a few things about PW whilst doing that!

Thanks for this very useful module Soma! Will try it out straight away!

#15 diogo

diogo

    Hero Member

  • Moderators
  • 2,008 posts
  • 1089

  • LocationPorto, Portugal

Posted 09 March 2012 - 10:59 AM

... I just adapted (don't really know PHP to do it on my own!) a script for multilevel navigation and this comes out!!! At least I learnt a few things about PW whilst doing that!


It's great that people are coming with modules like this, but the reason PW is so flexible, is because it's so easy to build your own snippets of code to achieve this kind of things. I have mixed feelings concerning the modules, and tend to prefer the idea of the snippets repository...

#16 MarcC

MarcC

    Sr. Member

  • Members
  • PipPipPipPip
  • 255 posts
  • 63

  • LocationCalifornia

Posted 09 March 2012 - 12:39 PM

Thanks Marc! Well not with the module, usually you make the pages you don't want to appear status "hidden".



Doh, just checked, that's what I was already doing. My brain is fried :-[ Thanks again !

I'm a freelance, processwire-using web designer based in california. work site | personal site | visuals


#17 tnt

tnt

    Newbie

  • Members
  • Pip
  • 4 posts
  • 0

Posted 09 March 2012 - 12:43 PM

Modified it a bit to fit my needs, but someone might find it useful as well.

Basically, I added a 'first' and 'last' class to the first and last item of each level and also added an exclusion list, so that pages with certain templates can have their children excluded.

The usage is:


$treeMenu = $modules->get("MarkupSimpleNavigation"); // load the module
echo $treeMenu->render( $options, $exclusions, $page, $rootPage);

The $exclusions is an array that contains the name of the template of a page which we don't want to see its children. For example if we have a 'News' page with a template of 'news-list' that aggregates a list of article pages with template 'news-article', then 'news-list' should be added in the $exclusions array. I hope that's clear. Not sure if this is the most flexible way to do this, but it works for me right now and I'm sure someone will come along and improve on it!!

One other change was that I removed the newlines from the <li>'s to make the menu code easier to read and also I've changed the $childs to $children just because it bugged me... sorry!!

I haven't tested the module extensively (read: at all) and as I mentioned in a previous post I'm not really a PHP coder (or a web dev for that matter!) so bear that in mind when you read the few lines that I changed!!! :-)

<?php
/**
*
* Simple Tree Menu Module 1.0.0
*
* @author Soma, with code based by Apeisa, Ryan.
*
* @date_created 08/03/2012
* @last_modified 08/03/2012
*
* ProcessWire 2.x
* Copyright © 2011 by Ryan Cramer
* Licensed under GNU/GPL v2, see LICENSE.TXT
*
* http://www.processwire.com
* http://www.ryancramer.com
*
*/
class MarkupSimpleNavigation extends WireData implements Module {
public static $defaultOptions = array(
  'css_parent' => 'parent',
  'css_current' => 'current',
  'css_levels_on' => false,
  'collapsed' => false,
  'show_root' => false,
  'ul_id' => '',
  'ul_class' => '',
  'max_levels' => null
);

public static function getModuleInfo() {
  return array(
   'title' => "Markup for simple nested navigation",
   'summary' => 'Module to render simple nested ul tree of the site structure. See readme for usage and options avaiable.',
   'version' => 100,
   'href' => 'http://processwire.com/talk/topic/1036-markupsimplenavigation/',
   'autoload' => false,
   'singular' => true
  );
}
public function init() {
  //$this->fuel->set('treeMenu', $this );
  $this->set('iteration',0);
}

/**
*
*   Main method called ony pages by echo $treeMenu->render(); to render
*   init tree rendering, merge options with defaults
*
*/
public function render( Array $options = null, Array $exclusions = null, Page $page = null, Page $rootPage = null ) {
  if($options != null && is_array($options)){
   $options = array_merge(self::$defaultOptions, $options);
  } else {
   $options = self::$defaultOptions;
  }
  return $this->_renderTree( $options, $exclusions, $page, $rootPage );
}

/**
*
*   Render the tree method
*
*/
private function _renderTree( $options, $exclusions, $page, $rootPage ){
  $this->iteration++;
  if(is_null($page)) $page = wire('page');
  if(is_null($rootPage)) $rootPage = wire('pages')->get('/');
  $ul_class = '';
  $ul_id = '';
  if($options['ul_class'] != '') $ul_class = " class='".$options['ul_class']."'";
  if($options['ul_id'] != '') $ul_id = " id='".$options['ul_id']."'";
  if($this->iteration == 1) $out = "\n<ul$ul_class$ul_id>";
   else  $out = "\n<ul>";
  $parents = $page->parents;
  if($options['show_root'] && $this->iteration == 1) {
   $children = $rootPage->children;
   $children->prepend( $rootPage );
  } else {
   $children = $rootPage->children;
  }
  foreach($children as $key=>$child) {
			$s = '';
			$level = ($child === $rootPage) ? 1 : count($child->parents);
			if($options['css_levels_on']) $class = " level-" . $level;
			else $class = '';
		  
			$template = $child->template;
			if ( !in_array($template->name, $exclusions) ) {
				
			   if(!$key) $class .= " first";
			   if($key == (count($children) - 1 ) ) $class .= " last";
			   if($options['max_levels'] != null && $level >= $options['max_levels']) $stopit = true;
				  else $stopit = false;
			   if(!$options['collapsed']){
				  if($parents->has($child)) {
					 $class .= ($child !== $rootPage) ? " " . $options['css_parent'] : '' ;
				  }
				  else if($child === $page){
					 $class .= " " . $options['css_current'];
				  }
				  if($child->numChildren && $child !== $rootPage){
					 if(!$stopit) {
						$s = str_replace("\n", "\n\t\t", $this->_renderTree($options, $exclusions, $page, $child));
					 }
				  }
			   }
			   else
			   {
				  if($child->numChildren && $parents->has($child)) {
					 $class .= ($child !== $rootPage) ? " " . $options['css_parent'] : '' ;
					 if(!$stopit) {
						$s = ($child !== $rootPage) ? str_replace("\n", "\n\t\t", $this->_renderTree($options, $exclusions, $page, $child)) : '';
					 }
				  } else if($child === $page) {
					 $class .= " " . $options['css_current'];
					 if($page->numChildren && $child !== $rootPage) {
						if(!$stopit) {
						   $s = str_replace("\n", "\n\t\t", $this->_renderTree($options, $exclusions, $page, $child));
						}
					 }
				  }
			   }
			$class = substr($class,1);
			if(strlen($class) > 0) {
			   $class = " class='$class'";
			}
		 }  
		 $out .= "\n\t<li><a$class href='{$child->url}'>{$child->title}</a>$s</li>";
  }
  $out .= "\n</ul>\n";
  return $out;
}
}


#18 Soma

Soma

    Hero Member

  • Moderators
  • 3,207 posts
  • 1761

  • LocationSH, Switzerland

Posted 09 March 2012 - 07:02 PM

Hey tnt, thanks for posting a modified version.

- That's a good addition to exclude page per template, it can make sense in the example with news pages. I will implement it as an option.

- Hehe, yes I'm not native english speaker, so I often use false words like "childs" instead of children. Thanks for pointing out.

- Your right the markup outputted could be improved, but I mostly use a web inspector anyway so that it wouldn't matter much.

- I'm not sure if I think about it, last and first is something that can be done more easy with css using li:first-child, li:last-child. And if implemented I would see it as turn on/off feature like the levels-. I don't want that outputted by default.

EDIT: Thinking about setting classes, I thought it way could make sense to have an option for where to put the item classes, either <a> or <li>.

EDIT: Oh and I would be good to may use github "fork" to then make a pull request so I could implement or merge additions. Or even easier, make a feature request. Same with bugs. It would help not having multiple version around, as people start copying your code and would may lose it after updating it with the github version.

@somartist | modules created | support me, flattr my work flattr.com


#19 Soma

Soma

    Hero Member

  • Moderators
  • 3,207 posts
  • 1761

  • LocationSH, Switzerland

Posted 09 March 2012 - 09:16 PM

I made an update to the module. If you get the latest version you'll get new features.

Added support for custom selector:

Instead of adding more options to exclude pages, since PW is so open as to how to set up you pages/template stucture, I've implemented the option to specify a PW selector. So some of the power of it comes into play. (Remember it's always best-practice to sanitize values that may come from user input you can trust. This module doesn't do any)

You can for example hide page(s) with a certain or parent(s):

echo $tree->render( array("selector" => "parent!=1008|1002") );

And child pages from those parent will not be rendered.

Or if you want to exclude page(s) with certain template(s) you would do :

echo $tree->render( array("selector" => "template!=news-item|event-item") );

Or you could limit the items per level:

echo $tree->render( array("selector" => "limit=5") );


Added support for "first,last" class:

A new option that is off by default, that will output extra class to links. You can turn it on with the options "css_firstlast_on" set to true

array('css_firstlast_on' => true)


Minor changes:

Done some renaming and restructuring. Also removed some newlines in the markup output.

@somartist | modules created | support me, flattr my work flattr.com


#20 nikola

nikola

    Sr. Member

  • Members
  • PipPipPipPip
  • 224 posts
  • 81

  • LocationZagreb, Croatia

Posted 10 March 2012 - 06:59 AM

Hey Soma,

this is nice plugin, it will definitely simplify various navigation scenarios.

I've tried it and it works like a charm.

Thanks
Check out my ProcessWire admin themes: Futura Remixed Admin Theme / Moderna Admin Theme / Futura Admin Theme





Also tagged with one or more of these keywords: Module

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users