Skip to content

Commit

Permalink
MDL-32824: Make dragdrop work correctly with section titles/links
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Ruslan Kabalin committed May 25, 2012
1 parent 5a5cdaf commit 9f3015e
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 23 deletions.
25 changes: 17 additions & 8 deletions course/format/renderer.php
Expand Up @@ -56,6 +56,21 @@ abstract protected function end_section_list();
*/
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
Expand Down Expand Up @@ -106,7 +121,7 @@ protected function section_left_content($section, $course, $onsectionpage) {
*
* @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) {
Expand All @@ -115,7 +130,6 @@ protected function section_header($section, $course, $onsectionpage) {
$o = '';
$currenttext = '';
$sectionstyle = '';
$linktitle = false;

if ($section->section != 0) {
// Only in the non-general sections.
Expand All @@ -124,7 +138,6 @@ protected function section_header($section, $course, $onsectionpage) {
} 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,
Expand All @@ -138,11 +151,7 @@ protected function section_header($section, $course, $onsectionpage) {
$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'));
Expand Down
27 changes: 23 additions & 4 deletions course/format/topics/format.js
@@ -1,4 +1,4 @@
// Javascript functions for course format
// Javascript functions for Topics course format

M.course = M.course || {};

Expand Down Expand Up @@ -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 changes: 21 additions & 0 deletions course/format/topics/lib.php
Expand Up @@ -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');
}
32 changes: 24 additions & 8 deletions course/format/weeks/format.js
@@ -1,4 +1,4 @@
// Javascript functions for course format
// Javascript functions for Weeks course format

M.course = M.course || {};

Expand Down Expand Up @@ -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 changes: 21 additions & 0 deletions course/format/weeks/lib.php
Expand Up @@ -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 changes: 9 additions & 0 deletions course/rest.php
Expand Up @@ -89,6 +89,15 @@

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);
Expand Down
15 changes: 15 additions & 0 deletions course/yui/coursebase/coursebase.js
Expand Up @@ -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
Expand Down
18 changes: 15 additions & 3 deletions course/yui/dragdrop/dragdrop.js
Expand Up @@ -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 {
Expand All @@ -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);
Expand Down

0 comments on commit 9f3015e

Please sign in to comment.