]> git.mjollnir.org Git - moodle.git/commitdiff
navigation MDL-20558 Fixed AJAX bug with multiple navigation trees concerning ajax...
authorsamhemelryk <samhemelryk>
Wed, 14 Oct 2009 09:08:43 +0000 (09:08 +0000)
committersamhemelryk <samhemelryk>
Wed, 14 Oct 2009 09:08:43 +0000 (09:08 +0000)
lib/ajax/getnavbranch.php
lib/javascript-navigation.js
lib/navigationlib.php

index 8be709a76e403474376b18effea0b34895fa278a..dd57c0f6ae82042bdfe703388c46aa3c55d3ee9f 100644 (file)
@@ -49,7 +49,7 @@ if ($instanceid!==null) {
     // Get the db record for the block instance
     $blockrecords = $DB->get_record('block_instances', array('id'=>$instanceid,'blockname'=>'global_navigation_tree'));
     if ($blockrecords!=false) {
-        // Instantiate a block_instance object so we can access congif
+            // Instantiate a block_instance object so we can access congif
         $block = block_instance('global_navigation_tree', $blockrecords);
         // Check if the expansion limit config option has been set and isn't the default [everything]
         if (!empty($block->config->expansionlimit) && $block->config->expansionlimit > '0') {
@@ -65,10 +65,12 @@ if ($instanceid!==null) {
 
 // Create a navigation object to use, we can't guarantee PAGE will be complete
 $expandable = $navigation->initialise($branchtype, $branchid);
+$converter = new navigation_xml();
 
 if ($toggledisplay) {
     // Toggle display of item types we dont' want to display
     $navigation->toggle_type_display($navigation->expansionlimit);
+    $converter->set_expansionceiling($navigation->expansionlimit);
 }
 // Find the actuall branch we are looking for
 $branch = $navigation->find_child($branchid, $branchtype);
@@ -87,7 +89,6 @@ if (empty($branch) || $branch->nodetype !== navigation_node::NODETYPE_BRANCH) {
 }
 
 // Prepare an XML converter for the branch
-$converter = new navigation_xml();
 $converter->set_expandable($expandable);
 // Set XML headers
 header('Content-type: text/xml');
index d16f0658d299c153c26843ec34eb683ecd4cc7b8..59c591d5a68b0874d7f20d2248e0c94ed253031b 100644 (file)
@@ -43,6 +43,7 @@ YAHOO.namespace('moodle.navigation.treecollection');
 YAHOO.moodle.navigation.sideblockwidth = null;
 YAHOO.moodle.navigation.tabpanel = null;
 YAHOO.moodle.navigation.treecollection = Array();
+YAHOO.moodle.navigation.expandablebranchcount = 0;
 
 /**
  * Navigation Tree object (function) used to control a global navigation tree
@@ -108,6 +109,7 @@ navigation_tree.prototype.initialise = function() {
         try {
             this.expansions[i].element = document.getElementById(this.expansions[i].id);
             YAHOO.util.Event.addListener(this.expansions[i].id, 'click', this.init_load_ajax, this.expansions[i], this);
+            YAHOO.moodle.navigation.expandablebranchcount++;
         } catch (err) {
             this.errorlog += "attaching ajax load events: \t"+err+"\n";
         }
@@ -242,7 +244,7 @@ navigation_tree.prototype.load_ajax = function(outcome) {
  * @return {bool}
  */
 navigation_tree.prototype.add_branch = function(branchxml, target, depth) {
-    var branch = new navigation_tree_branch();
+    var branch = new navigation_tree_branch(this.name);
     branch.load_from_xml_node(branchxml);
     if (depth>1) {
         target = branch.inject_into_dom(target,this);
@@ -694,7 +696,8 @@ navigation_tab_panel.prototype.remove_from_tab_panel = function(tabname) {
  * @class navigation_tree_branch
  * @constructor
  */
-function navigation_tree_branch() {
+function navigation_tree_branch(treename) {
+    this.treename = treename;
     this.myname = null;
     this.mytitle = null;
     this.myclass = null;
@@ -704,6 +707,7 @@ function navigation_tree_branch() {
     this.mylink = null;
     this.myicon = null;
     this.myexpandable = null;
+    this.expansionceiling = null;
     this.myhidden = false;
     this.haschildren = false;
     this.mychildren = false;
@@ -722,8 +726,15 @@ navigation_tree_branch.prototype.load_from_xml_node = function (branch) {
     this.mykey = branch.getAttribute('key');
     this.mytype = branch.getAttribute('type');
     this.myexpandable = branch.getAttribute('expandable');
+    this.expansionceiling = branch.getAttribute('expansionceiling');
     this.myhidden = (branch.getAttribute('hidden')=='true');
     this.haschildren = (branch.getAttribute('haschildren')=='true');
+
+    if (this.myid && this.myid.match(/^expandable_branch_\d+$/)) {
+        YAHOO.moodle.navigation.expandablebranchcount++;
+        this.myid = 'expandable_branch_'+YAHOO.moodle.navigation.expandablebranchcount;
+    }
+
     for (var i=0; i<branch.childNodes.length;i++) {
         var node = branch.childNodes[i];
         switch (node.nodeName.toLowerCase()) {
@@ -746,7 +757,7 @@ navigation_tree_branch.prototype.inject_into_dom = function (element, gntinstanc
     var branchli = document.createElement('li');
     var branchp = document.createElement('p');
     YAHOO.util.Dom.addClass(branchp, 'tree_item');
-    if (this.myexpandable !==null || this.haschildren) {
+    if ((this.myexpandable !==null || this.haschildren) && this.expansionceiling===null) {
         YAHOO.util.Dom.addClass(branchp, 'branch');
         YAHOO.util.Dom.addClass(branchli, 'collapsed');
         YAHOO.util.Event.addListener(branchp, 'click', gntinstance.toggleexpansion, this, gntinstance);
index 5a711a74e21f58e84ec2804639b9e014542d2843..a128204f43ccaeb6798a44c2462aa3db58e02748 100644 (file)
@@ -527,6 +527,28 @@ class navigation_node {
         return $depth;
     }
 
+    /**
+     * Finds all nodes (recursivily) that have the specified type, regardless of
+     * assumed order or position.
+     *
+     * @param int $type One of navigation_node::TYPE_*
+     * @return array An array of navigation_node references for nodes of type $type
+     */
+    public function find_children_by_type($type) {
+        $nodes = array();
+        if (count($this->children)>0) {
+            foreach ($this->children as &$child) {
+                if ($child->type === $type) {
+                    $nodes[] = $child;
+                }
+                if (count($child->children)>0) {
+                    $nodes = array_merge($nodes, $child->find_children_by_type($type));
+                }
+            }
+        }
+        return $nodes;
+    }
+
     /**
      * Toogles display of nodes and child nodes based on type
      *
@@ -571,19 +593,21 @@ class navigation_node {
      *
      * @param array $expandable An array to fill with the HTML id's of all branches
      * that can be expanded by AJAX. This is a forced reference.
+     * @param int $expansionlimit Optional/used internally can be one of navigation_node::TYPE_*
      */
-    public function find_expandable(&$expandable) {
+    public function find_expandable(&$expandable, $expansionlimit = null) {
         static $branchcount;
         if ($branchcount==null) {
             $branchcount=1;
         }
-        if ($this->nodetype == self::NODETYPE_BRANCH && count($this->children)==0) {
+        if ($this->nodetype == self::NODETYPE_BRANCH && count($this->children)==0 && ($expansionlimit === null || $this->type < $expansionlimit)) {
             $this->id = 'expandable_branch_'.$branchcount;
+            $this->add_class('canexpand');
             $branchcount++;
             $expandable[] = array('id'=>$this->id,'branchid'=>$this->key,'type'=>$this->type);
-        } else if ($this->nodetype==self::NODETYPE_BRANCH) {
+        } else if ($this->nodetype==self::NODETYPE_BRANCH && ($expansionlimit === null || $this->type <= $expansionlimit)) {
             foreach ($this->children as $child) {
-                $child->find_expandable($expandable);
+                $child->find_expandable($expandable, $expansionlimit);
             }
         }
     }
@@ -1559,7 +1583,7 @@ class global_navigation extends navigation_node {
         foreach ($courses as $course) {
             // If a category id has been specified and the current course is not within
             // that category or one of its children then skip this course
-            if ($categoryid!==0 && !preg_match('#/('.$categoryid.')(\/|$)#', $course->categorypath)) {
+            if ($categoryid!==0 && !preg_match('#/('.$categoryid.')(/|$)#', $course->categorypath)) {
                 continue;
             }
             $categorypathids = explode('/',trim($course->categorypath,' /'));
@@ -1588,7 +1612,7 @@ class global_navigation extends navigation_node {
             }
             // Add the courses that were retrieved earlier to the
             $this->add_courses($courses);
-        } else {
+        } else if ($categoryid === 0) {
             $keys = array();
             if ($categoryid!=0) {
                 if (!$this->cache->cached('category'.$categoryid)) {
@@ -1617,6 +1641,44 @@ class global_navigation extends navigation_node {
     public function clear_cache() {
         $this->cache->volatile();
     }
+
+    /**
+     * Finds all expandable nodes whilst ensuring that expansion limit is respected
+     *
+     * @param array $expandable A reference to an array that will be populated as
+     * we go.
+     */
+    public function find_expandable(&$expandable) {
+        parent::find_expandable($expandable, $this->expansionlimit);
+    }
+
+    /**
+     * Loads categories that contain no courses into the structure.
+     *
+     * These categories would normally be skipped, as such this function is purely
+     * for the benefit of code external to navigationlib
+     */
+    public function load_empty_categories() {
+        $categories = array();
+        $categorynames = array();
+        $categoryparents = array();
+        make_categories_list($categorynames, $categoryparents, '', 0, $category = NULL);
+        foreach ($categorynames as $id=>$name) {
+            if (!$this->find_child($id, self::TYPE_CATEGORY)) {
+                $category = new stdClass;
+                $category->id = $id;
+                if (array_key_exists($id, $categoryparents)) {
+                    $category->path = '/'.join('/',array_merge($categoryparents[$id],array($id)));
+                    $name = explode('/', $name);
+                    $category->name = join('/', array_splice($name, count($categoryparents[$id])));
+                } else {
+                    $category->path = '/'.$id;
+                    $category->name = $name;
+                }
+                $this->add_category_by_path($category);
+            }
+        }
+    }
 }
 
 /**
@@ -1681,10 +1743,10 @@ class limited_global_navigation extends global_navigation {
      * @param int $instanceid
      */
     protected function load_category($instanceid) {
-        if (!$this->cache->cached('coursecontext'.$instanceid)) {
-            $this->cache->{'coursecontext'.$instanceid} = get_context_instance(CONTEXT_COURSE, $instanceid);
+        if (!$this->cache->cached('coursecatcontext'.$instanceid)) {
+            $this->cache->{'coursecatcontext'.$instanceid} = get_context_instance(CONTEXT_COURSECAT, $instanceid);
         }
-        $this->context = $this->cache->{'coursecontext'.$instanceid};
+        $this->context = $this->cache->{'coursecatcontext'.$instanceid};
         $this->load_categories($instanceid);
     }
 
@@ -3080,6 +3142,8 @@ class navigation_xml {
     protected $nodetype = array('node','branch');
     /** @var array */
     protected $expandable = array();
+    /** @var int */
+    protected $expansionceiling = array();
     /**
      * Turns a branch and all of its children into XML
      *
@@ -3099,6 +3163,15 @@ class navigation_xml {
             $this->expandable[(string)$node['branchid']] = $node;
         }
     }
+    /**
+     * Sets the upper limit for expandable nodes. Any nodes that are of the specified
+     * type or larger will not be expandable
+     *
+     * @param int $expansionceiling One of navigation_node::TYPE_*
+     */
+    public function set_expansionceiling($expansionceiling) {
+        $tihs->expansionceiling = $expansionceiling;
+    }
     /**
      * Recusively converts a child node and its children to XML for output
      *
@@ -3123,7 +3196,10 @@ class navigation_xml {
         if (array_key_exists((string)$child->key, $this->expandable)) {
             $attributes['expandable'] = $child->key;
             $child->add_class($this->expandable[$child->key]['id']);
+        } else if ($child->type >= $this->expansionceiling) {
+            $attributes['expansionceiling'] = $child->key;
         }
+
         if (count($child->classes)>0) {
             $attributes['class'] .= ' '.join(' ',$child->classes);
         }