Merge branch 'MDL-32135_m32v2' of https://github.com/sbourget/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 28 Jun 2016 09:07:43 +0000 (10:07 +0100)
committerDan Poltawski <dan@moodle.com>
Thu, 30 Jun 2016 08:24:55 +0000 (09:24 +0100)
205 files changed:
.eslintrc
admin/settings/plugins.php
admin/tool/behat/cli/run.php
admin/tool/health/styles.css
admin/tool/lp/amd/build/competencies.min.js
admin/tool/lp/amd/build/tree.min.js
admin/tool/lp/amd/src/actionselector.js
admin/tool/lp/amd/src/competencies.js
admin/tool/lp/amd/src/competency_outcomes.js
admin/tool/lp/amd/src/competency_plan_navigation.js
admin/tool/lp/amd/src/competency_rule.js
admin/tool/lp/amd/src/competencyactions.js
admin/tool/lp/amd/src/competencydialogue.js
admin/tool/lp/amd/src/competencypicker.js
admin/tool/lp/amd/src/competencypicker_user_plans.js
admin/tool/lp/amd/src/competencyruleconfig.js
admin/tool/lp/amd/src/course_competency_settings.js
admin/tool/lp/amd/src/dialogue.js
admin/tool/lp/amd/src/dragdrop-reorder.js
admin/tool/lp/amd/src/event_base.js
admin/tool/lp/amd/src/evidence_delete.js
admin/tool/lp/amd/src/frameworkactions.js
admin/tool/lp/amd/src/frameworks_datasource.js
admin/tool/lp/amd/src/grade_dialogue.js
admin/tool/lp/amd/src/grade_user_competency_inline.js
admin/tool/lp/amd/src/menubar.js
admin/tool/lp/amd/src/parentcompetency_form.js
admin/tool/lp/amd/src/planactions.js
admin/tool/lp/amd/src/scaleconfig.js
admin/tool/lp/amd/src/scalevalues.js
admin/tool/lp/amd/src/templateactions.js
admin/tool/lp/amd/src/tree.js
admin/tool/lp/amd/src/user_competency_course_navigation.js
admin/tool/lp/amd/src/user_competency_info.js
admin/tool/lp/amd/src/user_competency_plan_popup.js
admin/tool/lp/amd/src/user_competency_workflow.js
admin/tool/lp/amd/src/user_evidence_actions.js
admin/tool/lp/classes/external/course_module_summary_exporter.php
admin/tool/lp/styles.css
admin/tool/mobile/tests/externallib_test.php
admin/tool/templatelibrary/amd/build/display.min.js
admin/tool/templatelibrary/amd/src/display.js
admin/tool/templatelibrary/amd/src/search.js
blocks/community/styles.css
blocks/navigation/amd/src/ajax_response_renderer.js
blocks/navigation/amd/src/nav_loader.js
blocks/private_files/tests/behat/block_private_files_dashboard.feature
blocks/private_files/tests/behat/block_private_files_frontpage.feature
comment/lib.php
competency/classes/api.php
competency/classes/evidence.php
competency/tests/api_test.php
completion/criteria/completion_criteria_activity.php
composer.json
composer.lock
course/completion_form.php
course/format/README.txt
course/format/topics/tests/behat/edit_delete_sections.feature
course/format/upgrade.txt
course/renderer.php
course/tests/behat/behat_course.php
course/tests/behat/restrict_available_activities.feature
course/view.php
course/yui/build/moodle-course-modchooser/moodle-course-modchooser-debug.js
course/yui/build/moodle-course-modchooser/moodle-course-modchooser-min.js
course/yui/build/moodle-course-modchooser/moodle-course-modchooser.js
course/yui/src/modchooser/js/modchooser.js
enrol/tests/behat/behat_enrol.php
filter/mediaplugin/styles.css
grade/grading/form/guide/amd/src/comment_chooser.js
grade/grading/form/guide/lang/en/gradingform_guide.php
grade/grading/form/guide/tests/behat/behat_gradingform_guide.php
grade/grading/form/guide/tests/behat/edit_guide.feature
grade/lib.php
grade/report/grader/styles.css
grade/report/grader/tests/behat/ajax_grader.feature
grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-debug.js
grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-min.js
grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable.js
grade/report/grader/yui/src/gradereporttable/js/floatingheaders.js
grade/report/singleview/styles.css
group/clientlib.js
install/lang/da_rum/langconfig.php [new file with mode: 0644]
install/lang/pt/moodle.php
install/lang/ro/install.php
install/lang/ru/admin.php
install/lang/ru/moodle.php
install/lang/zh_tw/install.php
lang/en/admin.php
lang/en/auth.php
lang/en/backup.php
lang/en/badges.php
lang/en/deprecated.txt
lang/en/install.php
lang/en/moodle.php
lang/en/question.php
lib/amd/build/form-autocomplete.min.js
lib/amd/build/permissionmanager.min.js
lib/amd/build/templates.min.js
lib/amd/src/ajax.js
lib/amd/src/event.js
lib/amd/src/first.js
lib/amd/src/form-autocomplete.js
lib/amd/src/fragment.js
lib/amd/src/localstorage.js
lib/amd/src/log.js
lib/amd/src/notification.js
lib/amd/src/permissionmanager.js
lib/amd/src/str.js
lib/amd/src/tag.js
lib/amd/src/templates.js
lib/amd/src/tree.js
lib/amd/src/url.js
lib/behat/behat_base.php
lib/behat/form_field/behat_form_select.php
lib/classes/user.php
lib/filestorage/file_storage.php
lib/form/form.js
lib/moodlelib.php
lib/navigationlib.php
lib/tests/behat/behat_general.php
lib/tests/behat/behat_hooks.php
lib/tests/moodlelib_test.php
lib/upgrade.txt
lib/upgradelib.php
login/tests/behat/behat_login.php [new file with mode: 0644]
login/tests/behat/change_password.feature [new file with mode: 0644]
mod/assign/amd/src/grading_actions.js
mod/assign/amd/src/grading_navigation.js
mod/assign/amd/src/grading_navigation_user_info.js
mod/assign/amd/src/grading_panel.js
mod/assign/externallib.php
mod/assign/feedback/editpdf/styles.css
mod/assign/feedback/editpdf/tests/behat/annotate_pdf.feature
mod/assign/feedback/editpdf/tests/behat/group_annotations.feature
mod/assign/tests/behat/quickgrading.feature
mod/book/tool/print/print.css
mod/choice/backup/moodle2/backup_choice_stepslib.php
mod/choice/lib.php
mod/choice/styles.css
mod/data/lang/en/data.php
mod/data/mod_form.php
mod/data/preset/imagegallery/csstemplate.css
mod/feedback/classes/observer.php [new file with mode: 0644]
mod/feedback/db/events.php [moved from course/category.php with 57% similarity]
mod/feedback/lang/en/feedback.php
mod/feedback/lib.php
mod/feedback/mod_form.php
mod/feedback/tests/behat/behat_mod_feedback.php
mod/feedback/tests/events_test.php
mod/feedback/version.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/styles.css
mod/forum/tests/behat/discussion_navigation.feature
mod/lesson/lib.php
mod/lesson/mod_form.php
mod/lti/amd/src/cartridge_registration_form.js
mod/lti/amd/src/external_registration.js
mod/lti/amd/src/external_registration_return.js
mod/lti/amd/src/tool_card_controller.js
mod/lti/amd/src/tool_configure_controller.js
mod/lti/amd/src/tool_proxy.js
mod/lti/amd/src/tool_proxy_card_controller.js
mod/lti/amd/src/tool_type.js
mod/lti/lang/en/lti.php
mod/lti/tests/behat/addtool.feature
mod/lti/tests/behat/toolconfigure.feature
mod/quiz/amd/src/preflightcheck.js
mod/quiz/lib.php
mod/quiz/tests/behat/attempt_begin.feature
mod/quiz/tests/behat/editing_add.feature
mod/scorm/styles.css
mod/survey/save.php
mod/upgrade.txt
report/competency/amd/src/grading_popup.js
report/competency/amd/src/user_course_navigation.js
report/eventlist/tests/behat/mainsection.feature
report/upgrade.txt
repository/filepicker.php
repository/filesystem/lib.php
repository/lib.php
repository/repository_ajax.php
repository/upgrade.txt
search/classes/manager.php
search/tests/fixtures/mock_search_area.php
search/tests/fixtures/testable_core_search.php
search/tests/manager_test.php
user/classes/course_form.php [new file with mode: 0644]
user/course.php [new file with mode: 0644]
user/edit.php
user/editadvanced.php
user/editadvanced_form.php
user/editlib.php
user/externallib.php
user/tests/behat/course_preference.feature [new file with mode: 0644]
user/tests/externallib_test.php
version.php
webservice/lib.php
webservice/soap/locallib.php
webservice/tests/externallib_test.php
webservice/upgrade.txt
webservice/xmlrpc/locallib.php
webservice/xmlrpc/tests/locallib_test.php [new file with mode: 0644]
webservice/xmlrpc/tests/xmlrpc_server_test.php [new file with mode: 0644]

index 31bd8ab..03dc85a 100644 (file)
--- a/.eslintrc
+++ b/.eslintrc
@@ -40,7 +40,7 @@
     'no-unreachable': 'warn',
     'no-unsafe-finally': 'error',
     'use-isnan': 'error',
-    'valid-jsdoc': ['warn', { 'requireReturn': false }],
+    'valid-jsdoc': ['warn', { 'requireReturn': false, 'requireParamDescription': false, 'requireReturnDescription': false }],
     'valid-typeof': 'error',
 
     // === Best Practices ===
     'max-params': 'off',
     'max-statements': 'off',
     'max-statements-per-line': 'off',
-    'new-cap': 'warn',
+    'new-cap': ['warn', { 'properties': false }],
     'new-parens': 'warn',
     'newline-after-var': 'off',
     'newline-before-return': 'off',
index 1beaca5..680bd3d 100644 (file)
@@ -40,7 +40,9 @@ if ($hassiteconfig) {
         get_string('requiremodintro', 'admin'), get_string('requiremodintro_desc', 'admin'), 0));
     $ADMIN->add('modsettings', $temp);
 
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('mod') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('mod');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\mod $plugin */
         $plugin->load_settings($ADMIN, 'modsettings', $hassiteconfig);
     }
@@ -50,7 +52,9 @@ if ($hassiteconfig) {
     $temp = new admin_settingpage('manageformats', new lang_string('manageformats', 'core_admin'));
     $temp->add(new admin_setting_manageformats());
     $ADMIN->add('formatsettings', $temp);
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('format') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('format');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\format $plugin */
         $plugin->load_settings($ADMIN, 'formatsettings', $hassiteconfig);
     }
@@ -58,7 +62,9 @@ if ($hassiteconfig) {
     // blocks
     $ADMIN->add('modules', new admin_category('blocksettings', new lang_string('blocks')));
     $ADMIN->add('blocksettings', new admin_page_manageblocks());
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('block') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('block');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\block $plugin */
         $plugin->load_settings($ADMIN, 'blocksettings', $hassiteconfig);
     }
@@ -67,7 +73,9 @@ if ($hassiteconfig) {
     $ADMIN->add('modules', new admin_category('messageoutputs', new lang_string('messageoutputs', 'message')));
     $ADMIN->add('messageoutputs', new admin_page_managemessageoutputs());
     $ADMIN->add('messageoutputs', new admin_page_defaultmessageoutputs());
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('message') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('message');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\message $plugin */
         $plugin->load_settings($ADMIN, 'messageoutputs', $hassiteconfig);
     }
@@ -108,7 +116,9 @@ if ($hassiteconfig) {
     $temp = new admin_externalpage('authtestsettings', get_string('testsettings', 'core_auth'), new moodle_url("/auth/test_settings.php"), 'moodle/site:config', true);
     $ADMIN->add('authsettings', $temp);
 
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('auth') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('auth');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\auth $plugin */
         $plugin->load_settings($ADMIN, 'authsettings', $hassiteconfig);
     }
@@ -122,7 +132,9 @@ if ($hassiteconfig) {
     $temp = new admin_externalpage('enroltestsettings', get_string('testsettings', 'core_enrol'), new moodle_url("/enrol/test_settings.php"), 'moodle/site:config', true);
     $ADMIN->add('enrolments', $temp);
 
-    foreach(core_plugin_manager::instance()->get_plugins_of_type('enrol') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('enrol');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\enrol $plugin */
         $plugin->load_settings($ADMIN, 'enrolments', $hassiteconfig);
     }
@@ -133,7 +145,9 @@ if ($hassiteconfig) {
     $temp = new admin_settingpage('manageeditors', new lang_string('editorsettings', 'editor'));
     $temp->add(new admin_setting_manageeditors());
     $ADMIN->add('editorsettings', $temp);
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('editor') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('editor');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\editor $plugin */
         $plugin->load_settings($ADMIN, 'editorsettings', $hassiteconfig);
     }
@@ -143,7 +157,9 @@ if ($hassiteconfig) {
     $temp = new admin_settingpage('manageantiviruses', new lang_string('antivirussettings', 'antivirus'));
     $temp->add(new admin_setting_manageantiviruses());
     $ADMIN->add('antivirussettings', $temp);
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('antivirus') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('antivirus');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /* @var \core\plugininfo\antivirus $plugin */
         $plugin->load_settings($ADMIN, 'antivirussettings', $hassiteconfig);
     }
@@ -182,7 +198,9 @@ if ($hassiteconfig) {
     }
     $ADMIN->add('filtersettings', $temp);
 
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('filter') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('filter');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\filter $plugin */
         $plugin->load_settings($ADMIN, 'filtersettings', $hassiteconfig);
     }
@@ -283,7 +301,9 @@ if ($hassiteconfig) {
         new lang_string('createrepository', 'repository'), $url, 'moodle/site:config', true));
     $ADMIN->add('repositorysettings', new admin_externalpage('repositoryinstanceedit',
         new lang_string('editrepositoryinstance', 'repository'), $url, 'moodle/site:config', true));
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('repository') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('repository');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\repository $plugin */
         $plugin->load_settings($ADMIN, 'repositorysettings', $hassiteconfig);
     }
@@ -337,7 +357,9 @@ if ($hassiteconfig) {
                         'admin'), new lang_string('configenablewsdocumentation', 'admin', $wsdoclink), false));
     $ADMIN->add('webservicesettings', $temp);
     /// links to protocol pages
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('webservice') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('webservice');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\webservice $plugin */
         $plugin->load_settings($ADMIN, 'webservicesettings', $hassiteconfig);
     }
@@ -409,7 +431,9 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext))
             get_string('responsehistory', 'question'), '', 0, $hiddenofvisible));
 
     // Settings for particular question types.
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('qtype') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('qtype');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\qtype $plugin */
         $plugin->load_settings($ADMIN, 'qtypesettings', $hassiteconfig);
     }
@@ -421,7 +445,9 @@ if ($hassiteconfig && !empty($CFG->enableplagiarism)) {
     $ADMIN->add('plagiarism', new admin_externalpage('manageplagiarismplugins', new lang_string('manageplagiarism', 'plagiarism'),
         $CFG->wwwroot . '/' . $CFG->admin . '/plagiarism.php'));
 
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('plagiarism') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('plagiarism');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\plagiarism $plugin */
         $plugin->load_settings($ADMIN, 'plagiarism', $hassiteconfig);
     }
@@ -445,6 +471,7 @@ if ($hassiteconfig) {
     }
     if (!empty($pages)) {
         $ADMIN->add('modules', new admin_category('coursereports', new lang_string('coursereports')));
+        core_collator::asort_objects_by_property($pages, 'visiblename');
         foreach ($pages as $page) {
             $ADMIN->add('coursereports', $page);
         }
@@ -468,6 +495,7 @@ foreach (core_component::get_plugin_list('report') as $report => $plugindir) {
 $ADMIN->add('modules', new admin_category('reportplugins', new lang_string('reports')));
 $ADMIN->add('reportplugins', new admin_externalpage('managereports', new lang_string('reportsmanage', 'admin'),
                                                     $CFG->wwwroot . '/' . $CFG->admin . '/reports.php'));
+core_collator::asort_objects_by_property($pages, 'visiblename');
 foreach ($pages as $page) {
     $ADMIN->add('reportplugins', $page);
 }
@@ -510,6 +538,7 @@ if ($hassiteconfig) {
     }
     $ADMIN->add('searchplugins', $temp);
 
+    core_collator::asort_objects_by_property($pages, 'visiblename');
     foreach ($pages as $page) {
         $ADMIN->add('searchplugins', $page);
     }
@@ -523,7 +552,9 @@ if ($hassiteconfig) {
 }
 
 // Now add various admin tools.
-foreach (core_plugin_manager::instance()->get_plugins_of_type('tool') as $plugin) {
+$plugins = core_plugin_manager::instance()->get_plugins_of_type('tool');
+core_collator::asort_objects_by_property($plugins, 'displayname');
+foreach ($plugins as $plugin) {
     /** @var \core\plugininfo\tool $plugin */
     $plugin->load_settings($ADMIN, null, $hassiteconfig);
 }
@@ -534,6 +565,7 @@ if ($hassiteconfig) {
     $ADMIN->add('cache', new admin_externalpage('cacheconfig', new lang_string('cacheconfig', 'cache'), $CFG->wwwroot .'/cache/admin.php'));
     $ADMIN->add('cache', new admin_externalpage('cachetestperformance', new lang_string('testperformance', 'cache'), $CFG->wwwroot . '/cache/testperformance.php'));
     $ADMIN->add('cache', new admin_category('cachestores', new lang_string('cachestores', 'cache')));
+    $ADMIN->locate('cachestores')->set_sorting(true);
     foreach (core_component::get_plugin_list('cachestore') as $plugin => $path) {
         $settingspath = $path.'/settings.php';
         if (file_exists($settingspath)) {
@@ -547,7 +579,9 @@ if ($hassiteconfig) {
 // Add Calendar type settings.
 if ($hassiteconfig) {
     $ADMIN->add('modules', new admin_category('calendartype', new lang_string('calendartypes', 'calendar')));
-    foreach (core_plugin_manager::instance()->get_plugins_of_type('calendartype') as $plugin) {
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('calendartype');
+    core_collator::asort_objects_by_property($plugins, 'displayname');
+    foreach ($plugins as $plugin) {
         /** @var \core\plugininfo\calendartype $plugin */
         $plugin->load_settings($ADMIN, 'calendartype', $hassiteconfig);
     }
@@ -562,7 +596,9 @@ if ($hassiteconfig) {
 
 // Extend settings for each local plugin. Note that their settings may be in any part of the
 // settings tree and may be visible not only for administrators.
-foreach (core_plugin_manager::instance()->get_plugins_of_type('local') as $plugin) {
+$plugins = core_plugin_manager::instance()->get_plugins_of_type('local');
+core_collator::asort_objects_by_property($plugins, 'displayname');
+foreach ($plugins as $plugin) {
     /** @var \core\plugininfo\local $plugin */
     $plugin->load_settings($ADMIN, null, $hassiteconfig);
 }
index 98fc305..f8a37e7 100644 (file)
@@ -101,6 +101,9 @@ if (empty($options['torun'])) {
 if (extension_loaded('pcntl')) {
     $disabled = explode(',', ini_get('disable_functions'));
     if (!in_array('pcntl_signal', $disabled)) {
+        // Handle interrupts on PHP7.
+        declare(ticks = 1);
+
         pcntl_signal(SIGTERM, "signal_handler");
         pcntl_signal(SIGINT, "signal_handler");
     }
index 7994a8c..6a625f6 100644 (file)
 .path-admin-tool-health dl.notice dd {
     background-color: #e5db36;
 }
-.path-admin-tool-health dt.solution,
-.path-admin-tool-health dd.solution,
+.path-admin-tool-health dl dt.solution,
+.path-admin-tool-health dl dd.solution,
 .path-admin-tool-health div#healthnoproblemsfound {
-    background-color: #5BB83E !important;
+    background-color: #5BB83E;
 }
 .path-admin-tool-health dl.healthissues dt,
 .path-admin-tool-health dl.healthissues dd {
index cf57df2..c14f771 100644 (file)
Binary files a/admin/tool/lp/amd/build/competencies.min.js and b/admin/tool/lp/amd/build/competencies.min.js differ
index 4cc8611..899e3ce 100644 (file)
Binary files a/admin/tool/lp/amd/build/tree.min.js and b/admin/tool/lp/amd/build/tree.min.js differ
index d36f06f..8b32a48 100644 (file)
@@ -138,6 +138,7 @@ define(['jquery',
      * Find a node in the dialogue.
      *
      * @param {String} selector
+     * @return {JQuery} The node
      * @method _find
      */
     ActionSelector.prototype._find = function(selector) {
@@ -170,8 +171,8 @@ define(['jquery',
         for (var i in self._actions) {
             choices.push(self._actions[i]);
         }
-        var content = {'message': self._message, 'choices' : choices,
-            'confirm' : self._confirm, 'cancel' : self._cancel};
+        var content = {'message': self._message, 'choices': choices,
+            'confirm': self._confirm, 'cancel': self._cancel};
 
         return Templates.render('tool_lp/action_selector', content);
     };
index 6e1973c..8b5ae2e 100644 (file)
@@ -35,6 +35,7 @@ define(['jquery',
      *
      * @param {Number} itemid
      * @param {String} itemtype
+     * @param {Number} pagectxid
      */
     var competencies = function(itemid, itemtype, pagectxid) {
         this.itemid = itemid;
@@ -106,7 +107,7 @@ define(['jquery',
                 }
             ]);
         } else {
-            return null;
+            return;
         }
 
         requests[0].fail(notification.exception);
@@ -276,7 +277,7 @@ define(['jquery',
                 { key: message, component: 'tool_lp', param: competency.shortname },
                 { key: 'confirm', component: 'moodle' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Unlink the competency X from the course?
@@ -300,7 +301,7 @@ define(['jquery',
 
         if (localthis.itemtype == 'course') {
             // Course completion rule handling.
-            $('[data-region="coursecompetenciespage"]').on('change', 'select[data-field="ruleoutcome"]', function(e){
+            $('[data-region="coursecompetenciespage"]').on('change', 'select[data-field="ruleoutcome"]', function(e) {
                 var requests = [];
                 var pagerender = 'tool_lp/course_competencies_page';
                 var pageregion = 'coursecompetenciespage';
index 1ff679e..36b2a68 100644 (file)
@@ -64,7 +64,7 @@ define(['jquery',
          * Get the string for an outcome.
          *
          * @param  {Number} id The outcome code.
-         * @return {Promise Resolved with the string.
+         * @return {Promise} Resolved with the string.
          * @method getString
          */
         getString: function(id) {
index 34a70c7..3a3e505 100644 (file)
@@ -26,11 +26,11 @@ define(['jquery'], function($) {
     /**
      * CompetencyPlanNavigation
      *
-     * @param {String} The selector of the competency element.
-     * @param {String} The base url for the page (no params).
-     * @param {Number} The user id
-     * @param {Number} The competency id
-     * @param {Number} The plan id
+     * @param {String} competencySelector The selector of the competency element.
+     * @param {String} baseUrl The base url for the page (no params).
+     * @param {Number} userId The user id
+     * @param {Number} competencyId The competency id
+     * @param {Number} planId The plan id
      */
     var CompetencyPlanNavigation = function(competencySelector, baseUrl, userId, competencyId, planId) {
         this._baseUrl = baseUrl;
index 35def4a..e631bc2 100644 (file)
@@ -71,6 +71,7 @@ define(['jquery'], function($) {
         return null;
     };
 
+    // eslint-disable-next-line valid-jsdoc
     /**
      * Return the type of the module.
      *
@@ -152,7 +153,7 @@ define(['jquery'], function($) {
      * Trigger an event.
      *
      * @param {String} type The type of event.
-     * @param {Object} The data to pass to the listeners.
+     * @param {Object} data The data to pass to the listeners.
      * @method _trigger
      * @protected
      */
index 21e084e..c9c37bc 100644 (file)
@@ -66,7 +66,7 @@ define(['jquery',
         var parent = $('[data-region="competencyactions"]').data('competency');
 
         var params = {
-            competencyframeworkid : treeModel.getCompetencyFrameworkId(),
+            competencyframeworkid: treeModel.getCompetencyFrameworkId(),
             pagecontextid: pageContextId
         };
 
@@ -86,7 +86,7 @@ define(['jquery',
                 { key: 'addingcompetencywillresetparentrule', component: 'tool_lp', param: parent.shortname },
                 { key: 'yes', component: 'core' },
                 { key: 'no', component: 'core' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0],
                     strings[1],
@@ -157,7 +157,7 @@ define(['jquery',
                 { key: confirmMessage, component: 'tool_lp' },
                 { key: 'yes', component: 'moodle' },
                 { key: 'no', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Delete competency X?
@@ -187,8 +187,13 @@ define(['jquery',
         });
         treeRoot.show();
 
-        body.on('click', '[data-action="move"]', function() { popup.close(); confirmMove(); });
-        body.on('click', '[data-action="cancel"]', function() { popup.close(); });
+        body.on('click', '[data-action="move"]', function() {
+          popup.close();
+          confirmMove();
+        });
+        body.on('click', '[data-action="cancel"]', function() {
+          popup.close();
+        });
     };
 
     /**
@@ -213,6 +218,7 @@ define(['jquery',
 
     /**
      * A node was chosen and "Move" was selected from the menu. Open a popup to select the target.
+     * @param {Event} e
      * @method moveHandler
      */
     var moveHandler = function(e) {
@@ -230,7 +236,7 @@ define(['jquery',
                     competencyframeworkid: competency.competencyframeworkid,
                     searchtext: ''
                 }
-            },{
+            }, {
                 methodname: 'core_competency_read_competency_framework',
                 args: {
                     id: competency.competencyframeworkid
@@ -257,7 +263,7 @@ define(['jquery',
                 { key: 'movecompetency', component: 'tool_lp', param: competency.shortname },
                 { key: 'move', component: 'tool_lp' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
 
                 var context = {
                     framework: framework,
@@ -288,8 +294,8 @@ define(['jquery',
         var competency = $('[data-region="competencyactions"]').data('competency');
 
         var params = {
-            competencyframeworkid : treeModel.getCompetencyFrameworkId(),
-            id : competency.id,
+            competencyframeworkid: treeModel.getCompetencyFrameworkId(),
+            id: competency.id,
             parentid: competency.parentid,
             pagecontextid: pageContextId
         };
@@ -300,6 +306,7 @@ define(['jquery',
 
     /**
      * Re-render the page with the latest data.
+     * @param {Object} context
      * @method reloadPage
      */
     var reloadPage = function(context) {
@@ -313,6 +320,7 @@ define(['jquery',
 
     /**
      * Perform a search and render the page with the new search results.
+     * @param {Event} e
      * @method updateSearchHandler
      */
     var updateSearchHandler = function(e) {
@@ -381,7 +389,7 @@ define(['jquery',
                 courses: courses
             };
             templates.render('tool_lp/linked_courses_summary', context).done(function(html) {
-                str.get_string('linkedcourses', 'tool_lp').done(function (linkedcourses) {
+                str.get_string('linkedcourses', 'tool_lp').done(function(linkedcourses) {
                     new Dialogue(
                         linkedcourses, // Title.
                         html, // The linked courses.
@@ -413,7 +421,7 @@ define(['jquery',
                     });
                 });
 
-                calls.push( {
+                calls.push({
                     methodname: 'tool_lp_data_for_related_competencies_section',
                     args: { competencyid: relatedTarget.id }
                 });
@@ -486,7 +494,7 @@ define(['jquery',
                 str.get_strings([
                 { key: 'competencycannotbedeleted', component: 'tool_lp', param: competency.shortname },
                 { key: 'cancel', component: 'moodle' }
-                ]).done(function (strings) {
+                ]).done(function(strings) {
                     notification.alert(
                         null,
                         strings[0]
@@ -514,7 +522,7 @@ define(['jquery',
             { key: confirmMessage, component: 'tool_lp', param: competency.shortname },
             { key: 'delete', component: 'moodle' },
             { key: 'cancel', component: 'moodle' }
-        ]).done(function (strings) {
+        ]).done(function(strings) {
             notification.confirm(
                 strings[0], // Confirm.
                 strings[1], // Delete competency X?
@@ -528,6 +536,7 @@ define(['jquery',
     /**
      * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
      * @method dragStart
+     * @param {Event} e
      */
     var dragStart = function(e) {
         e.originalEvent.dataTransfer.setData('text', $(e.target).parent().data('id'));
@@ -536,6 +545,7 @@ define(['jquery',
     /**
      * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
      * @method allowDrop
+     * @param {Event} e
      */
     var allowDrop = function(e) {
         e.originalEvent.dataTransfer.dropEffect = 'move';
@@ -545,6 +555,7 @@ define(['jquery',
     /**
      * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
      * @method dragEnter
+     * @param {Event} e
      */
     var dragEnter = function(e) {
         e.preventDefault();
@@ -554,6 +565,7 @@ define(['jquery',
     /**
      * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
      * @method dragLeave
+     * @param {Event} e
      */
     var dragLeave = function(e) {
         e.preventDefault();
@@ -563,6 +575,7 @@ define(['jquery',
     /**
      * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
      * @method dropOver
+     * @param {Event} e
      */
     var dropOver = function(e) {
         e.preventDefault();
@@ -614,7 +627,7 @@ define(['jquery',
     /**
      * Log the competency viewed event.
      *
-     * @param  {Object} The competency.
+     * @param  {Object} competency The competency.
      * @method triggerCompetencyViewedEvent
      */
     var triggerCompetencyViewedEvent = function(competency) {
@@ -729,6 +742,7 @@ define(['jquery',
      * @method selectionChanged
      * @param {Event} evt The event that triggered the selection change.
      * @param {Object} params The parameters for the event. Contains a list of selected nodes.
+     * @return {Boolean}
      */
     var selectionChanged = function(evt, params) {
         var node = params.selected,
@@ -781,7 +795,7 @@ define(['jquery',
      * Return the string "Selected <taxonomy>".
      *
      * @function parseTaxonomies
-     * @param  {String} Comma separated list of taxonomies.
+     * @param  {String} taxonomiesstr Comma separated list of taxonomies.
      * @return {Array} of level => taxonomystr
      */
     var parseTaxonomies = function(taxonomiesstr) {
index affcea6..9902eed 100644 (file)
@@ -43,12 +43,13 @@ define(['jquery',
      *
      */
     var Competencydialogue = function() {
+      // Intentionally left empty.
     };
 
     /**
      * Log the competency viewed event.
      *
-     * @param  {Number} The competency ID.
+     * @param  {Number} competencyId The competency ID.
      * @method triggerCompetencyViewedEvent
      */
     Competencydialogue.prototype.triggerCompetencyViewedEvent = function(competencyId) {
@@ -112,7 +113,7 @@ define(['jquery',
     /**
      * The action on the click event.
      *
-     * @param {Event} event click
+     * @param {Event} e event click
      * @method clickEventHandler
      */
     Competencydialogue.prototype.clickEventHandler = function(e) {
@@ -135,6 +136,7 @@ define(['jquery',
      * Get a promise on data competency.
      *
      * @param {Number} competencyid
+     * @param {Object} options
      * @return {Promise} return promise on data request
      * @method getCompetencyDataPromise
      */
@@ -160,8 +162,6 @@ define(['jquery',
          * Initialise the competency dialogue module.
          *
          * Only the first call matters.
-         *
-         * @return {Void}
          */
         init: function() {
             if (typeof instance !== 'undefined') {
index d6247fe..272d3e0 100644 (file)
@@ -231,7 +231,10 @@ define(['jquery',
                 competencyframeworkid: frameworkId
             }}
         ])[0].done(function(competencies) {
-
+          /**
+           * @param {Object} parent
+           * @param {Array} competencies
+           */
             function addCompetencyChildren(parent, competencies) {
                 for (var i = 0; i < competencies.length; i++) {
                     if (competencies[i].parentid == parent.id) {
@@ -265,6 +268,7 @@ define(['jquery',
      * Find a node in the dialogue.
      *
      * @param {String} selector
+     * @return {JQuery}
      * @method _find
      */
     Picker.prototype._find = function(selector) {
@@ -275,6 +279,7 @@ define(['jquery',
      * Convenience method to get a framework object.
      *
      * @param {Number} fid The framework ID.
+     * @return {Object}
      * @method _getFramework
      */
     Picker.prototype._getFramework = function(fid) {
@@ -437,7 +442,7 @@ define(['jquery',
      *
      * This needs to be set after reset/close.
      *
-     * @params {Number[]} The IDs.
+     * @param {Number[]} ids The IDs.
      * @method _setDisallowedCompetencyIDs
      */
     Picker.prototype.setDisallowedCompetencyIDs = function(ids) {
@@ -448,7 +453,7 @@ define(['jquery',
      * Trigger an event.
      *
      * @param {String} type The type of event.
-     * @param {Object} The data to pass to the listeners.
+     * @param {Object} data The data to pass to the listeners.
      * @method _reset
      */
     Picker.prototype._trigger = function(type, data) {
index 7291829..b417b67 100644 (file)
@@ -39,8 +39,8 @@ define(['jquery',
     /**
      * Competency picker in plan class.
      *
+     * @param {Number} userId
      * @param {Number|false} singlePlan The ID of the plan when limited to one.
-     * @param {String} pageContextIncludes One of 'children', 'parents', 'self'.
      * @param {Boolean} multiSelect Support multi-select in the tree.
      */
     var Picker = function(userId, singlePlan, multiSelect) {
@@ -88,7 +88,7 @@ define(['jquery',
      * @param {Number} planId The planId.
      * @param {String} searchText Limit the competencies to those matching the text.
      * @method _fetchCompetencies
-     * @return {Promise}
+     * @return {Promise} The promise object.
      */
     Picker.prototype._fetchCompetencies = function(planId, searchText) {
         var self = this;
index 4894d36..f207939 100644 (file)
@@ -70,7 +70,6 @@ define(['jquery',
      *
      * Triggered when a change occured.
      *
-     * @return {Void}
      * @method _afterChange
      * @protected
      */
@@ -87,9 +86,10 @@ define(['jquery',
      *
      * Triggered when a change occured in a specific rule config.
      *
-     * @return {Void}
      * @method _afterRuleConfigChange
      * @protected
+     * @param {Event} e
+     * @param {Rule} rule
      */
     RuleConfig.prototype._afterRuleConfigChange = function(e, rule) {
         if (rule != this._getRule()) {
@@ -102,7 +102,6 @@ define(['jquery',
     /**
      * After render hook.
      *
-     * @return {Promise}
      * @method _afterRender
      * @protected
      */
@@ -181,6 +180,7 @@ define(['jquery',
      * Find a node in the dialogue.
      *
      * @param {String} selector
+     * @return {JQuery}
      * @method _find
      * @protected
      */
@@ -444,7 +444,6 @@ define(['jquery',
     /**
      * Set up the instance.
      *
-     * @return {Void}
      * @method _setUp
      * @protected
      */
@@ -482,7 +481,6 @@ define(['jquery',
     /**
      * Called when the user switches outcome.
      *
-     * @return {Void}
      * @method _switchedOutcome
      * @protected
      */
@@ -507,7 +505,6 @@ define(['jquery',
     /**
      * Called when the user switches rule.
      *
-     * @return {Void}
      * @method _switchedRule
      * @protected
      */
@@ -535,7 +532,7 @@ define(['jquery',
      * Trigger an event.
      *
      * @param {String} type The type of event.
-     * @param {Object} The data to pass to the listeners.
+     * @param {Object} data The data to pass to the listeners.
      * @method _trigger
      * @protected
      */
index bff7349..1cc3933 100644 (file)
@@ -57,7 +57,7 @@ define(['jquery',
         e.preventDefault();
 
         templates.render('tool_lp/course_competency_settings', context).done(function(html) {
-            str.get_string('configurecoursecompetencysettings', 'tool_lp').done(function (title) {
+            str.get_string('configurecoursecompetencysettings', 'tool_lp').done(function(title) {
                 this._dialogue = new Dialogue(
                     title,
                     html,
index 882ee5b..04a570f 100644 (file)
@@ -43,7 +43,7 @@ define(['core/yui'], function(Y) {
             wide = false;
         }
 
-        Y.use('moodle-core-notification', 'timers', function () {
+        Y.use('moodle-core-notification', 'timers', function() {
             var width = '480px';
             if (wide) {
                 width = '800px';
@@ -92,6 +92,7 @@ define(['core/yui'], function(Y) {
 
     /**
      * Get content.
+     * @return {node}
      */
     dialogue.prototype.getContent = function() {
         return this.yuiDialogue.bodyNode.getDOMNode();
index d14c9dd..a94eb30 100644 (file)
@@ -70,8 +70,8 @@ define(['core/str', 'core/yui'], function(str, Y) {
                 { key: 'emptydragdropregion', component: 'moodle' },
                 { key: 'movecontent', component: 'moodle' },
                 { key: 'tocontent', component: 'moodle' },
-            ]).done( function () {
-                Y.use('moodle-tool_lp-dragdrop-reorder', function () {
+            ]).done(function() {
+                Y.use('moodle-tool_lp-dragdrop-reorder', function() {
 
                     var context = {
                         callback: callback
index 1bda7ed..fe8433c 100644 (file)
@@ -48,7 +48,7 @@ define(['jquery'], function($) {
      * Trigger an event.
      *
      * @param {String} type The type of event.
-     * @param {Object} The data to pass to the listeners.
+     * @param {Object} data The data to pass to the listeners.
      * @method _trigger
      */
     Base.prototype._trigger = function(type, data) {
index 19a5534..44698d1 100644 (file)
@@ -35,7 +35,6 @@ define(['jquery',
      *
      * @param {String} triggerSelector The node on which the click will happen.
      * @param {String} containerSelector The parent node that will be removed and contains the evidence ID.
-     * @return {Void}
      */
     var register = function(triggerSelector, containerSelector) {
         if (typeof selectors[triggerSelector] !== 'undefined') {
@@ -62,7 +61,7 @@ define(['jquery',
                 { key: 'areyousure', component: 'moodle' },
                 { key: 'delete', component: 'moodle' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 Notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Are you sure?
index a783033..b554495 100644 (file)
@@ -93,17 +93,17 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
                 }
             }
         }]);
-        requests[0].done(function (success) {
+        requests[0].done(function(success) {
             if (success === false) {
                 var req = ajax.call([{
                     methodname: 'core_competency_read_competency_framework',
                     args: { id: frameworkid }
                 }]);
-                req[0].done(function (framework) {
+                req[0].done(function(framework) {
                     str.get_strings([
                         { key: 'frameworkcannotbedeleted', component: 'tool_lp', param: framework.shortname },
                         { key: 'cancel', component: 'moodle' }
-                    ]).done(function (strings) {
+                    ]).done(function(strings) {
                         notification.alert(
                             null,
                             strings[0]
@@ -136,7 +136,7 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
                 { key: 'deletecompetencyframework', component: 'tool_lp', param: framework.shortname },
                 { key: 'delete', component: 'moodle' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Delete competency framework X?
index a4c9274..3638830 100644 (file)
@@ -75,7 +75,6 @@ define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notificat
          * @param {String} selector The selector of the auto complete element.
          * @param {String} query The query string.
          * @param {Function} callback A callback function receiving an array of results.
-         * @return {Void}
          */
         transport: function(selector, query, callback) {
             var el = $(selector),
index 9063b50..576b511 100644 (file)
@@ -31,6 +31,7 @@ define(['jquery',
 
     /**
      * Grade dialogue class.
+     * @param {Array} ratingOptions
      */
     var Grade = function(ratingOptions) {
         EventBase.prototype.constructor.apply(this, []);
@@ -46,7 +47,6 @@ define(['jquery',
     /**
      * After render hook.
      *
-     * @return {Promise}
      * @method _afterRender
      * @protected
      */
@@ -118,6 +118,7 @@ define(['jquery',
      *
      * @param {String} selector
      * @method _find
+     * @returns {node} The node
      * @protected
      */
     Grade.prototype._find = function(selector) {
index fd9d6ac..3558b9f 100644 (file)
@@ -34,12 +34,12 @@ define(['jquery',
      * InlineEditor
      *
      * @param {String} selector The selector to trigger the grading.
-     * @param {Number} The id of the scale for this competency.
-     * @param {Number} The id of the competency.
-     * @param {Number} The id of the user.
-     * @param {Number} The id of the plan.
-     * @param {Number} The id of the course.
-     * @param {String} Language string for choose a rating.
+     * @param {Number} scaleId The id of the scale for this competency.
+     * @param {Number} competencyId The id of the competency.
+     * @param {Number} userId The id of the user.
+     * @param {Number} planId The id of the plan.
+     * @param {Number} courseId The id of the course.
+     * @param {String} chooseStr Language string for choose a rating.
      */
     var InlineEditor = function(selector, scaleId, competencyId, userId, planId, courseId, chooseStr) {
         EventBase.prototype.constructor.apply(this, []);
index a91d770..6889936 100644 (file)
@@ -44,7 +44,7 @@ define(['jquery'], function($) {
     /**
      * Constructor
      *
-     * @param {$} Jquery collection matching the root of the menu.
+     * @param {$} menuRoot Jquery collection matching the root of the menu.
      * @param {Function[]} handlers, called when a menu item is chosen.
      */
     var Menubar = function(menuRoot, handlers) {
@@ -144,7 +144,7 @@ define(['jquery'], function($) {
      * @method handleClick
      * @param {Object} item is the jquery object of the item firing the event
      * @param {Event} e is the associated event object
-     * @return boolean Returns false
+     * @return {boolean} Returns false
      */
     Menubar.prototype.handleClick = function(item, e) {
         e.stopPropagation();
@@ -166,7 +166,7 @@ define(['jquery'], function($) {
             this.activeItem = null;
 
             // Close the menu.
-            this.menuRoot.find('ul').not('.root-level').attr('aria-hidden','true');
+            this.menuRoot.find('ul').not('.root-level').attr('aria-hidden', 'true');
             // Follow any link, or call the click handlers.
             var anchor = item.find('a').first();
             var clickEvent = new $.Event('click');
@@ -290,7 +290,7 @@ define(['jquery'], function($) {
                 subMenuContainer.css('margin-right', '-' + marginright + 'px');
             }
         } else {
-            if ( pos.left + menuRealWidth > $(window).width()) {
+            if (pos.left + menuRealWidth > $(window).width()) {
                 marginleft = menuRealWidth - widthmenuRoot;
                 subMenuContainer.css('margin-left', '-' + marginleft + 'px');
             }
@@ -319,7 +319,7 @@ define(['jquery'], function($) {
             return true;
         }
 
-        switch(e.keyCode) {
+        switch (e.keyCode) {
             case this.keys.tab: {
 
                 // Hide all menu items and update their aria attributes.
@@ -438,7 +438,7 @@ define(['jquery'], function($) {
             // This is the root level move to next sibling. This will require closing
             // the current child menu and opening the new one.
 
-            if (menuIndex < menuNum-1) {
+            if (menuIndex < menuNum - 1) {
                 // Not the last root menu.
                 newItem = item.next();
             } else { // Wrap to first item.
@@ -501,7 +501,7 @@ define(['jquery'], function($) {
                 menuIndex = this.rootMenus.index(rootItem);
 
                 // If this is not the last root menu item, move to the next one.
-                if (menuIndex < this.rootMenus.length-1) {
+                if (menuIndex < this.rootMenus.length - 1) {
                     newItem = rootItem.next();
                 } else {
                     // Loop.
@@ -687,7 +687,7 @@ define(['jquery'], function($) {
         // to the next item with a title that begins with that character.
         if (startChr) {
             var match = false;
-            var curNdx = menuIndex+1;
+            var curNdx = menuIndex + 1;
 
             // Check if the active item was the last one on the list.
             if (curNdx == menuNum) {
@@ -696,7 +696,7 @@ define(['jquery'], function($) {
 
             // Iterate through the menu items (starting from the current item and wrapping) until a match is found
             // or the loop returns to the current menu item.
-            while (curNdx != menuIndex)  {
+            while (curNdx != menuIndex) {
 
                 var titleChr = menuItems.eq(curNdx).html().charAt(0);
 
@@ -705,7 +705,7 @@ define(['jquery'], function($) {
                     break;
                 }
 
-                curNdx = curNdx+1;
+                curNdx = curNdx + 1;
 
                 if (curNdx == menuNum) {
                     // Reached the end of the list, start again at the beginning.
@@ -724,8 +724,8 @@ define(['jquery'], function($) {
                 return item;
             }
         } else {
-            if (menuIndex < menuNum-1) {
-                newItem = menuItems.eq(menuIndex+1);
+            if (menuIndex < menuNum - 1) {
+                newItem = menuItems.eq(menuIndex + 1);
             } else {
                 newItem = menuItems.first();
             }
@@ -763,7 +763,7 @@ define(['jquery'], function($) {
 
         // If item is not the first item in its menu, move to the previous item.
         if (menuIndex > 0) {
-            newItem = menuItems.eq(menuIndex-1);
+            newItem = menuItems.eq(menuIndex - 1);
         } else {
             // Loop to top of menu.
             newItem = menuItems.last();
@@ -823,7 +823,7 @@ define(['jquery'], function($) {
          *                             { "[data-action='add']" : callAddFunction }
          */
         enhance: function(selector, handler) {
-            $(selector).each(function (index, element) {
+            $(selector).each(function(index, element) {
                 var menuRoot = $(element);
                 // Don't enhance the same menu twice.
                 if (menuRoot.data("menubarEnhanced") !== true) {
index 2dabb3c..5a2648b 100644 (file)
@@ -61,7 +61,7 @@ define(['jquery', 'core/ajax', 'core/str', 'tool_lp/competencypicker', 'core/tem
     /**
      * Set the parent competency in the competency form.
      *
-     * @param {Object} Data containing selected cmpetency.
+     * @param {Object} data Data containing selected competency.
      * @method setParent
      */
     ParentCompetencyForm.prototype.setParent = function(data) {
@@ -129,7 +129,7 @@ define(['jquery', 'core/ajax', 'core/str', 'tool_lp/competencypicker', 'core/tem
         /**
          * Main initialisation.
          * @param {String} buttonSelector The parent competency button selector.
-         * @param {String} inputHiddenSelector The hidden input field selector.
+         * @param {String} inputSelector The hidden input field selector.
          * @param {String} staticElementSelector The static element displaying the parent competency.
          * @param {Number} frameworkId The competency framework ID.
          * @param {Number} pageContextId The page context ID.
index 8d3e050..39efd98 100644 (file)
@@ -178,7 +178,7 @@ define(['jquery',
                 { key: 'deleteplan', component: 'tool_lp', param: plan.name },
                 { key: 'delete', component: 'moodle' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Delete plan X?
@@ -225,7 +225,7 @@ define(['jquery',
                 { key: 'reopenplanconfirm', component: 'tool_lp', param: plan.name },
                 { key: 'reopenplan', component: 'tool_lp' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Reopen plan X?
@@ -272,7 +272,7 @@ define(['jquery',
                 { key: 'completeplanconfirm', component: 'tool_lp', param: plan.name },
                 { key: 'completeplan', component: 'tool_lp' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Complete plan X?
@@ -318,7 +318,7 @@ define(['jquery',
                 { key: 'unlinkplantemplateconfirm', component: 'tool_lp', param: plan.name },
                 { key: 'unlinkplantemplate', component: 'tool_lp' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Unlink plan X?
@@ -507,7 +507,7 @@ define(['jquery',
                 courses: courses
             };
             templates.render('tool_lp/linked_courses_summary', context).done(function(html) {
-                str.get_string('linkedcourses', 'tool_lp').done(function (linkedcourses) {
+                str.get_string('linkedcourses', 'tool_lp').done(function(linkedcourses) {
                     new Dialogue(
                         linkedcourses, // Title.
                         html // The linked courses.
index 11c8568..9ba1fd4 100644 (file)
@@ -198,7 +198,6 @@ define(['jquery', 'core/notification', 'core/templates', 'core/ajax', 'tool_lp/d
      *
      * @name   scaleChangeHandler
      * @param  {Event} e
-     * @return {Void}
      * @function
      */
     ScaleConfig.prototype.scaleChangeHandler = function(e) {
index d27abd3..46011f8 100644 (file)
@@ -32,7 +32,7 @@ define(['jquery', 'core/ajax'], function($, ajax) {
          * @param {Number} scaleid The scale id
          * @return [] {Promise}
          */
-
+        // eslint-disable-next-line camelcase
         get_values: function(scaleid) {
 
             var deferred = $.Deferred();
@@ -40,7 +40,7 @@ define(['jquery', 'core/ajax'], function($, ajax) {
             if (typeof localCache[scaleid] === 'undefined') {
                 ajax.call([{
                     methodname: 'core_competency_get_scale_values',
-                    args: {scaleid : scaleid},
+                    args: {scaleid: scaleid},
                     done: function(scaleinfo) {
                         localCache[scaleid] = scaleinfo;
                         deferred.resolve(scaleinfo);
index 0966cc2..e0ceecb 100644 (file)
@@ -21,7 +21,7 @@
  * @copyright  2015 Damyon Wiese <damyon@moodle.com>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str','tool_lp/actionselector'],
+define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str', 'tool_lp/actionselector'],
        function($, templates, ajax, notification, str, Actionselector) {
     // Private variables and functions.
 
@@ -135,9 +135,9 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
                         { key: 'unlinkplanstemplate', component: 'tool_lp' },
                         { key: 'confirm', component: 'moodle' },
                         { key: 'cancel', component: 'moodle' }
-                    ]).done(function (strings) {
-                        var actions = [{'text': strings[2], 'value' : 'delete'},
-                                       {'text': strings[3], 'value' : 'unlink'}];
+                    ]).done(function(strings) {
+                        var actions = [{'text': strings[2], 'value': 'delete'},
+                                       {'text': strings[3], 'value': 'unlink'}];
                         var actionselector = new Actionselector(
                                 strings[0], // Title.
                                 strings[1], // Message
@@ -152,14 +152,13 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
                             doDelete();
                         });
                     }).fail(notification.exception);
-                }
-                else {
+                } else {
                     str.get_strings([
                         { key: 'confirm', component: 'moodle' },
                         { key: 'deletetemplate', component: 'tool_lp', param: template.shortname },
                         { key: 'delete', component: 'moodle' },
                         { key: 'cancel', component: 'moodle' }
-                    ]).done(function (strings) {
+                    ]).done(function(strings) {
                         notification.confirm(
                         strings[0], // Confirm.
                         strings[1], // Delete learning plan template X?
index f52934d..179dcf6 100644 (file)
@@ -186,12 +186,12 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
             var oneItem = null;
 
             while (lastIndex < currentIndex) {
-                oneItem  = $(this.visibleItems.get(lastIndex));
+                oneItem = $(this.visibleItems.get(lastIndex));
                 oneItem.attr('aria-selected', 'true');
                 lastIndex++;
             }
             while (lastIndex > currentIndex) {
-                oneItem  = $(this.visibleItems.get(lastIndex));
+                oneItem = $(this.visibleItems.get(lastIndex));
                 oneItem.attr('aria-selected', 'true');
                 lastIndex--;
             }
@@ -230,7 +230,8 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
      */
     Tree.prototype.toggleItem = function(item) {
         if (!this.multiSelect) {
-            return this.selectItem(item);
+            this.selectItem(item);
+            return;
         }
 
         var current = item.attr('aria-selected');
@@ -271,6 +272,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
      * @method handleKeyDown
      * @param {Object} item is the jquery id of the parent item of the group
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleKeyDown = function(item, e) {
         var currentIndex = this.visibleItems.index(item);
@@ -419,6 +421,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
      * @method handleKeyPress
      * @param {Object} item is the jquery id of the parent item of the group
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleKeyPress = function(item, e) {
         if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
@@ -454,7 +457,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
 
                 // Iterate through the menu items (starting from the current item and wrapping) until a match is found
                 // or the loop returns to the current menu item.
-                while (currentIndex != itemIndex)  {
+                while (currentIndex != itemIndex) {
 
                     var currentItem = this.visibleItems.eq(currentIndex);
                     var titleChr = currentItem.text().charAt(0);
@@ -468,7 +471,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
                         break;
                     }
 
-                    currentIndex = currentIndex+1;
+                    currentIndex = currentIndex + 1;
                     if (currentIndex == itemCount) {
                         // Reached the end of the list, start again at the beginning.
                         currentIndex = 0;
@@ -483,6 +486,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
             }
         }
 
+        // eslint-disable-next-line no-unreachable
         return true;
     };
 
@@ -507,6 +511,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
      * @method handleDblClick
      * @param {Object} item is the jquery id of the parent item of the group
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleDblClick = function(item, e) {
 
@@ -531,6 +536,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
      * @method handleExpandCollapseClick
      * @param {Object} item is the jquery id of the parent item of the group
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleExpandCollapseClick = function(item, e) {
 
@@ -547,6 +553,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
      * @method handleClick
      * @param {Object} item is the jquery id of the parent item of the group
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleClick = function(item, e) {
 
@@ -568,6 +575,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
      * @method handleBlur
      * @param {Object} item item is the jquery id of the parent item of the group
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleBlur = function() {
         return true;
@@ -579,6 +587,7 @@ define(['jquery', 'core/url', 'core/log'], function($, url, log) {
      * @method handleFocus
      * @param {Object} item item is the jquery id of the parent item of the group
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleFocus = function(item) {
 
index bf61fe5..a560da7 100644 (file)
@@ -26,12 +26,12 @@ define(['jquery'], function($) {
     /**
      * UserCompetencyCourseNavigation
      *
-     * @param {String} The selector of the user element.
-     * @param {String} The selector of the competency element.
-     * @param {String} The base url for the page (no params).
-     * @param {Number} The course id
-     * @param {Number} The user id
-     * @param {Number} The competency id
+     * @param {String} userSelector The selector of the user element.
+     * @param {String} competencySelector The selector of the competency element.
+     * @param {String} baseUrl The base url for the page (no params).
+     * @param {Number} userId The user id
+     * @param {Number} competencyId The competency id
+     * @param {Number} courseId The course id
      */
     var UserCompetencyCourseNavigation = function(userSelector, competencySelector, baseUrl, userId, competencyId, courseId) {
         this._baseUrl = baseUrl;
index 2234414..334e8ff 100644 (file)
@@ -26,12 +26,12 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates'], function(
     /**
      * Info
      *
-     * @param {JQuery} Selector to replace when the information needs updating.
-     * @param {Number} The id of the competency.
-     * @param {Number} The id of the user.
-     * @param {Number} The id of the plan.
-     * @param {Number} The id of the course.
-     * @param {Boolean} If we should display the user info.
+     * @param {JQuery} rootElement Selector to replace when the information needs updating.
+     * @param {Number} competencyId The id of the competency.
+     * @param {Number} userId The id of the user.
+     * @param {Number} planId The id of the plan.
+     * @param {Number} courseId The id of the course.
+     * @param {Boolean} displayuser If we should display the user info.
      */
     var Info = function(rootElement, competencyId, userId, planId, courseId, displayuser) {
         this._rootElement = rootElement;
index 87c977c..5001991 100644 (file)
@@ -27,9 +27,9 @@ define(['jquery', 'core/notification', 'core/str', 'core/ajax', 'core/templates'
     /**
      * UserCompetencyPopup
      *
-     * @param {String} The regionSelector
-     * @param {String} The userCompetencySelector
-     * @param {Number} The plan ID
+     * @param {String} regionSelector The regionSelector
+     * @param {String} userCompetencySelector The userCompetencySelector
+     * @param {Number} planId The plan ID
      */
     var UserCompetencyPopup = function(regionSelector, userCompetencySelector, planId) {
         this._regionSelector = regionSelector;
@@ -53,14 +53,14 @@ define(['jquery', 'core/notification', 'core/str', 'core/ajax', 'core/templates'
         var planId = this._planId;
 
         var requests = ajax.call([{
-            methodname : 'tool_lp_data_for_user_competency_summary_in_plan',
+            methodname: 'tool_lp_data_for_user_competency_summary_in_plan',
             args: { competencyid: competencyId, planid: planId },
             done: this._contextLoaded.bind(this),
             fail: notification.exception
         }]);
 
         // Log the user competency viewed in plan event.
-        requests[0].then(function (result) {
+        requests[0].then(function(result) {
             var eventMethodName = 'core_competency_user_competency_viewed_in_plan';
             // Trigger core_competency_user_competency_plan_viewed event instead if plan is already completed.
             if (result.plan.iscompleted) {
@@ -98,7 +98,7 @@ define(['jquery', 'core/notification', 'core/str', 'core/ajax', 'core/templates'
         var planId = this._planId;
 
         ajax.call([{
-            methodname : 'tool_lp_data_for_plan_page',
+            methodname: 'tool_lp_data_for_plan_page',
             args: { planid: planId},
             done: this._pageContextLoaded.bind(this),
             fail: notification.exception
index 6c4376a..f61c0f9 100644 (file)
@@ -47,7 +47,6 @@ define(['jquery',
      * Cancel a review request and refresh the view.
      *
      * @param  {Object} data The user competency data.
-     * @return {Void}
      * @method _cancelReviewRequest
      */
     UserCompetencyWorkflow.prototype._cancelReviewRequest = function(data) {
@@ -71,7 +70,6 @@ define(['jquery',
      * Cancel a review request an refresh the view.
      *
      * @param  {Object} data The user competency data.
-     * @return {Void}
      * @method cancelReviewRequest
      */
     UserCompetencyWorkflow.prototype.cancelReviewRequest = function(data) {
@@ -82,7 +80,6 @@ define(['jquery',
      * Cancel a review request handler.
      *
      * @param  {Event} e The event.
-     * @return {Void}
      * @method _cancelReviewRequestHandler
      */
     UserCompetencyWorkflow.prototype._cancelReviewRequestHandler = function(e) {
@@ -95,7 +92,6 @@ define(['jquery',
      * Request a review and refresh the view.
      *
      * @param  {Object} data The user competency data.
-     * @return {Void}
      * @method _requestReview
      */
     UserCompetencyWorkflow.prototype._requestReview = function(data) {
@@ -119,7 +115,6 @@ define(['jquery',
      * Request a review.
      *
      * @param  {Object} data The user competency data.
-     * @return {Void}
      * @method requestReview
      */
     UserCompetencyWorkflow.prototype.requestReview = function(data) {
@@ -130,7 +125,6 @@ define(['jquery',
      * Request a review handler.
      *
      * @param  {Event} e The event.
-     * @return {Void}
      * @method _requestReviewHandler
      */
     UserCompetencyWorkflow.prototype._requestReviewHandler = function(e) {
@@ -143,7 +137,6 @@ define(['jquery',
      * Start a review and refresh the view.
      *
      * @param  {Object} data The user competency data.
-     * @return {Void}
      * @method _startReview
      */
     UserCompetencyWorkflow.prototype._startReview = function(data) {
@@ -167,7 +160,6 @@ define(['jquery',
      * Start a review.
      *
      * @param  {Object} data The user competency data.
-     * @return {Void}
      * @method startReview
      */
     UserCompetencyWorkflow.prototype.startReview = function(data) {
@@ -178,7 +170,6 @@ define(['jquery',
      * Start a review handler.
      *
      * @param  {Event} e The event.
-     * @return {Void}
      * @method _startReviewHandler
      */
     UserCompetencyWorkflow.prototype._startReviewHandler = function(e) {
@@ -191,7 +182,6 @@ define(['jquery',
      * Stop a review and refresh the view.
      *
      * @param  {Object} data The user competency data.
-     * @return {Void}
      * @method _stopReview
      */
     UserCompetencyWorkflow.prototype._stopReview = function(data) {
@@ -215,7 +205,6 @@ define(['jquery',
      * Stop a review.
      *
      * @param  {Object} data The user competency data.
-     * @return {Void}
      * @method stopReview
      */
     UserCompetencyWorkflow.prototype.stopReview = function(data) {
@@ -226,7 +215,6 @@ define(['jquery',
      * Stop a review handler.
      *
      * @param  {Event} e The event.
-     * @return {Void}
      * @method _stopReviewHandler
      */
     UserCompetencyWorkflow.prototype._stopReviewHandler = function(e) {
index 8c9e47e..f1f5cd3 100644 (file)
@@ -165,7 +165,7 @@ define(['jquery',
                 { key: 'deleteuserevidence', component: 'tool_lp', param: evidence.name },
                 { key: 'delete', component: 'moodle' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Delete evidence X?
@@ -320,7 +320,7 @@ define(['jquery',
                 { key: 'sendallcompetenciestoreview', component: 'tool_lp', param: evidence.name },
                 { key: 'confirm', component: 'moodle' },
                 { key: 'cancel', component: 'moodle' }
-            ]).done(function (strings) {
+            ]).done(function(strings) {
                 notification.confirm(
                     strings[0], // Confirm.
                     strings[1], // Send all competencies in review for X?
index dfd24fd..e776a1a 100644 (file)
@@ -40,14 +40,18 @@ class course_module_summary_exporter extends \core_competency\external\exporter
     }
 
     protected function get_other_values(renderer_base $output) {
-        $context = $this->related['cm']->context;
+        $cm = $this->related['cm'];
+        $context = $cm->context;
 
-        return array(
-            'id' => $this->related['cm']->id,
-            'name' => external_format_string($this->related['cm']->name, $context->id),
-            'url' => $this->related['cm']->url->out(),
-            'iconurl' => $this->related['cm']->get_icon_url()->out()
+        $values = array(
+            'id' => $cm->id,
+            'name' => external_format_string($cm->name, $context->id),
+            'iconurl' => $cm->get_icon_url()->out()
         );
+        if ($cm->url) {
+            $values['url'] = $cm->url->out();
+        }
+        return $values;
     }
 
 
@@ -60,7 +64,8 @@ class course_module_summary_exporter extends \core_competency\external\exporter
                 'type' => PARAM_TEXT
             ),
             'url' => array(
-                'type' => PARAM_URL
+                'type' => PARAM_URL,
+                'optional' => true,
             ),
             'iconurl' => array(
                 'type' => PARAM_URL
index 39d4e6e..9f13f6a 100644 (file)
 
 .tool-lp-menu li {
     float: left;
-    display: inline;
     position: relative;
     list-style-type: none;
     white-space: nowrap;
index 166fe5d..5a17c57 100644 (file)
@@ -50,7 +50,8 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
         $result = external::get_plugins_supporting_mobile();
         $result = external_api::clean_returnvalue(external::get_plugins_supporting_mobile_returns(), $result);
         $this->assertCount(0, $result['warnings']);
-        $this->assertCount(0, $result['plugins']);
+        $this->assertArrayHasKey('plugins', $result);
+        $this->assertTrue(is_array($result['plugins']));
     }
 
 }
index 55ae25d..503f280 100644 (file)
Binary files a/admin/tool/templatelibrary/amd/build/display.min.js and b/admin/tool/templatelibrary/amd/build/display.min.js differ
index 05507ee..66b3fbc 100644 (file)
@@ -120,14 +120,14 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
 
         var promises = ajax.call([{
             methodname: 'core_output_load_template',
-            args:{
+            args: {
                     component: component,
                     template: name,
                     themename: config.theme
             }
         }, {
             methodname: 'tool_templatelibrary_load_canonical_template',
-            args:{
+            args: {
                     component: component,
                     template: name
             }
@@ -136,13 +136,16 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
         // When returns a new promise that is resolved when all the passed in promises are resolved.
         // The arguments to the done become the values of each resolved promise.
         $.when.apply($, promises)
-            .done( function(source, originalSource) { templateLoaded(templateName, source, originalSource); })
+            .done(function(source, originalSource) {
+              templateLoaded(templateName, source, originalSource);
+            })
             .fail(notification.exception);
     };
 
     // Add the event listeners.
-    $('[data-region="list-templates"]').on('click', '[data-templatename]', function() {
+    $('[data-region="list-templates"]').on('click', '[data-templatename]', function(e) {
         var templatename = $(this).data('templatename');
+        e.preventDefault();
         loadTemplate(templatename);
     });
 
index 2c9d828..2fabeb2 100644 (file)
@@ -28,11 +28,11 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
      * The ajax call has returned with a new list of templates.
      *
      * @method reloadListTemplate
-     * @param String[] templates List of template ids.
+     * @param {String[]} templateList List of template ids.
      */
     var reloadListTemplate = function(templateList) {
         templates.render('tool_templatelibrary/search_results', { templates: templateList })
-            .done(function (result, js) {
+            .done(function(result, js) {
                 templates.replaceNode($('[data-region="searchresults"]'), result, js);
             }).fail(notification.exception);
     };
@@ -63,8 +63,8 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
      * the function will only be executed once.
      *
      * @method queueRefresh
-     * @param function callback
-     * @param int delay The time in milliseconds to delay.
+     * @param {function} callback
+     * @param {Number} delay The time in milliseconds to delay.
      */
     var queueRefresh = function(callback, delay) {
         if (throttle !== null) {
index 0211abd..8264677 100644 (file)
@@ -7,14 +7,11 @@
 #page-blocks-community-communitycourse .hubtext {display: block; width: 68%; padding-left: 165px;}
 #page-blocks-community-communitycourse .hubimgandtext {display:table;}
 #page-blocks-community-communitycourse .hubimage {float: left; display: block; width: 100px;}
-#page-blocks-community-communitycourse .hubdescriptiontext {}
 #page-blocks-community-communitycourse .hubstats {padding-top: 10px}
 #page-blocks-community-communitycourse .hubstats .iconhelp {float: left; padding-right: 3px;}
 #page-blocks-community-communitycourse .hubadditionaldesc {color: #666666; font-size: 90%; display:block;}
 #page-blocks-community-communitycourse .hubscreenshot {margin-right: 10px;}
-#page-blocks-community-communitycourse .hubnottrusted {}
 #page-blocks-community-communitycourse .hubtrusted {display:inline;}
-#page-blocks-community-communitycourse .hubnottrusted {}
 #page-blocks-community-communitycourse .trustedtr {background-color: #ffe1c3;}
 #page-blocks-community-communitycourse .prioritisetr {background-color: #ffd4ff;}
 #page-blocks-community-communitycourse .blockdescription {font-size: 80%; color: #555555;}
@@ -25,7 +22,6 @@
 #page-blocks-community-communitycourse .comment-link {font-size: 80%; color: #555555;}
 #page-blocks-community-communitycourse .coursescreenshot {text-align:center;cursor: pointer;}
 #page-blocks-community-communitycourse .hubcourseinfo {margin-left: 15px;}
-#page-blocks-community-communitycourse .coursesitelink {}
 #page-blocks-community-communitycourse .pagingbar {text-align: center;}
 #page-blocks-community-communitycourse .coursecomment {float: right;}
 #page-blocks-community-communitycourse .courseoperations {margin-top:9px; text-align:center}
     font-size: 95%;
     margin-bottom: 9px;
 }
-#page-blocks-community-communitycourse .comment-list li {
-    background-color:#FFFAFA !important;
-    -moz-border-radius: 6px;
-    -webkit-border-radius: 6px;
-    padding-right: 4px;
-    padding-bottom: 2px;
-}
 
 /*  STAR RATING  */
 #page-blocks-community-communitycourse .ratingcount {color: #8B8989;font-size: 80%;vertical-align: top;}
     margin-top:15px;
 }
 #page-blocks-community-communitycourse .hubrateandcomment { font-size: 80%;}
-#page-blocks-community-communitycourse .hubcourseoutcomes {}
 #page-blocks-community-communitycourse .nextlink {text-align: center;margin-top: 6px;}
 #page-blocks-community-communitycourse .textinfo { text-align: center;}
 
index 41b9b45..d935742 100644 (file)
@@ -28,9 +28,9 @@ define(['jquery'], function($) {
     // Copied from lib/navigationlib.php navigation_node constants.
     var NODETYPE = {
         // @type int Activity (course module) = 40.
-        ACTIVITY : 40,
+        ACTIVITY: 40,
         // @type int Resource (course module = 50.
-        RESOURCE : 50,
+        RESOURCE: 50,
     };
 
     /**
@@ -39,7 +39,6 @@ define(['jquery'], function($) {
      * @method buildDOM
      * @param {Object} rootElement the root element of DOM.
      * @param {object} nodes jquery object representing the nodes to be build.
-     * @return
      */
     function buildDOM(rootElement, nodes) {
         var ul = $('<ul></ul>');
@@ -94,7 +93,7 @@ define(['jquery'], function($) {
 
                 if (icon) {
                     link.append(icon);
-                    link.append('<span class="item-content-wrap">'+node.name+'</span>');
+                    link.append('<span class="item-content-wrap">' + node.name + '</span>');
                 } else {
                     link.append(node.name);
                 }
@@ -109,7 +108,7 @@ define(['jquery'], function($) {
 
                 if (icon) {
                     span.append(icon);
-                    span.append('<span class="item-content-wrap">'+node.name+'</span>');
+                    span.append('<span class="item-content-wrap">' + node.name + '</span>');
                 } else {
                     span.append(node.name);
                 }
index 2cb5137..ce5cb99 100644 (file)
@@ -29,8 +29,8 @@ define(['jquery', 'core/ajax', 'core/config', 'block_navigation/ajax_response_re
          * Get the block instance id.
          *
          * @function getBlockInstanceId
-         * @param element
-         * @returns {*}
+         * @param {Element} element
+         * @returns {String} the instance id
          */
         function getBlockInstanceId(element) {
             return element.closest('[data-block]').attr('data-instanceid');
index 976ae98..990cd96 100644 (file)
@@ -1,4 +1,4 @@
-@block @block_private_files @file_upload @javascript
+@block @block_private_files @_file_upload @javascript
 Feature: The private files block allows users to store files privately in moodle
   In order to store a private file in moodle
   As a user
index 77d5756..ec611bb 100644 (file)
@@ -1,4 +1,4 @@
-@block @block_private_files @file_upload
+@block @block_private_files @_file_upload
 Feature: The private files block allows users to store files privately in moodle
   In order to store a private file in moodle
   As a teacher
index 7df025c..42b3d42 100644 (file)
@@ -153,7 +153,11 @@ class comment {
         } else if (!empty($options->courseid)) {
             $this->courseid = $options->courseid;
         } else {
-            $this->courseid = SITEID;
+            if ($coursecontext = $this->context->get_course_context(false)) {
+                $this->courseid = $coursecontext->instanceid;
+            } else {
+                $this->courseid = SITEID;
+            }
         }
 
         // setup coursemodule
index b11daa4..a440bc2 100644 (file)
@@ -4152,7 +4152,7 @@ class api {
      * @param int $limit Number of records to return.
      * @return \core_competency\evidence[]
      */
-    public static function list_evidence_in_course($userid = 0, $courseid = 0, $competencyid = 0, $sort = 'timecreated',
+    public static function list_evidence_in_course($userid = 0, $courseid = 0, $competencyid = 0, $sort = 'timecreated, id',
                                                    $order = 'DESC', $skip = 0, $limit = 0) {
         static::require_enabled();
 
@@ -4166,11 +4166,8 @@ class api {
             return array();
         }
 
-        $params = array(
-            'usercompetencyid' => $usercompetency->get_id(),
-            'contextid' => context_course::instance($courseid)->id
-        );
-        return evidence::get_records($params, $sort, $order, $skip, $limit);
+        $context = context_course::instance($courseid);
+        return evidence::get_records_for_usercompetency($usercompetency->get_id(), $context, $sort, $order, $skip, $limit);
     }
 
     /**
index ed3445d..cc8ec05 100644 (file)
@@ -284,4 +284,52 @@ class evidence extends persistent {
         return has_capability('moodle/competency:evidencedelete', context_user::instance($userid));
     }
 
+    /**
+     * Load a list of records in a context for a user competency.
+     *
+     * @param int $usercompetencyid The id of the user competency.
+     * @param context $context Context to filter the evidence list.
+     * @param string $sort The field from the evidence table to sort on.
+     * @param string $order The sort direction
+     * @param int $skip Limitstart.
+     * @param int $limit Number of rows to return.
+     *
+     * @return \core_competency\persistent[]
+     */
+    public static function get_records_for_usercompetency($usercompetencyid,
+                                                          \context $context,
+                                                          $sort = '',
+                                                          $order = 'ASC',
+                                                          $skip = 0,
+                                                          $limit = 0) {
+        global $DB;
+
+        $params = array(
+            'usercompid' => $usercompetencyid,
+            'path' => $context->path . '/%',
+            'contextid' => $context->id
+        );
+
+        if (!empty($sort)) {
+            $sortcolumns = explode(',', $sort);
+            $sortcolumns = array_map('trim', $sortcolumns);
+            $sort = ' ORDER BY e.' . implode(', e.', $sortcolumns) . ' ' . $order;
+        }
+
+        $sql = 'SELECT e.*
+                  FROM {' . static::TABLE . '} e
+                  JOIN {context} c ON c.id = e.contextid
+                 WHERE (c.path LIKE :path OR c.id = :contextid)
+                   AND e.usercompetencyid = :usercompid
+                 ' . $sort;
+        $records = $DB->get_records_sql($sql, $params, $skip, $limit);
+        $instances = array();
+
+        foreach ($records as $record) {
+            $newrecord = new static(0, $record);
+            array_push($instances, $newrecord);
+        }
+        return $instances;
+    }
+
 }
index 9e5c4d3..44aaf76 100644 (file)
@@ -2579,6 +2579,47 @@ class core_competency_api_testcase extends advanced_testcase {
         $this->assertEquals(null, $ev4->get_actionuserid());
     }
 
+    public function test_list_evidence_in_course() {
+        global $SITE;
+
+        $this->resetAfterTest(true);
+        $dg = $this->getDataGenerator();
+        $lpg = $dg->get_plugin_generator('core_competency');
+        $u1 = $dg->create_user();
+        $course = $dg->create_course();
+        $coursecontext = context_course::instance($course->id);
+
+        $this->setAdminUser();
+        $f = $lpg->create_framework();
+        $c = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
+        $c2 = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
+        $cc = api::add_competency_to_course($course->id, $c->get_id());
+        $cc2 = api::add_competency_to_course($course->id, $c2->get_id());
+
+        $pagegenerator = $this->getDataGenerator()->get_plugin_generator('mod_page');
+        $page = $pagegenerator->create_instance(array('course' => $course->id));
+
+        $cm = get_coursemodule_from_instance('page', $page->id);
+        $cmcontext = context_module::instance($cm->id);
+        // Add the competency to the course module.
+        $ccm = api::add_competency_to_course_module($cm, $c->get_id());
+
+        // Now add the evidence to the course.
+        $evidence1 = api::add_evidence($u1->id, $c->get_id(), $coursecontext->id, \core_competency\evidence::ACTION_LOG,
+            'invaliddata', 'error');
+
+        $result = api::list_evidence_in_course($u1->id, $course->id, $c->get_id());
+        $this->assertEquals($result[0]->get_id(), $evidence1->get_id());
+
+        // Now add the evidence to the course module.
+        $evidence2 = api::add_evidence($u1->id, $c->get_id(), $cmcontext->id, \core_competency\evidence::ACTION_LOG,
+            'invaliddata', 'error');
+
+        $result = api::list_evidence_in_course($u1->id, $course->id, $c->get_id());
+        $this->assertEquals($result[0]->get_id(), $evidence2->get_id());
+        $this->assertEquals($result[1]->get_id(), $evidence1->get_id());
+    }
+
     public function test_list_course_modules_using_competency() {
         global $SITE;
 
index 05eda15..28437de 100644 (file)
@@ -61,10 +61,11 @@ class completion_criteria_activity extends completion_criteria {
      */
     public function config_form_display(&$mform, $data = null) {
         $modnames = get_module_types_names();
-        $mform->addElement('checkbox', 'criteria_activity['.$data->id.']',
-                $modnames[self::get_mod_name($data->module)].
-                ' - '.
-                format_string($data->name));
+        $mform->addElement('advcheckbox',
+                'criteria_activity['.$data->id.']',
+                $modnames[self::get_mod_name($data->module)] . ' - ' . format_string($data->name),
+                null,
+                array('group' => 1));
 
         if ($this->id) {
             $mform->setDefault('criteria_activity['.$data->id.']', 1);
index a96f802..ee734d8 100644 (file)
@@ -2,6 +2,6 @@
     "require-dev": {
         "phpunit/phpunit": "4.8.*",
         "phpunit/dbUnit": "1.4.*",
-        "moodlehq/behat-extension": "3.32.0"
+        "moodlehq/behat-extension": "3.32.1"
     }
 }
index f6f23ac..4eda2d9 100644 (file)
@@ -4,8 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "0bd3021c5dea5e28a07d7a58d0f1676d",
-    "content-hash": "528abab2d8628a8442924ec3defc561d",
+    "hash": "949f8a407958a19e2dba7929b3dc0576",
+    "content-hash": "bd742592f8ed4700884f6c651226c961",
     "packages": [],
     "packages-dev": [
         {
         },
         {
             "name": "moodlehq/behat-extension",
-            "version": "v3.32.0",
+            "version": "v3.32.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/moodlehq/moodle-behat-extension.git",
-                "reference": "f0b6a44de9111fd4fa82796aca712b9e9772d07e"
+                "reference": "f8305058ce9140864c23c9b667e3d7d487fdc006"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/moodlehq/moodle-behat-extension/zipball/f0b6a44de9111fd4fa82796aca712b9e9772d07e",
-                "reference": "f0b6a44de9111fd4fa82796aca712b9e9772d07e",
+                "url": "https://api.github.com/repos/moodlehq/moodle-behat-extension/zipball/f8305058ce9140864c23c9b667e3d7d487fdc006",
+                "reference": "f8305058ce9140864c23c9b667e3d7d487fdc006",
                 "shasum": ""
             },
             "require": {
                 "Behat",
                 "moodle"
             ],
-            "time": "2016-05-09 03:32:06"
+            "time": "2016-06-20 07:56:08"
         },
         {
             "name": "phpdocumentor/reflection-docblock",
         },
         {
             "name": "sebastian/exporter",
-            "version": "1.2.1",
+            "version": "1.2.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/exporter.git",
-                "reference": "7ae5513327cb536431847bcc0c10edba2701064e"
+                "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
-                "reference": "7ae5513327cb536431847bcc0c10edba2701064e",
+                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
+                "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
                 "shasum": ""
             },
             "require": {
                 "sebastian/recursion-context": "~1.0"
             },
             "require-dev": {
+                "ext-mbstring": "*",
                 "phpunit/phpunit": "~4.4"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.2.x-dev"
+                    "dev-master": "1.3.x-dev"
                 }
             },
             "autoload": {
                 "export",
                 "exporter"
             ],
-            "time": "2015-06-21 07:55:53"
+            "time": "2016-06-17 09:04:28"
         },
         {
             "name": "sebastian/global-state",
index ce4880a..53d4b47 100644 (file)
@@ -88,6 +88,9 @@ class course_completion_form extends moodleform {
         $activities = $completion->get_activities();
         if (!empty($activities)) {
 
+            if (!$completion->is_course_locked()) {
+                $this->add_checkbox_controller(1, null, null, 0);
+            }
             foreach ($activities as $activity) {
                 $params_a = array('moduleinstance' => $activity->id);
                 $criteria = new completion_criteria_activity(array_merge($params, $params_a));
index 9bb62ab..6705b5b 100644 (file)
@@ -139,8 +139,3 @@ Optional file (styles)
 
   If this file exists it will be included in the CSS Moodle generates.
 
-
-Optional delete course hook
----------------------------
-
-* in your yourformat/lib.php add function format_yourformat_delete_course($courseid)
\ No newline at end of file
index 1e6a7dd..03db896 100644 (file)
@@ -41,18 +41,14 @@ Feature: Sections can be edited and deleted in topics format
     Then I should see "Use default section name [Topic 2]"
 
   Scenario: Edit section summary in topics format
-    When I edit the section "2"
-    And I set the following fields to these values:
+    When I edit the section "2" and I fill the form with:
       | Summary | Welcome to section 2 |
-    And I press "Save changes"
     Then I should see "Welcome to section 2" in the "li#section-2" "css_element"
 
   Scenario: Edit section default name in topics format
-    When I edit the section "2"
-    And I set the following fields to these values:
+    When I edit the section "2" and I fill the form with:
       | Use default section name | 0                        |
       | name                     | This is the second topic |
-    And I press "Save changes"
     Then I should see "This is the second topic" in the "li#section-2" "css_element"
     And I should not see "Topic 2" in the "li#section-2" "css_element"
 
index 8d82f27..8bdcfe0 100644 (file)
@@ -2,6 +2,9 @@ This files describes API changes for course formats
 
 Overview of this plugin type at http://docs.moodle.org/dev/Course_formats
 
+=== 3.2 ===
+* Callback delete_course is deprecated and should be replaced with observer for event \core\event\course_content_deleted
+
 === 3.1 ===
 * Course format may use the inplace_editable template to allow quick editing of section names, see
   https://docs.moodle.org/dev/Inplace_editable and MDL-51802 for example implementation.
index 787866a..637a328 100644 (file)
@@ -58,7 +58,6 @@ class core_course_renderer extends plugin_renderer_base {
     public function __construct(moodle_page $page, $target) {
         $this->strings = new stdClass;
         parent::__construct($page, $target);
-        $this->add_modchoosertoggle();
     }
 
     /**
@@ -66,8 +65,12 @@ class core_course_renderer extends plugin_renderer_base {
      *
      * Theme can overwrite as an empty function to exclude it (for example if theme does not
      * use modchooser at all)
+     *
+     * @deprecated since 3.2
      */
     protected function add_modchoosertoggle() {
+        debugging('core_course_renderer::add_modchoosertoggle() is deprecated.', DEBUG_DEVELOPER);
+
         global $CFG;
 
         // Only needs to be done once per page.
@@ -182,9 +185,7 @@ class core_course_renderer extends plugin_renderer_base {
         array(array('courseid' => $course->id, 'closeButtonTitle' => get_string('close', 'editor')))
         );
         $this->page->requires->strings_for_js(array(
-                'addresourceoractivity',
-                'modchooserenable',
-                'modchooserdisable',
+                'addresourceoractivity'
         ), 'moodle');
 
         // Add the header
@@ -406,9 +407,6 @@ class core_course_renderer extends plugin_renderer_base {
     /**
      * Renders HTML for the menus to add activities and resources to the current course
      *
-     * Note, if theme overwrites this function and it does not use modchooser,
-     * see also {@link core_course_renderer::add_modchoosertoggle()}
-     *
      * @param stdClass $course
      * @param int $section relative section number (field course_sections.section)
      * @param int $sectionreturn The section to link back to
index ed78f98..cf006b9 100644 (file)
@@ -401,7 +401,7 @@ class behat_course extends behat_base {
     public function i_edit_the_section_and_i_fill_the_form_with($sectionnumber, TableNode $data) {
 
         // Edit given section.
-        $this->execute("behat_course::i_edit_the_section");
+        $this->execute("behat_course::i_edit_the_section", $sectionnumber);
 
         // Set form fields.
         $this->execute("behat_forms::i_set_the_following_fields_to_these_values", $data);
index 6fc0568..6d8485d 100644 (file)
@@ -43,6 +43,5 @@ Feature: Restrict activities availability
     And I log in as "teacher1"
     And I follow "Course 1"
     When I turn editing mode on
-    And I follow "Activity chooser off"
     Then the "Add an activity to section 'Topic 1'" select box should not contain "Chat"
     Then the "Add an activity to section 'Topic 1'" select box should not contain "Glossary"
index d4d67cf..2bd50f0 100644 (file)
@@ -17,7 +17,6 @@
     $move        = optional_param('move', 0, PARAM_INT);
     $marker      = optional_param('marker',-1 , PARAM_INT);
     $switchrole  = optional_param('switchrole',-1, PARAM_INT); // Deprecated, use course/switchrole.php instead.
-    $modchooser  = optional_param('modchooser', -1, PARAM_BOOL);
     $return      = optional_param('return', 0, PARAM_LOCALURL);
 
     $params = array();
                 redirect($PAGE->url);
             }
         }
-        if (($modchooser == 1) && confirm_sesskey()) {
-            set_user_preference('usemodchooser', $modchooser);
-        } else if (($modchooser == 0) && confirm_sesskey()) {
-            set_user_preference('usemodchooser', $modchooser);
-        }
 
         if (has_capability('moodle/course:sectionvisibility', $context)) {
             if ($hide && confirm_sesskey()) {
index 1689ac9..b986555 100644 (file)
Binary files a/course/yui/build/moodle-course-modchooser/moodle-course-modchooser-debug.js and b/course/yui/build/moodle-course-modchooser/moodle-course-modchooser-debug.js differ
index 1f08287..a690c8a 100644 (file)
Binary files a/course/yui/build/moodle-course-modchooser/moodle-course-modchooser-min.js and b/course/yui/build/moodle-course-modchooser/moodle-course-modchooser-min.js differ
index 1689ac9..b986555 100644 (file)
Binary files a/course/yui/build/moodle-course-modchooser/moodle-course-modchooser.js and b/course/yui/build/moodle-course-modchooser/moodle-course-modchooser.js differ
index ef6ac4d..8adbac4 100644 (file)
@@ -54,9 +54,6 @@ Y.extend(MODCHOOSER, M.core.chooserdialogue, {
         // Initialize existing sections and register for dynamically created sections
         this.setup_for_section();
         M.course.coursebase.register_module(this);
-
-        // Catch the page toggle
-        Y.all('.block_settings #settingsnav .type_course .modchoosertoggle a').on('click', this.toggle_mod_chooser, this);
     },
 
     /**
@@ -130,62 +127,6 @@ Y.extend(MODCHOOSER, M.core.chooserdialogue, {
         this.display_chooser(e);
     },
 
-    /**
-     * Toggle availability of the activity chooser.
-     *
-     * @method toggle_mod_chooser
-     * @param {EventFacade} e
-     */
-    toggle_mod_chooser : function(e) {
-        // Get the add section link
-        var modchooserlinks = Y.all('div.addresourcemodchooser');
-
-        // Get the dropdowns
-        var dropdowns = Y.all('div.addresourcedropdown');
-
-        if (modchooserlinks.size() === 0) {
-            // Continue with non-js action if there are no modchoosers to add
-            return;
-        }
-
-        // We need to update the text and link
-        var togglelink = Y.one('.block_settings #settingsnav .type_course .modchoosertoggle a');
-
-        // The actual text is in the last child
-        var toggletext = togglelink.get('lastChild');
-
-        var usemodchooser;
-        // Determine whether they're currently hidden
-        if (modchooserlinks.item(0).hasClass('visibleifjs')) {
-            // The modchooser is currently visible, hide it
-            usemodchooser = 0;
-            modchooserlinks
-                .removeClass('visibleifjs')
-                .addClass('hiddenifjs');
-            dropdowns
-                .addClass('visibleifjs')
-                .removeClass('hiddenifjs');
-            toggletext.set('data', M.util.get_string('modchooserenable', 'moodle'));
-            togglelink.set('href', togglelink.get('href').replace('off', 'on'));
-        } else {
-            // The modchooser is currently not visible, show it
-            usemodchooser = 1;
-            modchooserlinks
-                .addClass('visibleifjs')
-                .removeClass('hiddenifjs');
-            dropdowns
-                .removeClass('visibleifjs')
-                .addClass('hiddenifjs');
-            toggletext.set('data', M.util.get_string('modchooserdisable', 'moodle'));
-            togglelink.set('href', togglelink.get('href').replace('on', 'off'));
-        }
-
-        M.util.set_user_preference('usemodchooser', usemodchooser);
-
-        // Prevent the page from reloading
-        e.preventDefault();
-    },
-
     /**
      * Helper function to set the value of a hidden radio button when a
      * selection is made.
index 4b541cd..2818430 100644 (file)
@@ -58,6 +58,9 @@ class behat_enrol extends behat_base {
             array($this->escape($enrolmethod), get_string('addinstance', 'enrol'))
         );
 
+        // Wait again, for page to reloaded.
+        $this->execute('behat_general::i_wait_to_be_redirected');
+
         // Set form fields.
         $this->execute("behat_forms::i_set_the_following_fields_to_these_values", $table);
 
index a1283ce..f46f5f3 100644 (file)
@@ -1,14 +1,26 @@
 /**
  * Filters
  */
-.mediaplugin_html5audio, .mediaplugin_html5video, .mediaplugin_swf, .mediaplugin_flv, .mediaplugin_real, .mediaplugin_youtube, .mediaplugin_vimeo, .mediaplugin_wmp, .mediaplugin_qt
-    {display:block;margin-top:5px;margin-bottom:5px;text-align: center;}
-.mediaplugin.mediaplugin_mp3 object {display:inline;height:15px;width:180px;margin-left:0.5em;}
-
+.mediaplugin_html5audio,
+.mediaplugin_html5video,
+.mediaplugin_swf,
+.mediaplugin_flv,
+.mediaplugin_real,
+.mediaplugin_youtube,
+.mediaplugin_vimeo,
+.mediaplugin_wmp,
+.mediaplugin_qt {
+  display: block;
+  margin-top: 5px;
+  margin-bottom: 5px;
+  text-align: center;
+}
 
 /*
  * mp3 player colours -this read using JS and applied to swf audio flow player
  * see http://flowplayer.org/documentation/skinning/controlbar.html?skin=default for more color properties,
  * any property that ends with '...Color' is supported here.
  */
-.mp3flowplayer_backgroundColor {color: #000000;}
+.mp3flowplayer_backgroundColor {
+  color: #000000;
+}
index 6f9b158..09ffb0c 100644 (file)
@@ -22,7 +22,7 @@
  * @copyright  2015 Jun Pataleta <jun@moodle.com>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
   */
-define(['jquery', 'core/templates', 'core/notification', 'core/yui'], function ($, templates, notification) {
+define(['jquery', 'core/templates', 'core/notification', 'core/yui'], function($, templates, notification) {
 
     // Private variables and functions.
 
@@ -34,18 +34,18 @@ define(['jquery', 'core/templates', 'core/notification', 'core/yui'], function (
          * Basically, it performs the binding and handling of the button click event for
          * the 'Insert frequently used comment' button.
          *
-         * @param criterionId The criterion ID.
-         * @param buttonId The element ID of the button which the handler will be bound to.
-         * @param remarkId The element ID of the remark text area where the text of the selected comment will be copied to.
-         * @param commentOptions The array of frequently used comments to be used as options.
+         * @param {Integer} criterionId The criterion ID.
+         * @param {String} buttonId The element ID of the button which the handler will be bound to.
+         * @param {String} remarkId The element ID of the remark text area where the text of the selected comment will be copied to.
+         * @param {Array} commentOptions The array of frequently used comments to be used as options.
          */
-        initialise: function (criterionId, buttonId, remarkId, commentOptions) {
+        initialise: function(criterionId, buttonId, remarkId, commentOptions) {
             /**
              * Display the chooser dialog using the compiled HTML from the mustache template
              * and binds onclick events for the generated comment options.
              *
-             * @param compiledSource The compiled HTML from the mustache template
-             * @param comments Array containing comments.
+             * @param {String} compiledSource The compiled HTML from the mustache template
+             * @param {Array} comments Array containing comments.
              */
             function displayChooserDialog(compiledSource, comments) {
                 var titleLabel = '<label>' + M.util.get_string('insertcomment', 'gradingform_guide') + '</label>';
@@ -68,11 +68,11 @@ define(['jquery', 'core/templates', 'core/notification', 'core/yui'], function (
                 });
 
                 // Loop over each comment item and bind click events.
-                $.each(comments, function (index, comment) {
+                $.each(comments, function(index, comment) {
                     var commentOptionId = '#comment-option-' + criterionId + '-' + comment.id;
 
                     // Delegate click event for the generated option link.
-                    $(commentOptionId).click(function () {
+                    $(commentOptionId).click(function() {
                         var remarkTextArea = $('#' + remarkId);
                         var remarkText = remarkTextArea.val();
 
@@ -88,7 +88,7 @@ define(['jquery', 'core/templates', 'core/notification', 'core/yui'], function (
                     });
 
                     // Handle keypress on list items.
-                    $(document).off('keypress', commentOptionId).on('keypress', commentOptionId, function () {
+                    $(document).off('keypress', commentOptionId).on('keypress', commentOptionId, function() {
                         var keyCode = event.which || event.keyCode;
 
                         // Enter or space key.
@@ -124,14 +124,14 @@ define(['jquery', 'core/templates', 'core/notification', 'core/yui'], function (
 
                 // Render the template and display the comment chooser dialog.
                 templates.render('gradingform_guide/comment_chooser', context)
-                    .done(function (compiledSource) {
+                    .done(function(compiledSource) {
                         displayChooserDialog(compiledSource, commentOptions);
                     })
                     .fail(notification.exception);
             }
 
             // Bind click event for the comments chooser button.
-            $("#" + buttonId).click(function (e) {
+            $("#" + buttonId).click(function(e) {
                 e.preventDefault();
                 generateCommentsChooser();
             });
index 71e2c5d..ed2ae2d 100644 (file)
@@ -70,7 +70,7 @@ $string['guidestatus'] = 'Current marking guide status';
 $string['hidemarkerdesc'] = 'Hide marker criterion descriptions';
 $string['hidestudentdesc'] = 'Hide student criterion descriptions';
 $string['insertcomment'] = 'Insert frequently used comment';
-$string['maxscore'] = 'Maximum mark';
+$string['maxscore'] = 'Maximum score';
 $string['name'] = 'Name';
 $string['needregrademessage'] = 'The marking guide definition was changed after this student had been graded. The student can not see this marking guide until you check the marking guide and update the grade.';
 $string['pluginname'] = 'Marking guide';
index f368c14..7c90524 100644 (file)
@@ -57,7 +57,7 @@ class behat_gradingform_guide extends behat_base {
      * @param TableNode $guide
      */
     public function i_define_the_following_marking_guide(TableNode $guide) {
-        $steptableinfo = '| Criterion name | Description for students | Description for markers | Maximum mark |';
+        $steptableinfo = '| Criterion name | Description for students | Description for markers | Maximum score |';
 
         if ($criteria = $guide->getHash()) {
             $addcriterionbutton = $this->find_button(get_string('addcriterion', 'gradingform_guide'));
@@ -92,7 +92,7 @@ class behat_gradingform_guide extends behat_base {
                 $this->set_guide_field_value($criterionroot . '[descriptionmarkers]', $criterion['Description for markers']);
 
                 // Set the field value for the Max score field.
-                $this->set_guide_field_value($criterionroot . '[maxscore]', $criterion['Maximum mark']);
+                $this->set_guide_field_value($criterionroot . '[maxscore]', $criterion['Maximum score']);
             }
         }
     }
index abe994a..f043693 100644 (file)
@@ -29,10 +29,10 @@ Feature: Marking guides can be created and edited
       | Name        | Assignment 1 marking guide     |
       | Description | Marking guide test description |
     And I define the following marking guide:
-      | Criterion name    | Description for students         | Description for markers         | Maximum mark |
-      | Guide criterion A | Guide A description for students | Guide A description for markers | 30           |
-      | Guide criterion B | Guide B description for students | Guide B description for markers | 30           |
-      | Guide criterion C | Guide C description for students | Guide C description for markers | 40           |
+      | Criterion name    | Description for students         | Description for markers         | Maximum score |
+      | Guide criterion A | Guide A description for students | Guide A description for markers | 30            |
+      | Guide criterion B | Guide B description for students | Guide B description for markers | 30            |
+      | Guide criterion C | Guide C description for students | Guide C description for markers | 40            |
     And I define the following frequently used comments:
       | Comment 1 |
       | Comment 2 |
index 1c0da1e..2983874 100644 (file)
@@ -1039,7 +1039,8 @@ function print_grade_page_head($courseid, $active_type, $active_plugin=null,
             if (isset($user)) {
                 $output = $OUTPUT->context_header(
                         array(
-                            'heading' => fullname($user),
+                            'heading' => html_writer::link(new moodle_url('/user/view.php', array('id' => $user->id,
+                                'course' => $courseid)), fullname($user)),
                             'user' => $user,
                             'usercontext' => context_user::instance($user->id)
                         ), 2
index ef92e97..4c3aac7 100644 (file)
@@ -34,7 +34,6 @@
 .dir-rtl.path-grade-report-grader .gradeparent table {
     border-left-width: 0;
     border-right-width: 1px;
-    max-width: initial;
 }
 
 /**
 .path-grade-report-grader .yui3-overlay {
   border: 0;
   background: none;
-  background-color: initial;
+  background-color: inherit;
   min-width: 200px;
 }
 
index d341ffd..71dad25 100644 (file)
@@ -48,7 +48,6 @@ Feature: Using the AJAX grading feature of Grader report to update grades and fe
       | grade_report_showaverages | 0 |
       | grade_report_enableajax | 1 |
 
-
   @javascript
   Scenario: Use the grader report without editing, with AJAX on and quick feedback off
     When the following config values are set as admin:
index bb75576..c185c23 100644 (file)
Binary files a/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-debug.js and b/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-debug.js differ
index a151a1b..f81abac 100644 (file)
Binary files a/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-min.js and b/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-min.js differ
index 6fcd0dd..ac36953 100644 (file)
Binary files a/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable.js and b/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable.js differ
index 6d496bb..a57aed8 100644 (file)
@@ -259,6 +259,11 @@ FloatingHeaders.prototype = {
             return this;
         }
 
+        if (M.cfg.behatsiterunning) {
+            // If the behat site is running we don't want floating elements.
+            return;
+        }
+
         // Generate floating elements.
         this._setupFloatingUserColumn();
         this._setupFloatingUserHeader();
index 7bde323..075cb11 100644 (file)
@@ -61,7 +61,7 @@ dir-rtl.path-grade-report-singleview div.groupselector select {
 .path-grade-report-singleview .itemnav {
     font-size: small;
     display: inline;
-    margin-bottom: 0.5em;
+    padding-bottom: 0.5em;
 }
 .path-grade-report-singleview itemnav.previtem {
    float:left;
index ca22495..8255c44 100644 (file)
@@ -208,7 +208,9 @@ var removeLoaderImgs = function (elClass, parentId) {
     var parentEl = document.getElementById(parentId);
     if (parentEl) {
         var loader = document.getElementById("loaderImg");
-        parentEl.removeChild(loader);
+        if (loader) {
+            parentEl.removeChild(loader);
+        }
     }
 };
 
diff --git a/install/lang/da_rum/langconfig.php b/install/lang/da_rum/langconfig.php
new file mode 100644 (file)
index 0000000..1c8c74c
--- /dev/null
@@ -0,0 +1,35 @@
+<?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/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package   installer
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$string['parentlanguage'] = 'da';
+$string['thisdirection'] = 'ltr';
+$string['thislanguage'] = 'Dansk Rum';
index 2762ccc..5181c42 100644 (file)
@@ -31,7 +31,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 $string['language'] = 'Idioma';
-$string['moodlelogo'] = 'Logotipo Moodle';
+$string['moodlelogo'] = 'Logótipo Moodle';
 $string['next'] = 'Seguinte';
 $string['previous'] = 'Anterior';
 $string['reload'] = 'Recarregar';
index e723e1b..42a202e 100644 (file)
@@ -64,5 +64,6 @@ $string['phpversionhelp'] = '<p>Moodle necesită o versiune PHP de cel puțin  4
 <p>Trebuie să upgradați PHP sau să îl mutați pe o gazdă cu o nouă versiune de PHP!<br />
 (În cazul 5.0.x puteți, de asemenea, să downgradați la versiunea 4.4.x)</p>';
 $string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
+$string['welcomep20'] = 'Vedeți această pagină deoarece ați instalat și lansat cu succes pachetul  <strong>{$a->packname} {$a->packversion}</strong> în computerul dumneavoastră. Felicitări!';
 $string['welcomep40'] = 'Pachetul include și <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
 $string['wwwroot'] = 'Adresă Web';
index c09b45d..855b16e 100644 (file)
@@ -42,3 +42,4 @@ $string['cliunknowoption'] = 'Нераспознанные параметры:
 $string['cliyesnoprompt'] = 'Введите y (обозначает Да) или n (обозначает Нет)';
 $string['environmentrequireinstall'] = 'необходимо установить и включить';
 $string['environmentrequireversion'] = 'требуется версия {$a->needed}, у Вас используется версия {$a->current}';
+$string['upgradekeyset'] = 'Ключ обновления (оставьте пустым, если не хотите его задавать)';
index 599a475..5dffe08 100644 (file)
@@ -31,6 +31,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 $string['language'] = 'Язык';
+$string['moodlelogo'] = 'Логотип Moodle';
 $string['next'] = 'Далее';
 $string['previous'] = 'Назад';
 $string['reload'] = 'Обновить';
index 6f888e8..ab8604f 100644 (file)
@@ -69,7 +69,9 @@ $string['pathshead'] = '確認路徑';
 $string['pathsrodataroot'] = '資料根目錄是無法寫入的';
 $string['pathsroparentdataroot'] = '上層目錄({$a->parent})是不可寫入的。安裝程式無法建立資料目錄({$a->dataroot})。';
 $string['pathssubadmindir'] = '有些網站主機使用/admin這個網址來瀏覽控制面版或其他功能。很不幸,這個設定和Moodle管理頁面的標準路徑產生衝突。這個問題可以解決,只需在您的安裝目錄中把admin更換名稱,然後把新名稱輸入到這裡。例如<em>moodleadmin</em>這麼做會改變Moodle中的管理連接。';
-$string['pathssubdataroot'] = '你需要有一個地方讓Moodle可以儲存上傳的檔案。這一目錄對於網頁伺服器用戶(通常是"nobody"或"apache")而言,應該是可讀的和<b>可寫的</b>。但是它必須不能經由網頁直接存取。若此目錄不存在,這安裝程式將會試著建立它。';
+$string['pathssubdataroot'] = '<p>你需要有一個目錄讓Moodle可以儲存所有的用戶上傳的檔案。</p><p>這目錄對於網頁伺服器用戶(通常是"www-data"、"nobody"或"apache")而言,應該是可讀的和<b>可寫的</b>。</p>
+<p>它必須是不能透過網際網路直接存取的。</p>
+<p>若此目錄目前不存在,這安裝過程將會試著建立它。</p>';
 $string['pathssubdirroot'] = '包含Moodle程式碼的目錄的完整路徑';
 $string['pathssubwwwroot'] = '可以進入使用Moodle的完整網址,也就是用戶為了要使用Moodle,而需要輸入到瀏覽器的網址列的地址。
 
@@ -87,9 +89,10 @@ $string['phpversionhelp'] = '<p>Moodle 需要的PHP版本至少要4.3.0或是5.1
 <p>您必須更新您的 PHP 或在有更新版本的主機上進行安裝!(若是5.0.x,你可以下降到4.4.x 版本)</p>';
 $string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
 $string['welcomep20'] = '這個頁面是提醒您已經成功安裝與啟動 <strong>{$a->packname} {$a->packversion}</strong> ,恭喜!';
-$string['welcomep30'] = '<strong>{$a->installername}</strong>包含了可以建立<strong>Moodle</strong>執行環境的應用程序:';
+$string['welcomep30'] = '這一<strong>{$a->installername}</strong>的版本包含了一些可以建立<strong>Moodle</strong>執行環境的應用程序:';
 $string['welcomep40'] = '這個軟體還包含了<strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>。';
 $string['welcomep50'] = '使用本軟體包所包含的所有應用程序時,應遵循它們各自的授權協議。整個<strong>{$a->installername}</strong> 軟體都是<a href="http://www.opensource.org/docs/definition_plain.html">開放原始碼</a> ,並且是在 <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a> 授權協議下發佈。';
-$string['welcomep60'] = '接下來的頁面將會透過一些簡單的步驟引導您安裝 <strong>Moodle</strong> 到電腦中,您可以接受預設值,或是針對自己的需求調整修改。';
+$string['welcomep60'] = '接下來的一些頁面將會透過一些簡單的步驟引導您配置和設定在你電腦上的 <strong>Moodle</strong> 。
+您可以接受這些預設值,或是針對你自己的需要來調整。';
 $string['welcomep70'] = '點選 "下一步" 按鈕,繼續設定<strong>Moodle</strong>.';
 $string['wwwroot'] = '網站位址';
index 1101ecf..e4398be 100644 (file)
@@ -126,6 +126,7 @@ $string['componentinstalled'] = 'Component installed';
 $string['computedfromlogs'] = 'Computed from logs since {$a}.';
 $string['condifmodeditdefaults'] = 'Default values are used in the settings form when creating a new activity or resource.';
 $string['confeditorhidebuttons'] = 'Select the buttons that should be hidden in the HTML editor.';
+$string['configenableactivitychooser'] = 'The activity chooser is a dialog box with a short description of each activity and resource. If disabled, separate resource and activity dropdown menus are provided instead.';
 $string['configallcountrycodes'] = 'This is the list of countries that may be selected in various places, for example in a user\'s profile. If blank (the default) the list in countries.php in the standard English language pack is used. That is the list from ISO 3166-1. Otherwise, you can specify a comma-separated list of codes, for example \'GB,FR,ES\'. If you add new, non-standard codes here, you will need to add them to countries.php in \'en\' and your language pack.';
 $string['configallowassign'] = 'You can allow people who have the roles on the left side to assign some of the column roles to other people';
 $string['configallowblockstodock'] = 'If enabled and supported by the selected theme users can choose to move blocks to a special dock.';
@@ -458,6 +459,7 @@ $string['emoticons_desc'] = 'This form defines the emoticons (or smileys) used a
 * Alternative text (optional) - String identifier and component of the alternative text of the emoticon.';
 $string['emoticonsreset'] = 'Reset emoticons setting to default values';
 $string['emptysettingvalue'] = 'Empty';
+$string['enableactivitychooser'] = 'Enable activity chooser';
 $string['enableblogs'] = 'Enable blogs';
 $string['enablecalendarexport'] = 'Enable calendar export';
 $string['enablecomments'] = 'Enable comments';
index 0acd0b3..f540be7 100644 (file)
@@ -155,3 +155,5 @@ $string['update_onlogin'] = 'On every login';
 $string['update_onupdate'] = 'On update';
 $string['user_activatenotsupportusertype'] = 'auth: ldap user_activate() does not support selected usertype: {$a}';
 $string['user_disablenotsupportusertype'] = 'auth: ldap user_disable() does not support selected usertype (..yet)';
+$string['username'] = 'Username';
+$string['username_help'] = 'Please be aware that some authentication plugins will not allow you to change the username.';
index a63c3e6..3f75c53 100644 (file)
@@ -76,11 +76,11 @@ $string['backuptypesection'] = 'Section';
 $string['backupversion'] = 'Backup version';
 $string['cannotfindassignablerole'] = 'The {$a} role in the backup file cannot be mapped to any of the roles that you are allowed to assign.';
 $string['choosefilefromcoursebackup'] = 'Course backup area';
-$string['choosefilefromcoursebackup_help'] = 'When backup courses using default settings, backup files will be stored here';
+$string['choosefilefromcoursebackup_help'] = 'Course backups made using default settings are stored here.';
 $string['choosefilefromuserbackup'] = 'User private backup area';
-$string['choosefilefromuserbackup_help'] = 'When backup courses with "Anonymize user information" option ticked, backup files will be stored here';
+$string['choosefilefromuserbackup_help'] = 'Backup files with anonymized user information are stored here.';
 $string['choosefilefromactivitybackup'] = 'Activity backup area';
-$string['choosefilefromactivitybackup_help'] = 'When backup activities using default settings, backup files will be stored here';
+$string['choosefilefromactivitybackup_help'] = 'Activity backups made using default settings are stored here.';
 $string['choosefilefromautomatedbackup'] = 'Automated backups';
 $string['choosefilefromautomatedbackup_help'] = 'Contains automatically generated backups.';
 $string['configgeneralactivities'] = 'Sets the default for including activities in a backup.';
@@ -130,9 +130,9 @@ $string['filealiasesrestorefailures_help'] = 'Aliases are symbolic links to othe
 
 More details and the actual reason of the failure can be found in the restore log file.';
 $string['filealiasesrestorefailures_link'] = 'restore/filealiases';
-$string['filereferencesincluded'] = 'File references to external contents included in backup package, they won\'t work on other sites.';
-$string['filereferencessamesite'] = 'Backup is from the same site, file references can be restored';
-$string['filereferencesnotsamesite'] = 'Backup is from other site, file references cannot be restored';
+$string['filereferencesincluded'] = 'File references to external contents are included in the backup file. These won\'t work if the backup is restored on a different site.';
+$string['filereferencessamesite'] = 'The backup file is from this site, and so file references can be restored.';
+$string['filereferencesnotsamesite'] = 'The backup file is from a different site, and so file references cannot be restored.';
 $string['generalactivities'] = 'Include activities and resources';
 $string['generalanonymize'] = 'Anonymise information';
 $string['generalbackdefaults'] = 'General backup defaults';
@@ -180,7 +180,7 @@ $string['lockedbyconfig'] = 'This setting has been locked by the default backup
 $string['lockedbyhierarchy'] = 'Locked by dependencies';
 $string['loglifetime'] = 'Keep logs for';
 $string['managefiles'] = 'Manage backup files';
-$string['missingfilesinpool'] = 'Some files could not be saved during the backup, it won\'t be possible to restore them.';
+$string['missingfilesinpool'] = 'Some files could not be saved during the backup, and so it will not be possible to restore them.';
 $string['moodleversion'] = 'Moodle version';
 $string['moreresults'] = 'There are too many results, enter a more specific search.';
 $string['nomatchingcourses'] = 'There are no courses to display';
index abf487a..1077607 100644 (file)
@@ -87,7 +87,7 @@ $string['backpackdetails'] = 'Backpack settings';
 $string['backpackemail'] = 'Email address';
 $string['backpackemail_help'] = 'The email address associated with your backpack. While you are connected, any badges earned on this site will be associated with this email address.';
 $string['personaconnection'] = 'Sign in with your email';
-$string['personaconnection_help'] = 'Persona is a system for identifying yourself across the web, using an email address that you own. The Open Badges backpack uses Persona as a login system, so to be able to connect to a backpack you with need a Persona account.
+$string['personaconnection_help'] = 'Persona is a system for identifying yourself across the web, using an email address that you own. The Open Badges backpack uses Persona as a login system, so to be able to connect to a backpack you will need a Persona account.
 
 For more information about Persona visit <a href="https://login.persona.org/about">https://login.persona.org/about</a>.';
 $string['backpackimport'] = 'Badge import settings';
index 159bc3b..64f618c 100644 (file)
@@ -29,10 +29,12 @@ manageofficialtags,core_tag
 settypeofficial,core_tag
 filetoolarge,core
 maxbytesforfile,core
+modchooserenable,core
+modchooserdisable,core
 maxbytes,core_error
 downloadcsv,core_table
 downloadexcel,core_table
 downloadods,core_table
 downloadoptions,core_table
 downloadtsv,core_table
-downloadxhtml,core_table
+downloadxhtml,core_table
\ No newline at end of file
index 5386298..e3085a1 100644 (file)
@@ -172,11 +172,13 @@ $string['mysqliextensionisnotpresentinphp'] = 'PHP has not been properly configu
 $string['nativemariadb'] = 'MariaDB (native/mariadb)';
 $string['nativemariadbhelp'] = '<p>The database is where most of the Moodle settings and data are stored and must be configured here.</p>
 <p>The database name, username, and password are required fields; table prefix is optional.</p>
+<p>The database name may contain only alphanumeric characters, dollar ($) and underscore (_).</p>
 <p>If the database currently does not exist, and the user you specify has permission, Moodle will attempt to create a new database with the correct permissions and settings.</p>
 <p>This driver is not compatible with legacy MyISAM engine.</p>';
 $string['nativemysqli'] = 'Improved MySQL (native/mysqli)';
 $string['nativemysqlihelp'] = '<p>The database is where most of the Moodle settings and data are stored and must be configured here.</p>
 <p>The database name, username, and password are required fields; table prefix is optional.</p>
+<p>The database name may contain only alphanumeric characters, dollar ($) and underscore (_).</p>
 <p>If the database currently does not exist, and the user you specify has permission, Moodle will attempt to create a new database with the correct permissions and settings.</p>';
 $string['nativemssql'] = 'SQL*Server FreeTDS (native/mssql)';
 $string['nativemssqlhelp'] = 'Now you need to configure the database where most Moodle data will be stored.
index 9d0ac3c..aa19259 100644 (file)
@@ -322,6 +322,7 @@ $string['courseformats'] = 'Course formats';
 $string['courseformatoptions'] = 'Formatting options for {$a}';
 $string['courseformatudpate'] = 'Update format';
 $string['courseprofiles'] = 'Course profiles';
+$string['coursepreferences'] = 'Course preferences';
 $string['coursegrades'] = 'Course grades';
 $string['coursehelpcategory'] = 'Position the course on the course listing and may make it easier for students to find it.';
 $string['coursehelpforce'] = 'Force the course group mode to every activity in the course.';
@@ -1161,8 +1162,6 @@ $string['moodlelogo'] = 'Moodle logo';
 $string['month'] = 'Month';
 $string['months'] = 'Months';
 $string['modified'] = 'Modified';
-$string['modchooserenable'] = 'Activity chooser on';
-$string['modchooserdisable'] = 'Activity chooser off';
 $string['moduleintro'] = 'Description';
 $string['modulesetup'] = 'Setting up module tables';
 $string['modulesuccess'] = '{$a} tables have been set up correctly';
@@ -2027,3 +2026,7 @@ $string['zippingbackup'] = 'Zipping backup';
 // Deprecated since Moodle 3.1.
 $string['filetoolarge'] = 'is too large to upload';
 $string['maxbytesforfile'] = 'The file {$a} is larger than the maximum size allowed.';
+
+// Deprecated since Moodle 3.2.
+$string['modchooserenable'] = 'Activity chooser on';
+$string['modchooserdisable'] = 'Activity chooser off';
\ No newline at end of file
index d245288..b3c377d 100644 (file)
@@ -65,7 +65,7 @@ $string['categorycurrent'] = 'Current category';
 $string['categorycurrentuse'] = 'Use this category';
 $string['categorydoesnotexist'] = 'This category does not exist';
 $string['categoryinfo'] = 'Category info';
-$string['categorymove'] = 'The category \'{$a->name}\' contains {$a->count} questions (some of them may be old, hidden, questions, or Random questions that are still in use in some existing quizzes). Please choose another category to move them to.';
+$string['categorymove'] = 'The category \'{$a->name}\' contains {$a->count} questions (some of which may be hidden questions or random questions that are still in use in a quiz). Please choose another category to move them to.';
 $string['categorymoveto'] = 'Save in category';
 $string['categorynamecantbeblank'] = 'The category name cannot be blank.';
 $string['clickflag'] = 'Flag question';
index 73fe814..43fb119 100644 (file)
Binary files a/lib/amd/build/form-autocomplete.min.js and b/lib/amd/build/form-autocomplete.min.js differ
index 9f49f4a..d479d28 100644 (file)
Binary files a/lib/amd/build/permissionmanager.min.js and b/lib/amd/build/permissionmanager.min.js differ
index e5a4f14..0ffe642 100644 (file)
Binary files a/lib/amd/build/templates.min.js and b/lib/amd/build/templates.min.js differ
index 0ba0d5d..7c56b36 100644 (file)
@@ -99,7 +99,7 @@ define(['jquery', 'core/config'], function($, config) {
          * Make a series of ajax requests and return all the responses.
          *
          * @method call
-         * @param {Object[]} Array of requests with each containing methodname and args properties.
+         * @param {Object[]} requests Array of requests with each containing methodname and args properties.
          *                   done and fail callbacks can be set for each element in the array, or the
          *                   can be attached to the promises returned by this function.
          * @param {Boolean} async Optional, defaults to true.
index ce20865..b440364 100644 (file)
@@ -23,7 +23,7 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since      3.0
  */
-define([ 'jquery', 'core/yui' ],
+define(['jquery', 'core/yui'],
        function($, Y) {
 
     return /** @alias module:core/event */ {
@@ -32,7 +32,7 @@ define([ 'jquery', 'core/yui' ],
          * Trigger an event using both JQuery and YUI
          *
          * @method notifyFilterContentUpdated
-         * @param {string}|{JQuery} nodes - Selector or list of elements that were inserted.
+         * @param {string|JQuery} nodes - Selector or list of elements that were inserted.
          */
         notifyFilterContentUpdated: function(nodes) {
             nodes = $(nodes);
index 72646f0..14aa425 100644 (file)
@@ -28,9 +28,9 @@
  * @since      2.9
  */
 define(['jquery'], function($) {
-    $(document).bind("ajaxStart", function(){
+    $(document).bind("ajaxStart", function() {
         M.util.js_pending('jq');
-    }).bind("ajaxStop", function(){
+    }).bind("ajaxStop", function() {
         M.util.js_complete('jq');
     });
 });
index 3090b1f..3467c48 100644 (file)
@@ -90,7 +90,7 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
         }
         originalSelect.children('option').each(function(index, ele) {
             if ($(ele).prop('selected')) {
-                items.push( { label: $(ele).html(), value: $(ele).attr('value') } );
+                items.push({ label: $(ele).html(), value: $(ele).attr('value') });
             }
         });
         var context = $.extend({ items: items }, options, state);
@@ -115,7 +115,6 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
      * Notify of a change in the selection.
      *
      * @param {jQuery} originalSelect The jQuery object matching the hidden select list.
-     * @return {Void}
      */
     var notifyChange = function(originalSelect) {
         if (typeof M.core_formchangechecker !== 'undefined') {
@@ -131,7 +130,7 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
      * @private
      * @param {Object} options Original options for this autocomplete element.
      * @param {Object} state State variables for this autocomplete element.
-     * @param {Element} The item to be deselected.
+     * @param {Element} item The item to be deselected.
      * @param {Element} originalSelect The original select list.
      */
     var deselectItem = function(options, state, item, originalSelect) {
@@ -215,7 +214,7 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
         // Find it's index.
         var current = suggestionsElement.children('[aria-hidden=false]').index(element);
         // Activate the next one.
-        activateItem(current+1, state);
+        activateItem(current + 1, state);
     };
 
     /**
@@ -237,7 +236,7 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
         // Find it's index.
         var current = selectionsElement.children('[aria-selected=true]').index(element);
         // Activate the next one.
-        activateSelection(current-1, state);
+        activateSelection(current - 1, state);
     };
     /**
      * Find the index of the current active selection, and activate the next one.
@@ -258,7 +257,7 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
         // Find it's index.
         var current = selectionsElement.children('[aria-selected=true]').index(element);
         // Activate the next one.
-        activateSelection(current+1, state);
+        activateSelection(current + 1, state);
     };
 
     /**
@@ -276,7 +275,7 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
         // Find it's index.
         var current = suggestionsElement.children('[aria-hidden=false]').index(element);
         // Activate the next one.
-        activateItem(current-1, state);
+        activateItem(current - 1, state);
     };
 
     /**
@@ -690,13 +689,14 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
          * Turn a boring select box into an auto-complete beast.
          *
          * @method enhance
-         * @param {string} select The selector that identifies the select box.
+         * @param {string} selector The selector that identifies the select box.
          * @param {boolean} tags Whether to allow support for tags (can define new entries).
          * @param {string} ajax Name of an AMD module to handle ajax requests. If specified, the AMD
          *                      module must expose 2 functions "transport" and "processResults".
          *                      These are modeled on Select2 see: https://select2.github.io/options.html#ajax
          * @param {String} placeholder - The text to display before a selection is made.
          * @param {Boolean} caseSensitive - If search has to be made case sensitive.
+         * @param {Boolean} showSuggestions - If suggestions should be shown
          * @param {String} noSelectionString - Text to display when there is no selection
          */
         enhance: function(selector, tags, ajax, placeholder, caseSensitive, showSuggestions, noSelectionString) {
@@ -723,7 +723,7 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
                 options.showSuggestions = showSuggestions;
             }
             if (typeof noSelectionString === "undefined") {
-                str.get_string('noselection', 'form').done(function (result) {
+                str.get_string('noselection', 'form').done(function(result) {
                     options.noSelectionString = result;
                 }).fail(notification.exception);
             }
@@ -732,7 +732,7 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
             var originalSelect = $(selector);
             if (!originalSelect) {
                 log.debug('Selector not found: ' + selector);
-                return false;
+                return;
             }
 
             // Hide the original select.
index fcc354d..f12e49a 100644 (file)
@@ -50,7 +50,7 @@ define(['jquery', 'core/ajax'], function($, ajax) {
 
         var promises = ajax.call([{
             methodname: 'core_get_fragment',
-            args:{
+            args: {
                 component: component,
                 callback: callback,
                 contextid: contextid,
index e1e346a..27da8e4 100644 (file)
@@ -46,7 +46,7 @@ define(['core/config'], function(config) {
             // Disable cache if debugging.
             return false;
         }
-        if (typeof(window.localStorage) === "undefined") {
+        if (typeof (window.localStorage) === "undefined") {
             return false;
         }
         var testKey = 'test';
@@ -99,8 +99,8 @@ define(['core/config'], function(config) {
      * Hash a string, used to make shorter key prefixes.
      *
      * @method hashString
-     * @param string source The string to hash
-     * @return int The int hash
+     * @param {String} source The string to hash
+     * @return {Number}
      */
     var hashString = function(source) {
         // From http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery.
@@ -111,8 +111,8 @@ define(['core/config'], function(config) {
             return hash;
         }
         for (i = 0, len = source.length; i < len; i++) {
-            chr   = source.charCodeAt(i);
-            hash  = ((hash << 5) - hash) + chr;
+            chr = source.charCodeAt(i);
+            hash = ((hash << 5) - hash) + chr;
             hash |= 0; // Convert to 32bit integer
         }
         return hash;
index 5447ef8..ecf1076 100644 (file)
  */
 define(['core/loglevel'], function(log) {
     var originalFactory = log.methodFactory;
-    log.methodFactory = function (methodName, logLevel) {
+    log.methodFactory = function(methodName, logLevel) {
         var rawMethod = originalFactory(methodName, logLevel);
 
-        return function (message, source) {
+        return function(message, source) {
             if (source) {
                 rawMethod(source + ": " + message);
             } else {
@@ -40,7 +40,7 @@ define(['core/loglevel'], function(log) {
     /**
      * Set default config settings.
      *
-     * @param {String} level The level to use.
+     * @param {Object} config including the level to use.
      * @method setConfig
      */
     log.setConfig = function(config) {
index a887c8e..1bf0e6c 100644 (file)
@@ -97,7 +97,7 @@ function(Y, $, log) {
             if (notification.template) {
                 template = notification.template;
                 delete notification.template;
-            } else if (notification.type){
+            } else if (notification.type) {
                 if (typeof notificationModule.types[notification.type] !== 'undefined') {
                     template = notificationModule.types[notification.type];
                 }
@@ -126,10 +126,10 @@ function(Y, $, log) {
         alert: function(title, message, yesLabel) {
             // Here we are wrapping YUI. This allows us to start transitioning, but
             // wait for a good alternative without having inconsistent dialogues.
-            Y.use('moodle-core-notification-alert', function () {
+            Y.use('moodle-core-notification-alert', function() {
                 var alert = new M.core.alert({
-                    title : title,
-                    message : message,
+                    title: title,
+                    message: message,
                     yesLabel: yesLabel
                 });
 
@@ -140,10 +140,10 @@ function(Y, $, log) {
         confirm: function(title, question, yesLabel, noLabel, yesCallback, noCallback) {
             // Here we are wrapping YUI. This allows us to start transitioning, but
             // wait for a good alternative without having inconsistent dialogues.
-            Y.use('moodle-core-notification-confirm', function () {
+            Y.use('moodle-core-notification-confirm', function() {
                 var modal = new M.core.confirm({
-                    title : title,
-                    question : question,
+                    title: title,
+                    question: question,
                     yesLabel: yesLabel,
                     noLabel: noLabel
                 });
@@ -169,7 +169,7 @@ function(Y, $, log) {
                 ex.stack = ex.debuginfo;
                 ex.name = ex.errorcode;
             }
-            Y.use('moodle-core-notification-exception', function () {
+            Y.use('moodle-core-notification-exception', function() {
                 var modal = new M.core.exception(ex);
 
                 modal.show();
index 267f6cb..cb77bca 100644 (file)
@@ -23,7 +23,7 @@
  /**
   * @module admin/permissionmanager
   */
-define(['jquery', 'core/config','core/notification', 'core/templates'], function($, config, notification, templates) {
+define(['jquery', 'core/config', 'core/notification', 'core/templates'], function($, config, notification, templates) {
 
      /**
       * Used CSS selectors
@@ -54,7 +54,7 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
             sesskey: config.sesskey
         };
 
-        $.post(adminurl + 'roles/ajax.php', params, function() {})
+        $.post(adminurl + 'roles/ajax.php', params)
             .done(function(data) {
               try {
                   overideableroles = data;
@@ -62,8 +62,7 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
                       $('body').trigger(rolesloadedevent);
                   };
                   loadOverideableRoles();
-              }
-              catch(err) {
+              } catch (err) {
                   notification.exception(err);
               }
             })
@@ -77,7 +76,7 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
      *
      * @access private
      * @method changePermissions
-     * @param {jquery node} row
+     * @param {JQuery} row
      * @param {int} roleid
      * @param {string} action
      */
@@ -89,7 +88,7 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
             action: action,
             capability: row.data('name')
         };
-        $.post(adminurl + 'roles/ajax.php', params, function() {})
+        $.post(adminurl + 'roles/ajax.php', params)
         .done(function(data) {
             var action = data;
             try {
@@ -118,11 +117,11 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
                     default:
                         return;
                 }
-                templates.render('core/permissionmanager_role',templatedata)
-                .done(function (content) {
-                    if (action == 'allow'){
+                templates.render('core/permissionmanager_role', templatedata)
+                .done(function(content) {
+                    if (action == 'allow') {
                         $(content).insertBefore(row.find('.allowmore:first'));
-                    }else if (action == 'prohibit'){
+                    } else if (action == 'prohibit') {
                         $(content).insertBefore(row.find('.prohibitmore:first'));
                         // Remove allowed link
                         var allowedLink = row.find('.allowedroles').first().find('a[data-role-id="' + roleid + '"]');
@@ -133,8 +132,7 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
                     panel.hide();
                 })
                 .fail(notification.exception);
-            }
-            catch(err) {
+            } catch (err) {
                 notification.exception(err);
             }
         })
@@ -150,7 +148,7 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
      * @method handleAddRole
      * @param {event} e
      */
-    var handleAddRole = function(e){
+    var handleAddRole = function(e) {
         e.preventDefault();
 
         $('body').one('rolesloaded', function() {
@@ -162,8 +160,8 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
                 context: contextname
             };
             var message = M.util.get_string('role' + action + 'info', 'core_role', confirmationDetails);
-            if (panel === null){
-                panel = new M.core.dialogue ({
+            if (panel === null) {
+                panel = new M.core.dialogue({
                     draggable: true,
                     modal: true,
                     closeButton: true,
@@ -175,7 +173,7 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
             var i, existingrolelinks;
 
             var roles = [];
-            switch (action){
+            switch (action) {
                 case 'allow':
                     existingrolelinks = row.find(SELECTORS.REMOVEROLE);
                     break;
@@ -186,18 +184,18 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
             for (i in overideableroles) {
                 var disabled = '';
                 var disable = existingrolelinks.filter("[data-role-id='" + i + "']").length;
-                if (disable){
+                if (disable) {
                     disabled = 'disabled';
                 }
-                var roledetails = {roleid:i, rolename: overideableroles[i], disabled:disabled};
+                var roledetails = {roleid: i, rolename: overideableroles[i], disabled: disabled};
                 roles.push(roledetails);
             }
 
-            templates.render('core/permissionmanager_panelcontent',{message:message, roles:roles})
-            .done(function (content) {
+            templates.render('core/permissionmanager_panelcontent', {message: message, roles: roles})
+            .done(function(content) {
                 panel.set('bodyContent', content);
                 panel.show();
-                $('div.role_buttons').delegate('input', 'click',function(e){
+                $('div.role_buttons').delegate('input', 'click', function(e) {
                     var roleid = $(e.currentTarget).data('role-id');
                     changePermissions(row, roleid, action);
                 });
@@ -215,7 +213,7 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
      * @method handleRemoveRole
      * @param {event} e
      */
-    var handleRemoveRole = function(e){
+    var handleRemoveRole = function(e) {
         e.preventDefault();
         $('body').one('rolesloaded', function() {
             var link = $(e.currentTarget);
@@ -229,10 +227,10 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
             };
 
             notification.confirm(M.util.get_string('confirmunassigntitle', 'core_role'),
-                M.util.get_string('confirmrole' + action, 'core_role',questionDetails),
+                M.util.get_string('confirmrole' + action, 'core_role', questionDetails),
                 M.util.get_string('confirmunassignyes', 'core_role'),
                 M.util.get_string('confirmunassignno', 'core_role'),
-                function(){
+                function() {
                    changePermissions(row, roleid, action);
                 }
             );
@@ -244,11 +242,9 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
         /**
          * Initialize permissionmanager
          * @access public
-         * @param {int} contextid
-         * @param {string} contextname
-         * @param {string} adminurl
+         * @param {Object} args
          */
-        initialize : function(args) {
+        initialize: function(args) {
             contextid = args.contextid;
             contextname = args.contextname;
             adminurl = args.adminurl;
@@ -257,4 +253,4 @@ define(['jquery', 'core/config','core/notification', 'core/templates'], function
             body.delegate(SELECTORS.REMOVEROLE, 'click', handleRemoveRole);
         }
     };
-});
\ No newline at end of file
+});
index a8214c0..317d6d4 100644 (file)
@@ -39,6 +39,7 @@ define(['jquery', 'core/ajax', 'core/localstorage'], function($, ajax, storage)
          * @param {string} lang The users language - if not passed it is deduced.
          * @return {Promise}
          */
+         // eslint-disable-next-line camelcase
         get_string: function(key, component, param, lang) {
             var request = this.get_strings([{
                 key: key,
@@ -60,6 +61,7 @@ define(['jquery', 'core/ajax', 'core/localstorage'], function($, ajax, storage)
          *                                      See get_string for more info on these args.
          * @return {Promise}
          */
+         // eslint-disable-next-line camelcase
         get_strings: function(requests) {
 
             var deferred = $.Deferred();
index bb81962..3076d4b 100644 (file)
@@ -35,10 +35,14 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
             // Click handler for changing tag type.
             $('body').delegate('.tagarea[data-ta] a[data-quickload=1]', 'click', function(e) {
                 e.preventDefault();
-                var target = $( this ),
+                var target = $(this),
                     query = target.context.search.replace(/^\?/, ''),
                     tagarea = target.closest('.tagarea[data-ta]'),
-                    args = query.split('&').reduce(function(s,c){var t=c.split('=');s[t[0]]=decodeURIComponent(t[1]);return s;},{});
+                    args = query.split('&').reduce(function(s, c) {
+                      var t = c.split('=');
+                      s[t[0]] = decodeURIComponent(t[1]);
+                      return s;
+                    }, {});
 
                 var promises = ajax.call([{
                     methodname: 'core_tag_get_tagindex',
@@ -46,7 +50,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                 }], true);
 
                 $.when.apply($, promises)
-                    .done( function(data) {
+                    .done(function(data) {
                         templates.render('core_tag/index', data).done(function(html) {
                             tagarea.replaceWith(html);
                         });
@@ -81,10 +85,10 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                 e.preventDefault();
                 var href = $(this).attr('href');
                 str.get_strings([
-                        {key : 'delete'},
-                        {key : 'confirmdeletetag', component : 'tag'},
-                        {key : 'yes'},
-                        {key : 'no'},
+                        {key: 'delete'},
+                        {key: 'confirmdeletetag', component: 'tag'},
+                        {key: 'yes'},
+                        {key: 'no'},
                     ]).done(function(s) {
                         notification.confirm(s[0], s[1], s[2], s[3], function() {
                             window.location.href = href;
@@ -94,7 +98,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
             });
 
             // Confirmation for bulk tag delete button.
-            $("#tag-management-delete").click(function(e){
+            $("#tag-management-delete").click(function(e) {
                 var form = $(this).closest('form').get(0),
                     cnt = $(form).find("input[type=checkbox]:checked").length;
                 if (!cnt) {
@@ -103,10 +107,10 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                 var tempElement = $("<input type='hidden'/>").attr('name', this.name);
                 e.preventDefault();
                 str.get_strings([
-                        {key : 'delete'},
-                        {key : 'confirmdeletetags', component : 'tag'},
-                        {key : 'yes'},
-                        {key : 'no'},
+                        {key: 'delete'},
+                        {key: 'confirmdeletetags', component: 'tag'},
+                        {key: 'yes'},
+                        {key: 'no'},
                     ]).done(function(s) {
                         notification.confirm(s[0], s[1], s[2], s[3], function() {
                             tempElement.appendTo(form);
@@ -117,15 +121,15 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
             });
 
             // Confirmation for bulk tag combine button.
-            $("#tag-management-combine").click(function(e){
+            $("#tag-management-combine").click(function(e) {
                 e.preventDefault();
                 var form = $(this).closest('form').get(0),
                     tags = $(form).find("input[type=checkbox]:checked");
                 if (tags.length <= 1) {
                     str.get_strings([
-                        {key : 'combineselected', component : 'tag'},
-                        {key : 'selectmultipletags', component : 'tag'},
-                        {key : 'ok'},
+                        {key: 'combineselected', component: 'tag'},
+                        {key: 'selectmultipletags', component: 'tag'},
+                        {key: 'ok'},
                     ]).done(function(s) {
                             notification.alert(s[0], s[1], s[2]);
                         }
@@ -134,14 +138,14 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                 }
                 var tempElement = $("<input type='hidden'/>").attr('name', this.name);
                 str.get_strings([
-                    {key : 'combineselected', component : 'tag'},
-                    {key : 'selectmaintag', component : 'tag'},
-                    {key : 'continue'},
-                    {key : 'cancel'},
+                    {key: 'combineselected', component: 'tag'},
+                    {key: 'selectmaintag', component: 'tag'},
+                    {key: 'continue'},
+                    {key: 'cancel'},
                 ]).done(function(s) {
-                    var el = $('<div><form id="combinetags_form" class="form-inline">'+
+                    var el = $('<div><form id="combinetags_form" class="form-inline">' +
                         '<p class="description"></p><p class="options"></p>' +
-                        '<p class="mdl-align"><input type="submit" id="combinetags_submit"/>'+
+                        '<p class="mdl-align"><input type="submit" id="combinetags_submit"/>' +
                         '<input type="button" id="combinetags_cancel"/></p>' +
                         '</form></div>');
                     el.find('.description').html(s[1]);
@@ -150,11 +154,11 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                     var fldset = el.find('.options');
                     tags.each(function() {
                         var tagid = $(this).val(),
-                            tagname = $('.inplaceeditable[data-itemtype=tagname][data-itemid='+tagid+']').attr('data-value');
-                        fldset.append($('<input type="radio" name="maintag" id="combinetags_maintag_'+tagid+'" value="'+tagid+
-                            '"/><label for="combinetags_maintag_'+tagid+'">'+tagname+'</label><br>'));
+                            tagname = $('.inplaceeditable[data-itemtype=tagname][data-itemid=' + tagid + ']').attr('data-value');
+                        fldset.append($('<input type="radio" name="maintag" id="combinetags_maintag_' + tagid + '" value="' +
+                            tagid + '"/><label for="combinetags_maintag_' + tagid + '">' + tagname + '</label><br>'));
                     });
-                    var panel = new M.core.dialogue ({
+                    var panel = new M.core.dialogue({
                         draggable: true,
                         modal: true,
                         closeButton: true,
@@ -184,9 +188,9 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                 if (exception.errorcode === 'namesalreadybeeingused') {
                     e.preventDefault(); // This will prevent default error dialogue.
                     str.get_strings([
-                        {key : 'nameuseddocombine', component : 'tag'},
-                        {key : 'yes'},
-                        {key : 'cancel'},
+                        {key: 'nameuseddocombine', component: 'tag'},
+                        {key: 'yes'},
+                        {key: 'cancel'},
                     ]).done(function(s) {
                         notification.confirm(e.message, s[0], s[1], s[2], function() {
                             window.location.href = window.location.href + "&newname=" + encodeURIComponent(newvalue) +
@@ -201,10 +205,10 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
             $('body').on('click', 'a[data-action=addstandardtag]', function(e) {
                 e.preventDefault();
                 str.get_strings([
-                    {key : 'addotags', component : 'tag'},
-                    {key : 'inputstandardtags', component : 'tag'},
-                    {key : 'continue'},
-                    {key : 'cancel'},
+                    {key: 'addotags', component: 'tag'},
+                    {key: 'inputstandardtags', component: 'tag'},
+                    {key: 'continue'},
+                    {key: 'cancel'},
                 ]).done(function(s) {
                     var el = $('<div><form id="addtags_form" class="form-inline" method="POST">' +
                         '<input type="hidden" name="action" value="addstandardtag"/>' +
@@ -217,7 +221,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                     el.find('#addtags_form').attr('action', window.location.href);
                     el.find('#addtags_submit').attr('value', s[2]);
                     el.find('#addtags_cancel').attr('value', s[3]);
-                    var panel = new M.core.dialogue ({
+                    var panel = new M.core.dialogue({
                         draggable: true,
                         modal: true,
                         closeButton: true,
@@ -244,12 +248,12 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                     areaid, collid, isenabled;
                 if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareaenable') {
                     areaid = $(this).attr('data-itemid');
-                    $(".tag-collections-table ul[data-collectionid] li[data-areaid="+areaid+"]").addClass('hidden');
+                    $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").addClass('hidden');
                     isenabled = ajaxreturn.value;
                     if (isenabled === '1') {
                         $(this).closest('tr').removeClass('dimmed_text');
                         collid = $(this).closest('tr').find('[data-itemtype="tagareacollection"]').attr("data-value");
-                        $(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]")
+                        $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]")
                                 .removeClass('hidden');
                     } else {
                         $(this).closest('tr').addClass('dimmed_text');
@@ -257,11 +261,11 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                 }
                 if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareacollection') {
                     areaid = $(this).attr('data-itemid');
-                    $(".tag-collections-table ul[data-collectionid] li[data-areaid="+areaid+"]").addClass('hidden');
+                    $(".tag-collections-table ul[data-collectionid] li[data-areaid=" + areaid + "]").addClass('hidden');
                     collid = $(this).attr('data-value');
                     isenabled = $(this).closest('tr').find('[data-itemtype="tagareaenable"]').attr("data-value");
                     if (isenabled === "1") {
-                        $(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]")
+                        $(".tag-collections-table ul[data-collectionid=" + collid + "] li[data-areaid=" + areaid + "]")
                                 .removeClass('hidden');
                     }
                 }
@@ -271,25 +275,25 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                 e.preventDefault();
                 var href = $(this).attr('data-url') + '&sesskey=' + M.cfg.sesskey;
                 str.get_strings([
-                        {key : 'addtagcoll', component : 'tag'},
-                        {key : 'name'},
-                        {key : 'searchable', component : 'tag'},
-                        {key : 'create'},
-                        {key : 'cancel'},
+                        {key: 'addtagcoll', component: 'tag'},
+                        {key: 'name'},
+                        {key: 'searchable', component: 'tag'},
+                        {key: 'create'},
+                        {key: 'cancel'},
                     ]).done(function(s) {
-                        var el = $('<div><form id="addtagcoll_form" class="form-inline">'+
+                        var el = $('<div><form id="addtagcoll_form" class="form-inline">' +
                             '<p><label for="addtagcoll_name"></label>: ' +
                             '<input id="addtagcoll_name" type="text"/></p>' +
                             '<p><label for="addtagcoll_searchable"></label>: ' +
                             '<input id="addtagcoll_searchable" type="checkbox" value="1" checked/></p>' +
-                            '<p class="mdl-align"><input type="submit" id="addtagcoll_submit"/>'+
+                            '<p class="mdl-align"><input type="submit" id="addtagcoll_submit"/>' +
                             '<input type="button" id="addtagcoll_cancel"/></p>' +
                             '</form></div>');
                         el.find('label[for="addtagcoll_name"]').html(s[1]);
                         el.find('label[for="addtagcoll_searchable"]').html(s[2]);
                         el.find('#addtagcoll_submit').attr('value', s[3]);
                         el.find('#addtagcoll_cancel').attr('value', s[4]);
-                        var panel = new M.core.dialogue ({
+                        var panel = new M.core.dialogue({
                             draggable: true,
                             modal: true,
                             closeButton: true,
@@ -318,10 +322,10 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                 e.preventDefault();
                 var href = $(this).attr('data-url') + '&sesskey=' + M.cfg.sesskey;
                 str.get_strings([
-                        {key : 'delete'},
-                        {key : 'suredeletecoll', component : 'tag', param : $(this).attr('data-collname') },
-                        {key : 'yes'},
-                        {key : 'no'},
+                        {key: 'delete'},
+                        {key: 'suredeletecoll', component: 'tag', param: $(this).attr('data-collname') },
+                        {key: 'yes'},
+                        {key: 'no'},
                     ]).done(function(s) {
                         notification.confirm(s[0], s[1], s[2], s[3], function() {
                             window.location.href = href;
@@ -331,4 +335,4 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
             });
         }
     };
-});
\ No newline at end of file
+});
index bd43f93..75f7d9d 100644 (file)
@@ -23,7 +23,7 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since      2.9
  */
-define([ 'core/mustache',
+define(['core/mustache',
          'jquery',
          'core/ajax',
          'core/str',
@@ -62,6 +62,7 @@ define([ 'core/mustache',
      * @param {string} templateName - should consist of the component and the name of the template like this:
      *                              core/menu (lib/templates/menu.mustache) or
      *                              tool_bananas/yellow (admin/tool/bananas/templates/yellow.mustache)
+     * @param {Boolean} async If false - this function will not return until the promises are resolved.
      * @return {Promise} JQuery promise object resolved when the template has been fetched.
      */
     var getTemplate = function(templateName, async) {
@@ -90,7 +91,7 @@ define([ 'core/mustache',
         // Oh well - load via ajax.
         var promises = ajax.call([{
             methodname: 'core_output_load_template',
-            args:{
+            args: {
                 component: component,
                 template: name,
                 themename: currentThemeName
@@ -98,13 +99,13 @@ define([ 'core/mustache',
         }], async, false);
 
         promises[0].done(
-            function (templateSource) {
+            function(templateSource) {
                 storage.set('core_template/' + searchKey, templateSource);
                 templateCache[searchKey] = templateSource;
                 deferred.resolve(templateSource);
             }
         ).fail(
-            function (ex) {
+            function(ex) {
                 deferred.reject(ex);
             }
         );
@@ -259,11 +260,19 @@ define([ 'core/mustache',
         requiredStrings = [];
         requiredJS = [];
         context.uniqid = uniqid++;
-        context.str = function() { return stringHelper; };
-        context.pix = function() { return pixHelper; };
-        context.js = function() { return jsHelper; };
-        context.quote = function() { return quoteHelper; };
-        context.globals = { config : config };
+        context.str = function() {
+          return stringHelper;
+        };
+        context.pix = function() {
+          return pixHelper;
+        };
+        context.js = function() {
+          return jsHelper;
+        };
+        context.quote = function() {
+          return quoteHelper;
+        };
+        context.globals = { config: config };
         context.currentTheme = themeName;
     };
 
@@ -414,7 +423,7 @@ define([ 'core/mustache',
      */
     var runTemplateJS = function(source) {
         if (source.trim() !== '') {
-            var newscript = $('<script>').attr('type','text/javascript').html(source);
+            var newscript = $('<script>').attr('type', 'text/javascript').html(source);
             $('head').append(newscript);
         }
     };
@@ -521,20 +530,24 @@ define([ 'core/mustache',
          * Replace a node in the page with some new HTML and run the JS.
          *
          * @method replaceNodeContents
-         * @param {string} source - A block of javascript.
+         * @param {JQuery} element - Element or selector to replace.
+         * @param {String} newHTML - HTML to insert / replace.
+         * @param {String} newJS - Javascript to run after the insertion.
          */
         replaceNodeContents: function(element, newHTML, newJS) {
-            return domReplace(element, newHTML, newJS, true);
+            domReplace(element, newHTML, newJS, true);
         },
 
         /**
          * Insert a node in the page with some new HTML and run the JS.
          *
          * @method replaceNode
-         * @param {string} source - A block of javascript.
+         * @param {JQuery} element - Element or selector to replace.
+         * @param {String} newHTML - HTML to insert / replace.
+         * @param {String} newJS - Javascript to run after the insertion.
          */
         replaceNode: function(element, newHTML, newJS) {
-            return domReplace(element, newHTML, newJS, false);
+            domReplace(element, newHTML, newJS, false);
         }
     };
 });
index 3396b00..c3fff8b 100644 (file)
@@ -83,6 +83,7 @@ define(['jquery'], function($) {
      * Get all visible tree items.
      *
      * @method getVisibleItems
+     * @return {Object} visible items
      */
     Tree.prototype.getVisibleItems = function() {
         return this.treeRoot.data('visibleItems');
@@ -340,6 +341,7 @@ define(['jquery'], function($) {
      * @method handleKeyDown
      * @param {Object} item is the jquery id of the parent item of the group.
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleKeyDown = function(item, e) {
         var currentIndex = this.getVisibleItems().index(item);
@@ -459,6 +461,7 @@ define(['jquery'], function($) {
      * @method handleClick
      * @param {Object} item The jquery id of the parent item of the group.
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleClick = function(item, e) {
 
@@ -485,6 +488,7 @@ define(['jquery'], function($) {
      * @method handleFocus
      * @param {Object} item The jquery id of the parent item of the group.
      * @param {Event} e The event.
+     * @return {Boolean}
      */
     Tree.prototype.handleFocus = function(item, e) {
 
@@ -505,9 +509,15 @@ define(['jquery'], function($) {
         // Bind event handlers to the tree items. Use event delegates to allow
         // for dynamically loaded parts of the tree.
         this.treeRoot.on({
-            click: function(e) { return thisObj.handleClick($(this), e); },
-            keydown: function(e) { return thisObj.handleKeyDown($(this), e); },
-            focus: function(e) { return thisObj.handleFocus($(this), e); },
+            click: function(e) {
+              return thisObj.handleClick($(this), e);
+            },
+            keydown: function(e) {
+              return thisObj.handleKeyDown($(this), e);
+            },
+            focus: function(e) {
+              return thisObj.handleFocus($(this), e);
+            },
         }, SELECTORS.ITEM);
     };
 
index b3263ee..25f2db4 100644 (file)
@@ -29,10 +29,11 @@ define(['core/config'], function(config) {
     return /** @alias module:core/url */ {
         // Public variables and functions.
         /**
-         * Generate a style tag referencing this sheet and add it to the head of the page.
+         * Construct a file url
          *
          * @method fileUrl
-         * @param {string} sheet The style sheet name. Must exist in the theme, or one of it's parents.
+         * @param {string} relativeScript
+         * @param {string} slashArg
          * @return {string}
          */
         fileUrl: function(relativeScript, slashArg) {
index 6c8b5de..5276703 100644 (file)
@@ -619,9 +619,10 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
      *   - large: 2560x1600
      *
      * @param string $windowsize size of window.
+     * @param bool $viewport If true, changes viewport rather than window size
      * @throws ExpectationException
      */
-    protected function resize_window($windowsize) {
+    protected function resize_window($windowsize, $viewport = false) {
         // Non JS don't support resize window.
         if (!$this->running_javascript()) {
             return;
@@ -649,6 +650,25 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
                 $width = (int) $size[0];
                 $height = (int) $size[1];
         }
+        if ($viewport) {
+            // When setting viewport size, we set it so that the document width will be exactly
+            // as specified, assuming that there is a vertical scrollbar. (In cases where there is
+            // no scrollbar it will be slightly wider. We presume this is rare and predictable.)
+            // The window inner height will be as specified, which means the available viewport will
+            // actually be smaller if there is a horizontal scrollbar. We assume that horizontal
+            // scrollbars are rare so this doesn't matter.
+            $offset = $this->getSession()->getDriver()->evaluateScript(
+                    'return (function() { var before = document.body.style.overflowY;' .
+                    'document.body.style.overflowY = "scroll";' .
+                    'var result = {};' .
+                    'result.x = window.outerWidth - document.body.offsetWidth;' .
+                    'result.y = window.outerHeight - window.innerHeight;' .
+                    'document.body.style.overflowY = before;' .
+                    'return result; })();');
+            $width += $offset['x'];
+            $height += $offset['y'];
+        }
+
         $this->getSession()->getDriver()->resizeWindow($width, $height);
     }
 
index 8d6d9aa..0b16552 100644 (file)
@@ -71,16 +71,24 @@ class behat_form_select extends behat_form_field {
         // Wait for all the possible AJAX requests that have been
         // already triggered by selectOption() to be finished.
         if ($this->running_javascript()) {
-            // Trigger change event as this is needed by some drivers (Phantomjs). Don't do it for
-            // Singleselect as this will cause multiple event fire and lead to race-around condition.
-            $browser = \Moodle\BehatExtension\Driver\MoodleSelenium2Driver::getBrowser();
-            if (!$singleselect && ($browser == 'phantomjs')) {
-                $script = "Syn.trigger('change', {}, {{ELEMENT}})";
-                try {
-                    $this->session->getDriver()->triggerSynScript($this->field->getXpath(), $script);
-                } catch (Exception $e) {
-                    // No need to do anything if element has been removed by JS.
-                    // This is possible when inline editing element is used.
+            // Trigger change event and click on first skip link, as some OS/browsers (Phantomjs, Mac-FF),
+            // don't close select option field and trigger event.
+            if (!$singleselect) {
+                $dialoguexpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue-focused ')]";
+                if (!$node = $this->session->getDriver()->find($dialoguexpath)) {
+                    $script = "Syn.trigger('change', {}, {{ELEMENT}})";
+                    try {
+                        $this->session->getDriver()->triggerSynScript($this->field->getXpath(), $script);
+                        $this->session->getDriver()->click('//body//div[@class="skiplinks"]');
+                    } catch (\Exception $e) {
+                        return;
+                    }
+                } else {
+                    try {
+                        $this->session->getDriver()->click($dialoguexpath);
+                    } catch (\Exception $e) {
+                        return;
+                    }
                 }
             }
             $this->session->wait(behat_base::TIMEOUT * 1000, behat_base::PAGE_READY_JS);
index a730cc0..5a94658 100644 (file)
@@ -278,6 +278,67 @@ class core_user {
         }
     }
 
+    /**
+     * Updates the provided users profile picture based upon the expected fields returned from the edit or edit_advanced forms.
+     *
+     * @param stdClass $usernew An object that contains some information about the user being updated
+     * @param array $filemanageroptions
+     * @return bool True if the user was updated, false if it stayed the same.
+     */
+    public static function update_picture(stdClass $usernew, $filemanageroptions = array()) {
+        global $CFG, $DB;
+        require_once("$CFG->libdir/gdlib.php");
+
+        $context = context_user::instance($usernew->id, MUST_EXIST);
+        $user = core_user::get_user($usernew->id, 'id, picture', MUST_EXIST);
+
+        $newpicture = $user->picture;
+        // Get file_storage to process files.
+        $fs = get_file_storage();
+        if (!empty($usernew->deletepicture)) {
+            // The user has chosen to delete the selected users picture.
+            $fs->delete_area_files($context->id, 'user', 'icon'); // Drop all images in area.
+            $newpicture = 0;
+
+        } else {
+            // Save newly uploaded file, this will avoid context mismatch for newly created users.
+            file_save_draft_area_files($usernew->imagefile, $context->id, 'user', 'newicon', 0, $filemanageroptions);
+            if (($iconfiles = $fs->get_area_files($context->id, 'user', 'newicon')) && count($iconfiles) == 2) {
+                // Get file which was uploaded in draft area.
+                foreach ($iconfiles as $file) {
+                    if (!$file->is_directory()) {
+                        break;
+                    }
+                }
+                // Copy file to temporary location and the send it for processing icon.
+                if ($iconfile = $file->copy_content_to_temp()) {
+                    // There is a new image that has been uploaded.
+                    // Process the new image and set the user to make use of it.
+                    // NOTE: Uploaded images always take over Gravatar.
+                    $newpicture = (int)process_new_icon($context, 'user', 'icon', 0, $iconfile);
+                    // Delete temporary file.
+                    @unlink($iconfile);
+                    // Remove uploaded file.
+                    $fs->delete_area_files($context->id, 'user', 'newicon');
+                } else {
+                    // Something went wrong while creating temp file.
+                    // Remove uploaded file.
+                    $fs->delete_area_files($context->id, 'user', 'newicon');
+                    return false;
+                }
+            }
+        }
+
+        if ($newpicture != $user->picture) {
+            $DB->set_field('user', 'picture', $newpicture, array('id' => $user->id));
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+
     /**
      * Definition of user profile fields and the expected parameter type for data validation.
      *
index 7bcb8e3..18e3570 100644 (file)
@@ -238,17 +238,24 @@ class file_storage {
      */
     public static function can_convert_documents() {
         global $CFG;
+        $currentversion = 0;
+        $supportedversion = 0.7;
         $unoconvbin = \escapeshellarg($CFG->pathtounoconv);
         $command = "$unoconvbin --version";
         exec($command, $output);
-        preg_match('/([0-9]+\.[0-9]+)/', $output[0], $matches);
-        $currentversion = (float)$matches[0];
-        $supportedversion = 0.7;
-        if ($currentversion < $supportedversion) {
-            return false;
+        // If the command execution returned some output, then get the unoconv version.
+        if ($output) {
+            foreach ($output as $response) {
+                if (preg_match('/unoconv (\\d+\\.\\d+)/', $response, $matches)) {
+                    $currentversion = (float)$matches[1];
+                }
+            }
+            if ($currentversion < $supportedversion) {
+                return false;
+            }
+            return true;
         }
-
-        return true;
+        return false;
     }
 
     /**
index 6c571c6..268fba2 100644 (file)
 // Namespace for the form bits and bobs
 M.form = M.form || {};
 
-/**
- * Stores a list of the dependencyManager for each form on the page.
- */
-M.form.dependencyManagers = {};
-
-/**
- * Initialises a manager for a forms dependencies.
- * This should happen once per form.
- */
-M.form.initFormDependencies = function(Y, formid, dependencies) {
-
-    // If the dependencies isn't an array or object we don't want to
-    // know about it
-    if (!Y.Lang.isArray(dependencies) && !Y.Lang.isObject(dependencies)) {
-        return false;
-    }
-
-    /**
-     * Fixes an issue with YUI's processing method of form.elements property
-     * in Internet Explorer.
-     *     http://yuilibrary.com/projects/yui3/ticket/2528030
-     */
-    Y.Node.ATTRS.elements = {
-        getter: function() {
-            return Y.all(new Y.Array(this._node.elements, 0, true));
-        }
+if (typeof M.form.dependencyManager === 'undefined') {
+    var dependencyManager = function() {
+        dependencyManager.superclass.constructor.apply(this, arguments);
     };
+    Y.extend(dependencyManager, Y.Base, {
+        _locks: null,
+        _hides: null,
+        _dirty: null,
+        _nameCollections: null,
+        _fileinputs: null,
 
-    // Define the dependency manager if it hasn't already been defined.
-    M.form.dependencyManager = M.form.dependencyManager || (function(){
-        var dependencyManager = function(config) {
-            dependencyManager.superclass.constructor.apply(this, arguments);
-        };
-        dependencyManager.prototype = {
-            _form : null,
-            _locks : [],
-            _hides : [],
-            _dirty : [],
-            _nameCollections : null,
-            _fileinputs : null,
-            initializer : function(config) {
-                var i = 0, nodeName;
-                this._form = Y.one('#'+formid);
-                for (i in dependencies) {
-                    var elements = this.elementsByName(i);
-                    if (elements.size() == 0) {
-                        continue;
-                    }
-                    elements.each(function(node){
-                        nodeName = node.get('nodeName').toUpperCase();
-                        if (nodeName == 'INPUT') {
-                            if (node.getAttribute('type').match(/^(button|submit|radio|checkbox)$/)) {
-                                node.on('click', this.updateEventDependencies, this);
-                            } else {
-                                node.on('blur', this.updateEventDependencies, this);
-                            }
-                            node.on('change', this.updateEventDependencies, this);
-                        } else if (nodeName == 'SELECT') {
-                            node.on('change', this.updateEventDependencies, this);
-                        } else {
+        initializer: function() {
+            // Setup initial values for complex properties.
+            this._locks = {};
+            this._hides = {};
+            this._dirty = {};
+
+            // Setup event handlers.
+            Y.Object.each(this.get('dependencies'), function(value, i) {
+                var elements = this.elementsByName(i);
+                elements.each(function(node) {
+                    var nodeName = node.get('nodeName').toUpperCase();
+                    if (nodeName == 'INPUT') {
+                        if (node.getAttribute('type').match(/^(button|submit|radio|checkbox)$/)) {
                             node.on('click', this.updateEventDependencies, this);
+                        } else {
                             node.on('blur', this.updateEventDependencies, this);
-                            node.on('change', this.updateEventDependencies, this);
                         }
-                    }, this);
-                }
-                this._form.get('elements').each(function(input){
-                    if (input.getAttribute('type')=='reset') {
-                        input.on('click', function(){
-                            this._form.reset();
-                            this.updateAllDependencies();
-                        }, this);
+                        node.on('change', this.updateEventDependencies, this);
+                    } else if (nodeName == 'SELECT') {
+                        node.on('change', this.updateEventDependencies, this);
+                    } else {
+                        node.on('click', this.updateEventDependencies, this);
+                        node.on('blur', this.updateEventDependencies, this);
+                        node.on('change', this.updateEventDependencies, this);
                     }
                 }, this);
+            }, this);
 
-                return this.updateAllDependencies();
-            },
-            /**
-             * Initializes the mapping from element name to YUI NodeList
-             */
-            initElementsByName : function() {
-                var names = [];
-                // Collect element names
-                for (var i in dependencies) {
-                    names[i] = new Y.NodeList();
-                    for (var condition in dependencies[i]) {
-                        for (var value in dependencies[i][condition]) {
-                            for (var ei in dependencies[i][condition][value]) {
-                                names[dependencies[i][condition][value][ei]] = new Y.NodeList();
-                            }
-                        }
-                    }
+            // Handle the reset button.
+            this.get('form').get('elements').each(function(input) {
+                if (input.getAttribute('type') == 'reset') {
+                    input.on('click', function() {
+                        this.get('form').reset();
+                        this.updateAllDependencies();
+                    }, this);
                 }
-                // Locate elements for each name
-                this._form.get('elements').each(function(node){
-                    var name = node.getAttribute('name');
-                    if (names[name]) {
-                        names[name].push(node);
+            }, this);
+
+            this.updateAllDependencies();
+        },
+
+        /**
+         * Initializes the mapping from element name to YUI NodeList
+         */
+        initElementsByName: function() {
+            var names = {};
+
+            // Collect element names.
+            Y.Object.each(this.get('dependencies'), function(conditions, i) {
+                names[i] = new Y.NodeList();
+                for (var condition in conditions) {
+                    for (var value in conditions[condition]) {
+                        for (var ei in conditions[condition][value]) {
+                            names[conditions[condition][value][ei]] = new Y.NodeList();
+                        }
                     }
-                });
-                this._nameCollections = names;
-            },
-            /**
-             * Gets all elements in the form by their name and returns
-             * a YUI NodeList
-             *
-             * @param {string} name The form element name.
-             * @return {Y.NodeList}
-             */
-            elementsByName : function(name) {
-                if (!this._nameCollections) {
-                    this.initElementsByName();
                 }
-                if (!this._nameCollections[name]) {
-                    return new Y.NodeList();
-                }
-                return this._nameCollections[name];
-            },
-            /**
-             * Checks the dependencies the form has an makes any changes to the
-             * form that are required.
-             *
-             * Changes are made by functions title _dependency_{dependencytype}
-             * and more can easily be introduced by defining further functions.
-             *
-             * @param {EventFacade | null} e The event, if any.
-             * @param {string} name The form element name to check dependencies against.
-             */
-            checkDependencies : function(e, dependon) {
-                var tohide = [],
-                    tolock = [],
-                    condition, value, lock, hide,
-                    checkfunction, result, elements;
-                if (!dependencies[dependon]) {
-                    return true;
+            });
+
+            // Locate elements for each name.
+            this.get('form').get('elements').each(function(node) {
+                var name = node.getAttribute('name');
+                if (({}).hasOwnProperty.call(names, name)) {
+                    names[name].push(node);
                 }
-                elements = this.elementsByName(dependon);
-                for (condition in dependencies[dependon]) {
-                    for (value in dependencies[dependon][condition]) {
-                        checkfunction = '_dependency_'+condition;
-                        if (Y.Lang.isFunction(this[checkfunction])) {
-                            result = this[checkfunction].apply(this, [elements, value, e]);
+            });
+            this._nameCollections = names;
+        },
+
+        /**
+         * Gets all elements in the form by their name and returns
+         * a YUI NodeList
+         *
+         * @param {String} name The form element name.
+         * @return {Y.NodeList}
+         */
+        elementsByName: function(name) {
+            if (!this._nameCollections) {
+                this.initElementsByName();
+            }
+            if (!({}).hasOwnProperty.call(this._nameCollections, name)) {
+                return new Y.NodeList();
+            }
+            return this._nameCollections[name];
+        },
+
+        /**
+         * Checks the dependencies the form has an makes any changes to the
+         * form that are required.
+         *
+         * Changes are made by functions title _dependency{Dependencytype}
+         * and more can easily be introduced by defining further functions.
+         *
+         * @param {EventFacade | null} e The event, if any.
+         * @param {String} dependon The form element name to check dependencies against.
+         * @return {Boolean}
+         */
+        checkDependencies: function(e, dependon) {
+            var dependencies = this.get('dependencies'),
+                tohide = {},
+                tolock = {},
+                condition, value, lock, hide,
+                checkfunction, result, elements;
+            if (!({}).hasOwnProperty.call(dependencies, dependon)) {
+                return true;
+            }
+            elements = this.elementsByName(dependon);
+            for (condition in dependencies[dependon]) {
+                for (value in dependencies[dependon][condition]) {
+                    checkfunction = '_dependency' + condition[0].toUpperCase() + condition.slice(1);
+                    if (Y.Lang.isFunction(this[checkfunction])) {
+                        result = this[checkfunction].apply(this, [elements, value, e]);
+                    } else {
+                        result = this._dependencyDefault(elements, value, e);
+                    }
+                    lock = result.lock || false;
+                    hide = result.hide || false;
+                    for (var ei in dependencies[dependon][condition][value]) {
+                        var eltolock = dependencies[dependon][condition][value][ei];
+                        if (({}).hasOwnProperty.call(tohide, eltolock)) {
+                            tohide[eltolock] = tohide[eltolock] || hide;
                         } else {
-                            result = this._dependency_default(elements, value, e);
+                            tohide[eltolock] = hide;
                         }
-                        lock = result.lock || false;
-                        hide = result.hide || false;
-                        for (var ei in dependencies[dependon][condition][value]) {
-                            var eltolock = dependencies[dependon][condition][value][ei];
-                            tohide[eltolock] = tohide[eltolock] || hide;
+
+                        if (({}).hasOwnProperty.call(tolock, eltolock)) {
                             tolock[eltolock] = tolock[eltolock] || lock;
+                        } else {
+                            tolock[eltolock] = lock;
                         }
                     }
                 }
-                for (var el in tolock) {
-                    var needsupdate = false;
-                    if (tolock[el]) {
-                        this._locks[el] = this._locks[el] || [];
-                        if (!this._locks[el][dependon]) {
-                            this._locks[el][dependon] = true;
-                            needsupdate = true;
-                        }
-                    } else if (this._locks[el] && this._locks[el][dependon]) {
-                        delete this._locks[el][dependon];
+            }
+
+            for (var el in tolock) {
+                var needsupdate = false;
+                if (!({}).hasOwnProperty.call(this._locks, el)) {
+                    this._locks[el] = {};
+                }
+                if (({}).hasOwnProperty.call(tolock, el) && tolock[el]) {
+                    if (!({}).hasOwnProperty.call(this._locks[el], dependon) || this._locks[el][dependon]) {
+                        this._locks[el][dependon] = true;
                         needsupdate = true;
                     }
-                    if (tohide[el]) {
-                        this._hides[el] = this._hides[el] || [];
-                        if (!this._hides[el][dependon]) {
-                            this._hides[el][dependon] = true;
-                            needsupdate = true;
-                        }
-                    } else if (this._hides[el] && this._hides[el][dependon]) {
-                        delete this._hides[el][dependon];
+                } else if (({}).hasOwnProperty.call(this._locks[el], dependon) && this._locks[el][dependon]) {
+                    delete this._locks[el][dependon];
+                    needsupdate = true;
+                }
+
+                if (!({}).hasOwnProperty.call(this._hides, el)) {
+                    this._hides[el] = {};
+                }
+                if (({}).hasOwnProperty.call(tohide, el) && tohide[el]) {
+                    if (!({}).hasOwnProperty.call(this._hides[el], dependon) || this._hides[el][dependon]) {
+                        this._hides[el][dependon] = true;
                         needsupdate = true;
                     }
-                    if (needsupdate) {
-                        this._dirty[el] = true;
-                    }
+                } else if (({}).hasOwnProperty.call(this._hides[el], dependon) && this._hides[el][dependon]) {
+                    delete this._hides[el][dependon];
+                    needsupdate = true;
                 }
-                return true;
-            },
-            /**
-             * Update all dependencies in form
-             */
-            updateAllDependencies : function() {
-                for (var el in dependencies) {
-                    this.checkDependencies(null, el);
+
+                if (needsupdate) {
+                    this._dirty[el] = true;
                 }
-                this.updateForm();
-            },
-            /**
-             * Update dependencies associated with event
-             *
-             * @param {Event} e The event.
-             */
-            updateEventDependencies : function(e) {
-                var el = e.target.getAttribute('name');
-                this.checkDependencies(e, el);
-                this.updateForm();
-            },
-            /**
-             * Flush pending changes to the form
-             */
-            updateForm : function() {
-                for (var el in this._dirty) {
-                    if (this._locks[el]) {
-                        var locked = !this._isObjectEmpty(this._locks[el]);
-                        this._disableElement(el, locked);
-                    }
-                    if (this._hides[el]) {
-                        var hidden = !this._isObjectEmpty(this._hides[el]);
-                        this._hideElement(el, hidden);
-                    }
+            }
+
+            return true;
+        },
+        /**
+         * Update all dependencies in form