Merge branch 'MDL-68353-master' of git://github.com/rezaies/moodle
authorJun Pataleta <jun@moodle.com>
Fri, 29 May 2020 14:26:03 +0000 (22:26 +0800)
committerJun Pataleta <jun@moodle.com>
Fri, 29 May 2020 14:26:03 +0000 (22:26 +0800)
27 files changed:
admin/templates/setting.mustache
lib/adminlib.php
lib/behat/classes/partial_named_selector.php
lib/behat/core_behat_file_helper.php
lib/behat/form_field/behat_form_field.php
lib/behat/form_field/behat_form_filemanager.php
lib/form/templates/element-advcheckbox-inline.mustache
lib/form/templates/element-checkbox-inline.mustache
lib/form/templates/element-filemanager.mustache
lib/form/templates/element-filepicker.mustache
lib/form/templates/element-group.mustache
lib/form/templates/element-password-inline.mustache
lib/form/templates/element-password.mustache
lib/form/templates/element-template.mustache
lib/form/templates/element-text-inline.mustache
lib/form/templates/element-text.mustache
lib/form/templates/element-url.mustache
lib/templates/filemanager_fileselect.mustache
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js
lib/yui/src/notification/js/dialogue.js
message/templates/message_drawer_view_settings_body_content.mustache
message/templates/message_index.mustache
repository/tests/behat/cancel_add_file.feature
repository/tests/behat/select_file.feature
repository/upload/tests/behat/behat_repository_upload.php

index a3a3a22..498aa2c 100644 (file)
 }}
 <div class="form-item row" id="{{id}}">
     <div class="form-label col-sm-3 text-sm-right">
-        <label {{#labelfor}}for="{{labelfor}}"{{/labelfor}}>
-            {{{title}}}
-            {{#override}}
-                <div class="alert alert-info">{{override}}</div>
-            {{/override}}
-            {{#warning}}
-                <div class="alert alert-warning">{{warning}}</div>
-            {{/warning}}
-        </label>
+        {{#customcontrol}}
+            <p {{#labelfor}}id="{{labelfor}}_label"{{/labelfor}}>
+                {{{title}}}
+                {{#override}}
+                    <div class="alert alert-info">{{override}}</div>
+                {{/override}}
+                {{#warning}}
+                    <div class="alert alert-warning">{{warning}}</div>
+                {{/warning}}
+            </p>
+        {{/customcontrol}}
+        {{^customcontrol}}
+            <label {{#labelfor}}for="{{labelfor}}"{{/labelfor}}>
+                {{{title}}}
+                {{#override}}
+                    <div class="alert alert-info">{{override}}</div>
+                {{/override}}
+                {{#warning}}
+                    <div class="alert alert-warning">{{warning}}</div>
+                {{/warning}}
+            </label>
+        {{/customcontrol}}
         <span class="form-shortname d-block small text-muted">{{{name}}}</span>
     </div>
     <div class="form-setting col-sm-9">
         {{#dependenton}}<div class="form-dependenton mb-4 text-muted">{{{.}}}</div>{{/dependenton}}
     </div>
 </div>
+{{#customcontrol}}
+    {{#js}}
+        require(['jquery'], function($) {
+            $('#{{id}}_label').css('cursor', 'default');
+            $('#{{id}}_label').click(function() {
+                $('#{{id}}')
+                    .find('button, a, input:not([type="hidden"]), select, textarea, [tabindex]')
+                    .filter(':not([disabled]):not([tabindex="0"]):not([tabindex="-1"])')
+                    .first().focus();
+            });
+        });
+    {{/js}}
+{{/customcontrol}}
index 1541db2..fd87ec4 100644 (file)
@@ -1686,6 +1686,8 @@ abstract class admin_setting {
     private $forceltr = null;
     /** @var array list of other settings that may cause this setting to be hidden */
     private $dependenton = [];
+    /** @var bool Whether this setting uses a custom form control */
+    protected $customcontrol = false;
 
     /**
      * Constructor
@@ -2081,6 +2083,16 @@ abstract class admin_setting {
     public function get_dependent_on() {
         return $this->dependenton;
     }
+
+    /**
+     * Whether this setting uses a custom form control.
+     * This function is especially useful to decide if we should render a label element for this setting or not.
+     *
+     * @return bool
+     */
+    public function has_custom_form_control(): bool {
+        return $this->customcontrol;
+    }
 }
 
 /**
@@ -8925,6 +8937,7 @@ function format_admin_setting($setting, $title='', $form='', $description='', $l
     $context->description = highlight($query, markdown_to_html($description));
     $context->element = $form;
     $context->forceltr = $setting->get_force_ltr();
+    $context->customcontrol = $setting->has_custom_form_control();
 
     return $OUTPUT->render_from_template('core_admin/setting', $context);
 }
@@ -10384,6 +10397,7 @@ class admin_setting_configstoredfile extends admin_setting {
         $this->filearea = $filearea;
         $this->itemid   = $itemid;
         $this->options  = (array)$options;
+        $this->customcontrol = true;
     }
 
     /**
index a1825a6..1b2d43e 100644 (file)
@@ -221,7 +221,9 @@ XPATH
 .//*[contains(., %locator%) and not(.//*[contains(., %locator%)])]
 XPATH
         , 'form_row' => <<<XPATH
-.//*[self::label or self::div[contains(concat(' ', @class, ' '), ' fstaticlabel ')]][contains(., %locator%)]/ancestor::*[contains(concat(' ', @class, ' '), ' fitem ')]
+.//*[contains(concat(' ', @class, ' '), ' col-form-label ')]
+    [normalize-space(.)= %locator%]
+    /ancestor::*[contains(concat(' ', @class, ' '), ' fitem ')]
 XPATH
         , 'autocomplete_selection' => <<<XPATH
 .//div[contains(concat(' ', normalize-space(@class), ' '), concat(' ', 'form-autocomplete-selection', ' '))]/span[@role='listitem'][contains(normalize-space(.), %locator%)]
@@ -253,7 +255,7 @@ XPATH
         ,
             'filemanager' => <<<XPATH
 .//*[@data-fieldtype = 'filemanager' or @data-fieldtype = 'filepicker']
-    /descendant::input[@id = //label[contains(normalize-space(string(.)), %locator%)]/@for]
+    /descendant::input[@id = substring-before(//p[contains(normalize-space(string(.)), %locator%)]/@id, '_label')]
 XPATH
         ,
              'passwordunmask' => <<<XPATH
index 957a357..b4064ef 100644 (file)
@@ -74,7 +74,7 @@ trait core_behat_file_helper {
             $filepickerelement = behat_context_helper::escape($filepickerelement);
             $filepickercontainer = $this->find(
                     'xpath',
-                    "//input[./@id = //label[normalize-space(.)=$filepickerelement]/@for]" .
+                    "//input[./@id = substring-before(//p[normalize-space(.)=$filepickerelement]/@id, '_label')]" .
                     "//ancestor::*[@data-fieldtype = 'filemanager' or @data-fieldtype = 'filepicker']",
                     $exception
             );
index bb011e0..ff85a2f 100644 (file)
@@ -251,7 +251,7 @@ class behat_form_field {
         // Defaults to label.
         if ($locatortype == 'label' || $locatortype == false) {
 
-            $labelnode = $this->session->getPage()->find('xpath', '//label[@for="' . $fieldid . '"]');
+            $labelnode = $this->session->getPage()->find('xpath', "//label[@for='$fieldid']|//p[@id='{$fieldid}_label']");
 
             // Exception only if $locatortype was specified.
             if (!$labelnode && $locatortype == 'label') {
index 7d70949..1fa9ff6 100644 (file)
@@ -68,7 +68,7 @@ class behat_form_filemanager extends behat_form_field {
         $fieldlabel = $this->get_field_locator();
 
         // Get the name of the current directory elements.
-        $xpath = "//label[contains(., '" . $fieldlabel . "')]" .
+        $xpath = "//p[normalize-space(.)='$fieldlabel']" .
             "/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' fitem ')]" .
             "/descendant::div[@data-fieldtype = 'filemanager']" .
             "/descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-filename ')]";
index 0584acc..a47a25c 100644 (file)
@@ -13,7 +13,6 @@
         value="{{element.selectedvalue}}"
     {{/element.selectedvalue}}
     {{#element.checked}}checked{{/element.checked}}
-    size="{{element.size}}"
     {{#error}}
         autofocus aria-describedby="{{element.iderror}}"
     {{/error}}
index 994ebc5..fb90de4 100644 (file)
@@ -13,7 +13,6 @@
         value="1"
     {{/element.value}}
     {{#element.checked}}checked{{/element.checked}}
-    size="{{element.size}}"
     {{#error}}
         autofocus aria-describedby="{{element.iderror}}"
     {{/error}}
index 6f02ca0..f2607eb 100644 (file)
@@ -1,5 +1,26 @@
 {{< core_form/element-template }}
+    {{$label}}
+        {{^element.hiddenlabel}}
+            <p id="{{element.id}}_label" class="col-form-label d-inline" aria-hidden="true">
+                {{{label}}}
+            </p>
+        {{/element.hiddenlabel}}
+    {{/label}}
     {{$element}}
-        {{{element.html}}}
+        <fieldset class="w-100 m-0 p-0 border-0" id="{{element.id}}_fieldset">
+            <legend class="sr-only">{{label}}</legend>
+            {{{element.html}}}
+        </fieldset>
     {{/element}}
 {{/ core_form/element-template }}
+{{#js}}
+(function() {
+    var label = document.getElementById('{{element.id}}_label');
+    if (label) {
+        label.style.cursor = 'default';
+        label.addEventListener('click', function() {
+            document.querySelectorAll('#{{element.id}}_fieldset div.fp-toolbar a')[0].focus();
+        });
+    }
+})();
+{{/js}}
index 6f02ca0..579cf20 100644 (file)
@@ -1,5 +1,26 @@
 {{< core_form/element-template }}
+    {{$label}}
+        {{^element.hiddenlabel}}
+            <p id="{{element.id}}_label" class="col-form-label d-inline" aria-hidden="true">
+                {{{label}}}
+            </p>
+        {{/element.hiddenlabel}}
+    {{/label}}
     {{$element}}
-        {{{element.html}}}
+        <fieldset class="w-100 m-0 p-0 border-0" id="{{element.id}}_fieldset">
+            <legend class="sr-only">{{label}}</legend>
+            {{{element.html}}}
+        </fieldset>
     {{/element}}
 {{/ core_form/element-template }}
+{{#js}}
+(function() {
+    var label = document.getElementById('{{element.id}}_label');
+    if (label) {
+        label.style.cursor = 'default';
+        label.addEventListener('click', function() {
+            document.querySelectorAll('#{{element.id}}_fieldset .fp-btn-choose')[0].focus();
+        });
+    }
+})();
+{{/js}}
index 4664a09..e9a5c05 100644 (file)
 require(['jquery'], function($) {
     $('#{{element.id}}_label').css('cursor', 'default');
     $('#{{element.id}}_label').click(function() {
-        $('#{{element.id}}').find('button, a, input, select, textarea, [tabindex]:not([tabindex="-1"])').filter(':enabled').first().focus();
+        $('#{{element.id}}')
+            .find('button, a, input:not([type="hidden"]), select, textarea, [tabindex]')
+            .filter(':not([disabled]):not([tabindex="0"]):not([tabindex="-1"])')
+            .first().focus();
     });
 });
 {{/js}}
index 59da069..f832dec 100644 (file)
@@ -41,7 +41,7 @@
                 name="{{element.name}}"
                 id="{{element.id}}"
                 value="{{element.value}}"
-                size="{{element.size}}"
+                {{#element.size}}size="{{element.size}}"{{/element.size}}
                 {{#error}}
                     autofocus aria-describedby="{{element.iderror}}"
                 {{/error}} {{{element.attributes}}}>
index d6e80f8..9a7758d 100644 (file)
@@ -41,7 +41,7 @@
                 name="{{element.name}}"
                 id="{{element.id}}"
                 value="{{element.value}}"
-                size="{{element.size}}"
+                {{#element.size}}size="{{element.size}}"{{/element.size}}
                 {{#error}}
                     autofocus aria-describedby="{{element.iderror}}"
                 {{/error}} {{{element.attributes}}}>
index bbf538d..d9528fa 100644 (file)
@@ -49,7 +49,7 @@
             {{#advanced}}<abbr class="initialism text-info" title="{{#str}}advanced{{/str}}">!</abbr>{{/advanced}}
             {{{helpbutton}}}
         </span>
-        {{$ label }}
+        {{# label}}{{$ label }}
             {{^element.staticlabel}}
                 <label class="col-form-label d-inline {{#element.hiddenlabel}}sr-only{{/element.hiddenlabel}}" for="{{element.id}}">
                     {{{label}}}
@@ -60,7 +60,7 @@
                     {{{label}}}
                 </span>
             {{/element.staticlabel}}
-        {{/ label }}
+        {{/ label }}{{/ label}}
     </div>
     <div class="col-md-9 form-inline felement" data-fieldtype="{{element.type}}">
         {{$ element }}
index b6bb3e9..81f7a5a 100644 (file)
@@ -8,7 +8,7 @@
             readonly {{#element.hardfrozen}}disabled{{/element.hardfrozen}}
     {{/element.frozen}}
             value="{{element.value}}"
-            size="{{element.size}}"
+            {{#element.size}}size="{{element.size}}"{{/element.size}}
             {{#error}}
                 autofocus aria-describedby="{{element.iderror}}"
             {{/error}}
index 087201a..7e972a3 100644 (file)
@@ -8,7 +8,7 @@
         {{/element.frozen}}
                 id="{{element.id}}"
                 value="{{element.value}}"
-                size="{{element.size}}"
+                {{#element.size}}size="{{element.size}}"{{/element.size}}
                 {{#error}}
                     autofocus aria-describedby="{{element.iderror}}"
                 {{/error}}
index 5529d4a..e161c8f 100644 (file)
@@ -8,7 +8,7 @@
                 name="{{element.name}}"
                 id="{{element.id}}"
                 value="{{element.value}}"
-                size="{{element.size}}"
+                {{#element.size}}size="{{element.size}}"{{/element.size}}
                 {{#error}}
                     autofocus aria-describedby="{{element.iderror}}"
                 {{/error}}
index 09084b6..c827c9a 100644 (file)
                     </div>
                 </div>
                 <div class="fp-original form-group row mx-0">
-                    <label class="form-control-label col-4 px-0">{{#str}}original, repository{{/str}}</label>
+                    <div class="form-control-label col-4 px-0">{{#str}}original, repository{{/str}}</div>
                     <div class="col-8 form-inline">
                         <span class="fp-originloading">{{#pix}}i/loading_small{{/pix}} {{#str}}loading, repository{{/str}}</span><span class="fp-value"></span>
                     </div>
                 </div>
                 <div class="fp-reflist form-group row mx-0">
-                    <label class="form-control-label col-4 px-0">{{#str}}referenceslist, repository{{/str}}</label>
+                    <div class="form-control-label col-4 px-0">{{#str}}referenceslist, repository{{/str}}</div>
                     <div class="col-8 form-inline">
                         <p class="fp-refcount"></p>
                         <span class="fp-reflistloading">{{#pix}}i/loading_small{{/pix}} {{#str}}loading, repository{{/str}}</span>
index b7844a0..6551623 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js and b/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js differ
index 596a348..56cfc98 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js and b/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js differ
index 49a9120..e896593 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js and b/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js differ
index 95a79e3..7c44355 100644 (file)
@@ -97,8 +97,10 @@ Y.extend(DIALOGUE, Y.Panel, {
         var bb;
 
         if (this.get('closeButton') !== false) {
-            // The buttons constructor does not allow custom attributes
-            this.get('buttons').header[0].setAttribute('title', this.get('closeButtonTitle'));
+            var title = this.get('closeButtonTitle');
+            // The buttons constructor does not allow custom attributes.
+            this.get('buttons').header[0].setAttribute('title', title);
+            this.get('buttons').header[0].setAttribute('aria-label', title);
         }
 
         // Initialise the element cache.
index f359f34..4acd27d 100644 (file)
     <h3 class="h6 font-weight-bold">{{#str}} privacy, message {{/str}}</h3>
     <p>{{#str}} privacy_desc, message {{/str}}</p>
     <div data-preference="blocknoncontacts" class="mb-3">
-        {{#privacy}}
-            <div class="custom-control custom-radio mb-2">
-                <input
-                    type="radio"
-                    name="message_blocknoncontacts"
-                    class="custom-control-input"
-                    id="block-noncontacts-{{uniqid}}-{{value}}"
-                    value="{{value}}"
-                >
-                <label class="custom-control-label ml-2" for="block-noncontacts-{{uniqid}}-{{value}}">
-                    {{text}}
-                </label>
-            </div>
-        {{/privacy}}
+        <fieldset>
+            <legend class="sr-only">{{#str}} contactableprivacy, message {{/str}}</legend>
+            {{#privacy}}
+                <div class="custom-control custom-radio mb-2">
+                    <input
+                        type="radio"
+                        name="message_blocknoncontacts"
+                        class="custom-control-input"
+                        id="block-noncontacts-{{uniqid}}-{{value}}"
+                        value="{{value}}"
+                    >
+                    <label class="custom-control-label ml-2" for="block-noncontacts-{{uniqid}}-{{value}}">
+                        {{text}}
+                    </label>
+                </div>
+            {{/privacy}}
+        </fieldset>
     </div>
 
     <div class="hidden" data-region="notification-preference-container">
index 65c44fc..f47b39c 100644 (file)
@@ -15,7 +15,7 @@
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 }}
 {{!
-    @template core_message/message_drawer
+    @template core_message/message_index
 
     This template will render the message drawer.
 
index 2742d57..76c4359 100644 (file)
@@ -19,7 +19,7 @@ Feature: A selected file can be cancelled
       | Name | Folder name |
       | Description | Folder description |
     And I upload "lib/tests/fixtures/upload_users.csv" file to "Files" filemanager
-    And I click on "//label[contains(., 'Files')]/ancestor::div[contains(concat(' ', @class, ' '), ' fitem ')]//*[contains(@title, 'Add...')]" "xpath_element"
+    And I click on "Add..." "button" in the "Files" "form_row"
     And I click on "Recent files" "link" in the ".fp-repo-area" "css_element"
     And I click on "//a[contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')][normalize-space(.)='empty.txt']" "xpath_element"
     And I click on ".moodle-dialogue-focused .fp-select .fp-select-cancel" "css_element"
index e7cd4eb..43bce52 100644 (file)
@@ -21,7 +21,7 @@ Feature: Select file feature
     And I click on "Save and display" "button"
     And I follow "Dashboard" in the user menu
     And I follow "Manage private files"
-    And I click on "//label[contains(., 'Files')]/ancestor::div[contains(concat(' ', @class, ' '), ' fitem ')]//*[contains(@title, 'Add...')]" "xpath_element"
+    And I click on "Add..." "button" in the "Files" "form_row"
     And I click on "Recent files" "link" in the ".fp-repo-area" "css_element"
     And I click on "Display folder with file icons" "link" in the ".file-picker" "css_element"
     And I click on "//a[contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')][normalize-space(.)='empty.txt']" "xpath_element"
@@ -42,7 +42,7 @@ Feature: Select file feature
     And I click on "Save and display" "button"
     And I follow "Dashboard" in the user menu
     And I follow "Manage private files"
-    And I click on "//label[contains(., 'Files')]/ancestor::div[contains(concat(' ', @class, ' '), ' fitem ')]//*[contains(@title, 'Add...')]" "xpath_element"
+    And I click on "Add..." "button" in the "Files" "form_row"
     And I click on "Recent files" "link" in the ".fp-repo-area" "css_element"
     And I click on "Display folder with file details" "link" in the ".file-picker" "css_element"
     And I click on "//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')]/descendant::span[normalize-space(.)='empty.txt']/ancestor::a" "xpath_element"
@@ -63,7 +63,7 @@ Feature: Select file feature
     And I click on "Save and display" "button"
     And I follow "Dashboard" in the user menu
     And I follow "Manage private files"
-    And I click on "//label[contains(., 'Files')]/ancestor::div[contains(concat(' ', @class, ' '), ' fitem ')]//*[contains(@title, 'Add...')]" "xpath_element"
+    And I click on "Add..." "button" in the "Files" "form_row"
     And I click on "Recent files" "link" in the ".fp-repo-area" "css_element"
     And I click on "Display folder as file tree" "link" in the ".file-picker" "css_element"
     And I click on "//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')]/descendant::span[normalize-space(.)='empty.txt']/ancestor::a" "xpath_element"
index 74d6abf..52fa09b 100644 (file)
@@ -209,10 +209,8 @@ class behat_repository_upload extends behat_base {
             $filepickerelement = behat_context_helper::escape($filepickerelement);
             $filepickercontainer = $this->find(
                     'xpath',
-                    "//input[./@id = //label[normalize-space(.)=$filepickerelement]/@for]" .
-                    "//ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' felement ')] |" .
-                    "//input[./@id = //label[normalize-space(.)=$filepickerelement]/@for]" .
-                    "//ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' form-setting ')]",
+                    "//input[./@id = substring-before(//p[normalize-space(.)=$filepickerelement]/@id, '_label')]" .
+                    "//ancestor::*[@data-fieldtype = 'filemanager' or @data-fieldtype = 'filepicker']",
                     $exception
             );
         }