MDL-69608 core_form: frozen forms do not have form tag
[moodle.git] / theme / boost / amd / src / form-display-errors.js
CommitLineData
4691b2d0
DW
1// This file is part of Moodle - http://moodle.org/
2//
3// Moodle is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// Moodle is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
15
16/**
17 * Custom form error event handler to manipulate the bootstrap markup and show
18 * nicely styled errors in an mform.
19 *
2ede86d7 20 * @module theme_boost/form-display-errors
4691b2d0
DW
21 * @copyright 2016 Damyon Wiese <damyon@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24define(['jquery', 'core/event'], function($, Event) {
25 return {
26 enhance: function(elementid) {
27 var element = document.getElementById(elementid);
ae5d5f20
TH
28 if (!element) {
29 // Some elements (e.g. static) don't have a form field.
30 // Hence there is no validation. So, no setup required here.
31 return;
32 }
33
4691b2d0
DW
34 $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
35 event.preventDefault();
36 var parent = $(element).closest('.form-group');
37 var feedback = parent.find('.form-control-feedback');
c1ae9079
DW
38
39 // Sometimes (atto) we have a hidden textarea backed by a real contenteditable div.
40 if (($(element).prop("tagName") == 'TEXTAREA') && parent.find('[contenteditable]')) {
41 element = parent.find('[contenteditable]');
42 }
4691b2d0
DW
43 if (msg !== '') {
44 parent.addClass('has-danger');
7744f892 45 parent.data('client-validation-error', true);
3ec69c2e 46 $(element).addClass('is-invalid');
e0c5ffb6
FM
47 $(element).attr('aria-describedby', feedback.attr('id'));
48 $(element).attr('aria-invalid', true);
49 feedback.attr('tabindex', 0);
4691b2d0 50 feedback.html(msg);
e0c5ffb6
FM
51
52 // Only display and focus when the error was not already visible.
a5b56c4d 53 // This is so that, when tabbing around the form, you don't get stuck.
e0c5ffb6
FM
54 if (!feedback.is(':visible')) {
55 feedback.show();
56 feedback.focus();
57 }
58
4691b2d0 59 } else {
7744f892
DW
60 if (parent.data('client-validation-error') === true) {
61 parent.removeClass('has-danger');
62 parent.data('client-validation-error', false);
3ec69c2e 63 $(element).removeClass('is-invalid');
e0c5ffb6
FM
64 $(element).removeAttr('aria-describedby');
65 $(element).attr('aria-invalid', false);
7744f892
DW
66 feedback.hide();
67 }
4691b2d0
DW
68 }
69 });
ae5d5f20 70
a5b56c4d 71 var form = element.closest('form');
312ca07b 72 if (form && !('boostFormErrorsEnhanced' in form.dataset)) {
a5b56c4d
TH
73 form.addEventListener('submit', function() {
74 var visibleError = $('.form-control-feedback:visible');
75 if (visibleError.length) {
76 visibleError[0].focus();
77 }
78 });
79 form.dataset.boostFormErrorsEnhanced = 1;
80 }
4691b2d0
DW
81 }
82 };
2ede86d7 83});