Index: grade/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/grade/lib.php,v
retrieving revision 1.141
diff -u -r1.141 lib.php
--- grade/lib.php	11 Mar 2008 23:59:55 -0000	1.141
+++ grade/lib.php	4 Apr 2008 09:28:59 -0000
@@ -987,7 +987,7 @@
         }
 
         if ($url) {
-            return '<a href="'.$url.'"><img '.$overlib.' src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'.$stredit.'" title="'.$stredit.'"/></a>';
+            return '<a href="'.$url.'" class="edit"><img '.$overlib.' src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'.$stredit.'" title="'.$stredit.'"/></a>';
 
         } else {
             return '';
@@ -1022,13 +1022,13 @@
             $url     = $CFG->wwwroot.'/grade/edit/tree/action.php?id='.$this->courseid.'&amp;action=show&amp;sesskey='.sesskey()
                      . '&amp;eid='.$element['eid'];
             $url     = $gpr->add_url_params($url);
-            $action  = '<a href="'.$url.'"><img alt="'.$strshow.'" src="'.$CFG->pixpath.'/t/'.$icon.'.gif" class="iconsmall" title="'.$tooltip.'"/></a>';
+            $action  = '<a href="'.$url.'" class="hide"><img alt="'.$strshow.'" src="'.$CFG->pixpath.'/t/'.$icon.'.gif" class="iconsmall" title="'.$tooltip.'"/></a>';
 
         } else {
             $url     = $CFG->wwwroot.'/grade/edit/tree/action.php?id='.$this->courseid.'&amp;action=hide&amp;sesskey='.sesskey()
                      . '&amp;eid='.$element['eid'];
             $url     = $gpr->add_url_params($url);
-            $action  = '<a href="'.$url.'"><img src="'.$CFG->pixpath.'/t/hide.gif" class="iconsmall" alt="'.$strhide.'" title="'.$strhide.'"/></a>';
+            $action  = '<a href="'.$url.'" class="hide"><img src="'.$CFG->pixpath.'/t/hide.gif" class="iconsmall" alt="'.$strhide.'" title="'.$strhide.'"/></a>';
         }
         return $action;
     }
@@ -1066,7 +1066,7 @@
             $url     = $CFG->wwwroot.'/grade/edit/tree/action.php?id='.$this->courseid.'&amp;action=unlock&amp;sesskey='.sesskey()
                      . '&amp;eid='.$element['eid'];
             $url     = $gpr->add_url_params($url);
-            $action  = '<a href="'.$url.'"><img src="'.$CFG->pixpath.'/t/'.$icon.'.gif" alt="'.$strunlock.'" class="iconsmall" title="'.$tooltip.'"/></a>';
+            $action  = '<a href="'.$url.'" class="lock"><img src="'.$CFG->pixpath.'/t/'.$icon.'.gif" alt="'.$strunlock.'" class="iconsmall" title="'.$tooltip.'"/></a>';
 
         } else {
             if (!has_capability('moodle/grade:manage', $this->context) and !has_capability('moodle/grade:lock', $this->context)) {
@@ -1075,7 +1075,7 @@
             $url     = $CFG->wwwroot.'/grade/edit/tree/action.php?id='.$this->courseid.'&amp;action=lock&amp;sesskey='.sesskey()
                      . '&amp;eid='.$element['eid'];
             $url     = $gpr->add_url_params($url);
-            $action  = '<a href="'.$url.'"><img src="'.$CFG->pixpath.'/t/lock.gif" class="iconsmall" alt="'.$strlock.'" title="'
+            $action  = '<a href="'.$url.'" class="lock"><img src="'.$CFG->pixpath.'/t/lock.gif" class="iconsmall" alt="'.$strlock.'" title="'
                      . $strlock.'"/></a>';
         }
         return $action;
@@ -1111,7 +1111,7 @@
                 }
                 $url = $CFG->wwwroot.'/grade/edit/tree/calculation.php?courseid='.$this->courseid.'&amp;id='.$object->id;
                 $url = $gpr->add_url_params($url);
-                $calculation_icon = '<a href="'. $url.'"><img src="'.$CFG->pixpath.'/t/'.$icon.'" class="iconsmall" alt="'
+                $calculation_icon = '<a href="'. $url.'" class="calculation"><img src="'.$CFG->pixpath.'/t/'.$icon.'" class="iconsmall" alt="'
                                        . $streditcalculation.'" title="'.$streditcalculation.'" /></a>'. "\n";
             }
         }
Index: grade/edit/tree/action.php
===================================================================
RCS file: /cvsroot/moodle/moodle/grade/edit/tree/action.php,v
retrieving revision 1.6
diff -u -r1.6 action.php
--- grade/edit/tree/action.php	4 Apr 2008 02:54:28 -0000	1.6
+++ grade/edit/tree/action.php	4 Apr 2008 09:28:59 -0000
@@ -23,12 +23,14 @@
 //                                                                       //
 ///////////////////////////////////////////////////////////////////////////
 
-require_once '../../../config.php';
-require_once $CFG->dirroot.'/grade/lib.php';
+require_once('../../../config.php');
+require_once($CFG->dirroot.'/grade/lib.php');
+require_once($CFG->dirroot.'/grade/edit/tree/lib.php');
 
 $courseid = required_param('id', PARAM_INT);
 $action   = required_param('action', PARAM_ALPHA);
 $eid      = required_param('eid', PARAM_ALPHANUM);
+$ajax     = optional_param('ajax', false, PARAM_BOOL);
 
 /// Make sure they can even access this course
 if (!$course = get_record('course', 'id', $courseid)) {
@@ -40,6 +42,7 @@
 // default return url
 $gpr = new grade_plugin_return();
 $returnurl = $gpr->get_return_url($CFG->wwwroot.'/grade/edit/tree/index.php?id='.$course->id);
+$switch = grade_get_setting($courseid, 'aggregationposition', $CFG->grade_aggregationposition);
 
 // get the grading tree object
 $gtree = new grade_tree($courseid, false, false);
@@ -102,7 +105,12 @@
         break;
 }
 
-redirect($returnurl);
-//redirect($returnurl, 'debug delay', 5);
+if ($ajax) {
+    $gtree = new grade_tree($courseid, false, false);
+    print_grade_tree($gtree, $gtree->top_element, false, $gpr, $switch);
+} else {
+    redirect($returnurl);
+    //redirect($returnurl, 'debug delay', 5);
+}
 
 ?>
Index: grade/edit/tree/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/grade/edit/tree/index.php,v
retrieving revision 1.18
diff -u -r1.18 index.php
--- grade/edit/tree/index.php	4 Apr 2008 02:54:28 -0000	1.18
+++ grade/edit/tree/index.php	4 Apr 2008 09:28:59 -0000
@@ -23,9 +23,11 @@
 //                                                                       //
 ///////////////////////////////////////////////////////////////////////////
 
-require_once '../../../config.php';
-require_once $CFG->dirroot.'/grade/lib.php';
-require_once $CFG->dirroot.'/grade/report/lib.php'; // for preferences
+require_once('../../../config.php');
+require_once($CFG->dirroot.'/grade/edit/tree/lib.php');
+require_once($CFG->dirroot.'/grade/lib.php');
+require_once($CFG->dirroot.'/grade/report/lib.php'); // for preferences
+require_once($CFG->libdir.'/ajax/ajaxlib.php');
 
 $courseid = required_param('id', PARAM_INT);
 $action   = optional_param('action', 0, PARAM_ALPHA);
@@ -46,8 +48,31 @@
 $gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'tree', 'courseid'=>$courseid));
 $returnurl = $gpr->get_return_url(null);
 
+$bodytags = '';
+
 //first make sure we have proper final grades - we need it for locking changes
 grade_regrade_final_grades($courseid);
+if (ajaxenabled()) {
+    require_js(array('yui_yahoo',
+                     'yui_dom',
+                     'yui_event',
+                     'yui_dragdrop',
+                     'yui_connection'));
+    
+    if (debugging('', DEBUG_DEVELOPER)) {
+        require_js(array('yui_logger'));
+
+        $bodytags = 'onload = "javascript:
+        show_logger = function() {
+            var logreader = new YAHOO.widget.LogReader();
+            logreader.newestOnTop = false;
+            logreader.setTitle(\'Moodle Debug: YUI Log Console\');
+        };
+        show_logger();
+        "';
+    }
+
+}
 
 // get the grading tree object
 // note: total must be first for moving to work correctly, if you want it last moving code must be rewritten!
@@ -135,7 +160,7 @@
         break;
 }
 
-print_header_simple($strgrades . ': ' . $strgraderreport, ': ' . $strcategoriesedit, $navigation, '', '', true, '', navmenu($course));
+print_header_simple($strgrades . ': ' . $strgraderreport, ': ' . $strcategoriesedit, $navigation, '', '', true, '', navmenu($course), false, $bodytags);
 
 /// Print the plugin selector at the top
 print_grade_plugin_selector($courseid, 'edit', 'tree');
@@ -150,6 +175,55 @@
 print_box_end();
 
 echo '<div class="buttons">';
+
+echo '<script type="text/javascript">
+//<![CDATA[
+
+    // Custom event listener on the grade_tree <ul>: will listen for click action on icons in its children
+    function gradeTreeEditClickHandler(e) {
+        // Defining these in the function for clean namespace
+        var grade_tree = document.getElementById("grade_tree");
+
+        var actionSuccess = function(o) {
+            YAHOO.log("Replacing grade_tree list...", "info");
+            grade_tree.innerHTML = o.responseText;
+        }
+
+        var actionFailure = function(o) {
+            YAHOO.log("Error perform action: \nStatus: " + o.status + "\nStatus text: " + o.statusText, "error");
+        }
+
+        var actionCallback = {
+            success:actionSuccess,
+            failure:actionFailure
+        }
+        
+        // TODO check safety of sUrl
+        function action(sUrl) {
+            request = YAHOO.util.Connect.asyncRequest("GET", sUrl, actionCallback, null);
+            YAHOO.log("Calling " + sUrl, "info", "example"); 
+        }
+        
+        var elTarget = YAHOO.util.Event.getTarget(e);
+        
+        YAHOO.log(elTarget.nodeName + " clicked!", "info");
+
+        if (elTarget.nodeName.toUpperCase() == "IMG") {
+            elTarget = elTarget.parentNode;
+            if (elTarget.nodeName.toUpperCase() == "A") {
+                // Must be hide or lock
+                if (YAHOO.util.Dom.hasClass(elTarget, "hide") || YAHOO.util.Dom.hasClass(elTarget, "lock")) {
+                    YAHOO.util.Event.preventDefault(e);
+                    action(elTarget.href + "&ajax=true");
+                }
+            }
+        } 
+    }
+
+    YAHOO.util.Event.on("grade_tree", "click", gradeTreeEditClickHandler);
+    //]]>
+</script>';
+
 if ($moving) {
     print_single_button('index.php', array('id'=>$course->id), get_string('cancel'), 'get');
 } else {
@@ -164,112 +238,4 @@
 echo '</div>';
 print_footer($course);
 die;
-
-/**
- * TODO document
- */
-function print_grade_tree(&$gtree, $element, $moving, &$gpr, $switch, $switchedlast=false) {
-    global $CFG, $COURSE;
-
-/// fetch needed strings
-    $strmove     = get_string('move');
-    $strmovehere = get_string('movehere');
-    $strdelete   = get_string('delete');
-
-    $object = $element['object'];
-    $eid    = $element['eid'];
-
-    $header = $gtree->get_element_header($element, true, true, true);
-
-    if ($object->is_hidden()) {
-        $header = '<span class="dimmed_text">'.$header.'</span>';
-    }
-
-/// prepare actions
-    $actions = $gtree->get_edit_icon($element, $gpr);
-    $actions .= $gtree->get_calculation_icon($element, $gpr);
-
-    if ($element['type'] == 'item' or ($element['type'] == 'category' and $element['depth'] > 1)) {
-        if (element_deletable($element)) {
-            $actions .= '<a href="index.php?id='.$COURSE->id.'&amp;action=delete&amp;eid='
-                     . $eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'
-                     . $strdelete.'" title="'.$strdelete.'"/></a>';
-        }
-        $actions .= '<a href="index.php?id='.$COURSE->id.'&amp;action=moveselect&amp;eid='
-                 . $eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/move.gif" class="iconsmall" alt="'
-                 . $strmove.'" title="'.$strmove.'"/></a>';
-    }
-
-    $actions .= $gtree->get_hiding_icon($element, $gpr);
-    $actions .= $gtree->get_locking_icon($element, $gpr);
-
-/// prepare move target if needed
-    $last = '';
-    $catcourseitem = ($element['type'] == 'courseitem' or $element['type'] == 'categoryitem');
-    $moveto = '';
-    if ($moving) {
-        $actions = ''; // no action icons when moving
-        $moveto = '<li><a href="index.php?id='.$COURSE->id.'&amp;action=move&amp;eid='.$moving.'&amp;moveafter='
-                . $eid.'&amp;sesskey='.sesskey().'"><img class="movetarget" src="'.$CFG->wwwroot.'/pix/movehere.gif" alt="'
-                . $strmovehere.'" title="'.$strmovehere.'" /></a></li>';
-    }
-
-/// print the list items now
-    if ($moving == $eid) {
-        // do not diplay children
-        echo '<li class="'.$element['type'].' moving">'.$header.'('.get_string('move').')</li>';
-
-    } else if ($element['type'] != 'category') {
-        if ($catcourseitem and $switch) {
-            if ($switchedlast) {
-                echo '<li class="'.$element['type'].'">'.$header.$actions.'</li>';
-            } else {
-                echo $moveto;
-            }
-        } else {
-            echo '<li class="'.$element['type'].'">'.$header.$actions.'</li>'.$moveto;
-        }
-
-    } else {
-        echo '<li class="'.$element['type'].'">'.$header.$actions;
-        echo '<ul class="catlevel'.$element['depth'].'">';
-        $last = null;
-        foreach($element['children'] as $child_el) {
-            if ($switch and empty($last)) {
-                $last = $child_el;
-            }
-            print_grade_tree($gtree, $child_el, $moving, $gpr, $switch);
-        }
-        if ($last) {
-            print_grade_tree($gtree, $last, $moving, $gpr, $switch, true);
-        }
-        echo '</ul></li>';
-        if ($element['depth'] > 1) {
-            echo $moveto; // can not move after the top category
-        }
-    }
-}
-
-function element_deletable($element) {
-    global $COURSE;
-
-    if ($element['type'] != 'item') {
-        return true;
-    }
-
-    $grade_item = $element['object'];
-    
-    if ($grade_item->itemtype != 'mod' or $grade_item->is_outcome_item() or $grade_item->gradetype == GRADE_TYPE_NONE) {
-        return true;
-    }
-
-    $modinfo = get_fast_modinfo($COURSE);
-    if (!isset($modinfo->instances[$grade_item->itemmodule][$grade_item->iteminstance])) {
-        // module does not exist
-        return true;
-    }
-
-    return false;
-}
-
 ?>
Index: grade/edit/tree/lib.php
===================================================================
RCS file: grade/edit/tree/lib.php
diff -N grade/edit/tree/lib.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/tree/lib.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,142 @@
+<?php  // $Id: index.php,v 1.17 2008/02/17 19:12:11 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Prints a tree view of the grade categories and items with action icons.
+ * Recursive function.
+ *
+ * @param object $gtree The grade tree object being recursed.
+ * @param array  $element The "root" element of the current recursion
+ * @param string $moving The id of the element being moved, or false if none
+ * @param object $gpr grade_plugin_return object (use its get_return_url() method)
+ * @param int    $switch The position (first or last) of the aggregations
+ * @param bool   $switchedlast
+ * 
+ * @return bool $element
+ */
+function print_grade_tree(&$gtree, $element, $moving, &$gpr, $switch, $switchedlast=false) {
+    global $CFG, $COURSE;
+
+/// fetch needed strings
+    $strmove     = get_string('move');
+    $strmovehere = get_string('movehere');
+    $strdelete   = get_string('delete');
+
+    $object = $element['object'];
+    $eid    = $element['eid'];
+
+    $header = $gtree->get_element_header($element, true, true, true);
+
+    if ($object->is_hidden()) {
+        $header = '<span class="dimmed_text">'.$header.'</span>';
+    }
+
+/// prepare actions
+    $actions = $gtree->get_edit_icon($element, $gpr);
+    $actions .= $gtree->get_calculation_icon($element, $gpr);
+
+    if ($element['type'] == 'item' or ($element['type'] == 'category' and $element['depth'] > 1)) {
+        if (element_deletable($element)) {
+            $actions .= '<a href="index.php?id='.$COURSE->id.'&amp;action=delete&amp;eid='
+                     . $eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'
+                     . $strdelete.'" title="'.$strdelete.'"/></a>';
+        }
+        $actions .= '<a href="index.php?id='.$COURSE->id.'&amp;action=moveselect&amp;eid='
+                 . $eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/move.gif" class="iconsmall" alt="'
+                 . $strmove.'" title="'.$strmove.'"/></a>';
+    }
+
+    $actions .= $gtree->get_hiding_icon($element, $gpr);
+    $actions .= $gtree->get_locking_icon($element, $gpr);
+
+/// prepare move target if needed
+    $last = '';
+    $catcourseitem = ($element['type'] == 'courseitem' or $element['type'] == 'categoryitem');
+    $moveto = '';
+    if ($moving) {
+        $actions = ''; // no action icons when moving
+        $moveto = '<li><a href="index.php?id='.$COURSE->id.'&amp;action=move&amp;eid='.$moving.'&amp;moveafter='
+                . $eid.'&amp;sesskey='.sesskey().'"><img class="movetarget" src="'.$CFG->wwwroot.'/pix/movehere.gif" alt="'
+                . $strmovehere.'" title="'.$strmovehere.'" /></a></li>';
+    }
+
+/// print the list items now
+    if ($moving == $eid) {
+        // do not diplay children
+        echo '<li class="'.$element['type'].' moving">'.$header.'('.get_string('move').')</li>';
+
+    } else if ($element['type'] != 'category') {
+        if ($catcourseitem and $switch) {
+            if ($switchedlast) {
+                echo '<li class="'.$element['type'].'">'.$header.$actions.'</li>';
+            } else {
+                echo $moveto;
+            }
+        } else {
+            echo '<li class="'.$element['type'].'">'.$header.$actions.'</li>'.$moveto;
+        }
+
+    } else {
+        echo '<li class="'.$element['type'].'">'.$header.$actions;
+        echo '<ul class="catlevel'.$element['depth'].'">';
+        $last = null;
+        foreach($element['children'] as $child_el) {
+            if ($switch and empty($last)) {
+                $last = $child_el;
+            }
+            print_grade_tree($gtree, $child_el, $moving, $gpr, $switch);
+        }
+        if ($last) {
+            print_grade_tree($gtree, $last, $moving, $gpr, $switch, true);
+        }
+        echo '</ul></li>';
+        if ($element['depth'] > 1) {
+            echo $moveto; // can not move after the top category
+        }
+    }
+}
+
+function element_deletable($element) {
+    global $COURSE;
+
+    if ($element['type'] != 'item') {
+        return true;
+    }
+
+    $grade_item = $element['object'];
+    
+    if ($grade_item->itemtype != 'mod' or $grade_item->is_outcome_item() or $grade_item->gradetype == GRADE_TYPE_NONE) {
+        return true;
+    }
+
+    $modinfo = get_fast_modinfo($COURSE);
+    if (!isset($modinfo->instances[$grade_item->itemmodule][$grade_item->iteminstance])) {
+        // module does not exist
+        return true;
+    }
+
+    return false;
+}
+?>
