Merge branch 'form-errors' into 'master'
small ui/ux refinements See merge request !170
This commit is contained in:
commit
6fbb1888c5
@ -66,6 +66,14 @@
|
|||||||
input, textarea {
|
input, textarea {
|
||||||
border-color: var(--color-error) !important;
|
border-color: var(--color-error) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-error {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-error {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
|||||||
@ -8,6 +8,9 @@
|
|||||||
var AUTOSUBMIT_BUTTON_SELECTOR = '[type="submit"][data-autosubmit]';
|
var AUTOSUBMIT_BUTTON_SELECTOR = '[type="submit"][data-autosubmit]';
|
||||||
var AJAX_SUBMIT_FLAG = 'ajaxSubmit';
|
var AJAX_SUBMIT_FLAG = 'ajaxSubmit';
|
||||||
|
|
||||||
|
var FORM_GROUP_CLASS = 'form-group';
|
||||||
|
var FORM_GROUP_WITH_ERRORS_CLASS = 'form-group--has-error';
|
||||||
|
|
||||||
function formValidator(inputs) {
|
function formValidator(inputs) {
|
||||||
var done = true;
|
var done = true;
|
||||||
inputs.forEach(function(inp) {
|
inputs.forEach(function(inp) {
|
||||||
@ -52,6 +55,12 @@
|
|||||||
// inputs
|
// inputs
|
||||||
utilInstances.push(window.utils.setup('inputs', form, options));
|
utilInstances.push(window.utils.setup('inputs', form, options));
|
||||||
|
|
||||||
|
// form group errors
|
||||||
|
var formGroups = Array.from(form.querySelectorAll('.' + FORM_GROUP_CLASS));
|
||||||
|
formGroups.forEach(function(formGroup) {
|
||||||
|
utilInstances.push(window.utils.setup('errorRemover', formGroup, options));
|
||||||
|
});
|
||||||
|
|
||||||
form.classList.add(JS_INITIALIZED);
|
form.classList.add(JS_INITIALIZED);
|
||||||
|
|
||||||
function destroyUtils() {
|
function destroyUtils() {
|
||||||
@ -165,4 +174,29 @@
|
|||||||
destroy: function() {},
|
destroy: function() {},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// listens for focus events and removes any errors on an input
|
||||||
|
window.utils.errorRemover = function(formGroup, options) {
|
||||||
|
|
||||||
|
var inputElement = formGroup.querySelector('input:not([type="hidden"]), textarea, select');
|
||||||
|
if (!inputElement) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputElement.addEventListener('focus', focusListener);
|
||||||
|
|
||||||
|
function focusListener() {
|
||||||
|
var hasError = formGroup.classList.contains(FORM_GROUP_WITH_ERRORS_CLASS);
|
||||||
|
if (hasError) {
|
||||||
|
formGroup.classList.remove(FORM_GROUP_WITH_ERRORS_CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
scope: formGroup,
|
||||||
|
destroy: function() {
|
||||||
|
inputElement.removeEventListener('focus', focusListener);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@ -3,37 +3,37 @@
|
|||||||
|
|
||||||
window.utils = window.utils || {};
|
window.utils = window.utils || {};
|
||||||
|
|
||||||
var JS_INITIALIZED_CLASS = 'js-initialized';
|
var JS_INITIALIZED_CLASS = 'js-inputs-initialized';
|
||||||
|
|
||||||
function isNotInitialized(element) {
|
|
||||||
return !element.classList.contains(JS_INITIALIZED_CLASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.utils.inputs = function(wrapper, options) {
|
window.utils.inputs = function(wrapper, options) {
|
||||||
|
options = options || {};
|
||||||
var utilInstances = [];
|
var utilInstances = [];
|
||||||
|
|
||||||
|
if (wrapper.classList.contains(JS_INITIALIZED_CLASS) && !options.force) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// checkboxes
|
// checkboxes
|
||||||
var checkboxes = Array.from(wrapper.querySelectorAll('input[type="checkbox"]'));
|
var checkboxes = Array.from(wrapper.querySelectorAll('input[type="checkbox"]'));
|
||||||
checkboxes.filter(isNotInitialized).forEach(function(checkbox) {
|
checkboxes.forEach(function(checkbox) {
|
||||||
utilInstances.push(window.utils.setup('checkbox', checkbox));
|
utilInstances.push(window.utils.setup('checkbox', checkbox));
|
||||||
});
|
});
|
||||||
|
|
||||||
// radios
|
// radios
|
||||||
var radios = Array.from(wrapper.querySelectorAll('input[type="radio"]'));
|
var radios = Array.from(wrapper.querySelectorAll('input[type="radio"]'));
|
||||||
radios.filter(isNotInitialized).forEach(function(radio) {
|
radios.forEach(function(radio) {
|
||||||
utilInstances.push(window.utils.setup('radio', radio));
|
utilInstances.push(window.utils.setup('radio', radio));
|
||||||
});
|
});
|
||||||
|
|
||||||
// file-uploads
|
// file-uploads
|
||||||
var fileUploads = Array.from(wrapper.querySelectorAll('input[type="file"]'));
|
var fileUploads = Array.from(wrapper.querySelectorAll('input[type="file"]'));
|
||||||
fileUploads.filter(isNotInitialized).forEach(function(input) {
|
fileUploads.forEach(function(input) {
|
||||||
utilInstances.push(window.utils.setup('fileUpload', input, options));
|
utilInstances.push(window.utils.setup('fileUpload', input, options));
|
||||||
});
|
});
|
||||||
|
|
||||||
// file-checkboxes
|
// file-checkboxes
|
||||||
var fileCheckboxes = Array.from(wrapper.querySelectorAll('.file-checkbox'));
|
var fileCheckboxes = Array.from(wrapper.querySelectorAll('.file-checkbox'));
|
||||||
fileCheckboxes.filter(isNotInitialized).forEach(function(input) {
|
fileCheckboxes.forEach(function(input) {
|
||||||
utilInstances.push(window.utils.setup('fileCheckbox', input, options));
|
utilInstances.push(window.utils.setup('fileCheckbox', input, options));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -45,6 +45,8 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wrapper.classList.add(JS_INITIALIZED_CLASS);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
scope: wrapper,
|
scope: wrapper,
|
||||||
destroy: destroyUtils,
|
destroy: destroyUtils,
|
||||||
@ -74,7 +76,6 @@
|
|||||||
if (!i18n) {
|
if (!i18n) {
|
||||||
throw new Error('window.utils.fileUpload(input, options) needs to be passed i18n object via options');
|
throw new Error('window.utils.fileUpload(input, options) needs to be passed i18n object via options');
|
||||||
}
|
}
|
||||||
input.classList.add(JS_INITIALIZED_CLASS);
|
|
||||||
|
|
||||||
function renderFileList(files) {
|
function renderFileList(files) {
|
||||||
fileList.innerHTML = '';
|
fileList.innerHTML = '';
|
||||||
@ -166,8 +167,6 @@
|
|||||||
cont = cont.parentNode;
|
cont = cont.parentNode;
|
||||||
}
|
}
|
||||||
addListener(cont);
|
addListener(cont);
|
||||||
input.classList.add(JS_INITIALIZED_CLASS);
|
|
||||||
cont.classList.add(JS_INITIALIZED_CLASS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
@ -190,7 +189,6 @@
|
|||||||
labelEl.setAttribute('for', input.id);
|
labelEl.setAttribute('for', input.id);
|
||||||
wrapperEl.appendChild(input);
|
wrapperEl.appendChild(input);
|
||||||
wrapperEl.appendChild(labelEl);
|
wrapperEl.appendChild(labelEl);
|
||||||
input.classList.add(JS_INITIALIZED_CLASS);
|
|
||||||
|
|
||||||
if (siblingEl) {
|
if (siblingEl) {
|
||||||
parentEl.insertBefore(wrapperEl, siblingEl);
|
parentEl.insertBefore(wrapperEl, siblingEl);
|
||||||
@ -219,7 +217,6 @@
|
|||||||
wrapperEl.appendChild(siblingEl);
|
wrapperEl.appendChild(siblingEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
input.classList.add(JS_INITIALIZED_CLASS);
|
|
||||||
parentEl.appendChild(wrapperEl);
|
parentEl.appendChild(wrapperEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,8 +230,6 @@
|
|||||||
window.utils.implicitSubmit = function(input, options) {
|
window.utils.implicitSubmit = function(input, options) {
|
||||||
var submit = options.submit;
|
var submit = options.submit;
|
||||||
|
|
||||||
console.log('implicitSubmit', input, submit);
|
|
||||||
|
|
||||||
if (!submit) {
|
if (!submit) {
|
||||||
throw new Error('window.utils.implicitSubmit(input, options) needs to be passed a submit element via options');
|
throw new Error('window.utils.implicitSubmit(input, options) needs to be passed a submit element via options');
|
||||||
}
|
}
|
||||||
@ -247,7 +242,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
input.addEventListener('keypress', doSubmit);
|
input.addEventListener('keypress', doSubmit);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
scope: input,
|
scope: input,
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
|
|||||||
@ -37,6 +37,9 @@
|
|||||||
|
|
||||||
if (isAlreadySetup) {
|
if (isAlreadySetup) {
|
||||||
console.warn('Trying to setup a JS utility that\'s already been set up', { utility: utilName, scope, options });
|
console.warn('Trying to setup a JS utility that\'s already been set up', { utility: utilName, scope, options });
|
||||||
|
if (!options.force) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,17 +1,14 @@
|
|||||||
<div .container>
|
<section>
|
||||||
<h1>Uni2work - Admin Demopage
|
|
||||||
|
|
||||||
<p data-tooltip="Solch ein Tooltip kann mit dem <em>data-tooltip</em> Attribut erzeugt werden. Funktioniert aber nur in Block-Elementen die einen sinnvollen Wrapper haben.">
|
<p data-tooltip="Solch ein Tooltip kann mit dem <em>data-tooltip</em> Attribut erzeugt werden. Funktioniert aber nur in Block-Elementen die einen sinnvollen Wrapper haben.">
|
||||||
Diese interne Seite dient lediglich zum Testen diverser Funktionalitäten
|
Diese interne Seite dient lediglich zum Testen diverser Funktionalitäten
|
||||||
und zur Demonstration der verschiedenen Hilfsfunktionen/Module.
|
und zur Demonstration der verschiedenen Hilfsfunktionen/Module.
|
||||||
|
|
||||||
Der Handler sollte jeweils aktuelle Beispiele für alle möglichen Funktionalitäten enthalten, so dass man immer weiß, wo man nachschlagen kann.
|
Der Handler sollte jeweils aktuelle Beispiele für alle möglichen Funktionalitäten enthalten, so dass man immer weiß, wo man nachschlagen kann.
|
||||||
|
|
||||||
|
<section>
|
||||||
<div .container.js-show-hide>
|
|
||||||
<h2 .js-show-hide__toggle>Teilweise funktionierende Abschnitte
|
<h2 .js-show-hide__toggle>Teilweise funktionierende Abschnitte
|
||||||
|
|
||||||
<ul .js-show-hide__target>
|
<ul>
|
||||||
<li .list-group-item>
|
<li .list-group-item>
|
||||||
<a href=@{UsersR}>Benutzer Verwaltung
|
<a href=@{UsersR}>Benutzer Verwaltung
|
||||||
|
|
||||||
@ -22,7 +19,7 @@
|
|||||||
<li .list-group-item>
|
<li .list-group-item>
|
||||||
<a href=@{CourseNewR}>Kurse anlegen
|
<a href=@{CourseNewR}>Kurse anlegen
|
||||||
|
|
||||||
<div .container>
|
<section>
|
||||||
<h2>Funktionen zum Testen
|
<h2>Funktionen zum Testen
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@ -474,7 +474,7 @@ ul.list--inline {
|
|||||||
/* DEFINITION LIST */
|
/* DEFINITION LIST */
|
||||||
.deflist {
|
.deflist {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 100% ;
|
grid-template-columns: 100%;
|
||||||
}
|
}
|
||||||
.deflist__dt,
|
.deflist__dt,
|
||||||
.deflist__dd {
|
.deflist__dd {
|
||||||
@ -488,6 +488,10 @@ ul.list--inline {
|
|||||||
.deflist__dd {
|
.deflist__dd {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
> p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
@ -507,7 +511,6 @@ ul.list--inline {
|
|||||||
|
|
||||||
.deflist__dt,
|
.deflist__dt,
|
||||||
.deflist__dd {
|
.deflist__dd {
|
||||||
border-bottom: 1px solid #d3d3d3;
|
|
||||||
padding: 12px 0;
|
padding: 12px 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -527,16 +530,14 @@ ul.list--inline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
padding-bottom: 20px;
|
padding-bottom: 30px;
|
||||||
margin-bottom: 20px;
|
|
||||||
border-bottom: 1px solid #d3d3d3;
|
border-bottom: 1px solid #d3d3d3;
|
||||||
|
|
||||||
+ section {
|
+ section {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
padding-top: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-of-type {
|
&:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
|
<section>
|
||||||
|
UniWorX erfahrene Veranstalter finden
|
||||||
|
hier die wichtigsten Neuerungen.
|
||||||
|
|
||||||
UniWorX erfahrene Veranstalter finden
|
|
||||||
hier die wichtigsten Neuerungen.
|
|
||||||
<section>
|
<section>
|
||||||
<h2>Bekannte Probleme in Bearbeitung
|
<h2>Bekannte Probleme in Bearbeitung
|
||||||
|
|
||||||
@ -178,4 +179,4 @@ hier die wichtigsten Neuerungen.
|
|||||||
Planmäßige Wartungen werden ohne Ankündigung
|
Planmäßige Wartungen werden ohne Ankündigung
|
||||||
immer um 2:00h nachts durchgeführt.
|
immer um 2:00h nachts durchgeführt.
|
||||||
Es wird daher empfohlen, keine kritischen Abgabefristen
|
Es wird daher empfohlen, keine kritischen Abgabefristen
|
||||||
um oder kurz nach dieser Zeit einzustellen.
|
um oder kurz nach dieser Zeit einzustellen.
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
.table-filter {
|
.table-filter {
|
||||||
border-bottom: 1px solid #d3d3d3;
|
|
||||||
margin-bottom: 13px;
|
margin-bottom: 13px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
$newline never
|
$newline never
|
||||||
$# Wrapper for all kinds of forms
|
$# Wrapper for all kinds of forms
|
||||||
<form ##{formId} method=#{decodeUtf8 (renderStdMethod formMethod)} action=#{fromMaybe "" formActionUrl} enctype=#{formEncoding} *{formAttrs}>
|
<section>
|
||||||
$# Distinguish different falvours of submit button layouts here:
|
<form ##{formId} method=#{decodeUtf8 (renderStdMethod formMethod)} action=#{fromMaybe "" formActionUrl} enctype=#{formEncoding} *{formAttrs}>
|
||||||
$case formSubmit
|
$# Distinguish different falvours of submit button layouts here:
|
||||||
$of FormNoSubmit
|
$case formSubmit
|
||||||
^{formWidget}
|
$of FormNoSubmit
|
||||||
$of FormSubmit
|
^{formWidget}
|
||||||
^{formWidget}
|
$of FormSubmit
|
||||||
^{submitButtonView}
|
^{formWidget}
|
||||||
$of FormDualSubmit
|
^{submitButtonView}
|
||||||
^{submitButtonView}
|
$of FormDualSubmit
|
||||||
^{formWidget}
|
^{submitButtonView}
|
||||||
^{submitButtonView}
|
^{formWidget}
|
||||||
$of FormAutoSubmit
|
^{submitButtonView}
|
||||||
^{formWidget}
|
$of FormAutoSubmit
|
||||||
<button type=submit data-autosubmit>
|
^{formWidget}
|
||||||
^{btnLabel BtnSubmit}
|
<button type=submit data-autosubmit>
|
||||||
|
^{btnLabel BtnSubmit}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user