@yuneta/gobj-ui 7.6.1 → 7.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6951,26 +6951,13 @@ function create_form_field(gobj, $form, prefix, field_desc, { tag, inputType, na
6951
6951
  "",
6952
6952
  {
6953
6953
  "invalid": function(evt) {
6954
- this.classList.add("is-danger");
6955
- let $h = this.parentNode.querySelector(".help");
6956
- $h.textContent = this.validationMessage;
6957
- $h.style.display = "block";
6954
+ mark_field_validity(this);
6958
6955
  },
6959
6956
  "input": function(evt) {
6960
6957
  (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_RECORD_CHANGED", {}, gobj);
6961
6958
  },
6962
6959
  "blur": function(evt) {
6963
- if (!this.checkValidity()) {
6964
- this.classList.add("is-danger");
6965
- let $h = this.parentNode.querySelector(".help");
6966
- $h.textContent = this.validationMessage;
6967
- $h.style.display = "block";
6968
- } else {
6969
- this.classList.remove("is-danger");
6970
- let $h = this.parentNode.querySelector(".help");
6971
- $h.textContent = "";
6972
- $h.style.display = "none";
6973
- }
6960
+ mark_field_validity(this);
6974
6961
  }
6975
6962
  }
6976
6963
  ]);
@@ -7485,6 +7472,44 @@ function template2columns(gobj, columns, template, sub_elements) {
7485
7472
  return columns;
7486
7473
  }
7487
7474
  /************************************************************
7475
+ * What is wrong with a field, in the APP's language.
7476
+ *
7477
+ * `input.validationMessage` is the BROWSER's sentence in the BROWSER's
7478
+ * locale: a Spanish form on an English Firefox says "Please fill out
7479
+ * this field." and no i18n reaches it. The one case worth owning is
7480
+ * the empty required field — by far the common one — and the rest
7481
+ * falls back to the browser, whose wording for a bad pattern or an
7482
+ * out-of-range number is more precise than anything generic here.
7483
+ ************************************************************/
7484
+ function field_validation_message($input) {
7485
+ let v = $input.validity;
7486
+ if (v && v.valueMissing) return (0, i18next.t)("this field is required");
7487
+ return $input.validationMessage;
7488
+ }
7489
+ /************************************************************
7490
+ * Mark a field as wrong, or clear the mark. One place: the same
7491
+ * three lines lived in the `invalid` and `blur` handlers of every
7492
+ * field kind.
7493
+ ************************************************************/
7494
+ function mark_field_validity($input) {
7495
+ let $h = $input.parentNode ? $input.parentNode.querySelector(".help") : null;
7496
+ let v = $input.validity;
7497
+ if (!v || v.valid) {
7498
+ $input.classList.remove("is-danger");
7499
+ if ($h) {
7500
+ $h.textContent = "";
7501
+ $h.style.display = "none";
7502
+ }
7503
+ return true;
7504
+ }
7505
+ $input.classList.add("is-danger");
7506
+ if ($h) {
7507
+ $h.textContent = field_validation_message($input);
7508
+ $h.style.display = "block";
7509
+ }
7510
+ return false;
7511
+ }
7512
+ /************************************************************
7488
7513
  *
7489
7514
  ************************************************************/
7490
7515
  function validate_form(gobj, $form) {
@@ -7944,7 +7969,7 @@ function form_value_2_treedb_value(gobj, field_desc, value) {
7944
7969
  function ac_window_to_close(gobj, event, kw, src) {
7945
7970
  if ((0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "changes")) {
7946
7971
  kw.abort_close = true;
7947
- kw.warning = "All changes will be lost. Are you sure?";
7972
+ kw.warning = "all changes will be lost";
7948
7973
  }
7949
7974
  return 0;
7950
7975
  }
@@ -7971,10 +7996,16 @@ function ac_save_record(gobj, event, kw, src) {
7971
7996
  let values = get_form_values(gobj, $form);
7972
7997
  (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_SAVE_RECORD", values);
7973
7998
  set_changed_stated(gobj, false);
7974
- } else {
7975
- kw.abort_close = true;
7976
- kw.warning = "Cannot save with wrong fields";
7999
+ return 0;
8000
+ }
8001
+ try {
8002
+ $form.reportValidity();
8003
+ } catch (e) {
8004
+ (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot report the form's validity: ${e}`);
7977
8005
  }
8006
+ $form.querySelectorAll(".yui-form-data-input").forEach(($input) => {
8007
+ mark_field_validity($input);
8008
+ });
7978
8009
  return 0;
7979
8010
  }
7980
8011
  /************************************************************
@@ -17247,7 +17278,7 @@ function form_may_close(gobj) {
17247
17278
  let kw = {};
17248
17279
  (0, _yuneta_gobj_js.gobj_send_event)(priv.form, "EV_WINDOW_TO_CLOSE", kw, gobj);
17249
17280
  if (kw.abort_close) {
17250
- yui_shell_confirm_yesnocancel(yui_shell_of(gobj), "All changes will be lost. Are you sure?", {
17281
+ yui_shell_confirm_yesnocancel(yui_shell_of(gobj), kw.warning || "all changes will be lost", {
17251
17282
  t: i18next.t,
17252
17283
  yes_label: "yes",
17253
17284
  no_label: "no",
@@ -6946,26 +6946,13 @@ function create_form_field(gobj, $form, prefix, field_desc, { tag, inputType, na
6946
6946
  "",
6947
6947
  {
6948
6948
  "invalid": function(evt) {
6949
- this.classList.add("is-danger");
6950
- let $h = this.parentNode.querySelector(".help");
6951
- $h.textContent = this.validationMessage;
6952
- $h.style.display = "block";
6949
+ mark_field_validity(this);
6953
6950
  },
6954
6951
  "input": function(evt) {
6955
6952
  gobj_send_event(gobj, "EV_RECORD_CHANGED", {}, gobj);
6956
6953
  },
6957
6954
  "blur": function(evt) {
6958
- if (!this.checkValidity()) {
6959
- this.classList.add("is-danger");
6960
- let $h = this.parentNode.querySelector(".help");
6961
- $h.textContent = this.validationMessage;
6962
- $h.style.display = "block";
6963
- } else {
6964
- this.classList.remove("is-danger");
6965
- let $h = this.parentNode.querySelector(".help");
6966
- $h.textContent = "";
6967
- $h.style.display = "none";
6968
- }
6955
+ mark_field_validity(this);
6969
6956
  }
6970
6957
  }
6971
6958
  ]);
@@ -7480,6 +7467,44 @@ function template2columns(gobj, columns, template, sub_elements) {
7480
7467
  return columns;
7481
7468
  }
7482
7469
  /************************************************************
7470
+ * What is wrong with a field, in the APP's language.
7471
+ *
7472
+ * `input.validationMessage` is the BROWSER's sentence in the BROWSER's
7473
+ * locale: a Spanish form on an English Firefox says "Please fill out
7474
+ * this field." and no i18n reaches it. The one case worth owning is
7475
+ * the empty required field — by far the common one — and the rest
7476
+ * falls back to the browser, whose wording for a bad pattern or an
7477
+ * out-of-range number is more precise than anything generic here.
7478
+ ************************************************************/
7479
+ function field_validation_message($input) {
7480
+ let v = $input.validity;
7481
+ if (v && v.valueMissing) return t("this field is required");
7482
+ return $input.validationMessage;
7483
+ }
7484
+ /************************************************************
7485
+ * Mark a field as wrong, or clear the mark. One place: the same
7486
+ * three lines lived in the `invalid` and `blur` handlers of every
7487
+ * field kind.
7488
+ ************************************************************/
7489
+ function mark_field_validity($input) {
7490
+ let $h = $input.parentNode ? $input.parentNode.querySelector(".help") : null;
7491
+ let v = $input.validity;
7492
+ if (!v || v.valid) {
7493
+ $input.classList.remove("is-danger");
7494
+ if ($h) {
7495
+ $h.textContent = "";
7496
+ $h.style.display = "none";
7497
+ }
7498
+ return true;
7499
+ }
7500
+ $input.classList.add("is-danger");
7501
+ if ($h) {
7502
+ $h.textContent = field_validation_message($input);
7503
+ $h.style.display = "block";
7504
+ }
7505
+ return false;
7506
+ }
7507
+ /************************************************************
7483
7508
  *
7484
7509
  ************************************************************/
7485
7510
  function validate_form(gobj, $form) {
@@ -7939,7 +7964,7 @@ function form_value_2_treedb_value(gobj, field_desc, value) {
7939
7964
  function ac_window_to_close(gobj, event, kw, src) {
7940
7965
  if (gobj_read_bool_attr(gobj, "changes")) {
7941
7966
  kw.abort_close = true;
7942
- kw.warning = "All changes will be lost. Are you sure?";
7967
+ kw.warning = "all changes will be lost";
7943
7968
  }
7944
7969
  return 0;
7945
7970
  }
@@ -7966,10 +7991,16 @@ function ac_save_record(gobj, event, kw, src) {
7966
7991
  let values = get_form_values(gobj, $form);
7967
7992
  gobj_publish_event(gobj, "EV_SAVE_RECORD", values);
7968
7993
  set_changed_stated(gobj, false);
7969
- } else {
7970
- kw.abort_close = true;
7971
- kw.warning = "Cannot save with wrong fields";
7994
+ return 0;
7995
+ }
7996
+ try {
7997
+ $form.reportValidity();
7998
+ } catch (e) {
7999
+ log_error(`${gobj_short_name(gobj)}: cannot report the form's validity: ${e}`);
7972
8000
  }
8001
+ $form.querySelectorAll(".yui-form-data-input").forEach(($input) => {
8002
+ mark_field_validity($input);
8003
+ });
7973
8004
  return 0;
7974
8005
  }
7975
8006
  /************************************************************
@@ -17242,7 +17273,7 @@ function form_may_close(gobj) {
17242
17273
  let kw = {};
17243
17274
  gobj_send_event(priv.form, "EV_WINDOW_TO_CLOSE", kw, gobj);
17244
17275
  if (kw.abort_close) {
17245
- yui_shell_confirm_yesnocancel(yui_shell_of(gobj), "All changes will be lost. Are you sure?", {
17276
+ yui_shell_confirm_yesnocancel(yui_shell_of(gobj), kw.warning || "all changes will be lost", {
17246
17277
  t,
17247
17278
  yes_label: "yes",
17248
17279
  no_label: "no",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.6.1",
3
+ "version": "7.7.1",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
package/src/c_yui_form.js CHANGED
@@ -1168,26 +1168,13 @@ function create_form_field(
1168
1168
  }
1169
1169
  let extend = ['input', attrs, '', {
1170
1170
  'invalid': function (evt) {
1171
- this.classList.add('is-danger');
1172
- let $h = this.parentNode.querySelector('.help');
1173
- $h.textContent = this.validationMessage;
1174
- $h.style.display = 'block';
1171
+ mark_field_validity(this);
1175
1172
  },
1176
1173
  'input': function (evt) {
1177
1174
  gobj_send_event(gobj, "EV_RECORD_CHANGED", {}, gobj);
1178
1175
  },
1179
1176
  'blur': function (evt) {
1180
- if (!this.checkValidity()) {
1181
- this.classList.add('is-danger');
1182
- let $h = this.parentNode.querySelector('.help');
1183
- $h.textContent = this.validationMessage;
1184
- $h.style.display = 'block';
1185
- } else {
1186
- this.classList.remove('is-danger');
1187
- let $h = this.parentNode.querySelector('.help');
1188
- $h.textContent = '';
1189
- $h.style.display = 'none';
1190
- }
1177
+ mark_field_validity(this);
1191
1178
  }
1192
1179
  }];
1193
1180
 
@@ -1976,6 +1963,61 @@ function template2columns(gobj, columns, template, sub_elements)
1976
1963
  return columns;
1977
1964
  }
1978
1965
 
1966
+ /************************************************************
1967
+ * What is wrong with a field, in the APP's language.
1968
+ *
1969
+ * `input.validationMessage` is the BROWSER's sentence in the BROWSER's
1970
+ * locale: a Spanish form on an English Firefox says "Please fill out
1971
+ * this field." and no i18n reaches it. The one case worth owning is
1972
+ * the empty required field — by far the common one — and the rest
1973
+ * falls back to the browser, whose wording for a bad pattern or an
1974
+ * out-of-range number is more precise than anything generic here.
1975
+ ************************************************************/
1976
+ function field_validation_message($input)
1977
+ {
1978
+ let v = $input.validity;
1979
+ if(v && v.valueMissing) {
1980
+ return t("this field is required");
1981
+ }
1982
+ return $input.validationMessage;
1983
+ }
1984
+
1985
+ /************************************************************
1986
+ * Mark a field as wrong, or clear the mark. One place: the same
1987
+ * three lines lived in the `invalid` and `blur` handlers of every
1988
+ * field kind.
1989
+ ************************************************************/
1990
+ function mark_field_validity($input)
1991
+ {
1992
+ let $h = $input.parentNode? $input.parentNode.querySelector('.help') : null;
1993
+
1994
+ /* `validity.valid`, NEVER `checkValidity()`.
1995
+ *
1996
+ * checkValidity() FIRES the `invalid` event, and this function is what
1997
+ * that event's handler calls: one asks the other for ever. It cost a
1998
+ * page full of "too much recursion" the first time Save reported a bad
1999
+ * field. Reading `validity` asks the same question and fires nothing.
2000
+ * A control with no `validity` (a wrapper div) is not invalid. */
2001
+ let v = $input.validity;
2002
+ let ok = !v || v.valid;
2003
+
2004
+ if(ok) {
2005
+ $input.classList.remove('is-danger');
2006
+ if($h) {
2007
+ $h.textContent = '';
2008
+ $h.style.display = 'none';
2009
+ }
2010
+ return true;
2011
+ }
2012
+
2013
+ $input.classList.add('is-danger');
2014
+ if($h) {
2015
+ $h.textContent = field_validation_message($input);
2016
+ $h.style.display = 'block';
2017
+ }
2018
+ return false;
2019
+ }
2020
+
1979
2021
  /************************************************************
1980
2022
  *
1981
2023
  ************************************************************/
@@ -2718,7 +2760,11 @@ function ac_window_to_close(gobj, event, kw, src)
2718
2760
  {
2719
2761
  if(gobj_read_bool_attr(gobj, "changes")) {
2720
2762
  kw.abort_close = true; // Don't close the window until fields repaired
2721
- kw.warning = "All changes will be lost. Are you sure?";
2763
+ /* An i18n KEY, not a sentence: the dialog renders its message with
2764
+ * `i18n: message`. The English sentence that was here was a key
2765
+ * nobody had defined, so it rendered as itself in every language —
2766
+ * and no locale validator can see a key that travels as data. */
2767
+ kw.warning = "all changes will be lost";
2722
2768
  }
2723
2769
  return 0;
2724
2770
  }
@@ -2754,11 +2800,32 @@ function ac_save_record(gobj, event, kw, src)
2754
2800
  let values = get_form_values(gobj, $form);
2755
2801
  gobj_publish_event(gobj, "EV_SAVE_RECORD", values);
2756
2802
  set_changed_stated(gobj, false);
2803
+ return 0;
2804
+ }
2757
2805
 
2758
- } else {
2759
- kw.abort_close = true; // Don't close the window until fields repaired
2760
- kw.warning = "Cannot save with wrong fields";
2806
+ /* Pressing Save on a form with a bad field used to do NOTHING: the
2807
+ * `abort_close` / `warning` this branch set were written on the click's
2808
+ * own kw, which nobody reads that pair belongs to the close path, not
2809
+ * to this one. The button looked broken.
2810
+ *
2811
+ * reportValidity() is what the form owed the reader: it fires `invalid`
2812
+ * on EVERY bad field (so all of them get marked, not just the one last
2813
+ * touched) and puts the caret and the viewport on the first, which on a
2814
+ * long form is the difference between "it did nothing" and "it is that
2815
+ * one, up there". */
2816
+ try {
2817
+ $form.reportValidity();
2818
+ } catch(e) {
2819
+ log_error(`${gobj_short_name(gobj)}: cannot report the form's validity: ${e}`);
2761
2820
  }
2821
+
2822
+ /* reportValidity() stops at the first field the BROWSER validates, and
2823
+ * the nested tables validate themselves; mark every input we own so the
2824
+ * count of red fields is the true one. */
2825
+ $form.querySelectorAll('.yui-form-data-input').forEach(($input) => {
2826
+ mark_field_validity($input);
2827
+ });
2828
+
2762
2829
  return 0;
2763
2830
  }
2764
2831
 
@@ -1527,9 +1527,14 @@ function form_may_close(gobj)
1527
1527
  let kw = {};
1528
1528
  gobj_send_event(priv.form, "EV_WINDOW_TO_CLOSE", kw, gobj);
1529
1529
  if(kw.abort_close) {
1530
+ /* The message the FORM returned, not a copy of it. The dialog
1531
+ * takes its message as an i18n KEY, so a second literal here is
1532
+ * a second key to define — and the one that was here had never
1533
+ * been defined in any locale, which renders as the English
1534
+ * sentence itself, in every language, for ever. */
1530
1535
  yui_shell_confirm_yesnocancel(
1531
1536
  yui_shell_of(gobj),
1532
- 'All changes will be lost. Are you sure?',
1537
+ kw.warning || "all changes will be lost",
1533
1538
  {t: t, yes_label: "yes", no_label: "no", cancel_label: "cancel"}
1534
1539
  ).then(function(answer) {
1535
1540
  if(answer === "yes" && priv.form_modal) {