Skip to content

Commit 3e69d62

Browse files
committed
Add new settings to enforcerequiredprofilefields
1 parent 447f808 commit 3e69d62

File tree

6 files changed

+243
-0
lines changed

6 files changed

+243
-0
lines changed

amd/build/profilefields.min.js

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

amd/build/profilefields.min.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

amd/src/profilefields.js

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
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+
* Module to enforce required and locked profile fields during user creation.
18+
*
19+
* @module theme_trema/profilefields
20+
* @author Rodrigo Mady
21+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22+
*/
23+
24+
define(['jquery', 'core/str', 'core/notification'], function($, Str, Notification) {
25+
26+
/**
27+
* Initialize the module.
28+
*
29+
* @param {Object} profileFieldsData - Data containing required profile fields
30+
*/
31+
var init = function(profileFieldsData) {
32+
setupUserCreationPage(profileFieldsData || {});
33+
};
34+
35+
/**
36+
* Setup handlers for the user creation page.
37+
*
38+
* @param {Object} profileFieldsData - Data containing required profile fields
39+
*/
40+
var setupUserCreationPage = function(profileFieldsData) {
41+
if (profileFieldsData.length > 0) {
42+
addFormValidation(profileFieldsData);
43+
}
44+
};
45+
46+
/**
47+
* Add validation to the user creation form.
48+
*
49+
* @param {Array} fields - Array of fields that are required
50+
*/
51+
var addFormValidation = function(fields) {
52+
// Get the form element
53+
var $form = $('#id_mform1');
54+
55+
// Get the required string for validation messages
56+
var requiredString = 'Required';
57+
Str.get_string('required', 'core').then(function(string) {
58+
requiredString = string;
59+
return true;
60+
}).catch(Notification.exception);
61+
62+
// Process each profile field that is required.
63+
fields.forEach(function(field) {
64+
var fieldId = 'id_profile_field_' + field;
65+
var $field = $('#' + fieldId);
66+
67+
if ($field.length > 0) {
68+
var $formGroup = $field.closest('.form-group');
69+
70+
$field.attr('required', 'required');
71+
72+
$field.attr('aria-required', 'true');
73+
74+
var $labelCol = $formGroup.find('.col-form-label');
75+
var $labelAddon = $labelCol.find('.form-label-addon');
76+
77+
if ($labelAddon.length === 0) {
78+
$labelAddon = $('<div class="form-label-addon d-flex align-items-center align-self-start"></div>');
79+
$labelCol.append($labelAddon);
80+
}
81+
82+
// Add the required icon if not present
83+
if ($labelAddon.find('.text-danger').length === 0) {
84+
var $requiredIcon = $(
85+
'<div class="text-danger" title="Required">' +
86+
'<i class="icon fa fa-exclamation-circle text-danger fa-fw " ' +
87+
'title="Required" role="img" aria-label="Required"></i>' +
88+
'</div>'
89+
);
90+
$labelAddon.append($requiredIcon);
91+
}
92+
93+
var errorId = fieldId + '_error';
94+
var $felement = $formGroup.find('.felement');
95+
if ($felement.length > 0 && !$felement.find('#' + errorId).length) {
96+
var $errorContainer = $('<div class="form-control-feedback invalid-feedback" id="' + errorId + '"></div>');
97+
$felement.append($errorContainer);
98+
}
99+
100+
$field.on('blur', function() {
101+
validateField($field, requiredString);
102+
});
103+
104+
if (!$form.data('validation-added')) {
105+
$form.on('submit', function(e) {
106+
var isValid = true;
107+
108+
// Validate all required profile fields
109+
fields.forEach(function(fieldName) {
110+
var fieldSelector = '#id_profile_field_' + fieldName;
111+
var $fieldToValidate = $(fieldSelector);
112+
113+
if ($fieldToValidate.length > 0 && !validateField($fieldToValidate, requiredString)) {
114+
isValid = false;
115+
}
116+
});
117+
118+
if (!isValid) {
119+
e.preventDefault();
120+
// Scroll to the first invalid field
121+
var $firstInvalidField = $('.form-group.has-danger').first();
122+
if ($firstInvalidField.length > 0) {
123+
$('html, body').animate({
124+
scrollTop: $firstInvalidField.offset().top - 100
125+
}, 200);
126+
}
127+
}
128+
});
129+
130+
$form.data('validation-added', true);
131+
}
132+
}
133+
});
134+
};
135+
136+
/**
137+
* Validate a single field.
138+
*
139+
* @param {jQuery} $field - The field to validate
140+
* @param {String} requiredString - The text to display for required fields
141+
* @return {boolean} - Whether the field is valid
142+
*/
143+
var validateField = function($field, requiredString) {
144+
var fieldId = $field.attr('id');
145+
var $formGroup = $field.closest('.form-group');
146+
var $errorContainer = $('#' + fieldId + '_error');
147+
148+
// Get the field value, handling different input types
149+
var value = $field.val();
150+
if ($field.is('input[type="checkbox"]')) {
151+
value = $field.is(':checked');
152+
} else if ($field.is('input[type="radio"]')) {
153+
value = $formGroup.find('input[type="radio"]:checked').length > 0;
154+
} else if ($field.is('select')) {
155+
// For select elements, empty string or default "choose" option is invalid
156+
if (value === '' || value === '0' || value === '-1') {
157+
value = '';
158+
}
159+
}
160+
161+
// Check if the field has a value
162+
var isValid = value !== null && value !== '' && value !== false;
163+
164+
if (isValid) {
165+
// Field is valid - remove error styling
166+
$formGroup.removeClass('has-danger');
167+
$field.removeClass('is-invalid');
168+
if ($errorContainer.length) {
169+
$errorContainer.empty();
170+
}
171+
} else {
172+
// Field is invalid - add error styling
173+
$formGroup.addClass('has-danger');
174+
$field.addClass('is-invalid');
175+
if ($errorContainer.length) {
176+
$errorContainer.text(requiredString);
177+
}
178+
}
179+
180+
return isValid;
181+
};
182+
183+
return {
184+
init: init
185+
};
186+
});

0 commit comments

Comments
 (0)