Jul 05, 2009, 08:40 PM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
Search via SMF or Google: modx forums all of modxcms.com web
  MODxCMS.com   Forums   Help Login Register  
Pages: [1] 2 3 ... 18   Go Down
  Print  
Author Topic: Support/Comments for Wayfinder  (Read 63997 times)
0 Members and 1 Guest are viewing this topic.
kylej
Moderator
*
Posts: 758



WWW
« on: Aug 02, 2006, 02:29 PM »

This is an auto-generated support/comment thread for Wayfinder.

Use this forum to post any comments about this addition or any questions you have regarding its use.


I am locking this thread, as it is geting way to long.  If you have comment, question or request please create a new topic in the Wayfinder board.

http://modxcms.com/forums/index.php/board,182.0.html
« Last Edit: Nov 03, 2006, 06:44 PM by kylej » Logged

heliotrope
Coding Team
*
Posts: 2,517


WWW
« Reply #1 on: Aug 02, 2006, 03:57 PM »

Hi,

Looks pretty cool.

Not yet tested but after having a look at parameters and code, it seems that we cannot access to TV.
With DropMenu I had been able to add this features to make menu with image replacement technic.

Do you plan to add this in future version ?

Anyway, congratulations for this new version.

Logged

kylej
Moderator
*
Posts: 758



WWW
« Reply #2 on: Aug 02, 2006, 05:35 PM »

heliotrope,
  can you point me in the direction of your modification of dropmenu for tvs?  I will look into adding it, I'm just not sure what the functionality should be...
Logged

heliotrope
Coding Team
*
Posts: 2,517


WWW
« Reply #3 on: Aug 03, 2006, 03:23 AM »

kylej,

the idea is to be able to add a custom class or id to menu item according a TV(text).
The main issue is that we have to avoid css conflict between ID (if the menu is called twice in the same document for instance to work on the same tree level) so we will use class.

Well as I cannot explain as I'd like to, here is your code modified for this feature.
As I am not a developper I don't know if it's the best way to do.

The main changes are
- I've added a parameter to the wf class (customCss) which is the name of The TV from which the values are retrieved
- In the buidMenu function added in the $resource loop a call to getTemplateVar
- Added a parameter to setItemClass function

todo:
-debug mode

I guess that's all.

[[WayFinder? &customCss=`IdCssMenu` ]]


Code:
<?php

/*
 Snippet name: Wayfinder
 Short Desc: builds site navigation
 Version: beta
 Authors: Ryan Thrash (vertexworks.com)
          Kyle Jaebker (muddydogpaws.com)
*/

class Wayfinder {
    var 
$id 0;
    var 
$level 0;
    var 
$ph FALSE;
    var 
$debug;
    var 
$ignoreHidden FALSE;
    var 
$hideSubMenus FALSE;
    var 
$textOfLinks 'menutitle';
    var 
$titleOfLinks 'pagetitle';
    var 
$templates = array();
    var 
$parentTree = array();
    var 
$wfDocs = array();
    var 
$css = array();
    var 
$cssTpl FALSE;
    var 
$jsTpl FALSE;
    var 
$rowPlaceHolders = array('[+wf.link+]','[+wf.title+]','[+wf.linktext+]','[+wf.wrapper+]','[+wf.classes+]');
    var 
$outerPlaceHolders = array('[+wf.wrapper+]','[+wf.classes+]');
    var 
$ie "\n";
    var 
$customCss;//hack customCss which TV do  we have to look at
    
var $debugOutput '<h2>WayFinder Debug Output:</h2>';

    
//remove any docs specified with hidemenu
    
function filterHidden($var) {
return (!$var['hidemenu']==1);
}

function endKey(&$array){
        
end($array);
        return 
key($array);
    }

    
//generate the menu
    
function buildMenu($parentId,$curLevel 1) {
        global 
$modx;
        
$output '';

        
$getFields 'id,menutitle,pagetitle,menuindex,published,hidemenu,parent,isfolder,description,alias,longtitle';
        
$resource $modx->getActiveChildren($parentId,'menuindex','ASC',$getFields);

        if (!
$this->ignoreHidden) {
            
$resource array_filter($resource, array($this"filterHidden"));
        }

        
$firstItem 1;

        if (
is_array($resource) && !empty($resource)) {
            
$numItems $this->endKey($resource);
            foreach (
$resource as $n => $v) {
                
$v['link'] = $modx->makeUrl($v['id']);
                
$v['level'] = $curLevel;
                
$v['first'] = $firstItem;
                
//hack for specific css
                
if(!empty($this->customCss)){//
                
$mycss $modx->getTemplateVar($this->customCss,$fields='id',$v['id']);
                
//print_r($mycss);
                
if(!empty($mycss['value'])) {
                
$v['specific'] = $mycss['value'];
                
}
                }
                
//endhack
                
$firstItem 0;
                if (
$n == $numItems) {
                    
$v['last'] = 1;
                } else {
                    
$v['last'] = 0;
                }

                
$useTextField = (empty($v[$this->textOfLinks])) ? 'pagetitle' "$this->textOfLinks";
                
$v['linktext'] = $v[$useTextField];
                
$v['title'] = $v[$this->titleOfLinks];

                if (
$v['isfolder'] && ($curLevel $this->level || $this->level == 0) && (!$this->hideSubMenus || in_array($v['id'],$this->parentTree))) {
                    
$oldLevel $curLevel;
                    
$subMenu $this->ie $this->buildMenu($v['id'],++$curLevel) . $this->ie;
                    
$curLevel $oldLevel;
                } else {
                    
$subMenu '';
                }
                
$output .= $this->renderRow($v,$subMenu);
            }

            if (!empty(
$this->templates['innerTpl']) && $curLevel 1) {
                
$useChunk $this->templates['innerTpl'];
                
$usedTemplate 'innerTpl';
            } else {
                
$useChunk $this->templates['outerTpl'];
                
$usedTemplate 'outerTpl';
            }

            if (
$curLevel 1) {
                
$wrapperClass 'innercls';
            } else {
                
$wrapperClass 'outercls';
            }

            
$useClass $this->setItemClass($wrapperClass);
            
$phArray = array($output,$useClass);

            
$output str_replace($this->outerPlaceHolders,$phArray,$useChunk);

            if (
$this->debug) {
                
$numDocs $numItems 1;
                
$this->debugOutput .= '<strong>Nesting Complete</strong> - Previous ' $numDocs ' level ' $curLevel ' items inserted into ' $usedTemplate ' with class ' $useClass '<br/>';
            }
        }

        return 
$output;
    }

    
//render each rows output
    
function renderRow(&$resource,$subMenu) {
        global 
$modx;
        
$output '';

        if (
$resource['isfolder'] && !empty($this->templates['parentRowTpl'])) {
            
$usedTemplate 'parentRowTpl';
        } elseif (
$resource['id'] == $modx->documentObject['id'] && !empty($this->templates['innerHereTpl']) && $resource['level'] > 1) {
            
$usedTemplate 'innerHereTpl';
        } elseif (
$resource['id'] == $modx->documentObject['id'] && !empty($this->templates['hereTpl'])) {
            
$usedTemplate 'hereTpl';
        } elseif (
$resource['level'] > && !empty($this->templates['innerRowTpl'])) {
            
$usedTemplate 'innerRowTpl';
        } else {
            
$usedTemplate 'rowTpl';
        }
        
        
$useChunk $this->templates[$usedTemplate];

        
$useSub $subMenu;
        
$useClass $this->setItemClass('rowcls',$resource['id'],$resource['first'],$resource['last'],$resource['level'],$resource['isfolder'],$resource['specific']);

        
$phArray = array($resource['link'],$resource['title'],$resource['linktext'],$useSub,$useClass);

        
$output .= str_replace($this->rowPlaceHolders,$phArray,$useChunk);

        if (
$this->debug) {
            
$this->debugOutput .= '<strong>Item Processed: (' $resource['id'] . ') ' $resource['pagetitle'] . '</strong><br/>
            template: ' 
$usedTemplate ' | class: ' $useClass '<br/>
            level: ' 
$resource['level'] . ' | First/Last: ' $resource['first'] . '/' $resource['last'] . '<br/>';
        }

        return 
$output $this->ie;
    }

    
//debugging to check for valid chunks
    
function checkChunks() {
        global 
$modx;

        foreach (
$this->templates as $n => $v) {
            
$chunkcheck $modx->getChunk($v);
            if (empty(
$v) || !$chunkcheck) {
                if (
$n === 'outerTpl') {
                    
$this->templates[$n] = '<ul[+wf.classes+]>[+wf.wrapper+]</ul>';
                } elseif (
$n === 'rowTpl') {
                    
$this->templates[$n] = '<li[+wf.classes+]><a href="[+wf.link+]" title="[+wf.title+]">[+wf.linktext+]</a>[+wf.wrapper+]</li>';
                } else {
                    
$this->templates[$n] = '';
                }
                if (
$this->debug) {
                    
$this->debugOutput .= '<p>No chunk found for <strong>' $n '</strong> using default.</p>';
                }
            } else {
                
$this->templates[$n] = $chunkcheck;
            }
        }
    }

    
//determine "you are here"
    
function isHere($did) {
        return 
in_array($did,$this->parentTree);
    }

    
//determine style class for current item being processed
    
    //added 1param to the function for customCss hack
    
function setItemClass($classType$docId 0$first 0$last 0$level 0$isFolder 0$specificCss ='') {
        global 
$modx;
        
$returnClass '';
        
$hasClass 0;

        if (
$classType === 'outercls' && !empty($this->css['outer'])) {
            
//Set outer class if specified
            
$returnClass .= $this->css['outer'];
            
$hasClass 1;
        } elseif (
$classType === 'innercls' && !empty($this->css['inner'])) {
            
//Set inner class if specified
            
$returnClass .= $this->css['inner'];
            
$hasClass 1;
        } elseif (
$classType === 'rowcls') {
            
//Set row class if specified
            
if (!empty($this->css['row'])) {
                
$returnClass .= $this->css['row'];
                
$hasClass 1;
            }
            
//Set first class if specified
            
if ($first && !empty($this->css['first'])) {
                
$returnClass .= $hasClass ' ' $this->css['first'] : $this->css['first'];
                
$hasClass 1;
            }
            
//Set last class if specified
            
if ($last && !empty($this->css['last'])) {
                
$returnClass .= $hasClass ' ' $this->css['last'] : $this->css['last'];
                
$hasClass 1;
            }
            
//Set level class if specified
            
if (!empty($this->css['level'])) {
                
$returnClass .= $hasClass ' ' $this->css['level'] . $level $this->css['level'] . $level;
                
$hasClass 1;
            }
            
//Set parentFolder class if specified
            
if ($isFolder && !empty($this->css['parent']) && $level $this->level) {
                
$returnClass .= $hasClass ' ' $this->css['parent'] : $this->css['parent'];
                
$hasClass 1;
            }
            
//Set here class if specified
            
if (!empty($this->css['here']) && $this->isHere($docId)) {
                
$returnClass .= $hasClass ' ' $this->css['here'] : $this->css['here'];
                
$hasClass 1;
            }
            
//hack customCss
            //Set specific class if exists
            
if (!empty($specificCss)) {
                
$returnClass .= $hasClass ' ' $specificCss $specificCss;
                
$hasClass 1;
            }
        }

        if (
$hasClass) {
            
$returnClass ' class="' $returnClass '"';
        }
        return 
$returnClass;
    }
    
    
//Add the specified css & javascript chunks to the page
    
function regJsCss() {
        global 
$modx;
        
        if (
$this->debug) {
            
$this->debugOutput .= '<h3>Processing Css/Js Chunks</h3>';
        }
        
        if (
$this->cssTpl) {
            
$cssChunk $modx->getChunk($this->cssTpl);
            if (
$cssChunk) {
                
$modx->regClientCSS($cssChunk);
                if (
$this->debug) {$this->debugOutput .= '<p>The CSS chunk ' $this->cssTpl ' was added to the page.</p>';}
            } else {
                if (
$this->debug) {$this->debugOutput .= '<p>The CSS chunk ' $this->cssTpl ' was not found.</p>';}
            }
        }
        
        if (
$this->jsTpl) {
            
$jsChunk $modx->getChunk($this->jsTpl);
            if (
$jsChunk) {
                
$modx->regClientStartupScript($jsChunk);
                if (
$this->debug) {$this->debugOutput .= '<p>The JS chunk ' $this->jsTpl ' was added to the page.</p>';}
            } else {
                if (
$this->debug) {$this->debugOutput .= '<p>The JS chunk ' $this->jsTpl ' was not found.</p>';}
            }
        }
    }
    
    function 
ultimateParent($id,$top) {
        
// From UltimateParent - snippet for MODx 0.9x
        // March 2006 - sottwell@sottwell.com
        
global $modx;
        if(
$id==$top || $id==0) { return $id; }
        
$pid $modx->getParent($id,1,'id');
        if(
$pid['id'] == $top) { return $id; }
        while (
$pid['id'] != $top && $pid['id'] != "") {
            
$id $pid['id'];
            
$pid $modx->getParent($id,1,'id');
            if(
$pid['id'] == $top) { return $id; }
        }
        return 
0// if all else fails
    
}
}
?>


The snippet

Code:
<?php
/*
::::::::::::::::::::::::::::::::::::::::
 Snippet name: Wayfinder
 Short Desc: builds site navigation
 Version: beta
 Authors: Ryan Thrash (vertexworks.com)
          Kyle Jaebker (muddydogpaws.com)
 Date: August 2, 2006

 Changelog:
    August 2, 2006 - Initial Public Beta released
::::::::::::::::::::::::::::::::::::::::
Description:
    Totally refactored from original DropMenu nav builder to make it easier to
    create custom navigation by using chunks as output templates. By using templates,
    many of the paramaters are no longer needed for flexible output including tables,
    unordered- or ordered-lists (ULs or OLs), definition lists (DLs) or in any other
    format you desire.
::::::::::::::::::::::::::::::::::::::::
Example Usage:
    [[Wayfinder? &startId=`0`]]
::::::::::::::::::::::::::::::::::::::::
*/

include_once("assets/snippets/wayfinder/wayfinder.inc.php");

if (
class_exists('Wayfinder')) {
   
$wf = new Wayfinder();
} else {
        return 
'error: Wayfinder class not found';
}

//parameter overrides
if (isset($startUltimateParent)) {
    
$topDoc = isset($topDoc)? $topDoc0;
    
$wf->id $wf->ultimateParent($modx->documentIdentifier,$topDoc);
} else {
    
$wf->id = isset($startId)? $startId$modx->documentIdentifier;
}
$wf->level = isset($level)? $level0;
$wf->ph = isset($ph)? $phFALSE;
$wf->debug = isset($debug)? TRUEFALSE;
$wf->ignoreHidden = isset($ignoreHidden)? $ignoreHiddenFALSE;
$wf->hideSubMenus = isset($hideSubMenus)? $hideSubMenusFALSE;
isset(
$removeNewLines)? $wf->ie ''$wf->ie "\n";
//Include javascript & css chunks
$wf->cssTpl = isset($cssTpl)? $cssTpl FALSE;
$wf->jsTpl = isset($jsTpl)? $jsTpl FALSE;
//get user class definitions
$wf->css['first'] = isset($firstClass)? $firstClass'';
$wf->css['last'] = isset($lastClass)? $lastClass'last';
$wf->css['here'] = isset($hereClass)? $hereClass'active';
$wf->css['parent'] = isset($parentClass)? $parentClass'';
$wf->css['row'] = isset($rowClass)? $rowClass'';
$wf->css['outer'] = isset($outerClass)? $outerClass'';
$wf->css['inner'] = isset($innerClass)? $innerClass'';
$wf->css['level'] = isset($levelClass)? $levelClass'';

//hack to add custom css 
//specify the name of TV from which we get the values
$wf->customCss = isset($customCss) ? "$customCss" '';

//get fields to output
$wf->textOfLinks = (isset($textOfLinks)) ? $textOfLinks 'menutitle';
$wf->titleOfLinks = (isset($titleOfLinks)) ? $titleOfLinks 'pagetitle';
//get user templates
$wf->templates['outerTpl'] = isset($outerTpl) ? $outerTpl '';
$wf->templates['rowTpl'] = isset($rowTpl) ? $rowTpl '';
$wf->templates['parentRowTpl'] = isset($parentRowTpl) ? $parentRowTpl '';
$wf->templates['hereTpl'] = isset($hereTpl) ? $hereTpl '';
$wf->templates['innerTpl'] = isset($innerTpl) ? $innerTpl '';
$wf->templates['innerRowTpl'] = isset($innerRowTpl) ? $innerRowTpl '';
$wf->templates['innerHereTpl'] = isset($innerHereTpl) ? $innerHereTpl '';
//setup here checking array
$wf->parentTree $modx->getParentIds($modx->documentIdentifier);
$wf->parentTree[] = $modx->documentIdentifier;

if (
$wf->debug) {
    
$wf->debugOutput .= '<p>Starting Menu from Docid: ' $wf->id '<br/>';
    
$wf->debugOutput .= 'Docids for \'Here\' class checking: ' implode(', ',$wf->parentTree) . '</p>';
    
$wf->debugOutput .= '<h3>Chunk Checks</h3>';
}

$wf->checkChunks();

if (
$wf->cssTpl || $wf->jsTpl) {
    
$wf->regJsCss();
}

if (
$wf->debug) {
    
$wf->debugOutput .= '<h3>Document Processing</h3>';
}

$output $wf->buildMenu($wf->id);

if (
$wf->debug) {
    
$output $output $wf->debugOutput;
}

if (
$ph) {
    
$modx->setPlaceholder($ph,$output);
} else {
    return 
$output;
}

:-)


« Last Edit: Aug 03, 2006, 03:30 AM by heliotrope » Logged

heliotrope
Coding Team
*
Posts: 2,517


WWW
« Reply #4 on: Aug 03, 2006, 05:20 AM »

Sorry for the approximative english in the previous post, I just woke up.
Hope that make sense.

I keep on testing and can't get the topdoc to work.

here is a screenshot of my tree repository



the snippet call:
[!WayFinder? &startUltimateParent=true   &topDoc=`56` !]

and the result:



As you can see, it brings back all the docs contained in the tree repository and not the content from folder 56

I'm not sure of the aim of topDoc since I can produce the same effect with startId=56

Perhaps I misunderstood something.

:-)


EDIT: about the code posted above, I was thinking that we could achieve the same result by adding to each item a css id made with its id prefixed with doc. The only reason I prefered using TV is for css reading and coding.
« Last Edit: Aug 03, 2006, 05:39 AM by heliotrope » Logged

staed
Jr. Member
*
Posts: 41



« Reply #5 on: Aug 03, 2006, 06:56 AM »

Hi!

I have called WayFinder with both a &parentRowTpl and a &parentClass, but none of them seem to have any effect. Is the parent-features a work in progress or am I out of luck?

I believe WayFinder will be _really_ nice when it's done. Can't wait to start rebuilding the menus of my sites Smiley

Update: The &parentRowTpl works, but the &parentClass does still not appear.
« Last Edit: Aug 03, 2006, 07:06 AM by staed » Logged
kylej
Moderator
*
Posts: 758



WWW
« Reply #6 on: Aug 03, 2006, 09:14 AM »

@heliotrope - thanks for the code update.  I will give it a look over and see about integrating it into the main snippet.

Here is how the startUltimateParent & topDoc are supposed to work.  If you call it like your example, when you are on a page inside of folder 56 you will see a menu that shows all items under doc folder 56.  If you are not in folder 56 it will start from the site root 0.  It acts this way because the currentdocId and the topdoc is passed to the ultimateparent function (same as the snippet).  So if you are inside folder 56 ultimateparent will go up the tree until it hits 56 to find where to start the menu from.  If you are not inside folder 56 it will go up the tree all the way to 0 because it will never find doc 56. 

I hope that makes sense, let me know if it is not functioning this way for you.



@staed - &parentClass only gets set if the following conditions are met:

the item is a folder, a class was specified in the snippet call, and the level of the item is less than the &level parameter.

So if you have a folder and your menu is displaying the items underneath it it should get the class.

If that doesn't clear it up post your snippet call and the parentRowTpl chunk and I will help fix the problem.  Also a screen shot of your manager tree would help as well.
Logged

staed
Jr. Member
*
Posts: 41



« Reply #7 on: Aug 03, 2006, 09:27 AM »

I had &level=`0` (infinite), but then I changed that to 6 and then it worked great! I bet that is a bug and not a feature Smiley

Everything should be considered lower than 0, right?
Logged
kylej
Moderator
*
Posts: 758



WWW
« Reply #8 on: Aug 03, 2006, 09:42 AM »

Can you try taking out the level parameter and see if you get the same result.  Setting it to 0 should get you the full menu tree, it defaults to 0 also.  So you really shouldn't need to set it in the snippet call.
Logged

staed
Jr. Member
*
Posts: 41



« Reply #9 on: Aug 03, 2006, 11:02 AM »

I had it unspecified before I tried with a specific number, and after I specified `0` with the same result as when it was using the default value.
Logged
kylej
Moderator
*
Posts: 758



WWW
« Reply #10 on: Aug 03, 2006, 11:33 AM »

Thats strange, can you post your whole snippet call and a screenshot of what your doc tree looks like.  I can't duplicate the level=`0` not working on my tests and would like to fix any problem with it.

Thanks,
  Kyle
Logged

heliotrope
Coding Team
*
Posts: 2,517


WWW
« Reply #11 on: Aug 03, 2006, 11:55 AM »

Here is how the startUltimateParent & topDoc are supposed to work.  If you call it like your example, when you are on a page inside of folder 56 you will see a menu that shows all items under doc folder 56.  If you are not in folder 56 it will start from the site root 0.  It acts this way because the currentdocId and the topdoc is passed to the ultimateparent function (same as the snippet).  So if you are inside folder 56 ultimateparent will go up the tree until it hits 56 to find where to start the menu from.  If you are not inside folder 56 it will go up the tree all the way to 0 because it will never find doc 56. 

I hope that makes sense, let me know if it is not functioning this way for you.

Still a bit confused but sounds logical.

:-)
Logged

staed
Jr. Member
*
Posts: 41



« Reply #12 on: Aug 03, 2006, 12:03 PM »

Thats strange, can you post your whole snippet call and a screenshot of what your doc tree looks like.  I can't duplicate the level=`0` not working on my tests and would like to fix any problem with it.

Is it easy to read when I have specified almost everything? Smiley

Code:
[!WayFinder? &level=`0` &startId=`581` &outerTpl=`menu_outerTpl` &parentRowTpl=`menu_parentRowTpl` &hereTpl=`menu_hereTpl` &innerTpl=`menu_innerTpl` &innerRowTpl=`menu_innerRowTpl` &innerHereTpl=`menu_innerHereTpl` &firstClass=`first` &lastClass=`last` &hereClass=`here` &parentClass=`parent` &rowClass=`row` &levelClass=`level` &outerClass=`outer` &innerClass=`inner`!]

Mind the language in the shot of the tree structure...

No parent class appears, and it's the same if I remove the level statement completly.


* treefromhell.jpg (240.77 KB, 405x1825 - viewed 999 times.)
Logged
kylej
Moderator
*
Posts: 758



WWW
« Reply #13 on: Aug 03, 2006, 12:37 PM »

Ok, it is an error.  When the level param is set to 0 it will not display the parent class.  I must have overlooked that when I made a previous change to that same class setting.  I will update this and get out a new version.  Thanks for finding that error Smiley
Logged

staed
Jr. Member
*
Posts: 41



« Reply #14 on: Aug 03, 2006, 12:40 PM »

Thanks for finding that error Smiley

You're welcome. Thanks for correcting it Smiley
Logged
Pages: [1] 2 3 ... 18   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP

Copyright © 2005-2008 MODxCMS, All rights reserved. Contact Us
Styles by ziworks.com

Powered by SMF | SMF © 2006-2008, Simple Machines LLC

Valid XHTML 1.0! Valid CSS!