MDL-52869 course: use inplace_editable for activity names

This commit is contained in:
Marina Glancy
2016-03-15 17:19:38 +08:00
parent e8952c5951
commit f59f89b4a8
20 changed files with 404 additions and 732 deletions
+6 -37
View File
@@ -51,6 +51,7 @@ class block_site_main_menu extends block_list {
require_once($CFG->dirroot.'/course/lib.php');
$context = context_course::instance($course->id);
$isediting = $this->page->user_is_editing() && has_capability('moodle/course:manageactivities', $context);
$courserenderer = $this->page->get_renderer('core', 'course');
/// extra fast view mode
if (!$isediting) {
@@ -69,32 +70,18 @@ class block_site_main_menu extends block_list {
}
if (!empty($cm->url)) {
$attrs = array();
$attrs['title'] = $cm->modfullname;
$attrs['class'] = $cm->extraclasses . ' activity-action';
if ($cm->onclick) {
// Get on-click attribute value if specified and decode the onclick - it
// has already been encoded for display.
$attrs['onclick'] = htmlspecialchars_decode($cm->onclick);
}
if (!$cm->visible) {
$attrs['class'] .= ' dimmed';
}
$icon = '<img src="' . $cm->get_icon_url() . '" class="icon" alt="" />';
$content = html_writer::link($cm->url, $icon . $cm->get_formatted_name(), $attrs);
$content = html_writer::div($courserenderer->course_section_cm_name($cm), 'activity');
} else {
$content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
}
$this->content->items[] = $indent.html_writer::div($content, 'main-menu-content');
$this->content->items[] = $indent . $content;
}
}
return $this->content;
}
// Slow & hacky editing mode.
/** @var core_course_renderer $courserenderer */
$courserenderer = $this->page->get_renderer('core', 'course');
$ismoving = ismoving($course->id);
course_create_sections_if_missing($course, 0);
$modinfo = get_fast_modinfo($course);
@@ -104,11 +91,9 @@ class block_site_main_menu extends block_list {
$strmovehere = get_string('movehere');
$strmovefull = strip_tags(get_string('movefull', '', "'$USER->activitycopyname'"));
$strcancel= get_string('cancel');
$stractivityclipboard = $USER->activitycopyname;
} else {
$strmove = get_string('move');
}
$editbuttons = '';
if ($ismoving) {
$this->content->icons[] = '<img src="'.$OUTPUT->pix_url('t/move') . '" class="iconsmall" alt="" />';
@@ -116,7 +101,6 @@ class block_site_main_menu extends block_list {
}
if (!empty($modinfo->sections[0])) {
$options = array('overflowdiv'=>true);
foreach ($modinfo->sections[0] as $modnumber) {
$mod = $modinfo->cms[$modnumber];
if (!$mod->uservisible) {
@@ -153,27 +137,12 @@ class block_site_main_menu extends block_list {
} else {
$indent = '';
}
$url = $mod->url;
if (!$url) {
if (!$mod->url) {
$content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
} else {
//Accessibility: incidental image - should be empty Alt text
$attrs = array();
$attrs['title'] = $mod->modfullname;
$attrs['class'] = $mod->extraclasses . ' activity-action';
if ($mod->onclick) {
// Get on-click attribute value if specified and decode the onclick - it
// has already been encoded for display.
$attrs['onclick'] = htmlspecialchars_decode($mod->onclick);
}
if (!$mod->visible) {
$attrs['class'] .= ' dimmed';
}
$icon = '<img src="' . $mod->get_icon_url() . '" class="icon" alt="" />';
$content = html_writer::link($url, $icon . $mod->get_formatted_name(), $attrs);
$content = html_writer::div($courserenderer->course_section_cm_name($mod), ' activity');
}
$this->content->items[] = $indent.html_writer::div($content . $editbuttons, 'main-menu-content');
$this->content->items[] = $indent. $content . $editbuttons;
}
}
}
+1 -2
View File
@@ -6,5 +6,4 @@
.block_site_main_menu .footer { margin-top: 1em; }
.block_site_main_menu .section_add_menus noscript div { display: inline;}
.block_site_main_menu .mod-indent,
.block_site_main_menu .main-menu-content { display: table-cell; }
.block_site_main_menu .main-menu-content > .activity-action { display: block; }
.block_site_main_menu .activity { display: table-cell; }
@@ -0,0 +1,21 @@
@block @block_main_menu
Feature: Edit activities in main menu block
In order to use main menu block
As an admin
I need to add and edit activities there
@javascript
Scenario: Edit name of acitivity in-place in site main menu block
Given I log in as "admin"
And I am on site homepage
And I navigate to "Turn editing on" node in "Front page settings"
When I add a "Forum" to section "0" and I fill the form with:
| Forum name | My forum name |
And I click on "Edit title" "link" in the "//.[contains(@class,'block_site_main_menu')]//li[contains(.,'My forum name')]" "xpath_element"
And I set the field "New name for activity My forum name" to "New forum name"
And I press key "13" in the field "New name for activity My forum name"
Then I should not see "My forum name"
And I should see "New forum name"
And I follow "New forum name"
And I should not see "My forum name"
And I should see "New forum name"
@@ -48,6 +48,7 @@ class block_social_activities extends block_list {
}
$course = $this->page->course;
$courserenderer = $this->page->get_renderer('core', 'course');
require_once($CFG->dirroot.'/course/lib.php');
@@ -58,25 +59,18 @@ class block_social_activities extends block_list {
/// extra fast view mode
if (!$isediting) {
if (!empty($modinfo->sections[0])) {
$options = array('overflowdiv'=>true);
foreach($modinfo->sections[0] as $cmid) {
$cm = $modinfo->cms[$cmid];
if (!$cm->uservisible) {
continue;
}
$content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
$instancename = $cm->get_formatted_name();
if (!($url = $cm->url)) {
if (!$cm->url) {
$content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
$this->content->items[] = $content;
$this->content->icons[] = '';
} else {
$linkcss = $cm->visible ? '' : ' class="dimmed" ';
//Accessibility: incidental image - should be empty Alt text
$icon = '<img src="' . $cm->get_icon_url() . '" class="icon" alt="" />&nbsp;';
$this->content->items[] = '<a title="'.$cm->modplural.'" '.$linkcss.' '.$cm->extra.
' href="' . $url . '">' . $icon . $instancename . '</a>';
$this->content->items[] = html_writer::div($courserenderer->course_section_cm_name($cm), 'activity');
}
}
}
@@ -85,21 +79,16 @@ class block_social_activities extends block_list {
// Slow & hacky editing mode.
/** @var core_course_renderer $courserenderer */
$courserenderer = $this->page->get_renderer('core', 'course');
$ismoving = ismoving($course->id);
$modinfo = get_fast_modinfo($course);
$section = $modinfo->get_section_info(0);
if ($ismoving) {
$strmovehere = get_string('movehere');
$strmovefull = strip_tags(get_string('movefull', '', "'$USER->activitycopyname'"));
$strcancel= get_string('cancel');
$stractivityclipboard = $USER->activitycopyname;
} else {
$strmove = get_string('move');
}
$editbuttons = '';
if ($ismoving) {
$this->content->icons[] = '&nbsp;<img align="bottom" src="'.$OUTPUT->pix_url('t/move') . '" class="iconsmall" alt="" />';
@@ -107,7 +96,6 @@ class block_social_activities extends block_list {
}
if (!empty($modinfo->sections[0])) {
$options = array('overflowdiv'=>true);
foreach ($modinfo->sections[0] as $modnumber) {
$mod = $modinfo->cms[$modnumber];
if (!$mod->uservisible) {
@@ -139,19 +127,13 @@ class block_social_activities extends block_list {
'<img style="height:16px; width:80px; border:0px" src="'.$OUTPUT->pix_url('movehere') . '" alt="'.$strmovehere.'" /></a>';
$this->content->icons[] = '';
}
$content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
$instancename = $mod->get_formatted_name();
$linkcss = $mod->visible ? '' : ' class="dimmed" ';
if (!($url = $mod->url)) {
if (!$mod->url) {
$content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
$this->content->items[] = $content . $editbuttons;
$this->content->icons[] = '';
} else {
//Accessibility: incidental image - should be empty Alt text
$icon = '<img src="' . $mod->get_icon_url() . '" class="icon" alt="" />&nbsp;';
$this->content->items[] = '<a title="' . $mod->modfullname . '" ' . $linkcss . ' ' . $mod->extra .
' href="' . $url . '">' . $icon . $instancename . '</a>' . $editbuttons;
$this->content->items[] = html_writer::div($courserenderer->course_section_cm_name($mod), 'activity') .
$editbuttons;
}
}
}
@@ -0,0 +1,31 @@
@block @block_social_activities
Feature: Edit activities in social activities block
In order to use social activities block
As a teacher
I need to add and edit activities there
@javascript
Scenario: Edit name of acitivity in-place in social activities block
Given the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | social |
And the following "users" exist:
| username | firstname | lastname |
| user1 | User | One |
And the following "course enrolments" exist:
| user | course | role |
| user1 | C1 | editingteacher |
Given I log in as "user1"
And I follow "Course 1"
And I turn editing mode on
And I set the field "Add an activity to section 'section 0'" to "Forum"
And I set the field "Forum name" to "My forum name"
And I press "Save and return to course"
And I click on "Edit title" "link" in the "//.[contains(@class,'block_social_activities')]//li[contains(.,'My forum name')]" "xpath_element"
And I set the field "New name for activity My forum name" to "New forum name"
And I press key "13" in the field "New name for activity My forum name"
Then I should not see "My forum name" in the "Social activities" "block"
And I should see "New forum name"
And I follow "New forum name"
And I should not see "My forum name"
And I should see "New forum name"
@@ -0,0 +1,100 @@
<?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/>.
/**
* Contains class core_tag\output\course_module_name
*
* @package core_course
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_course\output;
use context_module;
use lang_string;
use cm_info;
/**
* Class to prepare a course module name for display and in-place editing
*
* @package core_course
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_module_name extends \core\output\inplace_editable {
/** @var cm_info */
protected $cm;
/** @var array */
protected $displayoptions;
/**
* Constructor.
*
* @param cm_info $cm
* @param bool $editable
* @param array $displayoptions
*/
public function __construct(cm_info $cm, $editable, $displayoptions = array()) {
$this->cm = $cm;
$this->displayoptions = $displayoptions;
$value = $cm->name;
$edithint = new lang_string('edittitle');
$editlabel = new lang_string('newactivityname', '', $cm->get_formatted_name());
$editable = $editable && has_capability('moodle/course:manageactivities',
context_module::instance($cm->id));
parent::__construct(
'core_course', 'activityname', $cm->id, $editable, $value, $value, $edithint, $editlabel);
}
/**
* Export this data so it can be used as the context for a mustache template (core/inplace_editable).
*
* @param renderer_base $output typically, the renderer that's calling this function
* @return array data context for a mustache template
*/
public function export_for_template(\renderer_base $output) {
global $PAGE;
$courserenderer = $PAGE->get_renderer('core', 'course');
$this->displayvalue = $courserenderer->course_section_cm_name_title($this->cm, $this->displayoptions);
if (strval($this->displayvalue) === '') {
$this->editable = false;
}
return parent::export_for_template($output);
}
/**
* Updates course module name
*
* @param int $itemid course module id
* @param string $newvalue new name
* @return static
*/
public static function update($itemid, $newvalue) {
list($course, $cm) = get_course_and_cm_from_cmid($itemid);
$context = context_module::instance($cm->id);
// Check access.
require_login($course, false, $cm, true, true);
require_capability('moodle/course:manageactivities', $context);
// Update value.
set_coursemodule_name($cm->id, $newvalue);
// Return instance.
$cm = get_fast_modinfo($course)->get_cm($cm->id);
return new static($cm, true);
}
}
+58 -47
View File
@@ -1605,6 +1605,50 @@ function set_coursemodule_visible($id, $visible) {
return true;
}
/**
* Changes the course module name
*
* @param int $id course module id
* @param string $name new value for a name
* @return bool whether a change was made
*/
function set_coursemodule_name($id, $name) {
global $CFG, $DB;
require_once($CFG->libdir . '/gradelib.php');
$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($name, PARAM_TEXT);
} else {
$module->name = clean_param($name, PARAM_CLEANHTML);
}
if ($module->name === $cm->name || strval($module->name) === '') {
return false;
}
if (\core_text::strlen($module->name) > 255) {
throw new \moodle_exception('maximumchars', 'moodle', '', 255);
}
$module->timemodified = time();
$DB->update_record($cm->modname, $module);
$cm->name = $module->name;
\core\event\course_module_updated::create_from_cm($cm)->trigger();
rebuild_course_cache($cm->course, true);
// Attempt to update the grade item if relevant.
$grademodule = $DB->get_record($cm->modname, array('id' => $cm->instance));
$grademodule->cmidnumber = $cm->idnumber;
$grademodule->modname = $cm->modname;
grade_update_mod_grades($grademodule);
return true;
}
/**
* This function will handle the whole deletion process of a module. This includes calling
* the modules delete_instance function, deleting files, events, grades, conditional data,
@@ -2241,53 +2285,6 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
return $actions;
}
/**
* Returns the rename action.
*
* @param cm_info $mod The module to produce editing buttons for
* @param int $sr The section to link back to (used for creating the links)
* @return The markup for the rename action, or an empty string if not available.
*/
function course_get_cm_rename_action(cm_info $mod, $sr = null) {
global $COURSE, $OUTPUT;
static $str;
static $baseurl;
$modcontext = context_module::instance($mod->id);
$hasmanageactivities = has_capability('moodle/course:manageactivities', $modcontext);
if (!isset($str)) {
$str = get_strings(array('edittitle'));
}
if (!isset($baseurl)) {
$baseurl = new moodle_url('/course/mod.php', array('sesskey' => sesskey()));
}
if ($sr !== null) {
$baseurl->param('sr', $sr);
}
// AJAX edit title.
if ($mod->has_view() && $hasmanageactivities && course_ajax_enabled($COURSE) &&
(($mod->course == $COURSE->id) || ($mod->course == SITEID))) {
// we will not display link if we are on some other-course page (where we should not see this module anyway)
return html_writer::span(
html_writer::link(
new moodle_url($baseurl, array('update' => $mod->id)),
$OUTPUT->pix_icon('t/editstring', '', 'moodle', array('class' => 'iconsmall visibleifjs', 'title' => '')),
array(
'class' => 'editing_title',
'data-action' => 'edittitle',
'title' => $str->edittitle,
)
)
);
}
return '';
}
/**
* Returns the move action.
*
@@ -3897,3 +3894,17 @@ function course_get_tagged_courses($tag, $exclusivemode = false, $fromctx = 0, $
return new core_tag\output\tagindex($tag, 'core', 'course', $content,
$exclusivemode, $fromctx, $ctx, $rec, $page, $totalpages);
}
/**
* Implements callback inplace_editable() allowing to edit values in-place
*
* @param string $itemtype
* @param int $itemid
* @param mixed $newvalue
* @return \core\output\inplace_editable
*/
function core_course_inplace_editable($itemtype, $itemid, $newvalue) {
if ($itemtype === 'activityname') {
return \core_course\output\course_module_name::update($itemid, $newvalue);
}
}
+26 -6
View File
@@ -733,10 +733,34 @@ class core_course_renderer extends plugin_renderer_base {
* @return string
*/
public function course_section_cm_name(cm_info $mod, $displayoptions = array()) {
global $CFG;
if ((!$mod->uservisible && empty($mod->availableinfo)) || !$mod->url) {
// Nothing to be displayed to the user.
return '';
}
// Render element that allows to edit activity name inline. It calls {@link course_section_cm_name_title()}
// to get the display title of the activity.
$tmpl = new \core_course\output\course_module_name($mod, $this->page->user_is_editing(), $displayoptions);
return $this->output->render_from_template('core/inplace_editable', $tmpl->export_for_template($this->output));
}
/**
* Renders html to display a name with the link to the course module on a course page
*
* If module is unavailable for user but still needs to be displayed
* in the list, just the name is returned without a link
*
* Note, that for course modules that never have separate pages (i.e. labels)
* this function return an empty string
*
* @param cm_info $mod
* @param array $displayoptions
* @return string
*/
public function course_section_cm_name_title(cm_info $mod, $displayoptions = array()) {
$output = '';
if (!$mod->uservisible && empty($mod->availableinfo)) {
// nothing to be displayed to the user
// Nothing to be displayed to the user.
return $output;
}
$url = $mod->url;
@@ -985,10 +1009,6 @@ class core_course_renderer extends plugin_renderer_base {
$output .= $cmname;
if ($this->page->user_is_editing()) {
$output .= ' ' . course_get_cm_rename_action($mod, $sectionreturn);
}
// Module can put text after the link (e.g. forum unread)
$output .= $mod->afterlink;
-43
View File
@@ -150,49 +150,6 @@ switch($requestmethod) {
$isvisible = moveto_module($cm, $section, $beforemod);
echo json_encode(array('visible' => (bool) $isvisible));
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);
require_once($CFG->libdir . '/gradelib.php');
$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 (strval($module->name) !== '') {
$DB->update_record($cm->modname, $module);
$cm->name = $module->name;
\core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger();
rebuild_course_cache($cm->course);
} else {
$module->name = $cm->name;
}
// Attempt to update the grade item if relevant
$grademodule = $DB->get_record($cm->modname, array('id' => $cm->instance));
$grademodule->cmidnumber = $cm->idnumber;
$grademodule->modname = $cm->modname;
grade_update_mod_grades($grademodule);
// We need to return strings after they've been through filters for multilang
$stringoptions = new stdClass;
$stringoptions->context = $coursecontext;
echo json_encode(array('instancename' => html_entity_decode(format_string($module->name, true, $stringoptions))));
break;
}
break;
@@ -0,0 +1,44 @@
@core @core_course
Feature: Edit activity name in-place
In order to quickly edit activity name
As a teacher
I need to use inplace editing
@javascript
Scenario: Edit activity name in-place
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
When I log in as "teacher1"
And I follow "Course 1"
And I turn editing mode on
And I add a "Forum" to section "1" and I fill the form with:
| Forum name | Test forum name |
| Description | Test forum description |
# Rename activity
And I click on "Edit title" "link" in the "//div[contains(@class,'activityinstance') and contains(.,'Test forum name')]" "xpath_element"
And I set the field "New name for activity Test forum name" to "Good news"
And I press key "13" in the field "New name for activity Test forum name"
Then I should not see "Test forum name" in the ".course-content" "css_element"
And "New name for activity Test forum name" "field" should not exist
And I should see "Good news"
And I follow "Course 1"
And I should see "Good news"
And I should not see "Test forum name"
# Cancel renaming
And I click on "Edit title" "link" in the "//div[contains(@class,'activityinstance') and contains(.,'Good news')]" "xpath_element"
And I set the field "New name for activity Good news" to "Terrible news"
And I press key "27" in the field "New name for activity Good news"
And "New name for activity Good news" "field" should not exist
And I should see "Good news"
And I should not see "Terrible news"
And I follow "Course 1"
And I should see "Good news"
And I should not see "Terrible news"
And I log out
+1 -1
View File
@@ -467,7 +467,7 @@ class behat_course extends behat_base {
foreach ($activities as $activity) {
// Dimmed.
$this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' activityinstance ')]" .
"/a[contains(concat(' ', normalize-space(@class), ' '), ' dimmed ')]", $dimmedexception, $activity);
"//a[contains(concat(' ', normalize-space(@class), ' '), ' dimmed ')]", $dimmedexception, $activity);
}
}
} else {
+30
View File
@@ -2779,4 +2779,34 @@ class core_course_courselib_testcase extends advanced_testcase {
$this->assertNull($DB->get_field('course_modules', 'availability',
array('id' => $label->cmid)));
}
/**
* Test update_inplace_editable()
*/
public function test_update_module_name_inplace() {
global $CFG, $DB, $PAGE;
require_once($CFG->dirroot . '/lib/external/externallib.php');
$this->setUser($this->getDataGenerator()->create_user());
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$forum = self::getDataGenerator()->create_module('forum', array('course' => $course->id, 'name' => 'forum name'));
// Call service for core_course component without necessary permissions.
try {
core_external::update_inplace_editable('core_course', 'activityname', $forum->cmid, 'New forum name');
$this->fail('Exception expected');
} catch (moodle_exception $e) {
$this->assertEquals('Course or activity not accessible. (Not enrolled)',
$e->getMessage());
}
// Change to admin user and make sure that cm name can be updated using web service update_inplace_editable().
$this->setAdminUser();
$res = core_external::update_inplace_editable('core_course', 'activityname', $forum->cmid, 'New forum name');
$res = external_api::clean_returnvalue(core_external::update_inplace_editable_returns(), $res);
$this->assertEquals('New forum name', $res['value']);
$this->assertEquals('New forum name', $DB->get_field('forum', 'name', array('id' => $forum->id)));
}
}
@@ -19,31 +19,28 @@ var CSS = {
DIMCLASS : 'dimmed',
DIMMEDTEXT : 'dimmed_text',
EDITINSTRUCTIONS : 'editinstructions',
EDITINGTITLE: 'editor_displayed',
HIDE : 'hide',
MODINDENTCOUNT : 'mod-indent-',
MODINDENTHUGE : 'mod-indent-huge',
MODULEIDPREFIX : 'module-',
SECTIONHIDDENCLASS : 'hidden',
SECTIONIDPREFIX : 'section-',
SHOW : 'editing_show',
TITLEEDITOR : 'titleeditor'
SHOW : 'editing_show'
},
// The CSS selectors we use.
SELECTOR = {
ACTIONAREA: '.actions',
ACTIONLINKTEXT : '.actionlinktext',
ACTIVITYACTION : 'a.cm-edit-action[data-action], a.editing_title',
ACTIVITYFORM : '.' + CSS.ACTIVITYINSTANCE + ' form',
ACTIVITYACTION : 'a.cm-edit-action[data-action]',
ACTIVITYICON : 'img.activityicon',
ACTIVITYINSTANCE : '.' + CSS.ACTIVITYINSTANCE,
ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a',
ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a, .'+ CSS.ACTIVITYINSTANCE +
' > span[data-inplaceeditable] > a:not([data-inplaceeditablelink])',
ACTIVITYLI : 'li.activity',
ACTIVITYTITLE : 'input[name=title]',
COMMANDSPAN : '.commands',
CONTENTAFTERLINK : 'div.contentafterlink',
CONTENTWITHOUTLINK : 'div.contentwithoutlink',
EDITTITLE: 'a.editing_title',
GROUPINGLABEL: '.' + CSS.ACTIVITYINSTANCE + ' .groupinglabel',
HIDE : 'a.editing_hide',
HIGHLIGHT : 'a.editing_highlight',
INSTANCENAME : 'span.instancename',
@@ -256,17 +253,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
*/
GROUPS_VISIBLE: 2,
/**
* An Array of events added when editing a title.
* These should all be detached when editing is complete.
*
* @property edittitleevents
* @protected
* @type Array
* @protected
*/
edittitleevents: [],
/**
* Initialize the resource toolbox
*
@@ -317,10 +303,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
// Switch based upon the action and do the desired thing.
switch (action) {
case 'edittitle':
// The user wishes to edit the title of the event.
this.edit_title(ev, node, activity, action);
break;
case 'moveleft':
case 'moveright':
// The user changing the indent of the activity.
@@ -633,11 +615,13 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
dimarea.addClass(toggleclass);
// We need to toggle dimming on the description too.
activity.all(SELECTOR.CONTENTAFTERLINK).addClass(CSS.DIMMEDTEXT);
activity.all(SELECTOR.GROUPINGLABEL).addClass(CSS.DIMMEDTEXT);
} else {
// Change the UI.
dimarea.removeClass(toggleclass);
// We need to toggle dimming on the description too.
activity.all(SELECTOR.CONTENTAFTERLINK).removeClass(CSS.DIMMEDTEXT);
activity.all(SELECTOR.GROUPINGLABEL).removeClass(CSS.DIMMEDTEXT);
}
}
// Toggle availablity info for conditional activities.
@@ -714,172 +698,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
return this;
},
/**
* Edit the title for the resource
*
* @method edit_title
* @protected
* @param {EventFacade} ev The event that was fired.
* @param {Node} button The button that triggered this action.
* @param {Node} activity The activity node that this action will be performed on.
* @param {String} action The action that has been requested.
* @chainable
*/
edit_title: function(ev, button, activity) {
// Get the element we're working on
var activityid = Y.Moodle.core_course.util.cm.getId(activity),
instancename = activity.one(SELECTOR.INSTANCENAME),
instance = activity.one(SELECTOR.ACTIVITYINSTANCE),
currenttitle = instancename.get('firstChild'),
oldtitle = currenttitle.get('data'),
titletext = oldtitle,
thisevent,
anchor = instancename.ancestor('a'),// Grab the anchor so that we can swap it with the edit form.
data = {
'class': 'resource',
'field': 'gettitle',
'id': activityid
};
// Prevent the default actions.
ev.preventDefault();
this.send_request(data, null, function(response) {
if (M.core.actionmenu && M.core.actionmenu.instance) {
M.core.actionmenu.instance.hideMenu(ev);
}
// Try to retrieve the existing string from the server
if (response.instancename) {
titletext = response.instancename;
}
// Create the editor and submit button
var editform = Y.Node.create('<form action="#" />');
var editinstructions = Y.Node.create('<span class="'+CSS.EDITINSTRUCTIONS+'" id="id_editinstructions" />')
.set('innerHTML', M.util.get_string('edittitleinstructions', 'moodle'));
var editor = Y.Node.create('<input name="title" type="text" class="'+CSS.TITLEEDITOR+'" />').setAttrs({
'value': titletext,
'autocomplete': 'off',
'aria-describedby': 'id_editinstructions',
'maxLength': '255'
});
// Clear the existing content and put the editor in
editform.appendChild(activity.one(SELECTOR.ACTIVITYICON).cloneNode());
editform.appendChild(editor);
editform.setData('anchor', anchor);
instance.insert(editinstructions, 'before');
anchor.replace(editform);
// Force the editing instruction to match the mod-indent position.
var padside = 'left';
if (window.right_to_left()) {
padside = 'right';
}
// We hide various components whilst editing:
activity.addClass(CSS.EDITINGTITLE);
// Focus and select the editor text
editor.focus().select();
// Cancel the edit if we lose focus or the escape key is pressed.
thisevent = editor.on('blur', this.edit_title_cancel, this, activity, false);
this.edittitleevents.push(thisevent);
thisevent = editor.on('key', this.edit_title_cancel, 'esc', this, activity, true);
this.edittitleevents.push(thisevent);
// Handle form submission.
thisevent = editform.on('submit', this.edit_title_submit, this, activity, oldtitle);
this.edittitleevents.push(thisevent);
});
return this;
},
/**
* Handles the submit event when editing the activity or resources title.
*
* @method edit_title_submit
* @protected
* @param {EventFacade} ev The event that triggered this.
* @param {Node} activity The activity whose title we are altering.
* @param {String} originaltitle The original title the activity or resource had.
*/
edit_title_submit: function(ev, activity, originaltitle) {
// We don't actually want to submit anything
ev.preventDefault();
var newtitle = Y.Lang.trim(activity.one(SELECTOR.ACTIVITYFORM + ' ' + SELECTOR.ACTIVITYTITLE).get('value'));
this.edit_title_clear(activity);
var spinner = this.add_spinner(activity);
if (newtitle !== null && newtitle !== "" && newtitle !== originaltitle) {
var data = {
'class': 'resource',
'field': 'updatetitle',
'title': newtitle,
'id': Y.Moodle.core_course.util.cm.getId(activity)
};
this.send_request(data, spinner, function(response) {
if (response.instancename) {
activity.one(SELECTOR.INSTANCENAME).setContent(response.instancename);
}
});
}
},
/**
* Handles the cancel event when editing the activity or resources title.
*
* @method edit_title_cancel
* @protected
* @param {EventFacade} ev The event that triggered this.
* @param {Node} activity The activity whose title we are altering.
* @param {Boolean} preventdefault If true we should prevent the default action from occuring.
*/
edit_title_cancel: function(ev, activity, preventdefault) {
if (preventdefault) {
ev.preventDefault();
}
this.edit_title_clear(activity);
},
/**
* Handles clearing the editing UI and returning things to the original state they were in.
*
* @method edit_title_clear
* @protected
* @param {Node} activity The activity whose title we were altering.
*/
edit_title_clear: function(activity) {
// Detach all listen events to prevent duplicate triggers
new Y.EventHandle(this.edittitleevents).detach();
var editform = activity.one(SELECTOR.ACTIVITYFORM),
instructions = activity.one('#id_editinstructions');
if (editform) {
editform.replace(editform.getData('anchor'));
}
if (instructions) {
instructions.remove();
}
// Remove the editing class again to revert the display.
activity.removeClass(CSS.EDITINGTITLE);
// Refocus the link which was clicked originally so the user can continue using keyboard nav.
Y.later(100, this, function() {
activity.one(SELECTOR.EDITTITLE).focus();
});
// TODO MDL-50768 This hack is to keep Behat happy until they release a version of
// MinkSelenium2Driver that fixes
// https://github.com/Behat/MinkSelenium2Driver/issues/80.
if (!Y.one('input[name=title]')) {
Y.one('body').append('<input type="text" name="title" style="display: none">');
}
},
/**
* Set the visibility of the specified resource to match the visible parameter.
*
File diff suppressed because one or more lines are too long
@@ -19,31 +19,28 @@ var CSS = {
DIMCLASS : 'dimmed',
DIMMEDTEXT : 'dimmed_text',
EDITINSTRUCTIONS : 'editinstructions',
EDITINGTITLE: 'editor_displayed',
HIDE : 'hide',
MODINDENTCOUNT : 'mod-indent-',
MODINDENTHUGE : 'mod-indent-huge',
MODULEIDPREFIX : 'module-',
SECTIONHIDDENCLASS : 'hidden',
SECTIONIDPREFIX : 'section-',
SHOW : 'editing_show',
TITLEEDITOR : 'titleeditor'
SHOW : 'editing_show'
},
// The CSS selectors we use.
SELECTOR = {
ACTIONAREA: '.actions',
ACTIONLINKTEXT : '.actionlinktext',
ACTIVITYACTION : 'a.cm-edit-action[data-action], a.editing_title',
ACTIVITYFORM : '.' + CSS.ACTIVITYINSTANCE + ' form',
ACTIVITYACTION : 'a.cm-edit-action[data-action]',
ACTIVITYICON : 'img.activityicon',
ACTIVITYINSTANCE : '.' + CSS.ACTIVITYINSTANCE,
ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a',
ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a, .'+ CSS.ACTIVITYINSTANCE +
' > span[data-inplaceeditable] > a:not([data-inplaceeditablelink])',
ACTIVITYLI : 'li.activity',
ACTIVITYTITLE : 'input[name=title]',
COMMANDSPAN : '.commands',
CONTENTAFTERLINK : 'div.contentafterlink',
CONTENTWITHOUTLINK : 'div.contentwithoutlink',
EDITTITLE: 'a.editing_title',
GROUPINGLABEL: '.' + CSS.ACTIVITYINSTANCE + ' .groupinglabel',
HIDE : 'a.editing_hide',
HIGHLIGHT : 'a.editing_highlight',
INSTANCENAME : 'span.instancename',
@@ -256,17 +253,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
*/
GROUPS_VISIBLE: 2,
/**
* An Array of events added when editing a title.
* These should all be detached when editing is complete.
*
* @property edittitleevents
* @protected
* @type Array
* @protected
*/
edittitleevents: [],
/**
* Initialize the resource toolbox
*
@@ -317,10 +303,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
// Switch based upon the action and do the desired thing.
switch (action) {
case 'edittitle':
// The user wishes to edit the title of the event.
this.edit_title(ev, node, activity, action);
break;
case 'moveleft':
case 'moveright':
// The user changing the indent of the activity.
@@ -633,11 +615,13 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
dimarea.addClass(toggleclass);
// We need to toggle dimming on the description too.
activity.all(SELECTOR.CONTENTAFTERLINK).addClass(CSS.DIMMEDTEXT);
activity.all(SELECTOR.GROUPINGLABEL).addClass(CSS.DIMMEDTEXT);
} else {
// Change the UI.
dimarea.removeClass(toggleclass);
// We need to toggle dimming on the description too.
activity.all(SELECTOR.CONTENTAFTERLINK).removeClass(CSS.DIMMEDTEXT);
activity.all(SELECTOR.GROUPINGLABEL).removeClass(CSS.DIMMEDTEXT);
}
}
// Toggle availablity info for conditional activities.
@@ -714,172 +698,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
return this;
},
/**
* Edit the title for the resource
*
* @method edit_title
* @protected
* @param {EventFacade} ev The event that was fired.
* @param {Node} button The button that triggered this action.
* @param {Node} activity The activity node that this action will be performed on.
* @param {String} action The action that has been requested.
* @chainable
*/
edit_title: function(ev, button, activity) {
// Get the element we're working on
var activityid = Y.Moodle.core_course.util.cm.getId(activity),
instancename = activity.one(SELECTOR.INSTANCENAME),
instance = activity.one(SELECTOR.ACTIVITYINSTANCE),
currenttitle = instancename.get('firstChild'),
oldtitle = currenttitle.get('data'),
titletext = oldtitle,
thisevent,
anchor = instancename.ancestor('a'),// Grab the anchor so that we can swap it with the edit form.
data = {
'class': 'resource',
'field': 'gettitle',
'id': activityid
};
// Prevent the default actions.
ev.preventDefault();
this.send_request(data, null, function(response) {
if (M.core.actionmenu && M.core.actionmenu.instance) {
M.core.actionmenu.instance.hideMenu(ev);
}
// Try to retrieve the existing string from the server
if (response.instancename) {
titletext = response.instancename;
}
// Create the editor and submit button
var editform = Y.Node.create('<form action="#" />');
var editinstructions = Y.Node.create('<span class="'+CSS.EDITINSTRUCTIONS+'" id="id_editinstructions" />')
.set('innerHTML', M.util.get_string('edittitleinstructions', 'moodle'));
var editor = Y.Node.create('<input name="title" type="text" class="'+CSS.TITLEEDITOR+'" />').setAttrs({
'value': titletext,
'autocomplete': 'off',
'aria-describedby': 'id_editinstructions',
'maxLength': '255'
});
// Clear the existing content and put the editor in
editform.appendChild(activity.one(SELECTOR.ACTIVITYICON).cloneNode());
editform.appendChild(editor);
editform.setData('anchor', anchor);
instance.insert(editinstructions, 'before');
anchor.replace(editform);
// Force the editing instruction to match the mod-indent position.
var padside = 'left';
if (window.right_to_left()) {
padside = 'right';
}
// We hide various components whilst editing:
activity.addClass(CSS.EDITINGTITLE);
// Focus and select the editor text
editor.focus().select();
// Cancel the edit if we lose focus or the escape key is pressed.
thisevent = editor.on('blur', this.edit_title_cancel, this, activity, false);
this.edittitleevents.push(thisevent);
thisevent = editor.on('key', this.edit_title_cancel, 'esc', this, activity, true);
this.edittitleevents.push(thisevent);
// Handle form submission.
thisevent = editform.on('submit', this.edit_title_submit, this, activity, oldtitle);
this.edittitleevents.push(thisevent);
});
return this;
},
/**
* Handles the submit event when editing the activity or resources title.
*
* @method edit_title_submit
* @protected
* @param {EventFacade} ev The event that triggered this.
* @param {Node} activity The activity whose title we are altering.
* @param {String} originaltitle The original title the activity or resource had.
*/
edit_title_submit: function(ev, activity, originaltitle) {
// We don't actually want to submit anything
ev.preventDefault();
var newtitle = Y.Lang.trim(activity.one(SELECTOR.ACTIVITYFORM + ' ' + SELECTOR.ACTIVITYTITLE).get('value'));
this.edit_title_clear(activity);
var spinner = this.add_spinner(activity);
if (newtitle !== null && newtitle !== "" && newtitle !== originaltitle) {
var data = {
'class': 'resource',
'field': 'updatetitle',
'title': newtitle,
'id': Y.Moodle.core_course.util.cm.getId(activity)
};
this.send_request(data, spinner, function(response) {
if (response.instancename) {
activity.one(SELECTOR.INSTANCENAME).setContent(response.instancename);
}
});
}
},
/**
* Handles the cancel event when editing the activity or resources title.
*
* @method edit_title_cancel
* @protected
* @param {EventFacade} ev The event that triggered this.
* @param {Node} activity The activity whose title we are altering.
* @param {Boolean} preventdefault If true we should prevent the default action from occuring.
*/
edit_title_cancel: function(ev, activity, preventdefault) {
if (preventdefault) {
ev.preventDefault();
}
this.edit_title_clear(activity);
},
/**
* Handles clearing the editing UI and returning things to the original state they were in.
*
* @method edit_title_clear
* @protected
* @param {Node} activity The activity whose title we were altering.
*/
edit_title_clear: function(activity) {
// Detach all listen events to prevent duplicate triggers
new Y.EventHandle(this.edittitleevents).detach();
var editform = activity.one(SELECTOR.ACTIVITYFORM),
instructions = activity.one('#id_editinstructions');
if (editform) {
editform.replace(editform.getData('anchor'));
}
if (instructions) {
instructions.remove();
}
// Remove the editing class again to revert the display.
activity.removeClass(CSS.EDITINGTITLE);
// Refocus the link which was clicked originally so the user can continue using keyboard nav.
Y.later(100, this, function() {
activity.one(SELECTOR.EDITTITLE).focus();
});
// TODO MDL-50768 This hack is to keep Behat happy until they release a version of
// MinkSelenium2Driver that fixes
// https://github.com/Behat/MinkSelenium2Driver/issues/80.
if (!Y.one('input[name=title]')) {
Y.one('body').append('<input type="text" name="title" style="display: none">');
}
},
/**
* Set the visibility of the specified resource to match the visible parameter.
*
+2 -181
View File
@@ -52,17 +52,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
*/
GROUPS_VISIBLE: 2,
/**
* An Array of events added when editing a title.
* These should all be detached when editing is complete.
*
* @property edittitleevents
* @protected
* @type Array
* @protected
*/
edittitleevents: [],
/**
* Initialize the resource toolbox
*
@@ -113,10 +102,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
// Switch based upon the action and do the desired thing.
switch (action) {
case 'edittitle':
// The user wishes to edit the title of the event.
this.edit_title(ev, node, activity, action);
break;
case 'moveleft':
case 'moveright':
// The user changing the indent of the activity.
@@ -429,11 +414,13 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
dimarea.addClass(toggleclass);
// We need to toggle dimming on the description too.
activity.all(SELECTOR.CONTENTAFTERLINK).addClass(CSS.DIMMEDTEXT);
activity.all(SELECTOR.GROUPINGLABEL).addClass(CSS.DIMMEDTEXT);
} else {
// Change the UI.
dimarea.removeClass(toggleclass);
// We need to toggle dimming on the description too.
activity.all(SELECTOR.CONTENTAFTERLINK).removeClass(CSS.DIMMEDTEXT);
activity.all(SELECTOR.GROUPINGLABEL).removeClass(CSS.DIMMEDTEXT);
}
}
// Toggle availablity info for conditional activities.
@@ -510,172 +497,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
return this;
},
/**
* Edit the title for the resource
*
* @method edit_title
* @protected
* @param {EventFacade} ev The event that was fired.
* @param {Node} button The button that triggered this action.
* @param {Node} activity The activity node that this action will be performed on.
* @param {String} action The action that has been requested.
* @chainable
*/
edit_title: function(ev, button, activity) {
// Get the element we're working on
var activityid = Y.Moodle.core_course.util.cm.getId(activity),
instancename = activity.one(SELECTOR.INSTANCENAME),
instance = activity.one(SELECTOR.ACTIVITYINSTANCE),
currenttitle = instancename.get('firstChild'),
oldtitle = currenttitle.get('data'),
titletext = oldtitle,
thisevent,
anchor = instancename.ancestor('a'),// Grab the anchor so that we can swap it with the edit form.
data = {
'class': 'resource',
'field': 'gettitle',
'id': activityid
};
// Prevent the default actions.
ev.preventDefault();
this.send_request(data, null, function(response) {
if (M.core.actionmenu && M.core.actionmenu.instance) {
M.core.actionmenu.instance.hideMenu(ev);
}
// Try to retrieve the existing string from the server
if (response.instancename) {
titletext = response.instancename;
}
// Create the editor and submit button
var editform = Y.Node.create('<form action="#" />');
var editinstructions = Y.Node.create('<span class="'+CSS.EDITINSTRUCTIONS+'" id="id_editinstructions" />')
.set('innerHTML', M.util.get_string('edittitleinstructions', 'moodle'));
var editor = Y.Node.create('<input name="title" type="text" class="'+CSS.TITLEEDITOR+'" />').setAttrs({
'value': titletext,
'autocomplete': 'off',
'aria-describedby': 'id_editinstructions',
'maxLength': '255'
});
// Clear the existing content and put the editor in
editform.appendChild(activity.one(SELECTOR.ACTIVITYICON).cloneNode());
editform.appendChild(editor);
editform.setData('anchor', anchor);
instance.insert(editinstructions, 'before');
anchor.replace(editform);
// Force the editing instruction to match the mod-indent position.
var padside = 'left';
if (window.right_to_left()) {
padside = 'right';
}
// We hide various components whilst editing:
activity.addClass(CSS.EDITINGTITLE);
// Focus and select the editor text
editor.focus().select();
// Cancel the edit if we lose focus or the escape key is pressed.
thisevent = editor.on('blur', this.edit_title_cancel, this, activity, false);
this.edittitleevents.push(thisevent);
thisevent = editor.on('key', this.edit_title_cancel, 'esc', this, activity, true);
this.edittitleevents.push(thisevent);
// Handle form submission.
thisevent = editform.on('submit', this.edit_title_submit, this, activity, oldtitle);
this.edittitleevents.push(thisevent);
});
return this;
},
/**
* Handles the submit event when editing the activity or resources title.
*
* @method edit_title_submit
* @protected
* @param {EventFacade} ev The event that triggered this.
* @param {Node} activity The activity whose title we are altering.
* @param {String} originaltitle The original title the activity or resource had.
*/
edit_title_submit: function(ev, activity, originaltitle) {
// We don't actually want to submit anything
ev.preventDefault();
var newtitle = Y.Lang.trim(activity.one(SELECTOR.ACTIVITYFORM + ' ' + SELECTOR.ACTIVITYTITLE).get('value'));
this.edit_title_clear(activity);
var spinner = this.add_spinner(activity);
if (newtitle !== null && newtitle !== "" && newtitle !== originaltitle) {
var data = {
'class': 'resource',
'field': 'updatetitle',
'title': newtitle,
'id': Y.Moodle.core_course.util.cm.getId(activity)
};
this.send_request(data, spinner, function(response) {
if (response.instancename) {
activity.one(SELECTOR.INSTANCENAME).setContent(response.instancename);
}
});
}
},
/**
* Handles the cancel event when editing the activity or resources title.
*
* @method edit_title_cancel
* @protected
* @param {EventFacade} ev The event that triggered this.
* @param {Node} activity The activity whose title we are altering.
* @param {Boolean} preventdefault If true we should prevent the default action from occuring.
*/
edit_title_cancel: function(ev, activity, preventdefault) {
if (preventdefault) {
ev.preventDefault();
}
this.edit_title_clear(activity);
},
/**
* Handles clearing the editing UI and returning things to the original state they were in.
*
* @method edit_title_clear
* @protected
* @param {Node} activity The activity whose title we were altering.
*/
edit_title_clear: function(activity) {
// Detach all listen events to prevent duplicate triggers
new Y.EventHandle(this.edittitleevents).detach();
var editform = activity.one(SELECTOR.ACTIVITYFORM),
instructions = activity.one('#id_editinstructions');
if (editform) {
editform.replace(editform.getData('anchor'));
}
if (instructions) {
instructions.remove();
}
// Remove the editing class again to revert the display.
activity.removeClass(CSS.EDITINGTITLE);
// Refocus the link which was clicked originally so the user can continue using keyboard nav.
Y.later(100, this, function() {
activity.one(SELECTOR.EDITTITLE).focus();
});
// TODO MDL-50768 This hack is to keep Behat happy until they release a version of
// MinkSelenium2Driver that fixes
// https://github.com/Behat/MinkSelenium2Driver/issues/80.
if (!Y.one('input[name=title]')) {
Y.one('body').append('<input type="text" name="title" style="display: none">');
}
},
/**
* Set the visibility of the specified resource to match the visible parameter.
*
+5 -8
View File
@@ -17,31 +17,28 @@ var CSS = {
DIMCLASS : 'dimmed',
DIMMEDTEXT : 'dimmed_text',
EDITINSTRUCTIONS : 'editinstructions',
EDITINGTITLE: 'editor_displayed',
HIDE : 'hide',
MODINDENTCOUNT : 'mod-indent-',
MODINDENTHUGE : 'mod-indent-huge',
MODULEIDPREFIX : 'module-',
SECTIONHIDDENCLASS : 'hidden',
SECTIONIDPREFIX : 'section-',
SHOW : 'editing_show',
TITLEEDITOR : 'titleeditor'
SHOW : 'editing_show'
},
// The CSS selectors we use.
SELECTOR = {
ACTIONAREA: '.actions',
ACTIONLINKTEXT : '.actionlinktext',
ACTIVITYACTION : 'a.cm-edit-action[data-action], a.editing_title',
ACTIVITYFORM : '.' + CSS.ACTIVITYINSTANCE + ' form',
ACTIVITYACTION : 'a.cm-edit-action[data-action]',
ACTIVITYICON : 'img.activityicon',
ACTIVITYINSTANCE : '.' + CSS.ACTIVITYINSTANCE,
ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a',
ACTIVITYLINK: '.' + CSS.ACTIVITYINSTANCE + ' > a, .'+ CSS.ACTIVITYINSTANCE +
' > span[data-inplaceeditable] > a:not([data-inplaceeditablelink])',
ACTIVITYLI : 'li.activity',
ACTIVITYTITLE : 'input[name=title]',
COMMANDSPAN : '.commands',
CONTENTAFTERLINK : 'div.contentafterlink',
CONTENTWITHOUTLINK : 'div.contentwithoutlink',
EDITTITLE: 'a.editing_title',
GROUPINGLABEL: '.' + CSS.ACTIVITYINSTANCE + ' .groupinglabel',
HIDE : 'a.editing_hide',
HIGHLIGHT : 'a.editing_highlight',
INSTANCENAME : 'span.instancename',
+1
View File
@@ -1228,6 +1228,7 @@ $string['never'] = 'Never';
$string['neverdeletelogs'] = 'Never delete logs';
$string['new'] = 'New';
$string['newaccount'] = 'New account';
$string['newactivityname'] = 'New name for activity {$a}';
$string['newcourse'] = 'New course';
$string['newpassword'] = 'New password';
$string['newpassword_help'] = 'Enter a new password or leave blank to keep current password.';
+51
View File
@@ -4408,3 +4408,54 @@ function get_clam_error_code($returncode) {
$antivirus = \core\antivirus\manager::get_antivirus('clamav');
return $antivirus->get_clam_error_code($returncode);
}
/**
* Returns the rename action.
*
* @deprecated since 3.1
* @param cm_info $mod The module to produce editing buttons for
* @param int $sr The section to link back to (used for creating the links)
* @return The markup for the rename action, or an empty string if not available.
*/
function course_get_cm_rename_action(cm_info $mod, $sr = null) {
global $COURSE, $OUTPUT;
static $str;
static $baseurl;
debugging('Function course_get_cm_rename_action() is deprecated. Please use inplace_editable ' .
'https://docs.moodle.org/dev/Inplace_editable', DEBUG_DEVELOPER);
$modcontext = context_module::instance($mod->id);
$hasmanageactivities = has_capability('moodle/course:manageactivities', $modcontext);
if (!isset($str)) {
$str = get_strings(array('edittitle'));
}
if (!isset($baseurl)) {
$baseurl = new moodle_url('/course/mod.php', array('sesskey' => sesskey()));
}
if ($sr !== null) {
$baseurl->param('sr', $sr);
}
// AJAX edit title.
if ($mod->has_view() && $hasmanageactivities && course_ajax_enabled($COURSE) &&
(($mod->course == $COURSE->id) || ($mod->course == SITEID))) {
// we will not display link if we are on some other-course page (where we should not see this module anyway)
return html_writer::span(
html_writer::link(
new moodle_url($baseurl, array('update' => $mod->id)),
$OUTPUT->pix_icon('t/editstring', '', 'moodle', array('class' => 'iconsmall visibleifjs', 'title' => '')),
array(
'class' => 'editing_title',
'data-action' => 'edittitle',
'title' => $str->edittitle,
)
)
);
}
return '';
}
+3
View File
@@ -11,6 +11,9 @@ information provided here is intended especially for theme designer.
* notification_problem.mustache => notification_error.mustache
* notification_message => notification_info
* notification_redirect => notification_warning
* Method core_course_renderer::course_section_cm_name() is split into two methods, custom themes that override
this method must be modified or otherwise editing functionality may become broken. This method is now also used by
social activities block and site menu block to display activities names.
=== 3.0 ===