mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 04:22:07 +02:00
course MDL-8369 Front page combo list is now restructured and exandable by JavaScript
This patch also implements a course renderer.
This commit is contained in:
parent
e00a95965e
commit
24e27ac0c1
@ -33,6 +33,8 @@
|
||||
print_error('coursehidden', '', $CFG->wwwroot .'/');
|
||||
}
|
||||
|
||||
$PAGE->set_context($context);
|
||||
$PAGE->set_pagelayout('course');
|
||||
$PAGE->set_url('/course/info.php', array('id' => $course->id));
|
||||
$PAGE->set_title(get_string("summaryof", "", $course->fullname));
|
||||
$PAGE->set_heading('Course info');
|
||||
|
@ -1856,6 +1856,67 @@ function make_categories_list(&$list, &$parents, $requiredcapability = '',
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function generates a structured array of courses and categories.
|
||||
*
|
||||
* The depth of categories is limited by $CFG->maxcategorydepth however there
|
||||
* is no limit on the number of courses!
|
||||
*
|
||||
* Suitable for use with the course renderers course_category_tree method:
|
||||
* $renderer = $PAGE->get_renderer('core','course');
|
||||
* echo $renderer->course_category_tree(get_course_category_tree());
|
||||
*
|
||||
* @global moodle_database $DB
|
||||
* @param int $id
|
||||
* @param int $depth
|
||||
*/
|
||||
function get_course_category_tree($id = 0, $depth = 0) {
|
||||
global $DB;
|
||||
$viewhiddencats = has_capability('moodle/category:viewhiddencategories', get_context_instance(CONTEXT_SYSTEM));
|
||||
$categories = get_child_categories($id);
|
||||
$categoryids = array();
|
||||
foreach ($categories as $key => &$category) {
|
||||
if (!$category->visible && !$viewhiddencats) {
|
||||
unset($categories[$key]);
|
||||
continue;
|
||||
}
|
||||
$categoryids[$category->id] = $category;
|
||||
if (empty($CFG->maxcategorydepth) || $depth <= $CFG->maxcategorydepth) {
|
||||
list($category->categories, $subcategories) = get_course_category_tree($category->id, $depth+1);
|
||||
$categoryids = array_merge($categoryids, $subcategories);
|
||||
$category->courses = array();
|
||||
}
|
||||
}
|
||||
|
||||
if ($depth > 0) {
|
||||
// This is a recursive call so return the required array
|
||||
return array($categories, $categoryids);
|
||||
}
|
||||
|
||||
// The depth is 0 this function has just been called so we can finish it off
|
||||
|
||||
list($ccselect, $ccjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
|
||||
list($catsql, $catparams) = $DB->get_in_or_equal(array_keys($categoryids));
|
||||
$sql = "SELECT
|
||||
c.id,c.sortorder,c.visible,c.fullname,c.shortname,c.password,c.summary,c.guest,c.cost,c.currency,c.category
|
||||
$ccselect
|
||||
FROM {course} c
|
||||
$ccjoin
|
||||
WHERE c.category $catsql ORDER BY c.sortorder ASC";
|
||||
if ($courses = $DB->get_records_sql($sql, $catparams)) {
|
||||
// loop throught them
|
||||
foreach ($courses as $course) {
|
||||
if ($course->id == SITEID) {
|
||||
continue;
|
||||
}
|
||||
context_instance_preload($course);
|
||||
if (!empty($course->visible) || has_capability('moodle/course:viewhiddencourses', get_context_instance(CONTEXT_COURSE, $course->id))) {
|
||||
$categoryids[$course->category]->courses[$course->id] = $course;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive function to print out all the categories in a nice format
|
||||
|
157
course/renderer.php
Normal file
157
course/renderer.php
Normal file
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Renderer for use with the course section and all the goodness that falls
|
||||
* within it.
|
||||
*
|
||||
* This renderer should contain methods useful to courses, and categories.
|
||||
*
|
||||
* @package moodlecore
|
||||
* @copyright 2010 Sam Hemelryk
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* The core course renderer
|
||||
*
|
||||
* Can be retrieved with the following:
|
||||
* $renderer = $PAGE->get_renderer('core','course');
|
||||
*/
|
||||
class core_course_renderer extends plugin_renderer_base {
|
||||
|
||||
/**
|
||||
* A cache of strings
|
||||
* @var stdClass
|
||||
*/
|
||||
protected $strings;
|
||||
|
||||
/**
|
||||
* Override the constructor so that we can initialise the string cache
|
||||
*
|
||||
* @param moodle_page $page
|
||||
* @param string $target
|
||||
*/
|
||||
public function __construct(moodle_page $page, $target) {
|
||||
$this->strings = new stdClass;
|
||||
parent::__construct($page, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renderers a structured array of courses and categories into a nice
|
||||
* XHTML tree structure.
|
||||
*
|
||||
* This method was designed initially to display the front page course/category
|
||||
* combo view. The structure can be retrieved by get_course_category_tree()
|
||||
*
|
||||
* @param array $structure
|
||||
* @return string
|
||||
*/
|
||||
public function course_category_tree(array $structure) {
|
||||
$this->strings->allowguests = get_string('allowguests');
|
||||
$this->strings->requireskey = get_string('requireskey');
|
||||
$this->strings->summary = get_string('summary');
|
||||
|
||||
// Generate an id and the required JS call to make this a nice widget
|
||||
$id = html_writer::random_id('course_category_tree');
|
||||
$this->page->requires->js_init_call('M.util.init_toggle_class_on_click', array($id, '.category.with_children', 'collapsed'));
|
||||
|
||||
// Start content generation
|
||||
$content = html_writer::start_tag('div', array('class'=>'course_category_tree', 'id'=>$id));
|
||||
foreach ($structure as $category) {
|
||||
$content .= $this->course_category_tree_category($category);
|
||||
}
|
||||
$content .= html_writer::start_tag('div', array('class'=>'controls'));
|
||||
$content .= html_writer::tag('div', get_string('collapseall'), array('class'=>'addtoall expandall'));
|
||||
$content .= html_writer::tag('div', get_string('expandall'), array('class'=>'removefromall collapseall'));
|
||||
$content .= html_writer::end_tag('div');
|
||||
$content .= html_writer::end_tag('div');
|
||||
|
||||
// Return the course category tree HTML
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renderers a category for use with course_category_tree
|
||||
*
|
||||
* @param array $category
|
||||
* @param int $depth
|
||||
* @return string
|
||||
*/
|
||||
protected function course_category_tree_category(stdClass $category, $depth=1) {
|
||||
$content = '';
|
||||
$hassubcategories = (count($category->categories)>0);
|
||||
$hascourses = (count($category->courses)>0);
|
||||
$classes = array('category');
|
||||
if ($category->parent != 0) {
|
||||
$classes[] = 'subcategory';
|
||||
}
|
||||
if ($hassubcategories || $hascourses) {
|
||||
$classes[] = 'with_children';
|
||||
if ($depth > 1) {
|
||||
$classes[] = 'collapsed';
|
||||
}
|
||||
}
|
||||
$content .= html_writer::start_tag('div', array('class'=>join(' ', $classes)));
|
||||
$content .= html_writer::start_tag('div', array('class'=>'category_label'));
|
||||
$content .= html_writer::link(new moodle_url('/course/category.php', array('id'=>$category->id)), $category->name, array('class'=>'category_link'));
|
||||
$content .= html_writer::end_tag('div');
|
||||
if ($hassubcategories) {
|
||||
$content .= html_writer::start_tag('div', array('class'=>'subcategories'));
|
||||
foreach ($category->categories as $subcategory) {
|
||||
$content .= $this->course_category_tree_category($subcategory, $depth+1);
|
||||
}
|
||||
$content .= html_writer::end_tag('div');
|
||||
}
|
||||
if ($hascourses) {
|
||||
$content .= html_writer::start_tag('div', array('class'=>'courses'));
|
||||
$coursecount = 0;
|
||||
foreach ($category->courses as $course) {
|
||||
$classes = array('course');
|
||||
$coursecount ++;
|
||||
$classes[] = ($coursecount%2)?'odd':'even';
|
||||
$content .= html_writer::start_tag('div', array('class'=>join(' ', $classes)));
|
||||
$content .= html_writer::link(new moodle_url('/course/view.php', array('id'=>$course->id)), $course->fullname, array('class'=>'course_link'));
|
||||
$content .= html_writer::start_tag('div', array('class'=>'course_info clearfix'));
|
||||
|
||||
if ($course->guest ) {
|
||||
$image = html_writer::empty_tag('img', array('src'=>$this->output->pix_url('i/guest'), 'alt'=>$this->strings->allowguests, 'title'=>$this->strings->allowguests));
|
||||
$content .= html_writer::tag('div', $image, array('class'=>'course_info_spacer'));
|
||||
} else {
|
||||
$content .= html_writer::tag('div', '', array('class'=>'course_info_spacer'));
|
||||
}
|
||||
if ($course->password) {
|
||||
$image = html_writer::empty_tag('img', array('src'=>$this->output->pix_url('i/key'), 'alt'=>$this->strings->requireskey, 'title'=>$this->strings->requireskey));
|
||||
$content .= html_writer::tag('div', $image, array('class'=>'course_info_spacer'));
|
||||
} else {
|
||||
$content .= html_writer::tag('div', '', array('class'=>'course_info_spacer'));
|
||||
}
|
||||
if ($course->summary) {
|
||||
$image = html_writer::empty_tag('img', array('src'=>$this->output->pix_url('i/info'), 'alt'=>$this->strings->summary));
|
||||
$content .= html_writer::link(new moodle_url('/course/info.php', array('id'=>$course->id)), $image, array('title'=>$this->strings->summary));
|
||||
} else {
|
||||
$content .= html_writer::tag('div', '', array('class'=>'course_info_spacer'));
|
||||
}
|
||||
$content .= html_writer::end_tag('div');
|
||||
$content .= html_writer::end_tag('div');
|
||||
}
|
||||
$content .= html_writer::end_tag('div');
|
||||
}
|
||||
$content .= html_writer::end_tag('div');
|
||||
return $content;
|
||||
}
|
||||
}
|
@ -196,11 +196,9 @@
|
||||
break;
|
||||
|
||||
case FRONTPAGECATEGORYCOMBO:
|
||||
|
||||
echo $OUTPUT->heading(get_string('categories'), 2, 'headingblock header');
|
||||
echo $OUTPUT->box_start('generalbox categorybox');
|
||||
print_whole_category_list(NULL, NULL, NULL, -1, true);
|
||||
echo $OUTPUT->box_end();
|
||||
$renderer = $PAGE->get_renderer('core','course');
|
||||
echo $renderer->course_category_tree(get_course_category_tree());
|
||||
print_course_search('', false, 'short');
|
||||
break;
|
||||
|
||||
|
@ -250,6 +250,7 @@ $string['clickhere'] = 'Click here ...';
|
||||
$string['clicktohideshow'] = 'Click to expand or collapse';
|
||||
$string['clicktochange'] = 'Click to change';
|
||||
$string['closewindow'] = 'Close this window';
|
||||
$string['collapseall'] = 'Collapse all';
|
||||
$string['commentincontext'] = 'Find this comment in context';
|
||||
$string['comments'] = 'Comments';
|
||||
$string['comparelanguage'] = 'Compare and edit current language';
|
||||
@ -675,6 +676,7 @@ $string['existingcoursedeleting'] = 'Existing course, deleting it first';
|
||||
$string['existingcreators'] = 'Existing course creators';
|
||||
$string['existingstudents'] = 'Enrolled students';
|
||||
$string['existingteachers'] = 'Existing teachers';
|
||||
$string['expandall'] = 'Expand all';
|
||||
$string['expirynotify'] = 'Enrolment expiry notification';
|
||||
$string['expirynotifyemail'] = 'The following students in this course are expiring after exactly {$a->threshold} days:
|
||||
|
||||
@ -1903,4 +1905,4 @@ $string['yourlastlogin'] = 'Your last login was';
|
||||
$string['yourself'] = 'yourself';
|
||||
$string['yourteacher'] = 'your {$a}';
|
||||
$string['yourwordforx'] = 'Your word for \'{$a}\'';
|
||||
$string['zippingbackup'] = 'Zipping backup';
|
||||
$string['zippingbackup'] = 'Zipping backup';
|
@ -393,6 +393,36 @@ M.util.init_frametop = function(Y) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds all nodes that match the given CSS selector and attaches events to them
|
||||
* so that they toggle a given classname when clicked.
|
||||
*
|
||||
* @param {YUI} Y
|
||||
* @param {string} id An id containing elements to target
|
||||
* @param {string} cssselector A selector to use to find targets
|
||||
* @param {string} toggleclassname A classname to toggle
|
||||
*/
|
||||
M.util.init_toggle_class_on_click = function(Y, id, cssselector, toggleclassname) {
|
||||
var node = Y.one('#'+id);
|
||||
node.all(cssselector).each(function(node){
|
||||
node.on('click', function(e){
|
||||
e.stopPropagation();
|
||||
if (e.target.get('nodeName')!='A' && e.target.get('nodeName')!='IMG') {
|
||||
this.toggleClass(toggleclassname);
|
||||
}
|
||||
}, node);
|
||||
});
|
||||
// Attach this click event to the node rather than all selectors... will be much better
|
||||
// for performance
|
||||
node.on('click', function(e){
|
||||
if (e.target.hasClass('addtoall')) {
|
||||
node.all(cssselector).addClass(toggleclassname);
|
||||
} else if (e.target.hasClass('removefromall')) {
|
||||
node.all(cssselector+'.'+toggleclassname).removeClass(toggleclassname);
|
||||
}
|
||||
}, node);
|
||||
}
|
||||
|
||||
//=== old legacy JS code, hopefully to be replaced soon by M.xx.yy and YUI3 code ===
|
||||
|
||||
function popupchecker(msg) {
|
||||
|
@ -7021,6 +7021,7 @@ function get_core_subsystems() {
|
||||
'condition' => NULL,
|
||||
'completion' => NULL,
|
||||
'countries' => NULL,
|
||||
'course' => 'course',
|
||||
'currencies' => NULL,
|
||||
'dbtransfer' => NULL,
|
||||
'debug' => NULL,
|
||||
|
@ -29,6 +29,7 @@ $strgrade = get_string("grade");
|
||||
$PAGE->set_url('/mod/assignment/index.php', array('id'=>$course->id));
|
||||
$PAGE->navbar->add($strassignments);
|
||||
$PAGE->set_title($strassignments);
|
||||
$PAGE->set_heading($course->fullname);
|
||||
echo $OUTPUT->header();
|
||||
|
||||
if (!$cms = get_coursemodules_in_course('assignment', $course->id, 'cm.idnumber, m.assignmenttype, m.timedue')) {
|
||||
|
@ -85,4 +85,19 @@
|
||||
.weeks-format, /* Window-width: 800 pixels.IE doesn't support, see inline IE conditional comment. */
|
||||
.topics-format {margin-top: 8px;min-width: 763px;}
|
||||
#page-course-user .section {border-width:1px;border-style:solid;padding:10px;}
|
||||
.categoryboxcontent {border-width:1px;border-style:solid;}
|
||||
.categoryboxcontent {border-width:1px;border-style:solid;}
|
||||
|
||||
/* Course and category combo list on front page */
|
||||
.course_category_tree .controls {visibility: hidden;}
|
||||
.course_category_tree .controls div {display:inline;cursor:pointer;}
|
||||
.course_category_tree .category.with_children .category_label {background-image:url([[pix:moodle|t/expanded]]);background-repeat: no-repeat;}
|
||||
.course_category_tree .category_label {padding-left:13px;}
|
||||
.course_category_tree .category .courses .course_link {display:block;background-image:url([[pix:moodle|i/course]]);background-repeat: no-repeat;padding-left:18px;}
|
||||
.course_category_tree .category .course {position:relative;}
|
||||
.course_category_tree .category .course_info {position:absolute;right:0;top:0;}
|
||||
.course_category_tree .category .course_info a,
|
||||
.course_category_tree .category .course_info div {float:left;width:16px;height:16px;}
|
||||
.jsenabled .course_category_tree .controls {visibility: visible;}
|
||||
.jsenabled .course_category_tree .category.with_children.collapsed .category_label {background-image:url([[pix:moodle|t/collapsed]]);}
|
||||
.jsenabled .course_category_tree .category.with_children.collapsed .subcategories,
|
||||
.jsenabled .course_category_tree .category.with_children.collapsed .courses {display:none;}
|
@ -84,4 +84,22 @@
|
||||
.addcoursebutton {text-align:center;}
|
||||
.categorypicker {text-align:center;margin-bottom:10px;}
|
||||
.path-course-report-outline .loginfo {text-align:center;margin: 1em;}
|
||||
.categorylist {width: 90%;margin:0 auto;text-align: left;}
|
||||
.categorylist {width: 90%;margin:0 auto;text-align: left;}
|
||||
|
||||
/* Course and category combo list on front page */
|
||||
.course_category_tree .controls {margin-bottom:5px;text-align:right;float:right;}
|
||||
.course_category_tree .controls div {padding-right:2em;font-size:75%;}
|
||||
.course_category_tree .category {background-color:#FFF;background-image:url([[pix:theme|hgradient]]);background-repeat: repeat-x;border:1px solid #ddd;margin-bottom:10px;}
|
||||
.course_category_tree .category .category {margin:5px;}
|
||||
.course_category_tree .category .subcategories {background-color:inherit;padding-left:16px;border:1px solid #FFF;}
|
||||
.course_category_tree .category.with_children .category_label {background-position:3px 3px;}
|
||||
.course_category_tree .category_link .category_link {font-size:95%;}
|
||||
.course_category_tree .category_label {padding-left:13px;}
|
||||
.course_category_tree .category_link {display:block;margin:5px;font-size:120%;font-weight:bold;}
|
||||
.course_category_tree .category .courses {background-color:inherit;padding-left:16px;}
|
||||
.course_category_tree .category .courses .course_link {margin:5px;}
|
||||
.course_category_tree .category .course {border:1px solid #f9f9f9;border-bottom-color: #eee;border-right-width:0;}
|
||||
.course_category_tree .category .course:last-child {border-bottom-color:#f6f6f6;}
|
||||
.course_category_tree .category .course.even {background-color:#f6f6f6;border-color:#eee;border-top-color: #f9f9f9;}
|
||||
.course_category_tree .category .course_info {right:3px;top:3px;}
|
||||
.course_category_tree .category .course:hover {background-color:#eee;}
|
Loading…
x
Reference in New Issue
Block a user