I was looking at the code and just don't get how to add a custom CSS class to ul tag?
<?php if (!empty($this->row->amenities)): ?>
<h3><?php echo JText::_('COM_JEA_AMENITIES')?> :</h3>
<?php echo JHtml::_('amenities.bindList', $this->row->amenities, 'ul') ?>
<?php endif ?>
Which generates:
<h3>Amenities</h3>
<ul>
<li></li>
<li></li>
<li></li>
etc.
</ul>
I need:
<h3>Amenities</h3>
<ul class="check">
<li></li>
<li></li>
<li></li>
etc.
</ul>
I'm sure, it should be something simple.
The Source of the function is -
static public function bindList($value=0, $format='raw')
{
if (is_string($value) && !empty($value)) {
$ids = explode('-' , $value);
} elseif (empty($value)) {
$ids = array();
} else {
JArrayHelper::toInteger($value);
$ids = $value;
}
$html = '';
$amenities = self::getAmenities();
$items = array();
foreach ($amenities as $row) {
if (in_array($row->id, $ids)) {
if ($format == 'ul'){
$items[] = "<li>{$row->value}</li>\n";
} else {
$items[] = $row->value;
}
}
}
if ($format == 'ul'){
$html = "<ul>\n" . implode("\n", $items) . "</ul>\n";
} else {
$html = implode(', ', $items);
}
return $html;
}
As per the source of the function the way I can see is to replace '<ul>' to '<ul class="check">'
<?php
$html = JHtml::_('amenities.bindList', $this->row->amenities, 'ul');
echo str_replace('<ul>','<ul class="check">',$html);
?>
Or you can call getAmenities function and loop through result and create your own ul and li.
Hope this helps.
Related
Using FuelPHP, I was wondering how to add attributes on li tags for the ul method ul($list, $style = false).
https://fuelphp.com/docs/classes/html.html
Here is what I want to achieve
<ul id="sortable">
<li id="red">red</li>
<li id="blue">blue</li>
</ul>
Here is what I tried but no luck
public static function get_ads_order_ul(){
$items =array(array('id'=>'red','value'=>'red'),array('id'=>'blue','value'=>'blue'));
$attr = array('id' => 'sortable');
return Html::ul($items, $attr);
}
I ended up adding new function in /fuel/core/classes/html.php object.
$items = array('red'=>array('id'=>'red'),'blue'=>array('id'=>'blue'),'green'=> null);
$attr = array('id' => 'sortable');
# The function 'ul_custom' calls 'build_list_custom' instead of 'build_list'
return Html::ul_custom($items, $attr);
protected static function build_list_custom($type = 'ul', array $list = array(), $attr = false, $indent = '')
{
if ( ! is_array($list))
{
$result = false;
}
$out = '';
foreach ($list as $key => $li_attr)
{
$out .= $indent."\t".html_tag('li', $li_attr, $key).PHP_EOL;
}
$result = $indent.html_tag($type, $attr, PHP_EOL.$out.$indent).PHP_EOL;
return $result;
}
result
<ul id="sortable" class="ui-sortable">
<li id="red">red</li>
<li id="blue">blue</li>
<li>green</li>
</ul>
This class is designed to iterate over a WordPress menu structure (nested arrays/objects) to produce a finished menu. While the source of my data is WordPress, I feel this question belongs on SO instead of WP.SO because the issue is rooted more in PHP (applies to anyone attempting a recursion).
For some reason, I'm seeing duplicate results in the hierarchy. Also, I'm noticing that certain HTML elements are not closing properly. It seems like I've nested everything properly, but the result is what you see here.
To assist with debugging, I've added some * to impact the markup visually. Maybe you guys know something I don't. Fingers crossed and thanks in advance for your input!
My class
class Nav_Menu
{
public $wp_nav;
public $nested_nav;
public $recursion_depth = 0;
function __construct( $menu, $args = array() )
{
$format = new Format;
if( $menu )
{
$this->wp_nav = wp_get_nav_menu_items($menu, $args);
$this->nested_nav = $this->build_tree($this->wp_nav);
$output = $this->build_output($this->nested_nav);
$output_formatted = $format->HTML($output);
// echo $output;
echo $output_formatted;
}
}
private function build_output( $menu = array() )
{
$output = '**';
$output.= $this->recurse_menu($menu, $output);
return $output;
}
private function recurse_menu( $menu = array(), $output )
{
global $post;
if( !empty($menu) && !empty($output) )
{
$this->recursion_depth++;
// ul classes
$classes_ul = array();
$classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
$classes_ul[] = 'depth-' . $this->recursion_depth;
// process list wrappers
$output.= '<ul class="' . $this->process_classes($classes_ul) . '">';
// loop through menu items
foreach( $menu as $menu_key => $menu_val )
{
// process list items
$output.= '<li>' . $menu_val->title;
// if necessary, handle children and recurse
if( !empty($menu_val->children) )
{
// recurse, and call this again
$output.= $this->recurse_menu($menu_val->children, $output);
}
// process list items
$output.= '</li>';
}
// process list wrappers
$output.= '</ul>';
}
return $output;
}
private function process_classes($classes = array())
{
if( !$classes )
{
return;
}
return trim(implode(' ', $classes));
}
private function build_tree( $elements = array(), $parent_id = 0 )
{
$branch = array();
foreach($elements as $element)
{
if ($element->menu_item_parent == $parent_id)
{
$children = $this->build_tree($elements, $element->ID);
if ($children)
{
$element->children = $children;
}
$branch[] = $element;
}
}
return $branch;
}
}
$mynav = new Nav_Menu('Test Menu');
The resulting output
****
<ul class="depth-1">
<li>
One**
<ul class="depth-1">
<li>
One
<ul class="sub-menu depth-2">
<li>
Sub One
</li>
<li>
Sub Two
</li>
<li>
Sub Three
</li>
</ul>
</li>
<li>
Two
</li>
<li>
Three**
<ul class="depth-1">
<li>
One**
<ul class="depth-1">
<li>
One
<ul class="sub-menu depth-2">
<li>
Sub One
</li>
<li>
Sub Two
</li>
<li>
Sub Three
</li>
</ul>
</li>
<li>
Two
</li>
<li>
Three
<ul class="sub-menu depth-3">
<li>
Sub One
</li>
<li>
Sub Two
</li>
</ul>
</li>
<li>
Four
</li>
</ul>
WordPress menu in the backend
If someone knows the reason why, I'd be willing to know, so I'll reserve choosing an answer for now. My guess is some kind of odd namespacing/scope issue for the variable $output. Who knows, I'm kinda tired right now.
The fix to get a legit structure was this...
Class
class Nav_Menu
{
public $wp_nav;
public $nested_nav;
public $recursion_depth = 0;
public $output = '';
function __construct( $menu, $args = array() )
{
$format = new Format;
if( $menu )
{
$this->wp_nav = wp_get_nav_menu_items($menu, $args);
$this->nested_nav = $this->build_tree($this->wp_nav);
$this->build_output($this->nested_nav);
$output_formatted = $format->HTML($this->output);
// echo $this->output;
echo $output_formatted;
}
}
private function build_output( $menu = array() )
{
$this->recurse_menu($menu);
}
private function recurse_menu( $menu = array() )
{
global $post;
if( !empty($menu) )
{
$this->recursion_depth++;
// ul classes
$classes_ul = array();
$classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
$classes_ul[] = 'depth-' . $this->recursion_depth;
// process list wrappers
$this->output.= '<ul class="' . $this->process_classes($classes_ul) . '">';
// loop through menu items
foreach( $menu as $menu_key => $menu_val )
{
// process list items
$this->output.= '<li>';
$this->output.= $menu_val->title;
// if necessary, handle children and recurse
if( !empty($menu_val->children) )
{
// recurse, and call this again
$this->recurse_menu($menu_val->children);
}
// process list items
$this->output.= '</li>';
}
// process list wrappers
$this->output.= '</ul>';
}
}
private function process_classes($classes = array())
{
if( !$classes )
{
return;
}
return trim(implode(' ', $classes));
}
private function build_tree( $elements = array(), $parent_id = 0 )
{
$branch = array();
foreach($elements as $element)
{
if ($element->menu_item_parent == $parent_id)
{
$children = $this->build_tree($elements, $element->ID);
if ($children)
{
$element->children = $children;
}
$branch[] = $element;
}
}
return $branch;
}
}
$mynav = new Nav_Menu('Test Menu'); exit;
Resulting output
<ul class="depth-1">
<li>
One
<ul class="sub-menu depth-2">
<li>
Sub One
</li>
<li>
Sub Two
</li>
<li>
Sub Three
</li>
</ul>
</li>
<li>
Two
</li>
<li>
Three
<ul class="sub-menu depth-3">
<li>
Sub One
</li>
<li>
Sub Two
</li>
</ul>
</li>
<li>
Four
</li>
</ul>
I just created a private variable for the class, and each time I need to reference it as a storage location, I just append to it. Same as before, but no more having to pass $output down some crazy method chain.
If anyone has any other ideas that could help the community, please share!
Update your build_output method as below:
private function build_output( $menu = array() )
{
$output = '<ul>';
$output = $this->recurse_menu($menu, $output);
$output.= '</ul>';
return $output;
}
Update your recurse_menu method as below:
private function recurse_menu( $menu = array(), $output = '')
{
global $post;
if( !empty($menu))
{
$this->recursion_depth++;
// ul classes
$classes_ul = array();
$classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
$classes_ul[] = 'depth-' . $this->recursion_depth;
// loop through menu items
foreach( $menu as $menu_key => $menu_val )
{
// if necessary, handle children and recurse
if( !empty($menu_val->children) )
{
// recurse, and call this again
$output.= '<li>'.$menu_val->title.'<ul class="' . $this->process_classes($classes_ul) . '">'.$this->recurse_menu($menu_val->children).'</ul></li>';
}
else {
$output.= '<li>'.$menu_val->title.'</li>';
}
}
}
return $output;
}
NOTE: I have tested it with more further sub-level and it is working fine.
I want to need to make a menu where i don't know how deep the menu will be.
this is how my database table looks like:
table menu fields id, parent_id, name
i already tryed this to get a nice array back, but it dont work:
public function get()
{
$nodeList = array();
$tree = array();
$query = $this->db->get('menu');
$result = $query->result_array();
foreach ($result as $row) {
$nodeList[$row['id']] = array_merge($row, array('children' => array()));
}
foreach ($nodeList as $nodeId => &$node) {
if (!$node['parent'] || !array_key_exists($node['parent'], $nodeList)) {
$tree[] =& $node;
} else {
$nodeList[$node['parent']]['children'][] =& $node;
}
}
return $nodeList;
}
eventually I want to achieve this(a nice looking menu):
<ul>
<li><a href="">Apple<a/>
<ul>
<li>Iphone</li>
<ul>
<li>4S</li>
<li>5</li>
</ul>
<li>Ipad</li>
<ul>
<li>4</li>
<li>5</li>
</ul>
</ul>
</li>
<li><a href="">Samsung<a/>
<ul>
<li>Galaxy</li>
<ul>
<li>S3</li>
<li>S4</li>
</ul>
</ul>
</li>
I hope you understand my question and can help me. i REALLYY!! need this.
thanks ;)
Your get() should probably return $tree, not $nodeList. Other than that, it seems perfectly fine.
Update. This example shows how to build HTML for nested menu:
function getUl($nodes)
{
$result = "<ul>\n";
foreach ($nodes as $n) {
$result .= '<li>...';
if (!empty($n['children'])) {
$result .= getUl($n['children']);
}
$result .= "</li>\n";
}
$result .= "\n</ul>";
return $result;
}
I have written a function for a multilevel wordpress menu, but I'd like it to work for any number of levels, at the moment it is written to work for 3 levels.
//only gets the top level items
$top_level_pages = get_pages('parent=0&sort_column=menu_order&exclude=129,2,13');
foreach($top_level_pages as $page){
//print_r($top_level_pages);
$p_id = $page->ID;
// gets all pages and subpages in one array
$children = get_pages("child_of=$p_id&sort_column=menu_order");
$immediate_children = get_pages("child_of=$p_id&parent=$p_id&sort_column=menu_order");
//print_r($immediate_children);
if($children) {
print '<li class="page_item page-item-'.$page->ID.'"><span class="first-level">'.$page->post_title;
print '</span><ul>';
foreach($immediate_children as $child){
$c_id = $child->ID;
//gets a preformatted menu
$grandchildren = wp_list_pages('depth=1&echo=0&parent='.$c_id.'&sort_column=menu_order&title_li=');
if($grandchildren) {
print '<li class="page_item page-item-'.$child->ID.'"><span class="second-level">'.$child->post_title;
print '</span><ul>';
print $grandchildren;
print '</ul></li>';
}
else {
print '<li class="page_item page-item-'.$child->ID.'">'.$child->post_title.'</li>';
}
}
print '</ul></li>';
}
else {
print '<li class="page_item page-item-'.$page->ID.'">'.$page->post_title.'</li>';
}
}
All we need to do to make your function recursive is move most of the loop into a recursive function:
<?php
//only gets the top level items
$top_level_pages = get_pages('parent=0&sort_column=menu_order&exclude=129,2,13');
foreach($top_level_pages as $page) {
//print_r($top_level_pages);
$p_id = $page->ID;
recursiveFunction($p_id);
}
function recursiveFunction($p_id){
$children = get_pages("child_of=$p_id&sort_column=menu_order");
$immediate_children = get_pages("child_of=$p_id&parent=$p_id&sort_column=menu_order");
//print_r($immediate_children);
if($children) {
print '<li class="page_item page-item-'.$page->ID.'"><span class="first-level">'.$page->post_title;
print '</span><ul>';
foreach($immediate_children as $child) {
recursiveFunction($child->ID);
}
print '</ul></li>';
}
else {
print '<li class="page_item page-item-'.$page->ID.'">'.$page->post_title.'</li>';
}
}
?>
The hard part is making the "first-level", "second-level" stuff work. I'd just change it "level-1", "level-2", etc. And then you can just start with $x = 1; and pass $x+1 each time you call the function recursively.
Something like this should probably do the trik (written in the stackoverflow textbox and untested).
function listChildren($parentID, &$menu)
{
static $options = 'parent=0&sort_column=menu_order&exclude=129,2,13';
static $level = 1;
foreach(get_pages(sprintf('child_of=%d&%s', $parentID, $options ) as $page)
{
$menu .= sprintf('<li class="level-%d">%s',
$level
get_page_link($page->ID),
$page->post_title);
if ($page->hasChildrenOrWhateverWPUses())
{
$level ++;
$menu .= sprintf('<ul class="menu-level-%d">', $level);
listChildren($page->ID, $menu);
$menu .= '</ul>';
$level --;
}
$menu .="</li>"
}
}
used like:
$menu = '<ul class="menu-tree">';
listChildren($rootPageID, $menu);
$menu .= '</ul>';
echo $menu;
I've got a result set from adLDAP of the form
OU=LEAF1,OU=PARENT1,OU=ROOT,DC=datacenter,DC=local
OU=PARENT1,OU=ROOT,DC=datacenter,DC=local
OU=ROOT,DC=datacenter,DC=local
OU=LEAF2,OU=CHILD,OU=PARENT2,OU=ROOT,DC=datacenter,DC=local
OU=CHILD,OU=PARENT2,OU=ROOT,DC=datacenter,DC=local
OU=PARENT2,OU=ROOT,DC=datacenter,DC=local
Where each line is a string element in an array.
The tree structure it represents is :
Root
|--Parent1
|--Leaf1
|--Parent2
|--Child
|--Leaf2
and I want to generate this
<ul>
<li>root
<ul>
<li>Parent1
<ul>
<li>leaf1</li>
</ul>
</li>
<li>Parent2
<ul>
<li>Child
<ul>
<li>Leaf2</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
</ul>
I know I need to process the strings backwards, and I know the solution is recursive, but it's friday afternoon, it's a long time since I've done it and my brain is stuck.
Here is my attempt:
<?php
$lines = array(
'OU=LEAF1,OU=PARENT1,OU=ROOT,DC=datacenter,DC=local',
'OU=PARENT1,OU=ROOT,DC=datacenter,DC=local',
'OU=ROOT,DC=datacenter,DC=local',
'OU=LEAF2,OU=CHILD,OU=PARENT2,OU=ROOT,DC=datacenter,DC=local',
'OU=CHILD,OU=PARENT2,OU=ROOT,DC=datacenter,DC=local',
'OU=PARENT2,OU=ROOT,DC=datacenter,DC=local',
);
//build tree structure
$tree = array();
foreach ($lines as $line) {
$ancestry = getLineAncestry($line);
$node = & $tree;
foreach ($ancestry as $nodeName) {
if (! isset($node[$nodeName])) {
$node[$nodeName] = array();
}
$node = & $node[$nodeName];
}
}
print makeUl($tree);
//recurse through tree to build unordered-list
function makeUl($array) {
$result = '<ul>';
foreach ($array as $nodeName => $children) {
$result .= '<li>' . ucfirst($nodeName);
if (count($children)) {
$result .= makeUl($children);
}
$result .= '</li>';
}
$result .= '</ul>';
return $result;
}
function getLineAncestry($line) {
$result = array();
$params = explode(',', $line);
foreach ($params as $param) {
$tmp = explode('=', $param);
if ($tmp[0] == 'OU') {
$result[] = $tmp[1];
}
}
$result = array_reverse($result);
return $result;
}