Dec 04, 2008, 12:21 AM *
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 55602 times)
0 Members and 2 Guests are viewing this topic.
kylej
Moderator
*
Posts: 738



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,447


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: 738



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,447


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'] > 1 && !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)? $topDoc: 0;
    
$wf->id = $wf->ultimateParent($modx->documentIdentifier,$topDoc);
} else {
    
$wf->id = isset($startId)? $startId: $modx->documentIdentifier;
}
$wf->level = isset($level)? $level: 0;
$wf->ph = isset($ph)? $ph: FALSE;
$wf->debug = isset($debug)? TRUE: FALSE;
$wf->ignoreHidden = isset($ignoreHidden)? $ignoreHidden: FALSE;
$wf->hideSubMenus = isset($hideSubMenus)? $hideSubMenus: FALSE;
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,447


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