MDL-38309 move HTML generation from print_tabs() to renderer
- created renderable object tabtree that represents the tree of tabs, extends tabobject - created core_renderer::tabtree(), and supporting core_renderer::render_tabtree(), core_renderer::render_tabobject() - change print_tabs() to use renderer function, deprecate supporting not needed functions
This commit is contained in:
@@ -4515,3 +4515,110 @@ function get_courses_wmanagers($categoryid=0, $sort="c.sortorder ASC", $fields=a
|
||||
|
||||
return $courses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a nested array tree into HTML ul:li [recursive]
|
||||
*
|
||||
* @deprecated since 2.5
|
||||
*
|
||||
* @param array $tree A tree array to convert
|
||||
* @param int $row Used in identifying the iteration level and in ul classes
|
||||
* @return string HTML structure
|
||||
*/
|
||||
function convert_tree_to_html($tree, $row=0) {
|
||||
debugging('Function convert_tree_to_html() is deprecated since Moodle 2.5. Consider using class tabtree and core_renderer::render_tabtree()', DEBUG_DEVELOPER);
|
||||
|
||||
$str = "\n".'<ul class="tabrow'.$row.'">'."\n";
|
||||
|
||||
$first = true;
|
||||
$count = count($tree);
|
||||
|
||||
foreach ($tree as $tab) {
|
||||
$count--; // countdown to zero
|
||||
|
||||
$liclass = '';
|
||||
|
||||
if ($first && ($count == 0)) { // Just one in the row
|
||||
$liclass = 'first last';
|
||||
$first = false;
|
||||
} else if ($first) {
|
||||
$liclass = 'first';
|
||||
$first = false;
|
||||
} else if ($count == 0) {
|
||||
$liclass = 'last';
|
||||
}
|
||||
|
||||
if ((empty($tab->subtree)) && (!empty($tab->selected))) {
|
||||
$liclass .= (empty($liclass)) ? 'onerow' : ' onerow';
|
||||
}
|
||||
|
||||
if ($tab->inactive || $tab->active || $tab->selected) {
|
||||
if ($tab->selected) {
|
||||
$liclass .= (empty($liclass)) ? 'here selected' : ' here selected';
|
||||
} else if ($tab->active) {
|
||||
$liclass .= (empty($liclass)) ? 'here active' : ' here active';
|
||||
}
|
||||
}
|
||||
|
||||
$str .= (!empty($liclass)) ? '<li class="'.$liclass.'">' : '<li>';
|
||||
|
||||
if ($tab->inactive || $tab->active || ($tab->selected && !$tab->linkedwhenselected)) {
|
||||
// The a tag is used for styling
|
||||
$str .= '<a class="nolink"><span>'.$tab->text.'</span></a>';
|
||||
} else {
|
||||
$str .= '<a href="'.$tab->link.'" title="'.$tab->title.'"><span>'.$tab->text.'</span></a>';
|
||||
}
|
||||
|
||||
if (!empty($tab->subtree)) {
|
||||
$str .= convert_tree_to_html($tab->subtree, $row+1);
|
||||
} else if ($tab->selected) {
|
||||
$str .= '<div class="tabrow'.($row+1).' empty"> </div>'."\n";
|
||||
}
|
||||
|
||||
$str .= ' </li>'."\n";
|
||||
}
|
||||
$str .= '</ul>'."\n";
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert nested tabrows to a nested array
|
||||
*
|
||||
* @deprecated since 2.5
|
||||
*
|
||||
* @param array $tabrows A [nested] array of tab row objects
|
||||
* @param string $selected The tabrow to select (by id)
|
||||
* @param array $inactive An array of tabrow id's to make inactive
|
||||
* @param array $activated An array of tabrow id's to make active
|
||||
* @return array The nested array
|
||||
*/
|
||||
function convert_tabrows_to_tree($tabrows, $selected, $inactive, $activated) {
|
||||
|
||||
debugging('Function convert_tabrows_to_tree() is deprecated since Moodle 2.5. Consider using class tabtree', DEBUG_DEVELOPER);
|
||||
/// Work backwards through the rows (bottom to top) collecting the tree as we go.
|
||||
|
||||
$tabrows = array_reverse($tabrows);
|
||||
|
||||
$subtree = array();
|
||||
|
||||
foreach ($tabrows as $row) {
|
||||
$tree = array();
|
||||
|
||||
foreach ($row as $tab) {
|
||||
$tab->inactive = in_array((string)$tab->id, $inactive);
|
||||
$tab->active = in_array((string)$tab->id, $activated);
|
||||
$tab->selected = (string)$tab->id == $selected;
|
||||
|
||||
if ($tab->active || $tab->selected) {
|
||||
if ($subtree) {
|
||||
$tab->subtree = $subtree;
|
||||
}
|
||||
}
|
||||
$tree[] = $tab;
|
||||
}
|
||||
$subtree = $tree;
|
||||
}
|
||||
|
||||
return $subtree;
|
||||
}
|
||||
|
||||
@@ -2857,3 +2857,155 @@ class custom_menu extends custom_menu_item {
|
||||
return ($itema > $itemb) ? +1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores one tab
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @package core
|
||||
*/
|
||||
class tabobject implements renderable {
|
||||
/** @var string unique id of the tab in this tree, it is used to find selected and/or inactive tabs */
|
||||
var $id;
|
||||
/** @var moodle_url|string link */
|
||||
var $link;
|
||||
/** @var string text on the tab */
|
||||
var $text;
|
||||
/** @var string title under the link, by defaul equals to text */
|
||||
var $title;
|
||||
/** @var bool whether to display a link under the tab name when it's selected */
|
||||
var $linkedwhenselected = false;
|
||||
/** @var bool whether the tab is inactive */
|
||||
var $inactive = false;
|
||||
/** @var bool indicates that this tab's child is selected */
|
||||
var $activated = false;
|
||||
/** @var bool indicates that this tab is selected */
|
||||
var $selected = false;
|
||||
/** @var array stores children tabobjects */
|
||||
var $subtree = array();
|
||||
/** @var int level of tab in the tree, 0 for root (instance of tabtree), 1 for the first row of tabs */
|
||||
var $level = 1;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $id unique id of the tab in this tree, it is used to find selected and/or inactive tabs
|
||||
* @param string|moodle_url $link
|
||||
* @param string $text text on the tab
|
||||
* @param string $title title under the link, by defaul equals to text
|
||||
* @param bool $linkedwhenselected whether to display a link under the tab name when it's selected
|
||||
*/
|
||||
public function __construct($id, $link = null, $text = '', $title = '', $linkedwhenselected = false) {
|
||||
$this->id = $id;
|
||||
$this->link = $link;
|
||||
$this->text = $text;
|
||||
$this->title = $title ? $title : $text;
|
||||
$this->linkedwhenselected = $linkedwhenselected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Travels through tree and finds the tab to mark as selected, all parents are automatically marked as activated
|
||||
*
|
||||
* @param string $selected the id of the selected tab (whatever row it's on),
|
||||
* if null marks all tabs as unselected
|
||||
* @return bool whether this tab is selected or contains selected tab in its subtree
|
||||
*/
|
||||
protected function set_selected($selected) {
|
||||
if ((string)$selected === (string)$this->id) {
|
||||
$this->selected = true;
|
||||
// This tab is selected. No need to travel through subtree.
|
||||
return true;
|
||||
}
|
||||
foreach ($this->subtree as $subitem) {
|
||||
if ($subitem->set_selected($selected)) {
|
||||
// This tab has child that is selected. Mark it as activated. No need to check other children.
|
||||
$this->activated = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Travels through tree and finds a tab with specified id
|
||||
*
|
||||
* @param string $id
|
||||
* @return tabtree|null
|
||||
*/
|
||||
public function find($id) {
|
||||
if ((string)$this->id === (string)$id) {
|
||||
return $this;
|
||||
}
|
||||
foreach ($this->subtree as $tab) {
|
||||
if ($obj = $tab->find($id)) {
|
||||
return $obj;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to mark each tab's level in the tree before rendering.
|
||||
*
|
||||
* @param int $level
|
||||
*/
|
||||
protected function set_level($level) {
|
||||
$this->level = $level;
|
||||
foreach ($this->subtree as $tab) {
|
||||
$tab->set_level($level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores tabs list
|
||||
*
|
||||
* Example how to print a single line tabs:
|
||||
* $rows = array(
|
||||
* new tabobject(...),
|
||||
* new tabobject(...)
|
||||
* );
|
||||
* echo $OUTPUT->tabtree($rows, $selectedid);
|
||||
*
|
||||
* Multiple row tabs may not look good on some devices but if you want to use them
|
||||
* you can specify ->subtree for the active tabobject.
|
||||
*
|
||||
* @copyright 2013 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @since Moodle 2.5
|
||||
* @package core
|
||||
* @category output
|
||||
*/
|
||||
class tabtree extends tabobject {
|
||||
/**
|
||||
* Constuctor
|
||||
*
|
||||
* It is highly recommended to call constructor when list of tabs is already
|
||||
* populated, this way you ensure that selected and inactive tabs are located
|
||||
* and attribute level is set correctly.
|
||||
*
|
||||
* @param array $tabs array of tabs, each of them may have it's own ->subtree
|
||||
* @param string|null $selected which tab to mark as selected, all parent tabs will
|
||||
* automatically be marked as activated
|
||||
* @param array|string|null $inactive list of ids of inactive tabs, regardless of
|
||||
* their level. Note that you can as weel specify tabobject::$inactive for separate instances
|
||||
*/
|
||||
public function __construct($tabs, $selected = null, $inactive = null) {
|
||||
$this->subtree = $tabs;
|
||||
if ($selected !== null) {
|
||||
$this->set_selected($selected);
|
||||
}
|
||||
if ($inactive !== null) {
|
||||
if (is_array($inactive)) {
|
||||
foreach ($inactive as $id) {
|
||||
if ($tab = $this->find($id)) {
|
||||
$tab->inactive = true;
|
||||
}
|
||||
}
|
||||
} else if ($tab = $this->find($inactive)) {
|
||||
$tab->inactive = true;
|
||||
}
|
||||
}
|
||||
$this->set_level(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2882,6 +2882,107 @@ EOD;
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders tabs
|
||||
*
|
||||
* This function replaces print_tabs() used before Moodle 2.5 but with slightly different arguments
|
||||
*
|
||||
* @param array $tabs array of tabs, each of them may have it's own ->subtree
|
||||
* @param string|null $selected which tab to mark as selected, all parent tabs will
|
||||
* automatically be marked as activated
|
||||
* @param array|string|null $inactive list of ids of inactive tabs, regardless of
|
||||
* their level. Note that you can as weel specify tabobject::$inactive for separate instances
|
||||
* @return string
|
||||
*/
|
||||
public function tabtree($tabs, $selected = null, $inactive = null) {
|
||||
return $this->render(new tabtree($tabs, $selected, $inactive));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders tabtree
|
||||
*
|
||||
* @param tabtree $tabtree
|
||||
* @return string
|
||||
*/
|
||||
protected function render_tabtree(tabtree $tabtree) {
|
||||
if (empty($tabtree->subtree)) {
|
||||
return '';
|
||||
}
|
||||
$str = '';
|
||||
$str .= html_writer::start_tag('div', array('class' => 'tabtree'));
|
||||
$str .= $this->render_tabobject($tabtree);
|
||||
$str .= html_writer::end_tag('div').
|
||||
html_writer::tag('div', ' ', array('class' => 'clearer'));
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders tabobject (part of tabtree)
|
||||
*
|
||||
* This function is called from {@link core_renderer::render_tabtree()}
|
||||
* and also it calls itself when printing the $tabobject subtree recursively.
|
||||
*
|
||||
* Property $tabobject->level indicates the number of row of tabs.
|
||||
*
|
||||
* @param tabobject $tabobject
|
||||
* @return string HTML fragment
|
||||
*/
|
||||
protected function render_tabobject(tabobject $tabobject) {
|
||||
$str = '';
|
||||
|
||||
// Print name of the current tab.
|
||||
if ($tabobject instanceof tabtree) {
|
||||
// No name for tabtree root.
|
||||
} else if ($tabobject->inactive || $tabobject->activated || ($tabobject->selected && !$tabobject->linkedwhenselected)) {
|
||||
// Tab name without a link. The <a> tag is used for styling.
|
||||
$str .= html_writer::tag('a', html_writer::span($tabobject->text), array('class' => 'nolink'));
|
||||
} else {
|
||||
// Tab name with a link.
|
||||
if (!($tabobject->link instanceof moodle_url)) {
|
||||
// backward compartibility when link was passed as quoted string
|
||||
$str .= "<a href=\"$tabobject->link\" title=\"$tabobject->title\"><span>$tabobject->text</span></a>";
|
||||
} else {
|
||||
$str .= html_writer::link($tabobject->link, html_writer::span($tabobject->text), array('title' => $tabobject->title));
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($tabobject->subtree)) {
|
||||
if ($tabobject->selected) {
|
||||
$str .= html_writer::tag('div', ' ', array('class' => 'tabrow'. ($tabobject->level + 1). ' empty'));
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
// Print subtree
|
||||
$str .= html_writer::start_tag('ul', array('class' => 'tabrow'. $tabobject->level));
|
||||
$cnt = 0;
|
||||
foreach ($tabobject->subtree as $tab) {
|
||||
$liclass = '';
|
||||
if (!$cnt) {
|
||||
$liclass .= ' first';
|
||||
}
|
||||
if ($cnt == count($tabobject->subtree) - 1) {
|
||||
$liclass .= ' last';
|
||||
}
|
||||
if ((empty($tab->subtree)) && (!empty($tab->selected))) {
|
||||
$liclass .= ' onerow';
|
||||
}
|
||||
|
||||
if ($tab->selected) {
|
||||
$liclass .= ' here selected';
|
||||
} else if ($tab->activated) {
|
||||
$liclass .= ' here active';
|
||||
}
|
||||
|
||||
// This will recursively call function render_tabobject() for each item in subtree
|
||||
$str .= html_writer::tag('li', $this->render($tab), array('class' => trim($liclass)));
|
||||
$cnt++;
|
||||
}
|
||||
$str .= html_writer::end_tag('ul');
|
||||
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+26
-156
@@ -2670,185 +2670,55 @@ function print_maintenance_message() {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for tabs, Some code to print tabs
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @package moodlecore
|
||||
*/
|
||||
class tabobject {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
var $id;
|
||||
var $link;
|
||||
var $text;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
var $linkedwhenselected;
|
||||
|
||||
/**
|
||||
* A constructor just because I like constructors
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $link
|
||||
* @param string $text
|
||||
* @param string $title
|
||||
* @param bool $linkedwhenselected
|
||||
*/
|
||||
function tabobject ($id, $link='', $text='', $title='', $linkedwhenselected=false) {
|
||||
$this->id = $id;
|
||||
$this->link = $link;
|
||||
$this->text = $text;
|
||||
$this->title = $title ? $title : $text;
|
||||
$this->linkedwhenselected = $linkedwhenselected;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string containing a nested list, suitable for formatting into tabs with CSS.
|
||||
*
|
||||
* @global object
|
||||
* It is not recommended to use this function in Moodle 2.5 but it is left for backward
|
||||
* compartibility.
|
||||
*
|
||||
* Example how to print a single line tabs:
|
||||
* $rows = array(
|
||||
* new tabobject(...),
|
||||
* new tabobject(...)
|
||||
* );
|
||||
* echo $OUTPUT->tabtree($rows, $selectedid);
|
||||
*
|
||||
* Multiple row tabs may not look good on some devices but if you want to use them
|
||||
* you can specify ->subtree for the active tabobject.
|
||||
*
|
||||
* @param array $tabrows An array of rows where each row is an array of tab objects
|
||||
* @param string $selected The id of the selected tab (whatever row it's on)
|
||||
* @param array $inactive An array of ids of inactive tabs that are not selectable.
|
||||
* @param array $activated An array of ids of other tabs that are currently activated
|
||||
* @param bool $return If true output is returned rather then echo'd
|
||||
**/
|
||||
function print_tabs($tabrows, $selected=NULL, $inactive=NULL, $activated=NULL, $return=false) {
|
||||
global $CFG;
|
||||
|
||||
/// $inactive must be an array
|
||||
if (!is_array($inactive)) {
|
||||
$inactive = array();
|
||||
}
|
||||
|
||||
/// $activated must be an array
|
||||
if (!is_array($activated)) {
|
||||
$activated = array();
|
||||
}
|
||||
|
||||
/// Convert the tab rows into a tree that's easier to process
|
||||
if (!$tree = convert_tabrows_to_tree($tabrows, $selected, $inactive, $activated)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Print out the current tree of tabs (this function is recursive)
|
||||
|
||||
$output = convert_tree_to_html($tree);
|
||||
|
||||
$output = "\n\n".'<div class="tabtree">'.$output.'</div><div class="clearer"> </div>'."\n\n";
|
||||
|
||||
/// We're done!
|
||||
|
||||
if ($return) {
|
||||
return $output;
|
||||
}
|
||||
echo $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a nested array tree into HTML ul:li [recursive]
|
||||
*
|
||||
* @param array $tree A tree array to convert
|
||||
* @param int $row Used in identifying the iteration level and in ul classes
|
||||
* @return string HTML structure
|
||||
*/
|
||||
function convert_tree_to_html($tree, $row=0) {
|
||||
|
||||
$str = "\n".'<ul class="tabrow'.$row.'">'."\n";
|
||||
|
||||
$first = true;
|
||||
$count = count($tree);
|
||||
|
||||
foreach ($tree as $tab) {
|
||||
$count--; // countdown to zero
|
||||
|
||||
$liclass = '';
|
||||
|
||||
if ($first && ($count == 0)) { // Just one in the row
|
||||
$liclass = 'first last';
|
||||
$first = false;
|
||||
} else if ($first) {
|
||||
$liclass = 'first';
|
||||
$first = false;
|
||||
} else if ($count == 0) {
|
||||
$liclass = 'last';
|
||||
}
|
||||
|
||||
if ((empty($tab->subtree)) && (!empty($tab->selected))) {
|
||||
$liclass .= (empty($liclass)) ? 'onerow' : ' onerow';
|
||||
}
|
||||
|
||||
if ($tab->inactive || $tab->active || $tab->selected) {
|
||||
if ($tab->selected) {
|
||||
$liclass .= (empty($liclass)) ? 'here selected' : ' here selected';
|
||||
} else if ($tab->active) {
|
||||
$liclass .= (empty($liclass)) ? 'here active' : ' here active';
|
||||
}
|
||||
}
|
||||
|
||||
$str .= (!empty($liclass)) ? '<li class="'.$liclass.'">' : '<li>';
|
||||
|
||||
if ($tab->inactive || $tab->active || ($tab->selected && !$tab->linkedwhenselected)) {
|
||||
// The a tag is used for styling
|
||||
$str .= '<a class="nolink"><span>'.$tab->text.'</span></a>';
|
||||
} else {
|
||||
$str .= '<a href="'.$tab->link.'" title="'.$tab->title.'"><span>'.$tab->text.'</span></a>';
|
||||
}
|
||||
|
||||
if (!empty($tab->subtree)) {
|
||||
$str .= convert_tree_to_html($tab->subtree, $row+1);
|
||||
} else if ($tab->selected) {
|
||||
$str .= '<div class="tabrow'.($row+1).' empty"> </div>'."\n";
|
||||
}
|
||||
|
||||
$str .= ' </li>'."\n";
|
||||
}
|
||||
$str .= '</ul>'."\n";
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert nested tabrows to a nested array
|
||||
*
|
||||
* @param array $tabrows A [nested] array of tab row objects
|
||||
* @param string $selected The tabrow to select (by id)
|
||||
* @param array $inactive An array of tabrow id's to make inactive
|
||||
* @param array $activated An array of tabrow id's to make active
|
||||
* @return array The nested array
|
||||
*/
|
||||
function convert_tabrows_to_tree($tabrows, $selected, $inactive, $activated) {
|
||||
|
||||
/// Work backwards through the rows (bottom to top) collecting the tree as we go.
|
||||
function print_tabs($tabrows, $selected = null, $inactive = null, $activated = null, $return = false) {
|
||||
global $OUTPUT;
|
||||
|
||||
$tabrows = array_reverse($tabrows);
|
||||
|
||||
$subtree = array();
|
||||
|
||||
foreach ($tabrows as $row) {
|
||||
$tree = array();
|
||||
|
||||
foreach ($row as $tab) {
|
||||
$tab->inactive = in_array((string)$tab->id, $inactive);
|
||||
$tab->active = in_array((string)$tab->id, $activated);
|
||||
$tab->inactive = is_array($inactive) && in_array((string)$tab->id, $inactive);
|
||||
$tab->activated = is_array($activated) && in_array((string)$tab->id, $activated);
|
||||
$tab->selected = (string)$tab->id == $selected;
|
||||
|
||||
if ($tab->active || $tab->selected) {
|
||||
if ($subtree) {
|
||||
$tab->subtree = $subtree;
|
||||
}
|
||||
if ($tab->activated || $tab->selected) {
|
||||
$tab->subtree = $subtree;
|
||||
}
|
||||
$tree[] = $tab;
|
||||
}
|
||||
$subtree = $tree;
|
||||
}
|
||||
|
||||
return $subtree;
|
||||
$output = $OUTPUT->tabtree($subtree);
|
||||
if ($return) {
|
||||
return $output;
|
||||
} else {
|
||||
print $output;
|
||||
return !empty($output);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user