Release 2.8.6
This commit is contained in:
@@ -1,6 +1,98 @@
|
||||
// Shared browser helpers for web UI escaping and formatting.
|
||||
|
||||
(function () {
|
||||
var urlValidationMessage = 'Please enter a URL.';
|
||||
|
||||
function isUrlInput(input) {
|
||||
return input && input.matches && input.matches('input[type="url"]');
|
||||
}
|
||||
|
||||
function isValidHttpUrl(input) {
|
||||
input.setCustomValidity('');
|
||||
var value = String(input.value || '').trim();
|
||||
var hasValidNativeUrl = input.validity.valid;
|
||||
var hasExplicitHttpScheme = /^https?:\/\/[^\s]+$/i.test(value);
|
||||
var isValid = hasValidNativeUrl && hasExplicitHttpScheme;
|
||||
if (!isValid) {
|
||||
input.setCustomValidity(urlValidationMessage);
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
function getUrlFeedback(input) {
|
||||
if (input._urlFeedback && input._urlFeedback.parentNode) {
|
||||
return input._urlFeedback;
|
||||
}
|
||||
|
||||
var feedbackId = input.id ? input.id + '-url-feedback' : '';
|
||||
var feedback = feedbackId ? document.getElementById(feedbackId) : null;
|
||||
if (feedback) {
|
||||
var inputGroup = input.closest ? input.closest('.input-group') : null;
|
||||
var feedbackAnchor = inputGroup || input;
|
||||
feedbackAnchor.parentNode.insertBefore(feedback, feedbackAnchor.nextSibling);
|
||||
input._urlFeedback = feedback;
|
||||
return feedback;
|
||||
}
|
||||
|
||||
feedback = document.createElement('div');
|
||||
if (feedbackId) {
|
||||
feedback.id = feedbackId;
|
||||
}
|
||||
feedback.className = 'invalid-feedback';
|
||||
feedback.setAttribute('role', 'alert');
|
||||
feedback.textContent = urlValidationMessage;
|
||||
|
||||
var inputGroup = input.closest ? input.closest('.input-group') : null;
|
||||
var feedbackAnchor = inputGroup || input;
|
||||
feedbackAnchor.parentNode.insertBefore(feedback, feedbackAnchor.nextSibling);
|
||||
if (input.id) {
|
||||
input.setAttribute('aria-describedby', feedback.id);
|
||||
}
|
||||
input._urlFeedback = feedback;
|
||||
return feedback;
|
||||
}
|
||||
|
||||
function updateUrlValidation(input, showFeedback) {
|
||||
if (!isUrlInput(input)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var isValid = isValidHttpUrl(input);
|
||||
if (!isValid && showFeedback) {
|
||||
var feedback = getUrlFeedback(input);
|
||||
feedback.hidden = false;
|
||||
feedback.classList.add('d-block');
|
||||
input.classList.add('is-invalid');
|
||||
} else if (isValid) {
|
||||
if (input.id) {
|
||||
document.querySelectorAll('[id="' + input.id + '-url-feedback"]').forEach(function (feedback) {
|
||||
feedback.hidden = true;
|
||||
feedback.classList.remove('d-block');
|
||||
});
|
||||
} else if (input._urlFeedback) {
|
||||
input._urlFeedback.hidden = true;
|
||||
input._urlFeedback.classList.remove('d-block');
|
||||
}
|
||||
input.classList.remove('is-invalid');
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
function initializeUrlValidation() {
|
||||
document.addEventListener('input', function (event) {
|
||||
if (isUrlInput(event.target)) {
|
||||
updateUrlValidation(event.target, true);
|
||||
}
|
||||
});
|
||||
document.addEventListener('invalid', function (event) {
|
||||
if (isUrlInput(event.target)) {
|
||||
event.preventDefault();
|
||||
updateUrlValidation(event.target, true);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value ?? '')
|
||||
.replace(/&/g, '&')
|
||||
@@ -97,6 +189,7 @@
|
||||
}
|
||||
|
||||
window.escapeHtml = escapeHtml;
|
||||
initializeUrlValidation();
|
||||
|
||||
var defaultQrOptions = window.defaultQrOptions || {
|
||||
width: 1000,
|
||||
|
||||
Reference in New Issue
Block a user