Permalink
Browse files

MDL-31215 Add the ability to change activity titles using AJAX calls

  • Loading branch information...
1 parent 314eae4 commit 7a9a07d24acaa4befd32698a69d26afcd9530437 @andrewnicols andrewnicols committed May 8, 2012
Showing with 180 additions and 2 deletions.
  1. +14 −1 course/lib.php
  2. +35 −1 course/rest.php
  3. +112 −0 course/yui/toolboxes/toolboxes.js
  4. +2 −0 lang/en/moodle.php
  5. BIN pix/t/editstring.png
  6. +17 −0 theme/base/style/course.css
View
@@ -3155,7 +3155,7 @@ function moveto_module($mod, $section, $beforemod=NULL) {
* @return string XHTML for the editing buttons
*/
function make_editing_buttons(stdClass $mod, $absolute_ignored = true, $moveselect = true, $indent=-1, $section=-1) {
- global $CFG, $OUTPUT;
+ global $CFG, $OUTPUT, $COURSE;
static $str;
@@ -3191,6 +3191,7 @@ function make_editing_buttons(stdClass $mod, $absolute_ignored = true, $movesele
$str->forcedgroupsnone = get_string('forcedmodeinbrackets', 'moodle', get_string("groupsnone"));
$str->forcedgroupsseparate = get_string('forcedmodeinbrackets', 'moodle', get_string("groupsseparate"));
$str->forcedgroupsvisible = get_string('forcedmodeinbrackets', 'moodle', get_string("groupsvisible"));
+ $str->edittitle = get_string('edittitle', 'moodle');
}
$baseurl = new moodle_url('/course/mod.php', array('sesskey' => sesskey()));
@@ -3200,6 +3201,16 @@ function make_editing_buttons(stdClass $mod, $absolute_ignored = true, $movesele
}
$actions = array();
+ // AJAX edit title
+ if ($mod->modname !== 'label' && $hasmanageactivities && course_ajax_enabled($COURSE)) {
+ $actions[] = new action_link(
+ new moodle_url($baseurl, array('update' => $mod->id)),
+ new pix_icon('t/editstring', $str->edittitle, 'moodle', array('class' => 'iconsmall visibleifjs')),
+ null,
+ array('class' => 'editing_title', 'title' => $str->edittitle)
+ );
+ }
+
// leftright
if ($hasmanageactivities) {
if (right_to_left()) { // Exchange arrows on RTL
@@ -4523,6 +4534,8 @@ function include_course_ajax($course, $modules = array(), $config = null) {
'moveleft',
'deletechecktype',
'deletechecktypename',
+ 'edittitle',
+ 'edittitleinstructions',
'show',
'hide',
'groupsnone',
View
@@ -43,6 +43,7 @@
$sequence = optional_param('sequence', '', PARAM_SEQUENCE);
$visible = optional_param('visible', 0, PARAM_INT);
$pageaction = optional_param('action', '', PARAM_ALPHA); // Used to simulate a DELETE command
+$title = optional_param('title', '', PARAM_TEXT);
$PAGE->set_url('/course/rest.php', array('courseId'=>$courseid,'class'=>$class));
@@ -56,8 +57,8 @@
$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
} else {
require_login($course);
- $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
}
+$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
require_sesskey();
echo $OUTPUT->header(); // send headers
@@ -128,6 +129,39 @@
moveto_module($cm, $section, $beforemod);
break;
+ case 'gettitle':
+ require_capability('moodle/course:manageactivities', $modcontext);
+ $cm = get_coursemodule_from_id('', $id, 0, false, MUST_EXIST);
+ $module = new stdClass();
+ $module->id = $cm->instance;
+
+ // Don't pass edit strings through multilang filters - we need the entire string
+ echo json_encode(array('instancename' => $cm->name));
+ break;
+ case 'updatetitle':
+ require_capability('moodle/course:manageactivities', $modcontext);
+ $cm = get_coursemodule_from_id('', $id, 0, false, MUST_EXIST);
+ $module = new stdClass();
+ $module->id = $cm->instance;
+
+ // Escape strings as they would be by mform
+ if (!empty($CFG->formatstringstriptags)) {
+ $module->name = clean_param($title, PARAM_TEXT);
+ } else {
+ $module->name = clean_param($title, PARAM_CLEANHTML);
+ }
+
+ if (!empty($module->name)) {
+ $DB->update_record($cm->modname, $module);
+ } else {
+ $module->name = $cm->name;
+ }
+
+ // We need to return strings after they've been through filters for multilang
+ $stringoptions = new stdClass;
+ $stringoptions->context = $coursecontext;
+ echo json_encode(array('instancename' => format_string($module->name, true, $stringoptions)));
+ break;
}
rebuild_course_cache($course->id);
break;
@@ -9,6 +9,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
DELETE : 'a.editing_delete',
DIMCLASS : 'dimmed',
DIMMEDTEXT : 'dimmed_text',
+ EDITTITLE : 'a.editing_title',
EDITTITLECLASS : 'edittitle',
GENERICICONCLASS : 'iconsmall',
GROUPSNONE : 'a.editing_groupsnone',
@@ -257,6 +258,9 @@ YUI.add('moodle-course-toolboxes', function(Y) {
Y.all(baseselector).each(this._setup_for_resource, this);
},
_setup_for_resource : function(toolboxtarget) {
+ // Edit Title
+ this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.EDITTITLE, this.edit_resource_title);
+
// Move left and right
this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.MOVELEFT, this.move_left);
this.replace_button(toolboxtarget, CSS.COMMANDSPAN + ' ' + CSS.MOVERIGHT, this.move_right);
@@ -482,6 +486,114 @@ YUI.add('moodle-course-toolboxes', function(Y) {
anchor.appendChild(newicon);
anchor.on('click', this.move_left, this);
moveright.insert(anchor, 'before');
+ },
+ /**
+ * Edit the title for the resource
+ */
+ edit_resource_title : function(e) {
+ // Get the element we're working on
+ var element = e.target.ancestor(CSS.ACTIVITYLI);
+ var instancename = element.one(CSS.INSTANCENAME);
+ var currenttitle = instancename.get('firstChild');
+ var oldtitle = currenttitle.get('data');
+ var titletext = oldtitle;
+ var editbutton = element.one('a.' + CSS.EDITTITLECLASS + ' img');
+
+ // Disable the current href to prevent redirections when editing
+ var anchor = instancename.ancestor('a');
+ anchor.setAttribute('oldhref', anchor.getAttribute('href'));
+ anchor.removeAttribute('href');
+
+ var data = {
+ 'class' : 'resource',
+ 'field' : 'gettitle',
+ 'id' : this.get_element_id(element)
+ };
+
+ // Try to retrieve the existing string from the server
+ var response = this.send_request(data, editbutton);
+ if (response.instancename) {
+ titletext = response.instancename;
+ }
+
+ // Create the editor and submit button
+ var editor = Y.Node.create('<input />')
+ .setAttrs({
+ 'name' : 'title',
+ 'value' : titletext,
+ 'autocomplete' : 'off'
+ })
+ .addClass('titleeditor');
+ var editform = Y.Node.create('<form />')
+ .setStyle('padding', '0')
+ .setStyle('display', 'inline')
+ .setAttribute('action', '#');
+
+ var editinstructions = Y.Node.create('<span />')
+ .addClass('editinstructions')
+ .set('innerHTML', M.util.get_string('edittitleinstructions', 'moodle'));
+
+ // Clear the existing content and put the editor in
+ currenttitle.set('data', '');
+ editform.appendChild(editor);
+ instancename.appendChild(editform);
+ element.appendChild(editinstructions);
+ e.preventDefault();
+
+ // Focus and select the editor text
+ editor.focus().select();
+
+ // Handle cancellation of the editor
+ editor.on('blur', function(e) {
+ // Detach the blur event before removing as some actions trigger multiple blurs in
+ // some browser
+ editor.detach('blur');
+ editform.remove();
+ editinstructions.remove();
+
+ // Set the title and anchor back to their previous settings
+ currenttitle.set('data', oldtitle);
+ anchor.setAttribute('href', anchor.getAttribute('oldhref'));
+ anchor.removeAttribute('oldhref');
+ });
+
+ // Handle form submission
+ editform.on('submit', function(e) {
+ // We don't actually want to submit anything
+ e.preventDefault();
+
+ // Detach the handlers to prevent multiple submissions
+ editform.detach('submit');
+ editor.detach('blur');
+
+ // We only accept strings which have valid content
+ var newtitle = Y.Lang.trim(editor.get('value'));
+ if (newtitle != null && newtitle != "" && newtitle != titletext) {
+ var data = {
+ 'class' : 'resource',
+ 'field' : 'updatetitle',
+ 'title' : newtitle,
+ 'id' : this.get_element_id(element)
+ };
+ var response = this.send_request(data, editbutton);
+ if (response.instancename) {
+ currenttitle.set('data', response.instancename);
+ }
+ } else {
+ // Invalid content. Set the title back to it's original contents
+ currenttitle.set('data', oldtitle);
+ }
+
+ editform.remove();
+ editinstructions.remove();
+
+ // We need a timeout here otherwise hitting return to save in some browsers triggers
+ // the anchor
+ setTimeout(function(e) {
+ anchor.setAttribute('href', anchor.getAttribute('oldhref'));
+ anchor.removeAttribute('oldhref');
+ }, 500);
+ }, this);
}
}, {
NAME : 'course-resource-toolbox',
View
@@ -508,6 +508,8 @@
$string['editorshortcutkeys'] = 'Editor shortcut keys';
$string['editsettings'] = 'Edit settings';
$string['editsummary'] = 'Edit summary';
+$string['edittitle'] = 'Edit title';
+$string['edittitleinstructions'] = 'Escape to cancel, Enter when finished';
$string['editthisactivity'] = 'Edit this activity';
$string['editthiscategory'] = 'Edit this category';
$string['edituser'] = 'Edit user accounts';
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -133,3 +133,20 @@
table.category_subcategories {margin-bottom:1em;}
table.category_subcategories td {white-space: nowrap;}
+
+span.editinstructions {
+ position: relative;
+ top: 5px;
+ left: 19px;
+ width: 329px;
+ padding: 3px;
+ background-color: #dddddd;
+ color: #000000;
+ text-decoration: none;
+ z-index: 100;
+ border: 1px solid black;
+}
+
+input.titleeditor {
+ width: 330px;
+}

0 comments on commit 7a9a07d

Please sign in to comment.