Commit 3406acde authored by Sam Hemelryk's avatar Sam Hemelryk
Browse files

navigation MDL-22044 Major navigation structure changes.

Navigation has now been re-ordered in accordance with http://docs.moodle.org/en/Development:Navigation_2.0_structure.
This has led to several changes in the way in which navigation is generated included API changes, most notably using the
navigation_nodes add method now returns the newly added node rather than the key.
At the same time the global_navigation_tree block has been renamed to navigation and settings_navigation_tree to settings.
parent 1cbdc5a3
......@@ -336,7 +336,7 @@ M.core_dock = {
}
}
var moveto = this.Y.Node.create('<input type="image" class="moveto customcommand requiresjs" src="'+M.util.image_url('t/block_to_dock', 'moodle')+'" alt="'+M.str.block.undockitem+'" title="'+M.str.block.undockitem+'" />');
var moveto = this.Y.Node.create('<input type="image" class="moveto customcommand requiresjs" src="'+M.util.image_url('t/block_to_dock', 'moodle')+'" alt="'+M.str.block.addtodock+'" title="'+M.str.block.addtodock+'" />');
moveto.on('movetodock|click', this.move_to_dock, this, commands);
var blockaction = node.one('.block_action');
......@@ -483,10 +483,13 @@ M.core_dock = {
this.resize_block_space(this.cachedcontentnode);
var commands = this.cachedcontentnode.one('.commands');
commands.all('.hidepanelicon').remove();
commands.all('.moveto').remove();
commands.remove();
if (commands) {
commands.all('.hidepanelicon').remove();
commands.all('.moveto').remove();
commands.remove();
}
this.cachedcontentnode.one('.title').append(commands);
this.cachedcontentnode = null;
M.util.set_user_preference('docked_block_instance_'+this.id, 0);
......@@ -540,13 +543,6 @@ M.core_dock = {
dockitem.addClass('firstdockitem');
}
dockitem.append(dockitemtitle);
if (this.commands.hasChildNodes) {
if (this.contents.ancestor().one('.footer')) {
this.contents.ancestor().one('.footer').appendChild(this.commands);
} else {
this.contents.appendChild(this.commands);
}
}
M.core_dock.append(dockitem);
var position = dockitemtitle.getXY();
......@@ -573,7 +569,9 @@ M.core_dock = {
this.panel.showMaskEvent.subscribe(function(){
this.Y.one(this.panel.mask).setStyle('zIndex', this.cfg.panel.modalzindex);
}, this, true);
this.panel.renderEvent.subscribe(this.resize_panel, this, true);
if (this.commands.hasChildNodes) {
this.panel.setHeader(this.Y.Node.getDOMNode(this.commands));
}
this.panel.setBody(this.Y.Node.getDOMNode(this.contents));
this.panel.render(M.core_dock.node);
this.Y.one(this.panel.body).addClass(this.blockclass);
......@@ -693,10 +691,14 @@ M.core_dock = {
*/
resize_panel : function() {
this.fire('dockeditem:resizestart');
var panelheader = this.Y.one(this.panel.header);
panelheader = (panelheader)?panelheader.get('offsetHeight'):0;
var panelbody = this.Y.one(this.panel.body);
var buffer = this.cfg.buffer;
var screenheight = parseInt(this.Y.get(document.body).get('winHeight'));
var panelheight = parseInt(panelbody.get('offsetHeight'));
var panelheight = parseInt(panelheader + panelbody.get('offsetHeight'));
var paneltop = parseInt(this.panel.cfg.getProperty('y'));
var titletop = parseInt(this.Y.one('#dock_item_'+this.id+'_title').getY());
var scrolltop = window.pageYOffset || document.body.scrollTop || 0;
......@@ -720,7 +722,7 @@ M.core_dock = {
// This makes the panel constrain to the screen's height if the panel is big
if (paneltop <= buffer && ((panelheight+paneltop*2) > screenheight || panelbody.hasClass('oversized_content'))) {
this.panel.cfg.setProperty('height', screenheight-(buffer*3));
panelbody.setStyle('height', (screenheight-(buffer*3)-10)+'px');
panelbody.setStyle('height', (screenheight-panelheader-(buffer*3)-10)+'px');
panelbody.addClass('oversized_content');
}
this.fire('dockeditem:resizecomplete');
......@@ -754,6 +756,7 @@ M.core_dock.genericblock.prototype.fix_title_orientation = M.core_dock.abstrac
* @param {this.Y.Node} title
* @param {this.Y.Node} contents
* @param {this.Y.Node} commands
* @param {string} blockclass
*/
M.core_dock.item = function(Y, uid, title, contents, commands, blockclass){
this.Y = Y;
......
/** JavaScript state rules **/
.jsenabled .block_global_navigation_tree.dock_on_load,
.block_global_navigation_tree .block_tree_box .requiresjs {display:none;}
.jsenabled .block_global_navigation_tree .block_tree_box .requiresjs {display:inline;}
/** General display rules **/
.block_global_navigation_tree .block_tree {margin:5px;padding-left:0px;overflow-x:auto;overflow-y:visible;}
.block_global_navigation_tree .block_tree li {margin:0;list-style: none;}
.block_global_navigation_tree .block_tree li ul {padding-left:16px;margin:0;}
.block_global_navigation_tree .block_tree .tree_item {padding-left: 16px;margin:3px 0px;text-align:left;}
.block_global_navigation_tree .block_tree .tree_item.branch {background-image: url([[pix:t/expanded]]);background-position: center left;background-repeat: no-repeat;}
.block_global_navigation_tree .block_tree .root_node.leaf {padding-left:0px;}
.block_global_navigation_tree .block_tree .current_branch {font-weight:bold;}
.jsenabled .block_global_navigation_tree .block_tree .tree_item.branch {cursor:pointer;}
.jsenabled .block_global_navigation_tree .block_tree .tree_item.emptybranch {background-image: url([[pix:t/collapsed_empty]]);background-position: center left;background-repeat: no-repeat;}
.jsenabled .block_global_navigation_tree .block_tree .collapsed ul {display: none;}
.jsenabled .block_global_navigation_tree .block_tree .collapsed .tree_item.branch {background-image: url([[pix:t/collapsed]]);}
/** Internet explorer specific rules **/
.ie6 .block_global_navigation_tree .block_tree .tree_item {width:100%;}
\ No newline at end of file
......@@ -113,8 +113,6 @@ class block_base {
var $cron = NULL;
static $dockinitialised = false;
/// Class Functions
/**
......@@ -562,7 +560,6 @@ class block_base {
}
function get_required_javascript() {
$this->_initialise_dock();
if ($this->instance_can_be_docked() && !$this->hide_header()) {
$this->page->requires->js_init_call('M.core_dock.init_genericblock', array($this->instance->id));
user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT);
......@@ -735,14 +732,6 @@ class block_base {
return (!empty($CFG->allowblockstodock) && $this->page->theme->enable_dock);
}
public function _initialise_dock() {
global $CFG;
if (!self::$dockinitialised) {
$this->page->requires->strings_for_js(array('addtodock','undockitem','undockall'), 'block');
self::$dockinitialised = true;
}
}
/** @callback callback functions for comments api */
public static function comment_template($options) {
$ret = <<<EOD
......
......@@ -34,7 +34,7 @@
* @copyright 2009 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class block_global_navigation_tree extends block_tree {
class block_navigation extends block_base {
/** @var int */
public static $navcount;
......@@ -79,11 +79,14 @@ class block_global_navigation_tree extends block_tree {
return true;
}
function instance_can_be_docked() {
return (parent::instance_can_be_docked() && (empty($this->config->enabledock) || $this->config->enabledock=='yes'));
}
function get_required_javascript() {
global $CFG;
$this->_initialise_dock();
$this->page->requires->js_module(array('name'=>'core_dock', 'fullpath'=>'/blocks/dock.js', 'requires'=>array('base', 'cookie', 'dom', 'io', 'node', 'event-custom', 'event-mouseenter', 'yui2-container')));
$this->page->requires->js_module(array('name'=>'block_navigation', 'fullpath'=>'/blocks/global_navigation_tree/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse')));
$this->page->requires->js_module(array('name'=>'block_navigation', 'fullpath'=>'/blocks/navigation/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse')));
user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT);
}
......@@ -102,50 +105,29 @@ class block_global_navigation_tree extends block_tree {
// Navcount is used to allow us to have multiple trees although I dont' know why
// you would want to trees the same
block_global_navigation_tree::$navcount++;
block_navigation::$navcount++;
// Check if this block has been docked
if ($this->docked === null) {
$this->docked = get_user_preferences('nav_in_tab_panel_globalnav'.block_global_navigation_tree::$navcount, 0);
$this->docked = get_user_preferences('nav_in_tab_panel_globalnav'.block_navigation::$navcount, 0);
}
// Check if there is a param to change the docked state
if ($this->docked && optional_param('undock', null, PARAM_INT)==$this->instance->id) {
unset_user_preference('nav_in_tab_panel_globalnav'.block_global_navigation_tree::$navcount);
unset_user_preference('nav_in_tab_panel_globalnav'.block_navigation::$navcount);
$url = $this->page->url;
$url->remove_params(array('undock'));
redirect($url);
} else if (!$this->docked && optional_param('dock', null, PARAM_INT)==$this->instance->id) {
set_user_preferences(array('nav_in_tab_panel_globalnav'.block_global_navigation_tree::$navcount=>1));
set_user_preferences(array('nav_in_tab_panel_globalnav'.block_navigation::$navcount=>1));
$url = $this->page->url;
$url->remove_params(array('dock'));
redirect($url);
}
// Set the expansionlimit if one has been set in block config
if (!empty($this->config->expansionlimit) && $this->config->expansionlimit!='0') {
$this->page->navigation->expansionlimit = $this->config->expansionlimit;
}
// Initialise (only actually happens if it hasn't already been done yet
$this->page->navigation->initialise();
// Remove empty branches if the user has selected to
if (empty($this->config->showemptybranches) || $this->config->showemptybranches=='no') {
$this->remove_empty_section_branches();
}
// Load the my courses branch if the user has selected to
if (isset($CFG->navshowcategories) && empty($CFG->navshowcategories)) {
$this->page->navigation->collapse_course_categories();
}
// Load the my courses branch if the user has selected to
if (!empty($this->config->showmycourses) && $this->config->showmycourses=='yes') {
$this->showmycourses();
}
if (!empty($this->config->showmyhistory) && $this->config->showmyhistory=='yes') {
$this->showmyhistory();
}
......@@ -155,16 +137,17 @@ class block_global_navigation_tree extends block_tree {
$this->page->navigation->find_expandable($expandable);
// Initialise the JS tree object
$module = array('name'=>'block_navigation', 'fullpath'=>'/blocks/global_navigation_tree/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse'));
$module = array('name'=>'block_navigation', 'fullpath'=>'/blocks/navigation/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse'));
$arguments = array($this->instance->id, array('expansions'=>$expandable, 'instance'=>$this->instance->id, 'candock'=>$this->instance_can_be_docked()));
$this->page->requires->js_init_call('M.block_navigation.init_add_tree', $arguments, false, $module);
// Grab the items to display
$this->content->items = array($this->page->navigation);
$renderer = $this->page->get_renderer('block_navigation');
$this->content->text = $renderer->navigation_tree($this->page->navigation);
$reloadlink = new moodle_url($this->page->url, array('regenerate'=>'navigation'));
$this->content->footer .= $OUTPUT->action_icon($reloadlink, new pix_icon('t/reload', get_string('reload')), null, array('class'=>'customcommand'));
$this->content->footer .= $OUTPUT->action_icon($reloadlink, new pix_icon('t/reload', get_string('reload')), null, array('class'=>'customcommand reloadnavigation'));
// Set content generated to true so that we know it has been done
$this->contentgenerated = true;
......@@ -294,9 +277,11 @@ class block_global_navigation_tree extends block_tree {
// If we have `more than nothing` in the history display it :D
if ($historycount > 0) {
// Add a branch to hold the users history
$mymoodle = $PAGE->navigation->get('mymoodle', navigation_node::TYPE_CUSTOM);
$mymoodle = $PAGE->navigation->get('profile', navigation_node::TYPE_USER);
$myhistorybranch = $mymoodle->add(get_string('showmyhistorytitle', $this->blockname), null, navigation_node::TYPE_CUSTOM, null, 'myhistory');
$mymoodle->get($myhistorybranch)->children = array_reverse($history);
foreach (array_reverse($history) as $node) {
$myhistorybranch->children->add($node);
}
}
// Cache the history (or update the cached history as it is)
......@@ -304,69 +289,4 @@ class block_global_navigation_tree extends block_tree {
return true;
}
/**
* This function loads the users my courses array into the navigation
*
* @return bool
*/
protected function showmycourses() {
global $USER, $PAGE;
// Create a navigation cache to point at the same node as the main navigation
// cache
$cache = new navigation_cache('navigation');
// If the user isn't logged in or is a guest we don't want to display anything
if (!isloggedin() || isguestuser()) {
return false;
}
// Check the cache to see if we have loaded my courses already
// there is a very good chance that we have
if (!$cache->cached('mycourses')) {
$cache->mycourses = get_my_courses($USER->id);
}
$courses = $cache->mycourses;
// If no courses to display here, return before adding anything
if (!is_array($courses) || count($courses)==0) {
return false;
}
// Add a branch labelled something like My Courses
$mymoodle = $PAGE->navigation->get('mymoodle', navigation_node::TYPE_CUSTOM);
$mycoursesbranch = $mymoodle->add(get_string('mycourses'), null,navigation_node::TYPE_CATEGORY, null, 'mycourses');
$PAGE->navigation->add_courses($courses, 'mycourses');
$mymoodle->get($mycoursesbranch)->type = navigation_node::TYPE_CUSTOM;
return true;
}
/**
* This function searches all branches and removes any empty section branches
* for the global navigation structure. This is usually called by the global
* navigation block based on a block setting
*/
protected function remove_empty_section_branches() {
global $PAGE;
$cache = new navigation_cache('navigation');
$course = &$PAGE->navigation->find_active_node(navigation_node::TYPE_COURSE);
if ($course===false || !$cache->cached('modinfo'.$course->key) || !$cache->cached('coursesections'.$course->key)) {
return 0;
}
$sectionstoremove = array();
$coursesections = $cache->{'coursesections'.$course->key};
$modinfosections = $cache->{'modinfo'.$course->key}->sections;
foreach ($coursesections as $id=>$section) {
if (!array_key_exists($id, $modinfosections)) {
$sectionstoremove[] = $section->id;
}
}
foreach ($course->children as $key=>$node) {
if ($node->type == navigation_node::TYPE_SECTION && in_array($node->key, $sectionstoremove)) {
$course->remove_child($key);
}
}
}
}
......@@ -16,7 +16,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file keeps track of upgrades to the global_navigation_tree block
* This file keeps track of upgrades to the navigation block
*
* Sometimes, changes between versions involve alterations to database structures
* and other major things that may break installations.
......@@ -41,7 +41,7 @@
/**
* As of the implementation of this block and the general navigation code
* in Moodle 2.0 the body of immediate upgrade work for this block and
* settings_navigation_tree is done in core upgrade {@see lib/db/upgrade.php}
* settings is done in core upgrade {@see lib/db/upgrade.php}
*
* There were several reasons that they were put there and not here, both becuase
* the process for the two blocks was very similar and because the upgrade process
......@@ -51,7 +51,7 @@
* @param int $oldversion
* @param object $block
*/
function xmldb_block_global_navigation_tree_upgrade($oldversion, $block) {
function xmldb_block_navigation_upgrade($oldversion, $block) {
// Implemented at 2009082800
return true;
}
\ No newline at end of file
......@@ -31,25 +31,12 @@
* @copyright 2009 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class block_global_navigation_tree_edit_form extends block_edit_form {
class block_navigation_edit_form extends block_edit_form {
protected function specific_definition($mform) {
global $CFG;
$mform->addElement('header', 'configheader', get_string('blocksettings', 'block'));
$options = array();
$options['0'] = get_string('everything', $this->block->blockname);
$options[global_navigation::TYPE_COURSE] = get_string('courses', $this->block->blockname);
$options[global_navigation::TYPE_SECTION] = get_string('coursestructures', $this->block->blockname);
$options[global_navigation::TYPE_ACTIVITY] = get_string('courseactivities', $this->block->blockname);
$mform->addElement('select', 'config_expansionlimit', get_string('expansionlimit', $this->block->blockname), $options);
if (isset($this->block->config->expansionlimit) && $this->block->config->expansionlimit!='0') {
$mform->getElement('config_expansionlimit')->setSelected($this->block->config->expansionlimit);
} else {
$mform->getElement('config_expansionlimit')->setSelected('0');
}
$mform->setType('expansionlimit', PARAM_MULTILANG);
$mods = array('showemptybranches'=>'no','enablesidebarpopout'=>'yes', 'enablehoverexpansion'=>'no', 'showmycourses'=>'yes', 'showmyhistory'=>'no');
$mods = array('enabledock'=>'yes', 'enablehoverexpansion'=>'no', 'showmyhistory'=>'no');
$yesnooptions = array('yes'=>get_string('yes'), 'no'=>get_string('no'));
foreach ($mods as $modname=>$default) {
$mform->addElement('select', 'config_'.$modname, get_string($modname.'desc', $this->block->blockname), $yesnooptions);
......
......@@ -16,22 +16,20 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'block_global_navigation_tree', language 'en', branch 'MOODLE_20_STABLE'
* This file contains language strings used in the global navigation block
*
* @package block_global_navigation_tree
* @since 2.0
* @package blocks
* @copyright 2009 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['courseactivities'] = 'Categories, courses, and course Activities';
$string['everything'] = 'Everything';
$string['courses'] = 'Categories and courses';
$string['coursestructures'] = 'Categories, courses, and course structures';
$string['courseactivities'] = 'Categories, courses, and course Activities';
$string['enablehoverexpansiondesc'] = 'Enable mouseover expansion of this block';
$string['enablesidebarpopoutdesc'] = 'Allow the user to switch the block to a sidbar popout';
$string['everything'] = 'Everything';
$string['expansionlimit'] = 'Generate navigation for the following';
$string['enabledockdesc'] = 'Allow the user to dock this block';
$string['pluginname'] = 'Navigation';
$string['showemptybranchesdesc'] = 'Show empty course section branches';
$string['showmycoursesdesc'] = 'Show my courses in the navigation';
$string['showmyhistorydesc'] = 'Show my history as a branch in the navigation';
$string['showmyhistorytitle'] = 'My history';
......@@ -62,7 +62,7 @@ M.block_navigation = M.block_navigation || {
/**
* @class tree
* @constructor
* @base M.core_dock.abstractblock
* @base M.core_dock.genericblock
* @param {YUI} Y A yui instance to use with the navigation
* @param {string} id The name of the tree
* @param {object} properties Object containing tree properties
......@@ -97,6 +97,12 @@ M.block_navigation.classes.tree = function(Y, id, properties) {
if (node === null) {
return;
}
var reloadicon = node.one('.footer .reloadnavigation');
if (reloadicon) {
reloadicon.remove();
}
// Attach event to toggle expansion
node.all('.tree_item.branch').on('click', this.toggleexpansion , this);
......@@ -115,6 +121,10 @@ M.block_navigation.classes.tree = function(Y, id, properties) {
if (this.candock) {
this.init(Y, node);
}
if (reloadicon) {
node.one('.header .block_action').insert(reloadicon, 0);
}
}
/**
......@@ -207,6 +217,13 @@ M.block_navigation.classes.tree.prototype.add_branch = function(branchobj, targe
M.block_navigation.classes.tree.prototype.toggleexpansion = function(e) {
// First check if they managed to click on the li iteslf, then find the closest
// LI ancestor and use that
if (e.target.get('nodeName').toUpperCase() == 'A') {
// A link has been clicked don't fire any more events just do the default.
e.stopPropagation();
return;
}
if (e.target.get('nodeName').toUpperCase() == 'LI') {
e.target.toggleClass('collapsed');
} else if (e.target.ancestor('LI')) {
......@@ -244,12 +261,18 @@ M.block_navigation.classes.branch = function(tree, obj) {
this.construct_from_json(obj);
}
}
/**
* Populates this branch from a JSON object
* @param {object} obj
*/
M.block_navigation.classes.branch.prototype.construct_from_json = function(obj) {
for (var i in obj) {
this[i] = obj[i];
}
if (this.children) {
if (this.children && this.children.length > 0) {
this.haschildren = true;
} else {
this.children = [];
}
if (this.id && this.id.match(/^expandable_branch_\d+$/)) {
// Assign a new unique id for this new expandable branch
......
<?php
class block_navigation_renderer extends plugin_renderer_base {
public function navigation_tree(global_navigation $navigation) {
$content = $this->navigation_node(array($navigation), array('class'=>'block_tree list'));
if (isset($navigation->id) && !is_numeric($navigation->id) && !empty($content)) {
$content = $this->output->box($content, 'block_tree_box', $navigation->id);
}
return $content;
}
protected function navigation_node($items, $attrs=array()) {
// exit if empty, we don't want an empty ul element
if (count($items)==0) {
return '';
}
// array of nested li elements
$lis = array();
foreach ($items as $item) {
if (!$item->display) {
continue;
}
$content = $item->get_content();
$title = $item->get_title();
if ($item->icon instanceof renderable) {
$icon = $this->output->render($item->icon);
$content = $icon.'&nbsp;'.$content; // use CSS for spacing of icons
}
if ($item->helpbutton !== null) {
$content = trim($item->helpbutton).html_writer::tag('span', $content, array('class'=>'clearhelpbutton'));
}
if ($content === '') {
continue;
}
if ($item->action instanceof action_link) {
//TODO: to be replaced with something else
$link = $item->action;
if ($item->hidden) {
$link->add_class('dimmed');
}
$content = $this->output->render($link);
} else if ($item->action instanceof moodle_url) {
$attributes = array();
if ($title !== '') {
$attributes['title'] = $title;
}
if ($item->hidden) {
$attributes['class'] = 'dimmed_text';
}
$content = html_writer::link($item->action, $content, $attributes);
} else if (is_string($item->action) || empty($item->action)) {
$attributes = array();
if ($title !== '') {
$attributes['title'] = $title;
}
if ($item->hidden) {
$attributes['class'] = 'dimmed_text';
}
$content = html_writer::tag('span', $content, $attributes);
}
// this applies to the li item which contains all child lists too
$liclasses = array($item->get_css_type());
if ($item->has_children() && (!$item->forceopen || $item->collapse)) {
$liclasses[] = 'collapsed';
}
if ($item->isactive === true) {
$liclasses[] = 'current_branch';
}
$liattr = array('class'=>join(' ',$liclasses));
// class attribute on the div item which only contains the item content
$divclasses = array('tree_item');
if ($item->children->count() > 0 || ($item->nodetype == navigation_node::NODETYPE_BRANCH && $item->children->count()==0 && isloggedin())) {
$divclasses[] = 'branch';
} else {
$divclasses[] = 'leaf';
}
if (!empty($item->classes) && count($item->classes)>0) {
$divclasses[] = join(' ', $item->classes);
}
$divattr = array('class'=>join(' ', $divclasses));
if (!empty($item->id)) {
$divattr['id'] = $item->id;
}
$content = html_writer::tag('p', $content, $divattr) . $this->navigation_node($item->children);
if (!empty($item->preceedwithhr) && $item->preceedwithhr===true) {
$content = html_writer::empty_tag('hr') . $content;
}
$content = html_writer::tag('li', $content, $liattr);
$lis[] = $content;
}
return html_writer::tag('ul', implode("\n", $lis), $attrs);
}
}
\ No newline at end of file
/** JavaScript state rules **/
.jsenabled .block_navigation.dock_on_load,
.block_navigation .block_tree_box .requiresjs {display:none;}
.jsenabled .block_navigation .block_tree_box .requiresjs {display:inline;}
/** General display rules **/
.block_navigation .block_tree {margin:5px;padding-left:0px;overflow:visible;}
.block_navigation .block_tree li {margin:0;list-style: none;}
.block_navigation .block_tree li ul {padding-left:16px;margin:0;}
.block_navigation .block_tree .tree_item {padding-left: 16px;margin:3px 0px;text-align:left;}
.block_navigation .block_tree .tree_item.branch {background-image: url([[pix:t/expanded]]);background-position: center left;background-repeat: no-repeat;}