@yuneta/gobj-ui 7.6.1 → 7.7.0

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,49 @@ 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 ok = true;
7497
+ try {
7498
+ ok = $input.checkValidity();
7499
+ } catch (e) {
7500
+ ok = true;
7501
+ }
7502
+ if (ok) {
7503
+ $input.classList.remove("is-danger");
7504
+ if ($h) {
7505
+ $h.textContent = "";
7506
+ $h.style.display = "none";
7507
+ }
7508
+ return true;
7509
+ }
7510
+ $input.classList.add("is-danger");
7511
+ if ($h) {
7512
+ $h.textContent = field_validation_message($input);
7513
+ $h.style.display = "block";
7514
+ }
7515
+ return false;
7516
+ }
7517
+ /************************************************************
7488
7518
  *
7489
7519
  ************************************************************/
7490
7520
  function validate_form(gobj, $form) {
@@ -7944,7 +7974,7 @@ function form_value_2_treedb_value(gobj, field_desc, value) {
7944
7974
  function ac_window_to_close(gobj, event, kw, src) {
7945
7975
  if ((0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "changes")) {
7946
7976
  kw.abort_close = true;
7947
- kw.warning = "All changes will be lost. Are you sure?";
7977
+ kw.warning = "all changes will be lost";
7948
7978
  }
7949
7979
  return 0;
7950
7980
  }
@@ -7971,10 +8001,16 @@ function ac_save_record(gobj, event, kw, src) {
7971
8001
  let values = get_form_values(gobj, $form);
7972
8002
  (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_SAVE_RECORD", values);
7973
8003
  set_changed_stated(gobj, false);
7974
- } else {
7975
- kw.abort_close = true;
7976
- kw.warning = "Cannot save with wrong fields";
8004
+ return 0;
7977
8005
  }
8006
+ try {
8007
+ $form.reportValidity();
8008
+ } catch (e) {
8009
+ (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot report the form's validity: ${e}`);
8010
+ }
8011
+ $form.querySelectorAll(".yui-form-data-input").forEach(($input) => {
8012
+ mark_field_validity($input);
8013
+ });
7978
8014
  return 0;
7979
8015
  }
7980
8016
  /************************************************************
@@ -17247,7 +17283,7 @@ function form_may_close(gobj) {
17247
17283
  let kw = {};
17248
17284
  (0, _yuneta_gobj_js.gobj_send_event)(priv.form, "EV_WINDOW_TO_CLOSE", kw, gobj);
17249
17285
  if (kw.abort_close) {
17250
- yui_shell_confirm_yesnocancel(yui_shell_of(gobj), "All changes will be lost. Are you sure?", {
17286
+ yui_shell_confirm_yesnocancel(yui_shell_of(gobj), kw.warning || "all changes will be lost", {
17251
17287
  t: i18next.t,
17252
17288
  yes_label: "yes",
17253
17289
  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,49 @@ 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 ok = true;
7492
+ try {
7493
+ ok = $input.checkValidity();
7494
+ } catch (e) {
7495
+ ok = true;
7496
+ }
7497
+ if (ok) {
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
+ /************************************************************
7483
7513
  *
7484
7514
  ************************************************************/
7485
7515
  function validate_form(gobj, $form) {
@@ -7939,7 +7969,7 @@ function form_value_2_treedb_value(gobj, field_desc, value) {
7939
7969
  function ac_window_to_close(gobj, event, kw, src) {
7940
7970
  if (gobj_read_bool_attr(gobj, "changes")) {
7941
7971
  kw.abort_close = true;
7942
- kw.warning = "All changes will be lost. Are you sure?";
7972
+ kw.warning = "all changes will be lost";
7943
7973
  }
7944
7974
  return 0;
7945
7975
  }
@@ -7966,10 +7996,16 @@ function ac_save_record(gobj, event, kw, src) {
7966
7996
  let values = get_form_values(gobj, $form);
7967
7997
  gobj_publish_event(gobj, "EV_SAVE_RECORD", values);
7968
7998
  set_changed_stated(gobj, false);
7969
- } else {
7970
- kw.abort_close = true;
7971
- kw.warning = "Cannot save with wrong fields";
7999
+ return 0;
7972
8000
  }
8001
+ try {
8002
+ $form.reportValidity();
8003
+ } catch (e) {
8004
+ log_error(`${gobj_short_name(gobj)}: cannot report the form's validity: ${e}`);
8005
+ }
8006
+ $form.querySelectorAll(".yui-form-data-input").forEach(($input) => {
8007
+ mark_field_validity($input);
8008
+ });
7973
8009
  return 0;
7974
8010
  }
7975
8011
  /************************************************************
@@ -17242,7 +17278,7 @@ function form_may_close(gobj) {
17242
17278
  let kw = {};
17243
17279
  gobj_send_event(priv.form, "EV_WINDOW_TO_CLOSE", kw, gobj);
17244
17280
  if (kw.abort_close) {
17245
- 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", {
17246
17282
  t,
17247
17283
  yes_label: "yes",
17248
17284
  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.0",
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,57 @@ 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
+ let ok = true;
1994
+ try {
1995
+ ok = $input.checkValidity();
1996
+ } catch(e) {
1997
+ ok = true; /* not a validatable control */
1998
+ }
1999
+
2000
+ if(ok) {
2001
+ $input.classList.remove('is-danger');
2002
+ if($h) {
2003
+ $h.textContent = '';
2004
+ $h.style.display = 'none';
2005
+ }
2006
+ return true;
2007
+ }
2008
+
2009
+ $input.classList.add('is-danger');
2010
+ if($h) {
2011
+ $h.textContent = field_validation_message($input);
2012
+ $h.style.display = 'block';
2013
+ }
2014
+ return false;
2015
+ }
2016
+
1979
2017
  /************************************************************
1980
2018
  *
1981
2019
  ************************************************************/
@@ -2718,7 +2756,11 @@ function ac_window_to_close(gobj, event, kw, src)
2718
2756
  {
2719
2757
  if(gobj_read_bool_attr(gobj, "changes")) {
2720
2758
  kw.abort_close = true; // Don't close the window until fields repaired
2721
- kw.warning = "All changes will be lost. Are you sure?";
2759
+ /* An i18n KEY, not a sentence: the dialog renders its message with
2760
+ * `i18n: message`. The English sentence that was here was a key
2761
+ * nobody had defined, so it rendered as itself in every language —
2762
+ * and no locale validator can see a key that travels as data. */
2763
+ kw.warning = "all changes will be lost";
2722
2764
  }
2723
2765
  return 0;
2724
2766
  }
@@ -2754,11 +2796,32 @@ function ac_save_record(gobj, event, kw, src)
2754
2796
  let values = get_form_values(gobj, $form);
2755
2797
  gobj_publish_event(gobj, "EV_SAVE_RECORD", values);
2756
2798
  set_changed_stated(gobj, false);
2799
+ return 0;
2800
+ }
2757
2801
 
2758
- } else {
2759
- kw.abort_close = true; // Don't close the window until fields repaired
2760
- kw.warning = "Cannot save with wrong fields";
2802
+ /* Pressing Save on a form with a bad field used to do NOTHING: the
2803
+ * `abort_close` / `warning` this branch set were written on the click's
2804
+ * own kw, which nobody reads that pair belongs to the close path, not
2805
+ * to this one. The button looked broken.
2806
+ *
2807
+ * reportValidity() is what the form owed the reader: it fires `invalid`
2808
+ * on EVERY bad field (so all of them get marked, not just the one last
2809
+ * touched) and puts the caret and the viewport on the first, which on a
2810
+ * long form is the difference between "it did nothing" and "it is that
2811
+ * one, up there". */
2812
+ try {
2813
+ $form.reportValidity();
2814
+ } catch(e) {
2815
+ log_error(`${gobj_short_name(gobj)}: cannot report the form's validity: ${e}`);
2761
2816
  }
2817
+
2818
+ /* reportValidity() stops at the first field the BROWSER validates, and
2819
+ * the nested tables validate themselves; mark every input we own so the
2820
+ * count of red fields is the true one. */
2821
+ $form.querySelectorAll('.yui-form-data-input').forEach(($input) => {
2822
+ mark_field_validity($input);
2823
+ });
2824
+
2762
2825
  return 0;
2763
2826
  }
2764
2827
 
@@ -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) {