Commit 0747c524 authored by Gabriel Monnerat's avatar Gabriel Monnerat Committed by Romain Courteaud

erp5_web_renderjs_ui: Improve fields to propagate error_text

* change the label field to not display the error text by default
* change all html5 fields (input, select, textarea) to add a custom *invalid* class when the field is invalid
* change all html5 fields to listen to the `focus` and `blur` event (with the renderjs onEvent method)
  Then, acquire (with `declareAcquiredMethod`) and call `notifyFocus` / `notifyBlur` methods respectively.
* change the label field to handle `notifyFocus` / `notifyBlur` (with `allowPublicAcquisition`).
  Change the validation error text display state depending on the field status
* Trigger onStateChange to set invalid class. If error comes from input field, we need to change state locally to set invalid class
* Regenerate gadget_erp5_nojqm.css from  erp5less.css using http://lesscss.org/less-preview/
parent 3aea11b9
...@@ -220,7 +220,7 @@ ...@@ -220,7 +220,7 @@
</item> </item>
<item> <item>
<key> <string>actor</string> </key> <key> <string>actor</string> </key>
<value> <string>zope</string> </value> <value> <string>ERP5TypeTestCase</string> </value>
</item> </item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1583764359.91</float> <float>1597709775.0</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
name: field_json.key, name: field_json.key,
key: field_json.key, key: field_json.key,
title: field_json.title, title: field_json.title,
error_text: field_json.error_text,
timezone_style: field_json.timezone_style, timezone_style: field_json.timezone_style,
date_only: field_json.date_only, date_only: field_json.date_only,
hide_day: field_json.hide_day, hide_day: field_json.hide_day,
...@@ -112,7 +113,8 @@ ...@@ -112,7 +113,8 @@
editable: gadget.state.editable, editable: gadget.state.editable,
required: gadget.state.required, required: gadget.state.required,
type: gadget.state.date_only ? "date" : "datetime-local", type: gadget.state.date_only ? "date" : "datetime-local",
hidden: gadget.state.hidden hidden: gadget.state.hidden,
error_text: modification_dict.error_text
}, },
select_state = { select_state = {
name: gadget.state.key + '_select', name: gadget.state.key + '_select',
...@@ -120,7 +122,8 @@ ...@@ -120,7 +122,8 @@
item_list: ZONE_LIST, item_list: ZONE_LIST,
editable: gadget.state.editable, editable: gadget.state.editable,
required: gadget.state.required, required: gadget.state.required,
hidden: gadget.state.hidden hidden: gadget.state.hidden,
error_text: modification_dict.error_text
// name: field_json.key, // name: field_json.key,
// title: field_json.title // title: field_json.title
}, },
......
...@@ -228,7 +228,7 @@ ...@@ -228,7 +228,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>983.56055.11203.16827</string> </value> <value> <string>986.51894.21525.38502</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -246,8 +246,8 @@ ...@@ -246,8 +246,8 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1589358221.58</float> <float>1600894302.31</float>
<string>GMT+0</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
</object> </object>
......
...@@ -240,7 +240,7 @@ ...@@ -240,7 +240,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>969.56695.26145.14506</string> </value> <value> <string>985.61208.29353.29986</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -258,7 +258,7 @@ ...@@ -258,7 +258,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1535383243.32</float> <float>1597610604.97</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>965.241.13759.3805</string> </value> <value> <string>985.61208.29353.29986</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1517321664.03</float> <float>1597610628.93</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -220,7 +220,7 @@ ...@@ -220,7 +220,7 @@
</item> </item>
<item> <item>
<key> <string>actor</string> </key> <key> <string>actor</string> </key>
<value> <string>superkato</string> </value> <value> <string>zope</string> </value>
</item> </item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>967.35221.49309.22852</string> </value> <value> <string>985.61208.29353.29986</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1526316882.68</float> <float>1597610664.04</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>983.13203.65355.60228</string> </value> <value> <string>985.61208.29353.29986</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1586873574.82</float> <float>1597610645.53</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
name: field_json.key, name: field_json.key,
title: field_json.title, title: field_json.title,
precision: window.parseFloat(field_json.precision), precision: window.parseFloat(field_json.precision),
error_text: field_json.error_text || "",
// erp5 always put value into "default" (never "value") // erp5 always put value into "default" (never "value")
value: window.parseFloat(field_json.default), value: window.parseFloat(field_json.default),
text_content: '', text_content: '',
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>983.35869.13162.60928</string> </value> <value> <string>986.14570.51196.18756</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,8 +252,8 @@ ...@@ -252,8 +252,8 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1599097800.89</float> <float>1598579261.92</float>
<string>GMT+2</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
</object> </object>
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>970.5118.62758.3362</string> </value> <value> <string>986.41646.43198.36846</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1536223691.31</float> <float>1600363167.27</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
editable: field_json.editable, editable: field_json.editable,
required: field_json.required, required: field_json.required,
id: field_json.key, id: field_json.key,
error_text: options.field_json.error_text || "",
name: field_json.key, name: field_json.key,
title: field_json.title, title: field_json.title,
hidden: field_json.hidden, hidden: field_json.hidden,
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>965.12118.35525.1655</string> </value> <value> <string>986.11537.50394.34935</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1517930232.43</float> <float>1598397556.71</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*global window, document, rJS */ /*global window, document, rJS*/
/*jslint indent: 2, maxerr: 3 */ /*jslint indent: 2, maxerr: 3 */
/** /**
* Label gadget takes care of displaying validation errors and label. * Label gadget takes care of displaying validation errors and label.
...@@ -80,6 +80,7 @@ ...@@ -80,6 +80,7 @@
error_text: '', error_text: '',
label: true, // the label element is already present in the HTML template label: true, // the label element is already present in the HTML template
css_class: '', css_class: '',
display_error_text: false,
first_call: false first_call: false
}) })
...@@ -101,6 +102,7 @@ ...@@ -101,6 +102,7 @@
state_dict.label = true; state_dict.label = true;
} }
return this.changeState(state_dict); return this.changeState(state_dict);
}) })
.onStateChange(function onStateChange(modification_dict) { .onStateChange(function onStateChange(modification_dict) {
...@@ -110,15 +112,13 @@ ...@@ -110,15 +112,13 @@
i, i,
queue, queue,
new_div; new_div;
if (modification_dict.hasOwnProperty('first_call')) { if (modification_dict.hasOwnProperty('first_call')) {
gadget.props = { gadget.props = {
container_element: gadget.element.querySelector('div'), container_element: gadget.element.querySelector('div'),
label_element: gadget.element.querySelector('label') label_element: gadget.element.querySelector('label')
}; };
} }
if (gadget.state.hidden && !gadget.state.error_text) {
if (gadget.state.hidden && !modification_dict.error_text) {
this.element.hidden = true; this.element.hidden = true;
} else { } else {
this.element.hidden = false; this.element.hidden = false;
...@@ -136,14 +136,23 @@ ...@@ -136,14 +136,23 @@
} }
} }
if (modification_dict.hasOwnProperty('error_text')) { // Remove/add label_element from DOM
if (modification_dict.hasOwnProperty('label')) {
if (this.state.label === true) {
this.props.container_element.insertBefore(this.props.label_element, this.props.container_element.firstChild);
} else {
this.props.container_element.removeChild(this.props.label_element);
}
}
if (modification_dict.hasOwnProperty('display_error_text') || modification_dict.hasOwnProperty('error_text')) {
// first remove old errors // first remove old errors
span = this.props.container_element.lastElementChild; span = this.props.container_element.lastElementChild;
if ((span !== null) && (span.tagName.toLowerCase() !== 'span')) { if ((span !== null) && (span.tagName.toLowerCase() !== 'span')) {
span = null; span = null;
} }
// display new error if present // display new error if present
if (this.state.error_text) { if (this.state.error_text && this.state.display_error_text) {
if (span === null) { if (span === null) {
span = document.createElement('span'); span = document.createElement('span');
span.textContent = this.state.error_text; span.textContent = this.state.error_text;
...@@ -151,17 +160,10 @@ ...@@ -151,17 +160,10 @@
} else { } else {
span.textContent = this.state.error_text; span.textContent = this.state.error_text;
} }
} else if (span !== null) {
this.props.container_element.removeChild(span);
}
}
// Remove/add label_element from DOM
if (modification_dict.hasOwnProperty('label')) {
if (this.state.label === true) {
this.props.container_element.insertBefore(this.props.label_element, this.props.container_element.firstChild);
} else { } else {
this.props.container_element.removeChild(this.props.label_element); if (span !== null) {
this.props.container_element.removeChild(span);
}
} }
} }
...@@ -199,6 +201,7 @@ ...@@ -199,6 +201,7 @@
}); });
} }
} }
}) })
.declareMethod("checkValidity", function checkValidity() { .declareMethod("checkValidity", function checkValidity() {
...@@ -231,6 +234,14 @@ ...@@ -231,6 +234,14 @@
}); });
}, {mutex: 'changestate'}) }, {mutex: 'changestate'})
.allowPublicAcquisition("notifyFocus", function notifyFocus() {
return this.changeState({display_error_text: true});
})
.allowPublicAcquisition("notifyBlur", function notifyBlur() {
return this.changeState({display_error_text: false});
})
.allowPublicAcquisition("notifyInvalid", function notifyInvalid(param_list) { .allowPublicAcquisition("notifyInvalid", function notifyInvalid(param_list) {
// Label doesn't know when a subgadget calls notifyInvalid // Label doesn't know when a subgadget calls notifyInvalid
// Prevent mutex dead lock by defering the changeState call // Prevent mutex dead lock by defering the changeState call
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>984.41193.2075.29252</string> </value> <value> <string>986.60444.45045.17527</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1596116391.77</float> <float>1601331703.32</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>964.58561.19908.14080</string> </value> <value> <string>985.61208.29353.29986</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1517321571.05</float> <float>1597610715.85</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
title: field_json.title, title: field_json.title,
first_item: field_json.first_item, first_item: field_json.first_item,
hidden: field_json.hidden, hidden: field_json.hidden,
error_text: field_json.error_text || "",
// Force calling subfield render // Force calling subfield render
// as user may have modified the input value // as user may have modified the input value
render_timestamp: new Date().getTime() render_timestamp: new Date().getTime()
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>979.41914.53909.44561</string> </value> <value> <string>986.42821.5680.17442</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1573126833.72</float> <float>1600275350.99</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -52,14 +52,20 @@ ...@@ -52,14 +52,20 @@
} }
rJS(window) rJS(window)
.setState({
display_error_text: false
})
.ready(function ready() {
this.props = {};
})
.declareMethod('render', function (options) { .declareMethod('render', function (options) {
var field_json = options.field_json || {}, var field_json = options.field_json || {},
state_dict = { state_dict = {
editable: field_json.editable, editable: field_json.editable,
name: field_json.key, name: field_json.key,
item_list: field_json.items, item_list: field_json.items,
value_list: field_json.value || field_json.default, value_list: field_json.value || field_json["default"],
error_text: field_json.error_text,
hidden: field_json.hidden, hidden: field_json.hidden,
// Force calling subfield render // Force calling subfield render
// as user may have modified the input value // as user may have modified the input value
...@@ -69,15 +75,22 @@ ...@@ -69,15 +75,22 @@
return this.changeState(state_dict); return this.changeState(state_dict);
}) })
.onStateChange(function () { .onStateChange(function (modification_dict) {
var element = this.element, var element = this.element,
gadget = this, gadget = this,
value_list = this.state.value_list, value_list = this.state.value_list,
value_dict = {}, value_dict = {},
item_list = this.state.item_list, item_list = this.state.item_list,
i, i,
span,
queue; queue;
if (!gadget.props.container_element) {
gadget.props = {
container_element: gadget.element.querySelector('div'),
label_element: gadget.element.querySelector('label')
};
}
// Clear first to DOM, append after to reduce flickering/manip // Clear first to DOM, append after to reduce flickering/manip
while (element.firstChild) { while (element.firstChild) {
element.removeChild(element.firstChild); element.removeChild(element.firstChild);
...@@ -87,6 +100,28 @@ ...@@ -87,6 +100,28 @@
value_dict[value_list[i]] = null; value_dict[value_list[i]] = null;
} }
if (modification_dict.hasOwnProperty('display_error_text')) {
// first remove old errors
span = this.props.container_element.lastElementChild;
if ((span !== null) && (span.tagName.toLowerCase() !== 'span')) {
span = null;
}
// display new error if present
if (this.state.error_text && this.state.display_error_text) {
if (span === null) {
span = document.createElement('span');
span.textContent = this.state.error_text;
this.props.container_element.appendChild(span);
} else {
span.textContent = this.state.error_text;
}
} else {
if (span !== null) {
this.props.container_element.removeChild(span);
}
}
}
function enQueue() { function enQueue() {
var argument_list = arguments; var argument_list = arguments;
queue queue
...@@ -148,6 +183,18 @@ ...@@ -148,6 +183,18 @@
return final_result; return final_result;
}, {mutex: 'changestate'}) }, {mutex: 'changestate'})
.allowPublicAcquisition("notifyFocus", function notifyFocus() {
if (this.state.error_text) {
return this.changeState({display_error_text: true});
}
})
.allowPublicAcquisition("notifyBlur", function notifyBlur() {
if (this.state.error_text) {
return this.changeState({display_error_text: false});
}
})
.declareMethod('checkValidity', function () { .declareMethod('checkValidity', function () {
var name = this.state.name; var name = this.state.name;
if (this.state.editable && this.state.required) { if (this.state.editable && this.state.required) {
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>971.50596.31143.27050</string> </value> <value> <string>986.54583.57508.4539</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1542818919.2</float> <float>1600980241.43</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>976.44236.22845.43076</string> </value> <value> <string>985.61208.29353.29986</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1561643243.53</float> <float>1597610832.8</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -329,12 +329,18 @@ select:focus { ...@@ -329,12 +329,18 @@ select:focus {
} }
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]):invalid, input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]):invalid,
textarea:invalid, textarea:invalid,
select:invalid { select:invalid,
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]).is-invalid,
textarea.is-invalid,
select.is-invalid {
border: 1px solid #FF6600; border: 1px solid #FF6600;
} }
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]):invalid:focus, input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]):invalid:focus,
textarea:invalid:focus, textarea:invalid:focus,
select:invalid:focus { select:invalid:focus,
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]).is-invalid:focus,
textarea.is-invalid:focus,
select.is-invalid:focus {
box-shadow: 0 0 12pt #FF6600; box-shadow: 0 0 12pt #FF6600;
} }
input[type="search"] { input[type="search"] {
...@@ -3264,4 +3270,4 @@ hmtl .ui-icon-carat-u::before { ...@@ -3264,4 +3270,4 @@ hmtl .ui-icon-carat-u::before {
} }
.ui-icon-clone::before { .ui-icon-clone::before {
content: "\f24d"; content: "\f24d";
} }
\ No newline at end of file
...@@ -75,9 +75,7 @@ ...@@ -75,9 +75,7 @@
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>content_type</string> </key>
<value> <value> <string>text/css</string> </value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
...@@ -246,7 +244,7 @@ ...@@ -246,7 +244,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>986.53918.32237.3225</string> </value> <value> <string>986.41601.40161.17629</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -264,7 +262,7 @@ ...@@ -264,7 +262,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1600941690.9</float> <float>1601474815.27</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>965.12118.35525.1655</string> </value> <value> <string>985.61208.29353.29986</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1517929207.17</float> <float>1597610855.52</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>979.2796.18260.40345</string> </value> <value> <string>986.41601.40161.17629</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1570779670.8</float> <float>1600363560.34</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -149,6 +149,7 @@ ...@@ -149,6 +149,7 @@
key: options.key, key: options.key,
view: options.view, view: options.view,
search_view: options.search_view, search_view: options.search_view,
error_text: options.error_text || "",
url: options.url, url: options.url,
allow_creation: options.allow_creation, allow_creation: options.allow_creation,
portal_types: JSON.stringify(options.portal_types), portal_types: JSON.stringify(options.portal_types),
...@@ -231,8 +232,19 @@ ...@@ -231,8 +232,19 @@
// First display of the input // First display of the input
buildEditableInputHTML(gadget); buildEditableInputHTML(gadget);
} }
input = gadget.element.querySelector("input"); input = gadget.element.querySelector("input");
if (gadget.state.error_text &&
!input.classList.contains("is-invalid")) {
input.classList.add("is-invalid");
} else if (
// value_portal_type not empty means that user
// wants to create a Document
(!gadget.state.error_text || gadget.state.value_portal_type) &&
input.classList.contains("is-invalid")
) {
input.classList.remove("is-invalid");
}
if (modification_dict.hasOwnProperty("value_text")) { if (modification_dict.hasOwnProperty("value_text")) {
input.value = gadget.state.value_text; input.value = gadget.state.value_text;
} }
...@@ -417,6 +429,14 @@ ...@@ -417,6 +429,14 @@
"Invalid Search Criteria" "Invalid Search Criteria"
]) ])
.push(function (translation_list) { .push(function (translation_list) {
if (gadget.state.error_text !== translation_list[0]) {
// Avoid call deferErrorText if error_text is already set
// Otherwise, onStateChange will run forever
return RSVP.all([
gadget.deferErrorText(translation_list[0]),
gadget.notifyInvalid(translation_list[0])
]);
}
return gadget.notifyInvalid(translation_list[0]); return gadget.notifyInvalid(translation_list[0]);
}); });
} }
...@@ -429,9 +449,25 @@ ...@@ -429,9 +449,25 @@
]) ])
.push(function (translation_list) { .push(function (translation_list) {
if (error.target.status === 0) { if (error.target.status === 0) {
if (gadget.state.error_text !== translation_list[0]) {
// Avoid call deferErrorText if error_text is already
// set. Otherwise, onStateChange will run forever
return RSVP.all([
gadget.deferErrorText(translation_list[0]),
gadget.notifyInvalid(translation_list[0])
]);
}
return gadget.notifyInvalid(translation_list[0]); return gadget.notifyInvalid(translation_list[0]);
} }
if (error.target.status >= 500) { if (error.target.status >= 500) {
if (gadget.state.error_text !== translation_list[0]) {
// Avoid call deferErrorText if error_text is already
// set. Otherwise, onStateChange will run forever
return RSVP.all([
gadget.deferErrorText(translation_list[1]),
gadget.notifyInvalid(translation_list[1])
]);
}
return gadget.notifyInvalid(translation_list[1]); return gadget.notifyInvalid(translation_list[1]);
} }
throw error; throw error;
...@@ -513,6 +549,7 @@ ...@@ -513,6 +549,7 @@
} }
}, false, false) }, false, false)
.declareAcquiredMethod("notifyBlur", "notifyBlur")
.onEvent('blur', function (evt) { .onEvent('blur', function (evt) {
var gadget = this; var gadget = this;
if (evt.target.tagName.toLowerCase() === 'input') { if (evt.target.tagName.toLowerCase() === 'input') {
...@@ -525,22 +562,27 @@ ...@@ -525,22 +562,27 @@
return gadget.changeState({ return gadget.changeState({
has_focus: false has_focus: false
}); });
})
.push(function () {
return gadget.notifyBlur();
}); });
} }
}, true, false) }, true, false)
.declareAcquiredMethod("notifyFocus", "notifyFocus")
.onEvent('focus', function (evt) { .onEvent('focus', function (evt) {
var gadget = this; var gadget = this;
if (evt.target.tagName.toLowerCase() === 'input') { if (evt.target.tagName.toLowerCase() === 'input') {
return gadget.changeState({ return RSVP.all([
has_focus: true gadget.notifyFocus(),
}); gadget.changeState({has_focus: true})
]);
} }
}, true, false) }, true, false)
.declareAcquiredMethod("notifyValid", "notifyValid")
.declareMethod('checkValidity', function () { .declareMethod('checkValidity', function () {
var gadget = this; var gadget = this;
if ((this.state.value_text) && ( if ((this.state.value_text) && (
(this.state.value_relative_url === null) && (this.state.value_relative_url === null) &&
(this.state.value_uid === null) && (this.state.value_uid === null) &&
...@@ -548,43 +590,64 @@ ...@@ -548,43 +590,64 @@
)) { )) {
return gadget.translate("No such document was found") return gadget.translate("No such document was found")
.push(function (error_message) { .push(function (error_message) {
return gadget.notifyInvalid(error_message); return RSVP.all([
gadget.deferErrorText(error_message),
gadget.notifyInvalid(error_message)
]);
}) })
.push(function () { .push(function () {
return false; return false;
}); });
} }
return true; return gadget.notifyValid()
.push(function () {
return true;
});
}, {mutex: 'changestate'}) }, {mutex: 'changestate'})
.declareJob('deferErrorText', function deferErrorText(error_text) {
return this.changeState({
error_text: error_text
});
})
// XXX Use html5 input // XXX Use html5 input
.onEvent('invalid', function (evt) { .onEvent('invalid', function (evt) {
// invalid event does not bubble // invalid event does not bubble
return this.notifyInvalid(evt.target.validationMessage); return RSVP.all([
this.deferErrorText(evt.target.validationMessage),
this.notifyInvalid(evt.target.validationMessage)
]);
}, true, false) }, true, false)
.onEvent('change', function () { .onEvent('change', function () {
return this.notifyChange(); return RSVP.all([
this.checkValidity(),
this.notifyChange()
]);
}, false, false) }, false, false)
.onEvent('input', function (event) { .onEvent('input', function (event) {
var gadget = this;
if (!this.state.editable) { if (!this.state.editable) {
return; return;
} }
var context = this;
return this.changeState({ return this.changeState({
value_text: event.target.value, value_text: event.target.value,
value_relative_url: null, value_relative_url: null,
value_uid: null, value_uid: null,
value_portal_type: null, value_portal_type: null,
has_focus: true has_focus: true,
error_text: ""
}) })
.push(function () { .push(function () {
return context.notifyChange(); return RSVP.all([
gadget.notifyValid(),
gadget.notifyChange()
]);
}); });
}, true, false); }, true, false);
}(window, rJS, RSVP, URI, document, }(window, rJS, RSVP, URI, document,
SimpleQuery, ComplexQuery, Query, QueryFactory, XMLHttpRequest, console)); SimpleQuery, ComplexQuery, Query, QueryFactory, XMLHttpRequest, console));
\ No newline at end of file
...@@ -69,9 +69,7 @@ ...@@ -69,9 +69,7 @@
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>content_type</string> </key>
<value> <value> <string>text/javascript</string> </value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
...@@ -240,7 +238,7 @@ ...@@ -240,7 +238,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>983.6083.54777.37051</string> </value> <value> <string>986.61480.35990.11093</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -258,7 +256,7 @@ ...@@ -258,7 +256,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1586446542.77</float> <float>1601395258.9</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
title: field_json.title, title: field_json.title,
key: field_json.key, key: field_json.key,
view: field_json.view, view: field_json.view,
error_text: field_json.error_text,
search_view: field_json.search_view, search_view: field_json.search_view,
url: field_json.url, url: field_json.url,
allow_creation: field_json.allow_creation, allow_creation: field_json.allow_creation,
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>970.13790.51027.29644</string> </value> <value> <string>986.41646.43198.36846</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1539872919.1</float> <float>1600685092.05</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -210,6 +210,9 @@ ...@@ -210,6 +210,9 @@
}); });
}, {mutex: 'changestate'}) }, {mutex: 'changestate'})
.allowPublicAcquisition("notifyFocus", function notifyFocus() {})
.allowPublicAcquisition("notifyBlur", function notifyBlur() {})
.declareAcquiredMethod("triggerSubmit", "triggerSubmit") .declareAcquiredMethod("triggerSubmit", "triggerSubmit")
.onEvent('click', function (evt) { .onEvent('click', function (evt) {
if ((evt.target.nodeType === Node.ELEMENT_NODE) && if ((evt.target.nodeType === Node.ELEMENT_NODE) &&
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>969.37531.32072.23688</string> </value> <value> <string>985.45375.12940.10598</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1536936754.19</float> <float>1597428338.32</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*global window, rJS */ /*global window, document, rJS */
/*jslint indent: 2, maxerr: 3 */ /*jslint indent: 2, maxerr: 3 */
(function (window, rJS) { (function (window, document, rJS) {
"use strict"; "use strict";
rJS(window) rJS(window)
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
required: field_json.required, required: field_json.required,
id: field_json.key, id: field_json.key,
name: field_json.key, name: field_json.key,
error_text: field_json.error_text || "",
title: field_json.title, title: field_json.title,
hidden: field_json.hidden, hidden: field_json.hidden,
trim: true, trim: true,
...@@ -72,4 +73,4 @@ ...@@ -72,4 +73,4 @@
return true; return true;
}, {mutex: 'changestate'}); }, {mutex: 'changestate'});
}(window, rJS)); }(window, document, rJS));
\ No newline at end of file \ No newline at end of file
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>965.41976.11439.18449</string> </value> <value> <string>986.42689.22481.46592</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1526396915.47</float> <float>1600380471.64</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
editable: field_json.editable, editable: field_json.editable,
name: field_json.key, name: field_json.key,
id: field_json.key, id: field_json.key,
error_text: field_json.error_text,
title: field_json.title, title: field_json.title,
hidden: field_json.hidden, hidden: field_json.hidden,
// Force calling subfield render // Force calling subfield render
......
...@@ -240,7 +240,7 @@ ...@@ -240,7 +240,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>965.12118.35525.1655</string> </value> <value> <string>986.42841.34859.34594</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -258,7 +258,7 @@ ...@@ -258,7 +258,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1517927278.74</float> <float>1600277966.0</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -96,6 +96,17 @@ ...@@ -96,6 +96,17 @@
} }
return data; return data;
}) })
.declareAcquiredMethod("notifyFocus", "notifyFocus")
.onEvent('focus', function focus(evt) {
return this.notifyFocus();
}, true, false)
.declareAcquiredMethod("notifyBlur", "notifyBlur")
.onEvent('blur', function blur(evt) {
return this.notifyBlur();
}, true, false)
.declareMethod("checkValidity", function checkValidity() { .declareMethod("checkValidity", function checkValidity() {
return true; return true;
}); });
......
...@@ -228,7 +228,7 @@ ...@@ -228,7 +228,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>982.42532.14902.56951</string> </value> <value> <string>985.61208.29353.29986</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -246,7 +246,7 @@ ...@@ -246,7 +246,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1584701796.37</float> <float>1597615378.38</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
type: options.type || 'text', type: options.type || 'text',
title: options.title, title: options.title,
focus: options.focus, focus: options.focus,
error_text: options.error_text || "",
step: options.step, step: options.step,
hidden: options.hidden, hidden: options.hidden,
trim: options.trim || false, trim: options.trim || false,
...@@ -43,13 +44,13 @@ ...@@ -43,13 +44,13 @@
.onStateChange(function onStateChange(modification_dict) { .onStateChange(function onStateChange(modification_dict) {
var textarea = this.element.querySelector('input'), var textarea = this.element.querySelector('input'),
tmp; // general use short-scope variable tmp; // general use short-scope variable
if (this.state.type === 'checkbox') { if (this.state.type === 'checkbox') {
textarea.checked = this.state.checked; textarea.checked = this.state.checked;
} else { } else {
textarea.setAttribute('value', this.state.value); textarea.setAttribute('value', this.state.value);
textarea.value = this.state.value; textarea.value = this.state.value;
} }
if (this.state.type === 'radio') { if (this.state.type === 'radio') {
textarea.checked = this.state.checked; textarea.checked = this.state.checked;
} }
...@@ -86,7 +87,7 @@ ...@@ -86,7 +87,7 @@
textarea.readonly = false; textarea.readonly = false;
} }
if (this.state.hidden) { if (this.state.hidden && !modification_dict.error_text) {
textarea.hidden = true; textarea.hidden = true;
} else { } else {
textarea.hidden = false; textarea.hidden = false;
...@@ -117,6 +118,15 @@ ...@@ -117,6 +118,15 @@
this.element.insertBefore(tmp, textarea); this.element.insertBefore(tmp, textarea);
tmp = undefined; tmp = undefined;
} }
if (this.state.error_text &&
!textarea.classList.contains("is-invalid")) {
textarea.classList.add("is-invalid");
} else if (!this.state.error_text &&
textarea.classList.contains("is-invalid")) {
textarea.classList.remove("is-invalid");
}
}) })
.declareService(function focus() { .declareService(function focus() {
...@@ -194,7 +204,10 @@ ...@@ -194,7 +204,10 @@
if (isNaN(date)) { if (isNaN(date)) {
return gadget.translate("Invalid DateTime") return gadget.translate("Invalid DateTime")
.push(function (error_message) { .push(function (error_message) {
return gadget.notifyInvalid(error_message); return RSVP.all([
gadget.deferErrorText(error_message),
gadget.notifyInvalid(error_message)
]);
}) })
.push(function () { .push(function () {
return false; return false;
...@@ -208,6 +221,14 @@ ...@@ -208,6 +221,14 @@
return result; return result;
}, {mutex: 'changestate'}) }, {mutex: 'changestate'})
.declareJob('deferErrorText', function deferErrorText(error_text) {
var input = this.element.querySelector("input");
return this.changeState({
value: input.value,
error_text: error_text
});
})
.declareAcquiredMethod("notifyChange", "notifyChange") .declareAcquiredMethod("notifyChange", "notifyChange")
.onEvent('change', function change() { .onEvent('change', function change() {
return RSVP.all([ return RSVP.all([
...@@ -215,6 +236,7 @@ ...@@ -215,6 +236,7 @@
this.notifyChange("change") this.notifyChange("change")
]); ]);
}, false, false) }, false, false)
.onEvent('input', function input() { .onEvent('input', function input() {
return RSVP.all([ return RSVP.all([
this.checkValidity(), this.checkValidity(),
...@@ -222,10 +244,23 @@ ...@@ -222,10 +244,23 @@
]); ]);
}, false, false) }, false, false)
.declareAcquiredMethod("notifyFocus", "notifyFocus")
.onEvent('focus', function focus() {
return this.notifyFocus();
}, true, false)
.declareAcquiredMethod("notifyBlur", "notifyBlur")
.onEvent('blur', function blur() {
return this.notifyBlur();
}, true, false)
.declareAcquiredMethod("notifyInvalid", "notifyInvalid") .declareAcquiredMethod("notifyInvalid", "notifyInvalid")
.onEvent('invalid', function invalid(evt) { .onEvent('invalid', function invalid(evt) {
// invalid event does not bubble // invalid event does not bubble
return this.notifyInvalid(evt.target.validationMessage); return RSVP.all([
this.deferErrorText(evt.target.validationMessage),
this.notifyInvalid(evt.target.validationMessage)
]);
}, true, false); }, true, false);
}(window, document, rJS, RSVP, jIO, getFirstNonEmpty)); }(window, document, rJS, RSVP, jIO, getFirstNonEmpty));
\ No newline at end of file
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>967.40700.16743.2833</string> </value> <value> <string>986.63389.32983.19234</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1526653024.9</float> <float>1601508986.01</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
item_list: JSON.stringify(options.item_list), item_list: JSON.stringify(options.item_list),
editable: options.editable, editable: options.editable,
required: options.required, required: options.required,
error_text: options.error_text || "",
id: options.id, id: options.id,
name: options.name, name: options.name,
title: options.title, title: options.title,
...@@ -41,6 +42,13 @@ ...@@ -41,6 +42,13 @@
select.id = this.state.id || this.state.name; select.id = this.state.id || this.state.name;
select.setAttribute('name', this.state.name); select.setAttribute('name', this.state.name);
if (modification_dict.error_text &&
!select.classList.contains("is-invalid")) {
select.classList.add("is-invalid");
} else if (select.classList.contains("is-invalid")) {
select.classList.remove("is-invalid");
}
if (this.state.title) { if (this.state.title) {
select.setAttribute('title', this.state.title); select.setAttribute('title', this.state.title);
} }
...@@ -118,7 +126,8 @@ ...@@ -118,7 +126,8 @@
.declareAcquiredMethod("notifyValid", "notifyValid") .declareAcquiredMethod("notifyValid", "notifyValid")
.declareMethod('checkValidity', function checkValidity() { .declareMethod('checkValidity', function checkValidity() {
var result = this.element.querySelector('select').checkValidity(); var select = this.element.querySelector('select'),
result = select.checkValidity() || this.state.error_text === "";
if (result) { if (result) {
return this.notifyValid() return this.notifyValid()
.push(function () { .push(function () {
...@@ -142,6 +151,16 @@ ...@@ -142,6 +151,16 @@
]); ]);
}, false, false) }, false, false)
.declareAcquiredMethod("notifyFocus", "notifyFocus")
.onEvent('focus', function focus() {
return this.notifyFocus();
}, true, false)
.declareAcquiredMethod("notifyBlur", "notifyBlur")
.onEvent('blur', function blur() {
return this.notifyBlur();
}, true, false)
.declareAcquiredMethod("notifyInvalid", "notifyInvalid") .declareAcquiredMethod("notifyInvalid", "notifyInvalid")
.onEvent('invalid', function invalid(evt) { .onEvent('invalid', function invalid(evt) {
// invalid event does not bubble // invalid event does not bubble
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>978.42847.9438.64699</string> </value> <value> <string>986.42836.14245.5444</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1569589427.71</float> <float>1600275334.01</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -24,6 +24,14 @@ ...@@ -24,6 +24,14 @@
.onStateChange(function onStateChange(modification_dict) { .onStateChange(function onStateChange(modification_dict) {
var textarea = this.element.querySelector('textarea'); var textarea = this.element.querySelector('textarea');
if (this.state.error_text &&
!textarea.classList.contains("is-invalid")) {
textarea.classList.add("is-invalid");
} else if (!this.state.error_text &&
textarea.classList.contains("is-invalid")) {
textarea.classList.remove("is-invalid");
}
if (modification_dict.hasOwnProperty("value")) { if (modification_dict.hasOwnProperty("value")) {
textarea.value = modification_dict.value; textarea.value = modification_dict.value;
} }
...@@ -74,7 +82,8 @@ ...@@ -74,7 +82,8 @@
.declareAcquiredMethod("notifyValid", "notifyValid") .declareAcquiredMethod("notifyValid", "notifyValid")
.declareMethod('checkValidity', function checkValidity() { .declareMethod('checkValidity', function checkValidity() {
var result = this.element.querySelector('textarea').checkValidity(); var textarea = this.element.querySelector('textarea'),
result = textarea.checkValidity();
if (result) { if (result) {
return this.notifyValid() return this.notifyValid()
.push(function () { .push(function () {
...@@ -94,6 +103,16 @@ ...@@ -94,6 +103,16 @@
return this.notifyInvalid(evt.target.validationMessage); return this.notifyInvalid(evt.target.validationMessage);
}, true, true) }, true, true)
.declareAcquiredMethod("notifyFocus", "notifyFocus")
.onEvent('focus', function focus() {
return this.notifyFocus();
}, true, false)
.declareAcquiredMethod("notifyBlur", "notifyBlur")
.onEvent('blur', function blur() {
return this.notifyBlur();
}, true, false)
.declareAcquiredMethod("notifySubmit", "notifySubmit") .declareAcquiredMethod("notifySubmit", "notifySubmit")
.onEvent('keydown', function keydown(evt) { .onEvent('keydown', function keydown(evt) {
var textarea = this.element.querySelector('textarea'); var textarea = this.element.querySelector('textarea');
......
...@@ -240,7 +240,7 @@ ...@@ -240,7 +240,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>966.49875.42877.4590</string> </value> <value> <string>986.62926.53764.37222</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -258,7 +258,7 @@ ...@@ -258,7 +258,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1526653198.19</float> <float>1601505155.98</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -434,7 +434,7 @@ input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]) ...@@ -434,7 +434,7 @@ input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio])
border: @focus-border; border: @focus-border;
box-shadow: @focus-box-shadow; box-shadow: @focus-box-shadow;
} }
&:invalid { &:invalid, &.is-invalid {
border: @invalid-border; border: @invalid-border;
&:focus { &:focus {
box-shadow: @invalid-box-shadow; box-shadow: @invalid-box-shadow;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment