MDL-32824: Make dragdrop work correctly with section titles/links

Initially, the default section title was swapped within the course format
javascript functions. Though some section titles may be custom and does not
require swapping, in addition they may have links to single section view. This
introduces some callback functions for define what needs to be done in
sections libs and js files.
This commit is contained in:
Ruslan Kabalin
2012-05-25 11:39:44 +01:00
parent 5a5cdaf92e
commit 9f3015ecf8
8 changed files with 145 additions and 23 deletions
+17 -8
View File
@@ -56,6 +56,21 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
*/
abstract protected function page_title();
/**
* Generate the section title
*
* @param stdClass $section The course_section entry from DB
* @param stdClass $course The course entry from DB
* @return string HTML to output.
*/
public function section_title($section, $course) {
$title = get_section_name($course, $section);
if ($section->section != 0 && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
$title = html_writer::link(course_get_url($course, $section->section), $title);
}
return $title;
}
/**
* Generate the content to displayed on the right part of a section
* before course modules are included
@@ -106,7 +121,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
*
* @param stdClass $section The course_section entry from DB
* @param stdClass $course The course entry from DB
* @param bool $onsectionpage true if being printed on a section page
* @param bool $onsectionpage true if being printed on a single-section page
* @return string HTML to output.
*/
protected function section_header($section, $course, $onsectionpage) {
@@ -115,7 +130,6 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
$o = '';
$currenttext = '';
$sectionstyle = '';
$linktitle = false;
if ($section->section != 0) {
// Only in the non-general sections.
@@ -124,7 +138,6 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
} else if ($course->marker == $section->section) {
$sectionstyle = ' current';
}
$linktitle = ($course->coursedisplay == COURSE_DISPLAY_MULTIPAGE);
}
$o.= html_writer::start_tag('li', array('id' => 'section-'.$section->section,
@@ -138,11 +151,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
$o.= html_writer::start_tag('div', array('class' => 'content'));
if (!$onsectionpage) {
$title = get_section_name($course, $section);
if ($linktitle) {
$title = html_writer::link(course_get_url($course, $section->section), $title);
}
$o.= $this->output->heading($title, 3, 'sectionname');
$o.= $this->output->heading($this->section_title($section, $course), 3, 'sectionname');
}
$o.= html_writer::start_tag('div', array('class' => 'summary'));
+23 -4
View File
@@ -1,4 +1,4 @@
// Javascript functions for course format
// Javascript functions for Topics course format
M.course = M.course || {};
@@ -36,13 +36,32 @@ M.course.format.get_config = function() {
M.course.format.swap_sections = function(Y, node1, node2) {
var CSS = {
COURSECONTENT : 'course-content',
LEFT : 'left',
SECTIONADDMENUS : 'section_add_menus'
};
var sectionlist = Y.Node.all('.'+CSS.COURSECONTENT+' '+M.course.format.get_section_selector(Y));
// Swap left block
sectionlist.item(node1).one('.'+CSS.LEFT).swap(sectionlist.item(node2).one('.'+CSS.LEFT));
// Swap menus
sectionlist.item(node1).one('.'+CSS.SECTIONADDMENUS).swap(sectionlist.item(node2).one('.'+CSS.SECTIONADDMENUS));
}
/**
* Process sections after ajax response
*
* @param {YUI} Y YUI3 instance
* @param {array} response ajax response
* @param {string} sectionfrom first affected section
* @param {string} sectionto last affected section
* @return void
*/
M.course.format.process_sections = function(Y, sectionlist, response, sectionfrom, sectionto) {
var CSS = {
SECTIONNAME : 'sectionname'
};
if (response.action == 'move') {
// update titles in all affected sections
for (var i = sectionfrom; i <= sectionto; i++) {
sectionlist.item(i).one('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]);
}
}
}
+21
View File
@@ -80,3 +80,24 @@ function callback_topics_ajax_support() {
$ajaxsupport->testedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari' => 531, 'Chrome' => 6.0);
return $ajaxsupport;
}
/**
* Callback function to do some action after section move
*
* @param stdClass $course The course entry from DB
* @return array This will be passed in ajax respose.
*/
function callback_topics_ajax_section_move($course) {
global $COURSE, $PAGE;
$titles = array();
rebuild_course_cache($course->id);
$modinfo = get_fast_modinfo($COURSE);
$renderer = $PAGE->get_renderer('format_topics');
if ($renderer && ($sections = $modinfo->get_section_info_all())) {
foreach ($sections as $number => $section) {
$titles[$number] = $renderer->section_title($section, $course);
}
}
return array('sectiontitles' => $titles, 'action' => 'move');
}
+24 -8
View File
@@ -1,4 +1,4 @@
// Javascript functions for course format
// Javascript functions for Weeks course format
M.course = M.course || {};
@@ -36,16 +36,32 @@ M.course.format.get_config = function() {
M.course.format.swap_sections = function(Y, node1, node2) {
var CSS = {
COURSECONTENT : 'course-content',
LEFT : 'left',
SECTIONADDMENUS : 'section_add_menus',
WEEKDATES: 'weekdates'
SECTIONADDMENUS : 'section_add_menus'
};
var sectionlist = Y.Node.all('.'+CSS.COURSECONTENT+' '+M.course.format.get_section_selector(Y));
// Swap left block
sectionlist.item(node1).one('.'+CSS.LEFT).swap(sectionlist.item(node2).one('.'+CSS.LEFT));
// Swap menus
sectionlist.item(node1).one('.'+CSS.SECTIONADDMENUS).swap(sectionlist.item(node2).one('.'+CSS.SECTIONADDMENUS));
// Swap week dates
sectionlist.item(node1).one('.'+CSS.WEEKDATES).swap(sectionlist.item(node2).one('.'+CSS.WEEKDATES));
}
/**
* Process sections after ajax response
*
* @param {YUI} Y YUI3 instance
* @param {array} response ajax response
* @param {string} sectionfrom first affected section
* @param {string} sectionto last affected section
* @return void
*/
M.course.format.process_sections = function(Y, sectionlist, response, sectionfrom, sectionto) {
var CSS = {
SECTIONNAME : 'sectionname'
};
if (response.action == 'move') {
// update titles in all affected sections
for (var i = sectionfrom; i <= sectionto; i++) {
sectionlist.item(i).one('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]);
}
}
}
+21
View File
@@ -102,3 +102,24 @@ function callback_weeks_ajax_support() {
$ajaxsupport->testedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari' => 531, 'Chrome' => 6.0);
return $ajaxsupport;
}
/**
* Callback function to do some action after section move
*
* @param stdClass $course The course entry from DB
* @return array This will be passed in ajax respose.
*/
function callback_weeks_ajax_section_move($course) {
global $COURSE, $PAGE;
$titles = array();
rebuild_course_cache($course->id);
$modinfo = get_fast_modinfo($COURSE);
$renderer = $PAGE->get_renderer('format_weeks');
if ($renderer && ($sections = $modinfo->get_section_info_all())) {
foreach ($sections as $number => $section) {
$titles[$number] = $renderer->section_title($section, $course);
}
}
return array('sectiontitles' => $titles, 'action' => 'move');
}
+9
View File
@@ -89,6 +89,15 @@ switch($requestmethod) {
case 'move':
move_section_to($course, $id, $value);
// See if format wants to do something about it
$libfile = $CFG->dirroot.'/course/format/'.$course->format.'/lib.php';
$functionname = 'callback_'.$course->format.'_ajax_section_move';
if (!function_exists($functionname) && file_exists($libfile)) {
require_once $libfile;
}
if (function_exists($functionname)) {
echo json_encode($functionname($course));
}
break;
}
rebuild_course_cache($course->id);
+15
View File
@@ -68,6 +68,21 @@ YUI.add('moodle-course-coursebase', function(Y) {
return null;
}
/**
* Process sections after ajax response (should be defined in format.js)
* If some response is expected, we pass it over to format, as it knows better
* hot to process it.
*
* @param {YUI} Y YUI3 instance
* @param {NodeList} list of sections
* @param {array} response ajax response
* @param {string} sectionfrom first affected section
* @param {string} sectionto last affected section
* @return void
*/
M.course.format.process_sections = M.course.format.process_sections || function(Y, sectionlist, response, sectionfrom, sectionto) {
return null;
}
/**
* Get sections config for this format, for examples see function definition
+15 -3
View File
@@ -172,9 +172,16 @@ YUI.add('moodle-course-dragdrop', function(Y) {
lightbox.show();
},
success: function(tid, response) {
window.setTimeout(function(e) {
lightbox.hide();
}, 250);
// Update section titles, we can't simply swap them as
// they might have custom title
try {
var responsetext = Y.JSON.parse(response.responseText);
if (responsetext.error) {
new M.core.ajaxException(responsetext);
}
M.course.format.process_sections(Y, sectionlist, responsetext, loopstart, loopend);
} catch (e) {}
// Classic bubble sort algorithm is applied to the section
// nodes between original drag node location and the new one.
do {
@@ -193,6 +200,11 @@ YUI.add('moodle-course-dragdrop', function(Y) {
}
loopend = loopend - 1;
} while (swapped);
// Finally, hide the lightbox
window.setTimeout(function(e) {
lightbox.hide();
}, 250);
},
failure: function(tid, response) {
this.ajax_failure(response);