LT-67: Styling select2 error state and adding its error tooltip
This commit is contained in:
parent
620f5fd4ff
commit
c05e36eca8
@ -22,3 +22,8 @@
|
||||
theme('background-color', '$uiStateError')
|
||||
theme('border-color', '$uiStateErrorBorder')
|
||||
theme('color', '$uiStateErrorText')
|
||||
|
||||
.select2-selection
|
||||
theme('background-color', '$uiStateError')
|
||||
theme('border-color', '$uiStateErrorBorder')
|
||||
theme('color', '$uiStateErrorText')
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
key='regionsOfMetastaticDisease'
|
||||
multiple=true
|
||||
options=(clone
|
||||
placeholder='Choose a region...'
|
||||
placeholder='Choose a region'
|
||||
allowClear=true
|
||||
)
|
||||
}}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
{{>inputSelect labelClass='form-group' key='imageRendering' hideSearch=true
|
||||
options=(clone placeholder='Select an option...')}}
|
||||
options=(clone placeholder='Select an option')}}
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
{{>inputText labelClass='form-group' key='qidoRoot'}}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<div class="col-lg-6">
|
||||
{{>inputSelect labelClass='form-group' key='type'
|
||||
hideSearch=true disabled=(eq this.mode.get 'edit')
|
||||
options=(clone placeholder='Choose a server type...')}}
|
||||
options=(clone placeholder='Choose a server type')}}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
@ -27,6 +27,18 @@ OHIF.mixins.form = new OHIF.Mixin({
|
||||
// Enable reactivity by changing a Tracker.Dependency observer
|
||||
component.validationObserver.changed();
|
||||
}, 200);
|
||||
|
||||
// Change the validation function to focus the fields with error
|
||||
const validateSelf = component.validate;
|
||||
component.validate = () => {
|
||||
// Call the original validation function
|
||||
validateSelf();
|
||||
|
||||
// Focus the first error field if some validation failed
|
||||
if (component.schema && component.schema._invalidKeys.length) {
|
||||
instance.$('.state-error :input:first').focus();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
onRendered() {
|
||||
@ -35,16 +47,6 @@ OHIF.mixins.form = new OHIF.Mixin({
|
||||
|
||||
// Set the component main and style elements
|
||||
component.$style = component.$element = instance.$('form:first');
|
||||
|
||||
instance.autorun(() => {
|
||||
// Run this computation everytime the validation is triggered
|
||||
component.validationObserver.depend();
|
||||
|
||||
// Focus the first error field if some validation failed
|
||||
if (component.schema && component.schema._invalidKeys.length) {
|
||||
instance.$('.state-error :input:first').focus();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
events: {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { Tracker } from 'meteor/tracker';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { $ } from 'meteor/jquery';
|
||||
|
||||
@ -53,6 +54,19 @@ OHIF.mixins.formItem = new OHIF.Mixin({
|
||||
component.$wrapper[method]();
|
||||
};
|
||||
|
||||
// Check if the focus is inside this element
|
||||
component.hasFocus = () => {
|
||||
// Get the focused element
|
||||
const focused = $(':focus')[0];
|
||||
|
||||
// Check if the focused element is inside the component
|
||||
const contains = $.contains(component.$wrapper[0], focused);
|
||||
const isEqual = component.$wrapper[0] === focused;
|
||||
|
||||
// Return true if he component has the focus
|
||||
return contains || isEqual;
|
||||
};
|
||||
|
||||
// Add or remove a state from the component
|
||||
component.state = (state, flag) => {
|
||||
component.$wrapper.toggleClass(`state-${state}`, !!flag);
|
||||
@ -71,19 +85,50 @@ OHIF.mixins.formItem = new OHIF.Mixin({
|
||||
}
|
||||
};
|
||||
|
||||
// Toggle the state over the component
|
||||
// Toggle the tooltip over the component
|
||||
component.toggleTooltip = (isShow, message) => {
|
||||
if (isShow) {
|
||||
console.warn('>>>>message', message);
|
||||
if (isShow && message) {
|
||||
// Stop here if the tooltip is already created
|
||||
if (component.$wrapper.next('.tooltip').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the tooltip
|
||||
component.$wrapper.tooltip({
|
||||
trigger: 'manual',
|
||||
title: message
|
||||
}).tooltip('show');
|
||||
} else {
|
||||
// Destroy the tooltip
|
||||
component.$wrapper.tooltip('destroy');
|
||||
}
|
||||
};
|
||||
|
||||
// Toggle a state message as a tooltip over the component
|
||||
component.toggleMessage = isShow => {
|
||||
// Check if the action is to hide
|
||||
if (!isShow) {
|
||||
Meteor.setTimeout(() => {
|
||||
// Check if the component has the focus
|
||||
if (component.hasFocus()) {
|
||||
// Prevent the tooltip from being hidden
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide the tooltip
|
||||
component.toggleTooltip(false);
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for error state and message
|
||||
const errorMessage = component.$wrapper.attr('data-error');
|
||||
if (errorMessage) {
|
||||
// Show the tooltip with the error message
|
||||
component.toggleTooltip(true, errorMessage);
|
||||
}
|
||||
},
|
||||
|
||||
// Search for the parent form component
|
||||
component.getForm = () => {
|
||||
let currentComponent = component;
|
||||
@ -198,25 +243,31 @@ OHIF.mixins.formItem = new OHIF.Mixin({
|
||||
focus(event, instance) {
|
||||
const component = instance.component;
|
||||
|
||||
// Stop here if it is an group
|
||||
if (component.isGroup || component.isCustomFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent event bubbling
|
||||
event.stopPropagation();
|
||||
|
||||
// Check for error state and message
|
||||
const errorMessage = component.$wrapper.attr('data-error');
|
||||
if (errorMessage) {
|
||||
// Show the tooltip with the error message
|
||||
component.toggleTooltip(true, errorMessage);
|
||||
}
|
||||
// Check for state messages and show it
|
||||
component.toggleMessage(true);
|
||||
},
|
||||
|
||||
blur(event, instance) {
|
||||
const component = instance.component;
|
||||
|
||||
// Stop here if it is an group
|
||||
if (component.isGroup || component.isCustomFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent event bubbling
|
||||
event.stopPropagation();
|
||||
|
||||
// Hide any tooltips
|
||||
component.toggleTooltip(false);
|
||||
// Hide state messages
|
||||
component.toggleMessage(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -12,6 +12,9 @@ OHIF.mixins.group = new OHIF.Mixin({
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Set the group identifier flag
|
||||
component.isGroup = true;
|
||||
|
||||
// Run this computation every time the schema property is changed
|
||||
instance.autorun(() => {
|
||||
let schema = instance.data.schema;
|
||||
|
||||
@ -11,6 +11,9 @@ OHIF.mixins.select2 = new OHIF.Mixin({
|
||||
onCreated() {
|
||||
const instance = Template.instance();
|
||||
|
||||
// Set the custom focus flag
|
||||
instance.component.isCustomFocus = true;
|
||||
|
||||
// Check if this select will include a placeholder
|
||||
const placeholder = instance.data.options && instance.data.options.placeholder;
|
||||
if (placeholder) {
|
||||
@ -54,6 +57,22 @@ OHIF.mixins.select2 = new OHIF.Mixin({
|
||||
|
||||
// Store the select2 instance to allow its further destruction
|
||||
component.select2Instance = component.$element.data('select2');
|
||||
|
||||
// Get the focusable elements
|
||||
const elements = [];
|
||||
elements.push(component.$element[0]);
|
||||
elements.push(component.$element.nextAll('.select2:first').find('.select2-selection')[0]);
|
||||
|
||||
// Attach focus and blur handlers to focusable elements
|
||||
$(elements).on('focus', event => {
|
||||
event.stopPropagation();
|
||||
// Show the state message on elements focus
|
||||
component.toggleMessage(true);
|
||||
}).on('blur', event => {
|
||||
event.stopPropagation();
|
||||
// Hide the state message on elements blur
|
||||
component.toggleMessage(false);
|
||||
});
|
||||
},
|
||||
|
||||
onDestroyed() {
|
||||
@ -62,16 +81,6 @@ OHIF.mixins.select2 = new OHIF.Mixin({
|
||||
|
||||
// Destroy the select2 instance to remove unwanted DOM elements
|
||||
component.select2Instance.destroy();
|
||||
},
|
||||
|
||||
events: {
|
||||
'focusin .select2-hidden-accessible'(event, instance) {
|
||||
event.preventDefault();
|
||||
|
||||
// Redirect the focus to select2 focus control in case of hidden
|
||||
// accessible being focused (e.g. clicking on outer label)
|
||||
$(event.currentTarget).nextAll('.select2:first').find('.select2-selection').focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -59,8 +59,8 @@ export const DICOMWebServer = new SimpleSchema({
|
||||
imageRendering: {
|
||||
type: String,
|
||||
label: 'Image rendering',
|
||||
allowedValues: ['wadouri', 'orthanc'],
|
||||
valuesLabels: ['WADO URI', 'ORTHANC']
|
||||
allowedValues: ['', 'wadouri', 'orthanc'],
|
||||
valuesLabels: ['', 'WADO URI', 'ORTHANC']
|
||||
},
|
||||
qidoRoot: {
|
||||
type: String,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user