textbrowser 0.41.1 → 0.42.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.
package/dist/index-es.js CHANGED
@@ -75,57 +75,6 @@ function _objectWithoutProperties(source, excluded) {
75
75
  return target;
76
76
  }
77
77
 
78
- function _getRequireWildcardCache$1() {
79
- if (typeof WeakMap !== "function") return null;
80
- var cache = new WeakMap();
81
-
82
- _getRequireWildcardCache$1 = function () {
83
- return cache;
84
- };
85
-
86
- return cache;
87
- }
88
-
89
- function _interopRequireWildcard$1(obj) {
90
- if (obj && obj.__esModule) {
91
- return obj;
92
- }
93
-
94
- if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
95
- return {
96
- default: obj
97
- };
98
- }
99
-
100
- var cache = _getRequireWildcardCache$1();
101
-
102
- if (cache && cache.has(obj)) {
103
- return cache.get(obj);
104
- }
105
-
106
- var newObj = {};
107
- var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
108
-
109
- for (var key in obj) {
110
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
111
- var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
112
-
113
- if (desc && (desc.get || desc.set)) {
114
- Object.defineProperty(newObj, key, desc);
115
- } else {
116
- newObj[key] = obj[key];
117
- }
118
- }
119
- }
120
-
121
- newObj.default = obj;
122
-
123
- if (cache) {
124
- cache.set(obj, newObj);
125
- }
126
-
127
- return newObj;
128
- }
129
78
  /* eslint-disable node/no-unsupported-features/es-syntax */
130
79
 
131
80
  /**
@@ -141,9 +90,7 @@ function _interopRequireWildcard$1(obj) {
141
90
  * @param {fetch} cfg.fetch
142
91
  * @returns {getJSONCallback}
143
92
  */
144
-
145
-
146
- function _await$3(value, then, direct) {
93
+ function _await$2$1(value, then, direct) {
147
94
  if (direct) {
148
95
  return then ? then(value) : value;
149
96
  }
@@ -155,7 +102,7 @@ function _await$3(value, then, direct) {
155
102
  return then ? value.then(then) : value;
156
103
  }
157
104
 
158
- function _invoke$2(body, then) {
105
+ function _invoke$1$1(body, then) {
159
106
  var result = body();
160
107
 
161
108
  if (result && result.then) {
@@ -202,10 +149,10 @@ function buildGetJSONWithFetch$1({
202
149
  return function getJSON(jsonURL, cb, errBack) {
203
150
  try {
204
151
  let _exit = false;
205
- return _catch$1(function () {
206
- return _invoke$2(function () {
152
+ return _await$2$1(_catch$1(function () {
153
+ return _invoke$1$1(function () {
207
154
  if (Array.isArray(jsonURL)) {
208
- return _await$3(Promise.all(jsonURL.map(url => {
155
+ return _await$2$1(Promise.all(jsonURL.map(url => {
209
156
  return getJSON(url);
210
157
  })), function (arrResult) {
211
158
  if (cb) {
@@ -218,8 +165,8 @@ function buildGetJSONWithFetch$1({
218
165
  });
219
166
  }
220
167
  }, function (_result) {
221
- return _exit ? _result : _await$3(fetch(jsonURL), function (resp) {
222
- return _await$3(resp.json(), function (result) {
168
+ return _exit ? _result : _await$2$1(fetch(jsonURL), function (resp) {
169
+ return _await$2$1(resp.json(), function (result) {
223
170
  return typeof cb === 'function' // eslint-disable-next-line promise/prefer-await-to-callbacks
224
171
  ? cb(result) : result; // https://github.com/bcoe/c8/issues/135
225
172
 
@@ -237,7 +184,7 @@ function buildGetJSONWithFetch$1({
237
184
  throw e; // https://github.com/bcoe/c8/issues/135
238
185
 
239
186
  /* c8 ignore next */
240
- });
187
+ }));
241
188
  /* c8 ignore next */
242
189
  } catch (e) {
243
190
  return Promise.reject(e);
@@ -282,7 +229,7 @@ function _invokeIgnored$1(body) {
282
229
  }
283
230
  }
284
231
 
285
- function _async$2(f) {
232
+ function _async$1$1(f) {
286
233
  return function () {
287
234
  for (var args = [], i = 0; i < arguments.length; i++) {
288
235
  args[i] = arguments[i];
@@ -296,10 +243,10 @@ function _async$2(f) {
296
243
  };
297
244
  }
298
245
 
299
- const setDirname$1 = _async$2(function () {
246
+ const setDirname$1 = _async$1$1(function () {
300
247
  return _invokeIgnored$1(function () {
301
248
  if (!dirname$1) {
302
- return _await$1$1(Promise.resolve().then(() => _interopRequireWildcard$1(require('path'))), function (_import) {
249
+ return _await$1$1(import('path'), function (_import) {
303
250
  ({
304
251
  dirname: dirname$1
305
252
  } = _import);
@@ -331,8 +278,10 @@ function getDirectoryForURL$1(url) {
331
278
  // "file://" +
332
279
  return fixWindowsPath$1(dirname$1(new URL(url).pathname));
333
280
  }
281
+ /* eslint-disable node/no-unsupported-features/es-syntax */
334
282
 
335
- function _await$2$1(value, then, direct) {
283
+
284
+ function _await$3(value, then, direct) {
336
285
  if (direct) {
337
286
  return then ? then(value) : value;
338
287
  }
@@ -352,7 +301,7 @@ let nodeFetch$1;
352
301
  * @returns {getJSONCallback}
353
302
  */
354
303
 
355
- function _invoke$1$1(body, then) {
304
+ function _invoke$2(body, then) {
356
305
  var result = body();
357
306
 
358
307
  if (result && result.then) {
@@ -375,7 +324,7 @@ function _call$1(body, then, direct) {
375
324
  }
376
325
  }
377
326
 
378
- function _async$1$1(f) {
327
+ function _async$2(f) {
379
328
  return function () {
380
329
  for (var args = [], i = 0; i < arguments.length; i++) {
381
330
  args[i] = arguments[i];
@@ -393,23 +342,25 @@ function buildGetJSON$1({
393
342
  baseURL,
394
343
  cwd: basePath
395
344
  } = {}) {
396
- const _fetch = typeof fetch !== 'undefined' ? fetch : _async$1$1(function (jsonURL) {
345
+ const _fetch = typeof fetch !== 'undefined' ? fetch : _async$2(function (jsonURL) {
397
346
  let _exit = false;
398
- return _invoke$1$1(function () {
347
+ return _invoke$2(function () {
399
348
  if (/^https?:/u.test(jsonURL)) {
400
- return _invoke$1$1(function () {
349
+ return _invoke$2(function () {
401
350
  if (!nodeFetch$1) {
402
- return _await$2$1(Promise.resolve().then(() => _interopRequireWildcard$1(require('node-fetch'))), function (_import) {
351
+ return _await$3(import('node-fetch'), function (_import) {
403
352
  nodeFetch$1 = _import;
404
353
  });
405
354
  }
406
355
  }, function () {
356
+ const _nodeFetch$default = nodeFetch$1.default(jsonURL);
357
+
407
358
  _exit = true;
408
- return nodeFetch$1.default(jsonURL);
359
+ return _nodeFetch$default;
409
360
  });
410
361
  }
411
362
  }, function (_result) {
412
- return _exit ? _result : _invoke$1$1(function () {
363
+ return _exit ? _result : _invoke$2(function () {
413
364
  if (!basePath) {
414
365
  return _call$1(setDirname$1, function () {
415
366
  basePath = baseURL ? getDirectoryForURL$1(baseURL) : typeof fetch === 'undefined' && process.cwd();
@@ -419,7 +370,7 @@ function buildGetJSON$1({
419
370
  // Filed https://github.com/bergos/file-fetch/issues/12 to see
420
371
  // about getting relative basePaths in `file-fetch` and using
421
372
  // that better-tested package instead
422
- return _await$2$1(Promise.resolve().then(() => _interopRequireWildcard$1(require('local-xmlhttprequest'))), function (localXMLHttpRequest) {
373
+ return _await$3(import('local-xmlhttprequest'), function (localXMLHttpRequest) {
423
374
  // eslint-disable-next-line no-shadow
424
375
  const XMLHttpRequest = localXMLHttpRequest.default({
425
376
  basePath
@@ -429,6 +380,7 @@ function buildGetJSON$1({
429
380
  return new Promise((resolve, reject) => {
430
381
  const r = new XMLHttpRequest();
431
382
  r.open('GET', jsonURL, true); // r.responseType = 'json';
383
+ // eslint-disable-next-line unicorn/prefer-add-event-listener -- May not be available
432
384
 
433
385
  r.onreadystatechange = function () {
434
386
  // Not sure how to simulate `if`
@@ -4618,1237 +4570,264 @@ function hashAssign(result, keys, value) {
4618
4570
  return value;
4619
4571
  }
4620
4572
 
4621
- var key = keys.shift();
4622
- var between = key.match(/^\[(.+?)]$/);
4623
-
4624
- if (key === '[]') {
4625
- result = result || [];
4626
-
4627
- if (Array.isArray(result)) {
4628
- result.push(hashAssign(null, keys, value));
4629
- } else {
4630
- // This might be the result of bad name attributes like "[][foo]",
4631
- // in this case the original `result` object will already be
4632
- // assigned to an object literal. Rather than coerce the object to
4633
- // an array, or cause an exception the attribute "_values" is
4634
- // assigned as an array.
4635
- result._values = result._values || [];
4636
-
4637
- result._values.push(hashAssign(null, keys, value));
4638
- }
4639
-
4640
- return result;
4641
- } // Key is an attribute name and can be assigned directly.
4642
-
4643
-
4644
- if (!between) {
4645
- result[key] = hashAssign(result[key], keys, value);
4646
- } else {
4647
- var string = between[1]; // +var converts the variable into a number
4648
- // better than parseInt because it doesn't truncate away trailing
4649
- // letters and actually fails if whole thing is not a number
4650
-
4651
- var index = Number(string); // If the characters between the brackets is not a number it is an
4652
- // attribute name and can be assigned directly.
4653
- // Switching to Number.isNaN would require a polyfill for IE11
4654
- // eslint-disable-next-line unicorn/prefer-number-properties
4655
-
4656
- if (isNaN(index)) {
4657
- result = result || {};
4658
- result[string] = hashAssign(result[string], keys, value);
4659
- } else {
4660
- result = result || [];
4661
- result[index] = hashAssign(result[index], keys, value);
4662
- }
4663
- }
4664
-
4665
- return result;
4666
- }
4667
- /**
4668
- * Object/hash encoding serializer.
4669
- * @param {PlainObject} result
4670
- * @param {string} key
4671
- * @param {string} value
4672
- * @returns {PlainObject}
4673
- */
4674
-
4675
-
4676
- function hashSerializer(result, key, value) {
4677
- var hasBrackets = key.match(brackets); // Has brackets? Use the recursive assignment function to walk the keys,
4678
- // construct any missing objects in the result tree and make the assignment
4679
- // at the end of the chain.
4680
-
4681
- if (hasBrackets) {
4682
- var keys = parseKeys(key);
4683
- hashAssign(result, keys, value);
4684
- } else {
4685
- // Non bracket notation can make assignments directly.
4686
- var existing = result[key]; // If the value has been assigned already (for instance when a radio and
4687
- // a checkbox have the same name attribute) convert the previous value
4688
- // into an array before pushing into it.
4689
- //
4690
- // NOTE: If this requirement were removed all hash creation and
4691
- // assignment could go through `hashAssign`.
4692
-
4693
- if (existing) {
4694
- if (!Array.isArray(existing)) {
4695
- result[key] = [existing];
4696
- }
4697
-
4698
- result[key].push(value);
4699
- } else {
4700
- result[key] = value;
4701
- }
4702
- }
4703
-
4704
- return result;
4705
- }
4706
- /**
4707
- * URL form encoding serializer.
4708
- * @param {string} result
4709
- * @param {string} key
4710
- * @param {string} value
4711
- * @returns {string} New result
4712
- */
4713
-
4714
-
4715
- function strSerialize(result, key, value) {
4716
- // encode newlines as \r\n cause the html spec says so
4717
- value = value.replace(/(\r)?\n/g, '\r\n');
4718
- value = encodeURIComponent(value); // spaces should be '+' rather than '%20'.
4719
-
4720
- value = value.replace(/%20/g, '+');
4721
- return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
4722
- }
4723
- /**
4724
- * @function module:FormSerialization.deserialize
4725
- * @param {HTMLFormElement} form
4726
- * @param {PlainObject} hash
4727
- * @returns {void}
4728
- */
4729
-
4730
-
4731
- function deserialize(form, hash) {
4732
- // input(text|radio|checkbox)|select(multiple)|textarea|keygen
4733
- Object.entries(hash).forEach(function (_ref3) {
4734
- var _ref4 = _slicedToArray(_ref3, 2),
4735
- name = _ref4[0],
4736
- value = _ref4[1];
4737
-
4738
- var control = form[name];
4739
- var hasBrackets = false; // istanbul ignore else
4740
-
4741
- if (!control) {
4742
- // Try again for jsdom
4743
- control = form.querySelector("[name=\"".concat(name, "\"]"));
4744
-
4745
- if (!control) {
4746
- // We want this for `RadioNodeList` so setting value
4747
- // auto-disables other boxes
4748
- control = form[name + '[]']; // istanbul ignore next
4749
-
4750
- if (!control || _typeof(control) !== 'object' || !('length' in control)) {
4751
- // The latter query would only get a single
4752
- // element, so if not a `RadioNodeList`, we get
4753
- // all values here
4754
- control = form.querySelectorAll("[name=\"".concat(name, "[]\"]"));
4755
-
4756
- if (!control.length) {
4757
- throw new Error("Name not found ".concat(name));
4758
- }
4759
- }
4760
-
4761
- hasBrackets = true;
4762
- }
4763
- }
4764
-
4765
- var _control = control,
4766
- type = _control.type;
4767
-
4768
- if (type === 'checkbox') {
4769
- control.checked = value !== '';
4770
- }
4771
-
4772
- if (type === 'radio' || control[0] && control[0].type === 'radio') {
4773
- _toConsumableArray(form.querySelectorAll("[name=\"".concat(name + (hasBrackets ? '[]' : ''), "\"]"))).forEach(function (radio) {
4774
- radio.checked = value === radio.value;
4775
- });
4776
- }
4777
-
4778
- if (control[0] && control[0].type === 'select-multiple') {
4779
- _toConsumableArray(control[0].options).forEach(function (o) {
4780
- if (value.includes(o.value)) {
4781
- o.selected = true;
4782
- }
4783
- });
4784
-
4785
- return;
4786
- }
4787
-
4788
- if (Array.isArray(value)) {
4789
- // options on a multiple select
4790
- if (type === 'select-multiple') {
4791
- _toConsumableArray(control.options).forEach(function (o) {
4792
- if (value.includes(o.value)) {
4793
- o.selected = true;
4794
- }
4795
- });
4796
-
4797
- return;
4798
- }
4799
-
4800
- value.forEach(function (v, i) {
4801
- var c = control[i];
4802
-
4803
- if (c.type === 'checkbox') {
4804
- var isMatch = c.value === v || v === 'on';
4805
- c.checked = isMatch;
4806
- return;
4807
- }
4808
-
4809
- if (c.type === 'select-multiple') {
4810
- _toConsumableArray(c.options).forEach(function (o) {
4811
- if (v.includes(o.value)) {
4812
- o.selected = true;
4813
- }
4814
- });
4815
-
4816
- return;
4817
- }
4818
-
4819
- c.value = v;
4820
- });
4821
- } else {
4822
- control.value = value;
4823
- }
4824
- });
4825
- }
4826
-
4827
- function getIMFFallbackResults({
4828
- $p,
4829
- lang,
4830
- langs,
4831
- langData,
4832
- fallbackLanguages,
4833
- resultsDisplay,
4834
- basePath = '',
4835
- localeCallback = false
4836
- }) {
4837
- return new Promise((resolve, reject) => {
4838
- const resultsCallback = (...args) => {
4839
- const [l10n] = args;
4840
-
4841
- if (!$p.l10n) {
4842
- $p.l10n = l10n;
4843
- }
4844
-
4845
- return resultsDisplay({
4846
- l: l10n,
4847
- lang,
4848
- fallbackLanguages,
4849
- imfLocales: imf.locales,
4850
- $p,
4851
- basePath
4852
- }, ...args);
4853
- };
4854
-
4855
- const imf = IMF({
4856
- languages: lang,
4857
- fallbackLanguages,
4858
-
4859
- localeFileResolver(code) {
4860
- // Todo: For editing of locales, we might instead resolve all
4861
- // `$ref` (as with <https://github.com/whitlockjc/json-refs>) and
4862
- // replace IMF() loadLocales behavior with our own now resolved
4863
- // locales; see https://github.com/jdorn/json-editor/issues/132
4864
- return basePath + langData.localeFileBasePath + langs.find(l => l.code === code).locale.$ref;
4865
- },
4866
-
4867
- async callback(...args) {
4868
- if (localeCallback && localeCallback(...args)) {
4869
- resolve();
4870
- return;
4871
- }
4872
-
4873
- await resultsCallback(...args);
4874
- resolve();
4875
- }
4876
-
4877
- });
4878
- });
4879
- }
4880
-
4881
- // nb. This is for IE10 and lower _only_.
4882
- var supportCustomEvent = window.CustomEvent;
4883
-
4884
- if (!supportCustomEvent || typeof supportCustomEvent === 'object') {
4885
- supportCustomEvent = function CustomEvent(event, x) {
4886
- x = x || {};
4887
- var ev = document.createEvent('CustomEvent');
4888
- ev.initCustomEvent(event, !!x.bubbles, !!x.cancelable, x.detail || null);
4889
- return ev;
4890
- };
4891
-
4892
- supportCustomEvent.prototype = window.Event.prototype;
4893
- }
4894
- /**
4895
- * Dispatches the passed event to both an "on<type>" handler as well as via the
4896
- * normal dispatch operation. Does not bubble.
4897
- *
4898
- * @param {!EventTarget} target
4899
- * @param {!Event} event
4900
- * @return {boolean}
4901
- */
4902
-
4903
-
4904
- function safeDispatchEvent(target, event) {
4905
- var check = 'on' + event.type.toLowerCase();
4906
-
4907
- if (typeof target[check] === 'function') {
4908
- target[check](event);
4909
- }
4910
-
4911
- return target.dispatchEvent(event);
4912
- }
4913
- /**
4914
- * @param {Element} el to check for stacking context
4915
- * @return {boolean} whether this el or its parents creates a stacking context
4916
- */
4917
-
4918
-
4919
- function createsStackingContext(el) {
4920
- while (el && el !== document.body) {
4921
- var s = window.getComputedStyle(el);
4922
-
4923
- var invalid = function (k, ok) {
4924
- return !(s[k] === undefined || s[k] === ok);
4925
- };
4926
-
4927
- if (s.opacity < 1 || invalid('zIndex', 'auto') || invalid('transform', 'none') || invalid('mixBlendMode', 'normal') || invalid('filter', 'none') || invalid('perspective', 'none') || s['isolation'] === 'isolate' || s.position === 'fixed' || s.webkitOverflowScrolling === 'touch') {
4928
- return true;
4929
- }
4930
-
4931
- el = el.parentElement;
4932
- }
4933
-
4934
- return false;
4935
- }
4936
- /**
4937
- * Finds the nearest <dialog> from the passed element.
4938
- *
4939
- * @param {Element} el to search from
4940
- * @return {HTMLDialogElement} dialog found
4941
- */
4942
-
4943
-
4944
- function findNearestDialog(el) {
4945
- while (el) {
4946
- if (el.localName === 'dialog') {
4947
- return (
4948
- /** @type {HTMLDialogElement} */
4949
- el
4950
- );
4951
- }
4952
-
4953
- if (el.parentElement) {
4954
- el = el.parentElement;
4955
- } else if (el.parentNode) {
4956
- el = el.parentNode.host;
4957
- } else {
4958
- el = null;
4959
- }
4960
- }
4961
-
4962
- return null;
4963
- }
4964
- /**
4965
- * Blur the specified element, as long as it's not the HTML body element.
4966
- * This works around an IE9/10 bug - blurring the body causes Windows to
4967
- * blur the whole application.
4968
- *
4969
- * @param {Element} el to blur
4970
- */
4971
-
4972
-
4973
- function safeBlur(el) {
4974
- // Find the actual focused element when the active element is inside a shadow root
4975
- while (el && el.shadowRoot && el.shadowRoot.activeElement) {
4976
- el = el.shadowRoot.activeElement;
4977
- }
4978
-
4979
- if (el && el.blur && el !== document.body) {
4980
- el.blur();
4981
- }
4982
- }
4983
- /**
4984
- * @param {!NodeList} nodeList to search
4985
- * @param {Node} node to find
4986
- * @return {boolean} whether node is inside nodeList
4987
- */
4988
-
4989
-
4990
- function inNodeList(nodeList, node) {
4991
- for (var i = 0; i < nodeList.length; ++i) {
4992
- if (nodeList[i] === node) {
4993
- return true;
4994
- }
4995
- }
4996
-
4997
- return false;
4998
- }
4999
- /**
5000
- * @param {HTMLFormElement} el to check
5001
- * @return {boolean} whether this form has method="dialog"
5002
- */
5003
-
5004
-
5005
- function isFormMethodDialog(el) {
5006
- if (!el || !el.hasAttribute('method')) {
5007
- return false;
5008
- }
5009
-
5010
- return el.getAttribute('method').toLowerCase() === 'dialog';
5011
- }
5012
- /**
5013
- * @param {!DocumentFragment|!Element} hostElement
5014
- * @return {?Element}
5015
- */
5016
-
5017
-
5018
- function findFocusableElementWithin(hostElement) {
5019
- // Note that this is 'any focusable area'. This list is probably not exhaustive, but the
5020
- // alternative involves stepping through and trying to focus everything.
5021
- var opts = ['button', 'input', 'keygen', 'select', 'textarea'];
5022
- var query = opts.map(function (el) {
5023
- return el + ':not([disabled])';
5024
- }); // TODO(samthor): tabindex values that are not numeric are not focusable.
5025
-
5026
- query.push('[tabindex]:not([disabled]):not([tabindex=""])'); // tabindex != "", not disabled
5027
-
5028
- var target = hostElement.querySelector(query.join(', '));
5029
-
5030
- if (!target && 'attachShadow' in Element.prototype) {
5031
- // If we haven't found a focusable target, see if the host element contains an element
5032
- // which has a shadowRoot.
5033
- // Recursively search for the first focusable item in shadow roots.
5034
- var elems = hostElement.querySelectorAll('*');
5035
-
5036
- for (var i = 0; i < elems.length; i++) {
5037
- if (elems[i].tagName && elems[i].shadowRoot) {
5038
- target = findFocusableElementWithin(elems[i].shadowRoot);
5039
-
5040
- if (target) {
5041
- break;
5042
- }
5043
- }
5044
- }
5045
- }
5046
-
5047
- return target;
5048
- }
5049
- /**
5050
- * Determines if an element is attached to the DOM.
5051
- * @param {Element} element to check
5052
- * @return {boolean} whether the element is in DOM
5053
- */
5054
-
5055
-
5056
- function isConnected(element) {
5057
- return element.isConnected || document.body.contains(element);
5058
- }
5059
- /**
5060
- * @param {!Event} event
5061
- * @return {?Element}
5062
- */
5063
-
5064
-
5065
- function findFormSubmitter(event) {
5066
- if (event.submitter) {
5067
- return event.submitter;
5068
- }
5069
-
5070
- var form = event.target;
5071
-
5072
- if (!(form instanceof HTMLFormElement)) {
5073
- return null;
5074
- }
5075
-
5076
- var submitter = dialogPolyfill.formSubmitter;
5077
-
5078
- if (!submitter) {
5079
- var target = event.target;
5080
- var root = 'getRootNode' in target && target.getRootNode() || document;
5081
- submitter = root.activeElement;
5082
- }
5083
-
5084
- if (!submitter || submitter.form !== form) {
5085
- return null;
5086
- }
5087
-
5088
- return submitter;
5089
- }
5090
- /**
5091
- * @param {!Event} event
5092
- */
5093
-
5094
-
5095
- function maybeHandleSubmit(event) {
5096
- if (event.defaultPrevented) {
5097
- return;
5098
- }
5099
-
5100
- var form =
5101
- /** @type {!HTMLFormElement} */
5102
- event.target; // We'd have a value if we clicked on an imagemap.
5103
-
5104
- var value = dialogPolyfill.imagemapUseValue;
5105
- var submitter = findFormSubmitter(event);
5106
-
5107
- if (value === null && submitter) {
5108
- value = submitter.value;
5109
- } // There should always be a dialog as this handler is added specifically on them, but check just
5110
- // in case.
5111
-
5112
-
5113
- var dialog = findNearestDialog(form);
5114
-
5115
- if (!dialog) {
5116
- return;
5117
- } // Prefer formmethod on the button.
5118
-
5119
-
5120
- var formmethod = submitter && submitter.getAttribute('formmethod') || form.getAttribute('method');
5121
-
5122
- if (formmethod !== 'dialog') {
5123
- return;
5124
- }
5125
-
5126
- event.preventDefault();
5127
-
5128
- if (value != null) {
5129
- // nb. we explicitly check against null/undefined
5130
- dialog.close(value);
5131
- } else {
5132
- dialog.close();
5133
- }
5134
- }
5135
- /**
5136
- * @param {!HTMLDialogElement} dialog to upgrade
5137
- * @constructor
5138
- */
5139
-
5140
-
5141
- function dialogPolyfillInfo(dialog) {
5142
- this.dialog_ = dialog;
5143
- this.replacedStyleTop_ = false;
5144
- this.openAsModal_ = false; // Set a11y role. Browsers that support dialog implicitly know this already.
5145
-
5146
- if (!dialog.hasAttribute('role')) {
5147
- dialog.setAttribute('role', 'dialog');
5148
- }
5149
-
5150
- dialog.show = this.show.bind(this);
5151
- dialog.showModal = this.showModal.bind(this);
5152
- dialog.close = this.close.bind(this);
5153
- dialog.addEventListener('submit', maybeHandleSubmit, false);
5154
-
5155
- if (!('returnValue' in dialog)) {
5156
- dialog.returnValue = '';
5157
- }
5158
-
5159
- if ('MutationObserver' in window) {
5160
- var mo = new MutationObserver(this.maybeHideModal.bind(this));
5161
- mo.observe(dialog, {
5162
- attributes: true,
5163
- attributeFilter: ['open']
5164
- });
5165
- } else {
5166
- // IE10 and below support. Note that DOMNodeRemoved etc fire _before_ removal. They also
5167
- // seem to fire even if the element was removed as part of a parent removal. Use the removed
5168
- // events to force downgrade (useful if removed/immediately added).
5169
- var removed = false;
5170
-
5171
- var cb = function () {
5172
- removed ? this.downgradeModal() : this.maybeHideModal();
5173
- removed = false;
5174
- }.bind(this);
5175
-
5176
- var timeout;
5177
-
5178
- var delayModel = function (ev) {
5179
- if (ev.target !== dialog) {
5180
- return;
5181
- } // not for a child element
5182
-
5183
-
5184
- var cand = 'DOMNodeRemoved';
5185
- removed |= ev.type.substr(0, cand.length) === cand;
5186
- window.clearTimeout(timeout);
5187
- timeout = window.setTimeout(cb, 0);
5188
- };
5189
-
5190
- ['DOMAttrModified', 'DOMNodeRemoved', 'DOMNodeRemovedFromDocument'].forEach(function (name) {
5191
- dialog.addEventListener(name, delayModel);
5192
- });
5193
- } // Note that the DOM is observed inside DialogManager while any dialog
5194
- // is being displayed as a modal, to catch modal removal from the DOM.
5195
-
5196
-
5197
- Object.defineProperty(dialog, 'open', {
5198
- set: this.setOpen.bind(this),
5199
- get: dialog.hasAttribute.bind(dialog, 'open')
5200
- });
5201
- this.backdrop_ = document.createElement('div');
5202
- this.backdrop_.className = 'backdrop';
5203
- this.backdrop_.addEventListener('mouseup', this.backdropMouseEvent_.bind(this));
5204
- this.backdrop_.addEventListener('mousedown', this.backdropMouseEvent_.bind(this));
5205
- this.backdrop_.addEventListener('click', this.backdropMouseEvent_.bind(this));
5206
- }
5207
-
5208
- dialogPolyfillInfo.prototype =
5209
- /** @type {HTMLDialogElement.prototype} */
5210
- {
5211
- get dialog() {
5212
- return this.dialog_;
5213
- },
5214
-
5215
- /**
5216
- * Maybe remove this dialog from the modal top layer. This is called when
5217
- * a modal dialog may no longer be tenable, e.g., when the dialog is no
5218
- * longer open or is no longer part of the DOM.
5219
- */
5220
- maybeHideModal: function () {
5221
- if (this.dialog_.hasAttribute('open') && isConnected(this.dialog_)) {
5222
- return;
5223
- }
5224
-
5225
- this.downgradeModal();
5226
- },
5227
-
5228
- /**
5229
- * Remove this dialog from the modal top layer, leaving it as a non-modal.
5230
- */
5231
- downgradeModal: function () {
5232
- if (!this.openAsModal_) {
5233
- return;
5234
- }
5235
-
5236
- this.openAsModal_ = false;
5237
- this.dialog_.style.zIndex = ''; // This won't match the native <dialog> exactly because if the user set top on a centered
5238
- // polyfill dialog, that top gets thrown away when the dialog is closed. Not sure it's
5239
- // possible to polyfill this perfectly.
5240
-
5241
- if (this.replacedStyleTop_) {
5242
- this.dialog_.style.top = '';
5243
- this.replacedStyleTop_ = false;
5244
- } // Clear the backdrop and remove from the manager.
5245
-
5246
-
5247
- this.backdrop_.parentNode && this.backdrop_.parentNode.removeChild(this.backdrop_);
5248
- dialogPolyfill.dm.removeDialog(this);
5249
- },
5250
-
5251
- /**
5252
- * @param {boolean} value whether to open or close this dialog
5253
- */
5254
- setOpen: function (value) {
5255
- if (value) {
5256
- this.dialog_.hasAttribute('open') || this.dialog_.setAttribute('open', '');
5257
- } else {
5258
- this.dialog_.removeAttribute('open');
5259
- this.maybeHideModal(); // nb. redundant with MutationObserver
5260
- }
5261
- },
5262
-
5263
- /**
5264
- * Handles mouse events ('mouseup', 'mousedown', 'click') on the fake .backdrop element, redirecting them as if
5265
- * they were on the dialog itself.
5266
- *
5267
- * @param {!Event} e to redirect
5268
- */
5269
- backdropMouseEvent_: function (e) {
5270
- if (!this.dialog_.hasAttribute('tabindex')) {
5271
- // Clicking on the backdrop should move the implicit cursor, even if dialog cannot be
5272
- // focused. Create a fake thing to focus on. If the backdrop was _before_ the dialog, this
5273
- // would not be needed - clicks would move the implicit cursor there.
5274
- var fake = document.createElement('div');
5275
- this.dialog_.insertBefore(fake, this.dialog_.firstChild);
5276
- fake.tabIndex = -1;
5277
- fake.focus();
5278
- this.dialog_.removeChild(fake);
5279
- } else {
5280
- this.dialog_.focus();
5281
- }
5282
-
5283
- var redirectedEvent = document.createEvent('MouseEvents');
5284
- redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
5285
- this.dialog_.dispatchEvent(redirectedEvent);
5286
- e.stopPropagation();
5287
- },
5288
-
5289
- /**
5290
- * Focuses on the first focusable element within the dialog. This will always blur the current
5291
- * focus, even if nothing within the dialog is found.
5292
- */
5293
- focus_: function () {
5294
- // Find element with `autofocus` attribute, or fall back to the first form/tabindex control.
5295
- var target = this.dialog_.querySelector('[autofocus]:not([disabled])');
5296
-
5297
- if (!target && this.dialog_.tabIndex >= 0) {
5298
- target = this.dialog_;
5299
- }
5300
-
5301
- if (!target) {
5302
- target = findFocusableElementWithin(this.dialog_);
5303
- }
5304
-
5305
- safeBlur(document.activeElement);
5306
- target && target.focus();
5307
- },
5308
-
5309
- /**
5310
- * Sets the zIndex for the backdrop and dialog.
5311
- *
5312
- * @param {number} dialogZ
5313
- * @param {number} backdropZ
5314
- */
5315
- updateZIndex: function (dialogZ, backdropZ) {
5316
- if (dialogZ < backdropZ) {
5317
- throw new Error('dialogZ should never be < backdropZ');
5318
- }
5319
-
5320
- this.dialog_.style.zIndex = dialogZ;
5321
- this.backdrop_.style.zIndex = backdropZ;
5322
- },
5323
-
5324
- /**
5325
- * Shows the dialog. If the dialog is already open, this does nothing.
5326
- */
5327
- show: function () {
5328
- if (!this.dialog_.open) {
5329
- this.setOpen(true);
5330
- this.focus_();
5331
- }
5332
- },
5333
-
5334
- /**
5335
- * Show this dialog modally.
5336
- */
5337
- showModal: function () {
5338
- if (this.dialog_.hasAttribute('open')) {
5339
- throw new Error('Failed to execute \'showModal\' on dialog: The element is already open, and therefore cannot be opened modally.');
5340
- }
5341
-
5342
- if (!isConnected(this.dialog_)) {
5343
- throw new Error('Failed to execute \'showModal\' on dialog: The element is not in a Document.');
5344
- }
5345
-
5346
- if (!dialogPolyfill.dm.pushDialog(this)) {
5347
- throw new Error('Failed to execute \'showModal\' on dialog: There are too many open modal dialogs.');
5348
- }
5349
-
5350
- if (createsStackingContext(this.dialog_.parentElement)) {
5351
- console.warn('A dialog is being shown inside a stacking context. ' + 'This may cause it to be unusable. For more information, see this link: ' + 'https://github.com/GoogleChrome/dialog-polyfill/#stacking-context');
5352
- }
5353
-
5354
- this.setOpen(true);
5355
- this.openAsModal_ = true; // Optionally center vertically, relative to the current viewport.
5356
-
5357
- if (dialogPolyfill.needsCentering(this.dialog_)) {
5358
- dialogPolyfill.reposition(this.dialog_);
5359
- this.replacedStyleTop_ = true;
5360
- } else {
5361
- this.replacedStyleTop_ = false;
5362
- } // Insert backdrop.
5363
-
5364
-
5365
- this.dialog_.parentNode.insertBefore(this.backdrop_, this.dialog_.nextSibling); // Focus on whatever inside the dialog.
5366
-
5367
- this.focus_();
5368
- },
5369
-
5370
- /**
5371
- * Closes this HTMLDialogElement. This is optional vs clearing the open
5372
- * attribute, however this fires a 'close' event.
5373
- *
5374
- * @param {string=} opt_returnValue to use as the returnValue
5375
- */
5376
- close: function (opt_returnValue) {
5377
- if (!this.dialog_.hasAttribute('open')) {
5378
- throw new Error('Failed to execute \'close\' on dialog: The element does not have an \'open\' attribute, and therefore cannot be closed.');
5379
- }
5380
-
5381
- this.setOpen(false); // Leave returnValue untouched in case it was set directly on the element
5382
-
5383
- if (opt_returnValue !== undefined) {
5384
- this.dialog_.returnValue = opt_returnValue;
5385
- } // Triggering "close" event for any attached listeners on the <dialog>.
5386
-
5387
-
5388
- var closeEvent = new supportCustomEvent('close', {
5389
- bubbles: false,
5390
- cancelable: false
5391
- });
5392
- safeDispatchEvent(this.dialog_, closeEvent);
5393
- }
5394
- };
5395
- var dialogPolyfill = {};
5396
-
5397
- dialogPolyfill.reposition = function (element) {
5398
- var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
5399
- var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
5400
- element.style.top = Math.max(scrollTop, topValue) + 'px';
5401
- };
5402
-
5403
- dialogPolyfill.isInlinePositionSetByStylesheet = function (element) {
5404
- for (var i = 0; i < document.styleSheets.length; ++i) {
5405
- var styleSheet = document.styleSheets[i];
5406
- var cssRules = null; // Some browsers throw on cssRules.
5407
-
5408
- try {
5409
- cssRules = styleSheet.cssRules;
5410
- } catch (e) {}
5411
-
5412
- if (!cssRules) {
5413
- continue;
5414
- }
5415
-
5416
- for (var j = 0; j < cssRules.length; ++j) {
5417
- var rule = cssRules[j];
5418
- var selectedNodes = null; // Ignore errors on invalid selector texts.
5419
-
5420
- try {
5421
- selectedNodes = document.querySelectorAll(rule.selectorText);
5422
- } catch (e) {}
5423
-
5424
- if (!selectedNodes || !inNodeList(selectedNodes, element)) {
5425
- continue;
5426
- }
5427
-
5428
- var cssTop = rule.style.getPropertyValue('top');
5429
- var cssBottom = rule.style.getPropertyValue('bottom');
5430
-
5431
- if (cssTop && cssTop !== 'auto' || cssBottom && cssBottom !== 'auto') {
5432
- return true;
5433
- }
5434
- }
5435
- }
5436
-
5437
- return false;
5438
- };
5439
-
5440
- dialogPolyfill.needsCentering = function (dialog) {
5441
- var computedStyle = window.getComputedStyle(dialog);
5442
-
5443
- if (computedStyle.position !== 'absolute') {
5444
- return false;
5445
- } // We must determine whether the top/bottom specified value is non-auto. In
5446
- // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
5447
- // Firefox returns the used value. So we do this crazy thing instead: check
5448
- // the inline style and then go through CSS rules.
5449
-
5450
-
5451
- if (dialog.style.top !== 'auto' && dialog.style.top !== '' || dialog.style.bottom !== 'auto' && dialog.style.bottom !== '') {
5452
- return false;
5453
- }
5454
-
5455
- return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
5456
- };
5457
- /**
5458
- * @param {!Element} element to force upgrade
5459
- */
5460
-
5461
-
5462
- dialogPolyfill.forceRegisterDialog = function (element) {
5463
- if (window.HTMLDialogElement || element.showModal) {
5464
- console.warn('This browser already supports <dialog>, the polyfill ' + 'may not work correctly', element);
5465
- }
5466
-
5467
- if (element.localName !== 'dialog') {
5468
- throw new Error('Failed to register dialog: The element is not a dialog.');
5469
- }
5470
-
5471
- new dialogPolyfillInfo(
5472
- /** @type {!HTMLDialogElement} */
5473
- element);
5474
- };
5475
- /**
5476
- * @param {!Element} element to upgrade, if necessary
5477
- */
5478
-
5479
-
5480
- dialogPolyfill.registerDialog = function (element) {
5481
- if (!element.showModal) {
5482
- dialogPolyfill.forceRegisterDialog(element);
5483
- }
5484
- };
5485
- /**
5486
- * @constructor
5487
- */
5488
-
5489
-
5490
- dialogPolyfill.DialogManager = function () {
5491
- /** @type {!Array<!dialogPolyfillInfo>} */
5492
- this.pendingDialogStack = [];
5493
- var checkDOM = this.checkDOM_.bind(this); // The overlay is used to simulate how a modal dialog blocks the document.
5494
- // The blocking dialog is positioned on top of the overlay, and the rest of
5495
- // the dialogs on the pending dialog stack are positioned below it. In the
5496
- // actual implementation, the modal dialog stacking is controlled by the
5497
- // top layer, where z-index has no effect.
5498
-
5499
- this.overlay = document.createElement('div');
5500
- this.overlay.className = '_dialog_overlay';
5501
- this.overlay.addEventListener('click', function (e) {
5502
- this.forwardTab_ = undefined;
5503
- e.stopPropagation();
5504
- checkDOM([]); // sanity-check DOM
5505
- }.bind(this));
5506
- this.handleKey_ = this.handleKey_.bind(this);
5507
- this.handleFocus_ = this.handleFocus_.bind(this);
5508
- this.zIndexLow_ = 100000;
5509
- this.zIndexHigh_ = 100000 + 150;
5510
- this.forwardTab_ = undefined;
5511
-
5512
- if ('MutationObserver' in window) {
5513
- this.mo_ = new MutationObserver(function (records) {
5514
- var removed = [];
5515
- records.forEach(function (rec) {
5516
- for (var i = 0, c; c = rec.removedNodes[i]; ++i) {
5517
- if (!(c instanceof Element)) {
5518
- continue;
5519
- } else if (c.localName === 'dialog') {
5520
- removed.push(c);
5521
- }
5522
-
5523
- removed = removed.concat(c.querySelectorAll('dialog'));
5524
- }
5525
- });
5526
- removed.length && checkDOM(removed);
5527
- });
5528
- }
5529
- };
5530
- /**
5531
- * Called on the first modal dialog being shown. Adds the overlay and related
5532
- * handlers.
5533
- */
5534
-
5535
-
5536
- dialogPolyfill.DialogManager.prototype.blockDocument = function () {
5537
- document.documentElement.addEventListener('focus', this.handleFocus_, true);
5538
- document.addEventListener('keydown', this.handleKey_);
5539
- this.mo_ && this.mo_.observe(document, {
5540
- childList: true,
5541
- subtree: true
5542
- });
5543
- };
5544
- /**
5545
- * Called on the first modal dialog being removed, i.e., when no more modal
5546
- * dialogs are visible.
5547
- */
5548
-
5549
-
5550
- dialogPolyfill.DialogManager.prototype.unblockDocument = function () {
5551
- document.documentElement.removeEventListener('focus', this.handleFocus_, true);
5552
- document.removeEventListener('keydown', this.handleKey_);
5553
- this.mo_ && this.mo_.disconnect();
5554
- };
5555
- /**
5556
- * Updates the stacking of all known dialogs.
5557
- */
5558
-
5559
-
5560
- dialogPolyfill.DialogManager.prototype.updateStacking = function () {
5561
- var zIndex = this.zIndexHigh_;
5562
-
5563
- for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {
5564
- dpi.updateZIndex(--zIndex, --zIndex);
5565
-
5566
- if (i === 0) {
5567
- this.overlay.style.zIndex = --zIndex;
5568
- }
5569
- } // Make the overlay a sibling of the dialog itself.
5570
-
5571
-
5572
- var last = this.pendingDialogStack[0];
5573
-
5574
- if (last) {
5575
- var p = last.dialog.parentNode || document.body;
5576
- p.appendChild(this.overlay);
5577
- } else if (this.overlay.parentNode) {
5578
- this.overlay.parentNode.removeChild(this.overlay);
5579
- }
5580
- };
5581
- /**
5582
- * @param {Element} candidate to check if contained or is the top-most modal dialog
5583
- * @return {boolean} whether candidate is contained in top dialog
5584
- */
5585
-
5586
-
5587
- dialogPolyfill.DialogManager.prototype.containedByTopDialog_ = function (candidate) {
5588
- while (candidate = findNearestDialog(candidate)) {
5589
- for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {
5590
- if (dpi.dialog === candidate) {
5591
- return i === 0; // only valid if top-most
5592
- }
5593
- }
5594
-
5595
- candidate = candidate.parentElement;
5596
- }
5597
-
5598
- return false;
5599
- };
5600
-
5601
- dialogPolyfill.DialogManager.prototype.handleFocus_ = function (event) {
5602
- var target = event.composedPath ? event.composedPath()[0] : event.target;
5603
-
5604
- if (this.containedByTopDialog_(target)) {
5605
- return;
5606
- }
5607
-
5608
- if (document.activeElement === document.documentElement) {
5609
- return;
5610
- }
5611
-
5612
- event.preventDefault();
5613
- event.stopPropagation();
5614
- safeBlur(
5615
- /** @type {Element} */
5616
- target);
5617
-
5618
- if (this.forwardTab_ === undefined) {
5619
- return;
5620
- } // move focus only from a tab key
4573
+ var key = keys.shift();
4574
+ var between = key.match(/^\[(.+?)]$/);
5621
4575
 
4576
+ if (key === '[]') {
4577
+ result = result || [];
5622
4578
 
5623
- var dpi = this.pendingDialogStack[0];
5624
- var dialog = dpi.dialog;
5625
- var position = dialog.compareDocumentPosition(target);
4579
+ if (Array.isArray(result)) {
4580
+ result.push(hashAssign(null, keys, value));
4581
+ } else {
4582
+ // This might be the result of bad name attributes like "[][foo]",
4583
+ // in this case the original `result` object will already be
4584
+ // assigned to an object literal. Rather than coerce the object to
4585
+ // an array, or cause an exception the attribute "_values" is
4586
+ // assigned as an array.
4587
+ result._values = result._values || [];
5626
4588
 
5627
- if (position & Node.DOCUMENT_POSITION_PRECEDING) {
5628
- if (this.forwardTab_) {
5629
- // forward
5630
- dpi.focus_();
5631
- } else if (target !== document.documentElement) {
5632
- // backwards if we're not already focused on <html>
5633
- document.documentElement.focus();
4589
+ result._values.push(hashAssign(null, keys, value));
5634
4590
  }
5635
- }
5636
-
5637
- return false;
5638
- };
5639
4591
 
5640
- dialogPolyfill.DialogManager.prototype.handleKey_ = function (event) {
5641
- this.forwardTab_ = undefined;
4592
+ return result;
4593
+ } // Key is an attribute name and can be assigned directly.
5642
4594
 
5643
- if (event.keyCode === 27) {
5644
- event.preventDefault();
5645
- event.stopPropagation();
5646
- var cancelEvent = new supportCustomEvent('cancel', {
5647
- bubbles: false,
5648
- cancelable: true
5649
- });
5650
- var dpi = this.pendingDialogStack[0];
5651
4595
 
5652
- if (dpi && safeDispatchEvent(dpi.dialog, cancelEvent)) {
5653
- dpi.dialog.close();
5654
- }
5655
- } else if (event.keyCode === 9) {
5656
- this.forwardTab_ = !event.shiftKey;
5657
- }
5658
- };
5659
- /**
5660
- * Finds and downgrades any known modal dialogs that are no longer displayed. Dialogs that are
5661
- * removed and immediately readded don't stay modal, they become normal.
5662
- *
5663
- * @param {!Array<!HTMLDialogElement>} removed that have definitely been removed
5664
- */
4596
+ if (!between) {
4597
+ result[key] = hashAssign(result[key], keys, value);
4598
+ } else {
4599
+ var string = between[1]; // +var converts the variable into a number
4600
+ // better than parseInt because it doesn't truncate away trailing
4601
+ // letters and actually fails if whole thing is not a number
5665
4602
 
4603
+ var index = Number(string); // If the characters between the brackets is not a number it is an
4604
+ // attribute name and can be assigned directly.
4605
+ // Switching to Number.isNaN would require a polyfill for IE11
4606
+ // eslint-disable-next-line unicorn/prefer-number-properties
5666
4607
 
5667
- dialogPolyfill.DialogManager.prototype.checkDOM_ = function (removed) {
5668
- // This operates on a clone because it may cause it to change. Each change also calls
5669
- // updateStacking, which only actually needs to happen once. But who removes many modal dialogs
5670
- // at a time?!
5671
- var clone = this.pendingDialogStack.slice();
5672
- clone.forEach(function (dpi) {
5673
- if (removed.indexOf(dpi.dialog) !== -1) {
5674
- dpi.downgradeModal();
4608
+ if (isNaN(index)) {
4609
+ result = result || {};
4610
+ result[string] = hashAssign(result[string], keys, value);
5675
4611
  } else {
5676
- dpi.maybeHideModal();
4612
+ result = result || [];
4613
+ result[index] = hashAssign(result[index], keys, value);
5677
4614
  }
5678
- });
5679
- };
4615
+ }
4616
+
4617
+ return result;
4618
+ }
5680
4619
  /**
5681
- * @param {!dialogPolyfillInfo} dpi
5682
- * @return {boolean} whether the dialog was allowed
4620
+ * Object/hash encoding serializer.
4621
+ * @param {PlainObject} result
4622
+ * @param {string} key
4623
+ * @param {string} value
4624
+ * @returns {PlainObject}
5683
4625
  */
5684
4626
 
5685
4627
 
5686
- dialogPolyfill.DialogManager.prototype.pushDialog = function (dpi) {
5687
- var allowed = (this.zIndexHigh_ - this.zIndexLow_) / 2 - 1;
4628
+ function hashSerializer(result, key, value) {
4629
+ var hasBrackets = key.match(brackets); // Has brackets? Use the recursive assignment function to walk the keys,
4630
+ // construct any missing objects in the result tree and make the assignment
4631
+ // at the end of the chain.
5688
4632
 
5689
- if (this.pendingDialogStack.length >= allowed) {
5690
- return false;
5691
- }
4633
+ if (hasBrackets) {
4634
+ var keys = parseKeys(key);
4635
+ hashAssign(result, keys, value);
4636
+ } else {
4637
+ // Non bracket notation can make assignments directly.
4638
+ var existing = result[key]; // If the value has been assigned already (for instance when a radio and
4639
+ // a checkbox have the same name attribute) convert the previous value
4640
+ // into an array before pushing into it.
4641
+ //
4642
+ // NOTE: If this requirement were removed all hash creation and
4643
+ // assignment could go through `hashAssign`.
4644
+
4645
+ if (existing) {
4646
+ if (!Array.isArray(existing)) {
4647
+ result[key] = [existing];
4648
+ }
5692
4649
 
5693
- if (this.pendingDialogStack.unshift(dpi) === 1) {
5694
- this.blockDocument();
4650
+ result[key].push(value);
4651
+ } else {
4652
+ result[key] = value;
4653
+ }
5695
4654
  }
5696
4655
 
5697
- this.updateStacking();
5698
- return true;
5699
- };
4656
+ return result;
4657
+ }
5700
4658
  /**
5701
- * @param {!dialogPolyfillInfo} dpi
4659
+ * URL form encoding serializer.
4660
+ * @param {string} result
4661
+ * @param {string} key
4662
+ * @param {string} value
4663
+ * @returns {string} New result
5702
4664
  */
5703
4665
 
5704
4666
 
5705
- dialogPolyfill.DialogManager.prototype.removeDialog = function (dpi) {
5706
- var index = this.pendingDialogStack.indexOf(dpi);
5707
-
5708
- if (index === -1) {
5709
- return;
5710
- }
5711
-
5712
- this.pendingDialogStack.splice(index, 1);
5713
-
5714
- if (this.pendingDialogStack.length === 0) {
5715
- this.unblockDocument();
5716
- }
5717
-
5718
- this.updateStacking();
5719
- };
4667
+ function strSerialize(result, key, value) {
4668
+ // encode newlines as \r\n cause the html spec says so
4669
+ value = value.replace(/(\r)?\n/g, '\r\n');
4670
+ value = encodeURIComponent(value); // spaces should be '+' rather than '%20'.
5720
4671
 
5721
- dialogPolyfill.dm = new dialogPolyfill.DialogManager();
5722
- dialogPolyfill.formSubmitter = null;
5723
- dialogPolyfill.imagemapUseValue = null;
4672
+ value = value.replace(/%20/g, '+');
4673
+ return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
4674
+ }
5724
4675
  /**
5725
- * Installs global handlers, such as click listers and native method overrides. These are needed
5726
- * even if a no dialog is registered, as they deal with <form method="dialog">.
4676
+ * @function module:FormSerialization.deserialize
4677
+ * @param {HTMLFormElement} form
4678
+ * @param {PlainObject} hash
4679
+ * @returns {void}
5727
4680
  */
5728
4681
 
5729
- if (window.HTMLDialogElement === undefined) {
5730
- /**
5731
- * If HTMLFormElement translates method="DIALOG" into 'get', then replace the descriptor with
5732
- * one that returns the correct value.
5733
- */
5734
- var testForm = document.createElement('form');
5735
- testForm.setAttribute('method', 'dialog');
5736
4682
 
5737
- if (testForm.method !== 'dialog') {
5738
- var methodDescriptor = Object.getOwnPropertyDescriptor(HTMLFormElement.prototype, 'method');
4683
+ function deserialize(form, hash) {
4684
+ // input(text|radio|checkbox)|select(multiple)|textarea|keygen
4685
+ Object.entries(hash).forEach(function (_ref3) {
4686
+ var _ref4 = _slicedToArray(_ref3, 2),
4687
+ name = _ref4[0],
4688
+ value = _ref4[1];
5739
4689
 
5740
- if (methodDescriptor) {
5741
- // nb. Some older iOS and older PhantomJS fail to return the descriptor. Don't do anything
5742
- // and don't bother to update the element.
5743
- var realGet = methodDescriptor.get;
4690
+ var control = form[name];
4691
+ var hasBrackets = false; // istanbul ignore else
5744
4692
 
5745
- methodDescriptor.get = function () {
5746
- if (isFormMethodDialog(this)) {
5747
- return 'dialog';
5748
- }
4693
+ if (!control) {
4694
+ // Try again for jsdom
4695
+ control = form.querySelector("[name=\"".concat(name, "\"]"));
5749
4696
 
5750
- return realGet.call(this);
5751
- };
4697
+ if (!control) {
4698
+ // We want this for `RadioNodeList` so setting value
4699
+ // auto-disables other boxes
4700
+ control = form[name + '[]']; // istanbul ignore next
5752
4701
 
5753
- var realSet = methodDescriptor.set;
5754
- /** @this {HTMLElement} */
4702
+ if (!control || _typeof(control) !== 'object' || !('length' in control)) {
4703
+ // The latter query would only get a single
4704
+ // element, so if not a `RadioNodeList`, we get
4705
+ // all values here
4706
+ control = form.querySelectorAll("[name=\"".concat(name, "[]\"]"));
5755
4707
 
5756
- methodDescriptor.set = function (v) {
5757
- if (typeof v === 'string' && v.toLowerCase() === 'dialog') {
5758
- return this.setAttribute('method', v);
4708
+ if (!control.length) {
4709
+ throw new Error("Name not found ".concat(name));
4710
+ }
5759
4711
  }
5760
4712
 
5761
- return realSet.call(this, v);
5762
- };
5763
-
5764
- Object.defineProperty(HTMLFormElement.prototype, 'method', methodDescriptor);
4713
+ hasBrackets = true;
4714
+ }
5765
4715
  }
5766
- }
5767
- /**
5768
- * Global 'click' handler, to capture the <input type="submit"> or <button> element which has
5769
- * submitted a <form method="dialog">. Needed as Safari and others don't report this inside
5770
- * document.activeElement.
5771
- */
5772
-
5773
-
5774
- document.addEventListener('click', function (ev) {
5775
- dialogPolyfill.formSubmitter = null;
5776
- dialogPolyfill.imagemapUseValue = null;
5777
-
5778
- if (ev.defaultPrevented) {
5779
- return;
5780
- } // e.g. a submit which prevents default submission
5781
4716
 
4717
+ var _control = control,
4718
+ type = _control.type;
5782
4719
 
5783
- var target =
5784
- /** @type {Element} */
5785
- ev.target;
4720
+ if (type === 'checkbox') {
4721
+ control.checked = value !== '';
4722
+ }
5786
4723
 
5787
- if ('composedPath' in ev) {
5788
- var path = ev.composedPath();
5789
- target = path.shift() || target;
4724
+ if (type === 'radio' || control[0] && control[0].type === 'radio') {
4725
+ _toConsumableArray(form.querySelectorAll("[name=\"".concat(name + (hasBrackets ? '[]' : ''), "\"]"))).forEach(function (radio) {
4726
+ radio.checked = value === radio.value;
4727
+ });
5790
4728
  }
5791
4729
 
5792
- if (!target || !isFormMethodDialog(target.form)) {
4730
+ if (control[0] && control[0].type === 'select-multiple') {
4731
+ _toConsumableArray(control[0].options).forEach(function (o) {
4732
+ if (value.includes(o.value)) {
4733
+ o.selected = true;
4734
+ }
4735
+ });
4736
+
5793
4737
  return;
5794
4738
  }
5795
4739
 
5796
- var valid = target.type === 'submit' && ['button', 'input'].indexOf(target.localName) > -1;
4740
+ if (Array.isArray(value)) {
4741
+ // options on a multiple select
4742
+ if (type === 'select-multiple') {
4743
+ _toConsumableArray(control.options).forEach(function (o) {
4744
+ if (value.includes(o.value)) {
4745
+ o.selected = true;
4746
+ }
4747
+ });
5797
4748
 
5798
- if (!valid) {
5799
- if (!(target.localName === 'input' && target.type === 'image')) {
5800
4749
  return;
5801
- } // this is a <input type="image">, which can submit forms
4750
+ }
5802
4751
 
4752
+ value.forEach(function (v, i) {
4753
+ var c = control[i];
5803
4754
 
5804
- dialogPolyfill.imagemapUseValue = ev.offsetX + ',' + ev.offsetY;
5805
- }
4755
+ if (c.type === 'checkbox') {
4756
+ var isMatch = c.value === v || v === 'on';
4757
+ c.checked = isMatch;
4758
+ return;
4759
+ }
5806
4760
 
5807
- var dialog = findNearestDialog(target);
4761
+ if (c.type === 'select-multiple') {
4762
+ _toConsumableArray(c.options).forEach(function (o) {
4763
+ if (v.includes(o.value)) {
4764
+ o.selected = true;
4765
+ }
4766
+ });
5808
4767
 
5809
- if (!dialog) {
5810
- return;
5811
- }
4768
+ return;
4769
+ }
5812
4770
 
5813
- dialogPolyfill.formSubmitter = target;
5814
- }, false);
5815
- /**
5816
- * Global 'submit' handler. This handles submits of `method="dialog"` which are invalid, i.e.,
5817
- * outside a dialog. They get prevented.
5818
- */
4771
+ c.value = v;
4772
+ });
4773
+ } else {
4774
+ control.value = value;
4775
+ }
4776
+ });
4777
+ }
5819
4778
 
5820
- document.addEventListener('submit', function (ev) {
5821
- var form = ev.target;
5822
- var dialog = findNearestDialog(form);
4779
+ function getIMFFallbackResults({
4780
+ $p,
4781
+ lang,
4782
+ langs,
4783
+ langData,
4784
+ fallbackLanguages,
4785
+ resultsDisplay,
4786
+ basePath = '',
4787
+ localeCallback = false
4788
+ }) {
4789
+ return new Promise((resolve, reject) => {
4790
+ const resultsCallback = (...args) => {
4791
+ const [l10n] = args;
5823
4792
 
5824
- if (dialog) {
5825
- return; // ignore, handle there
5826
- }
4793
+ if (!$p.l10n) {
4794
+ $p.l10n = l10n;
4795
+ }
5827
4796
 
5828
- var submitter = findFormSubmitter(ev);
5829
- var formmethod = submitter && submitter.getAttribute('formmethod') || form.getAttribute('method');
4797
+ return resultsDisplay({
4798
+ l: l10n,
4799
+ lang,
4800
+ fallbackLanguages,
4801
+ imfLocales: imf.locales,
4802
+ $p,
4803
+ basePath
4804
+ }, ...args);
4805
+ };
5830
4806
 
5831
- if (formmethod === 'dialog') {
5832
- ev.preventDefault();
5833
- }
5834
- });
5835
- /**
5836
- * Replace the native HTMLFormElement.submit() method, as it won't fire the
5837
- * submit event and give us a chance to respond.
5838
- */
4807
+ const imf = IMF({
4808
+ languages: lang,
4809
+ fallbackLanguages,
5839
4810
 
5840
- var nativeFormSubmit = HTMLFormElement.prototype.submit;
4811
+ localeFileResolver(code) {
4812
+ // Todo: For editing of locales, we might instead resolve all
4813
+ // `$ref` (as with <https://github.com/whitlockjc/json-refs>) and
4814
+ // replace IMF() loadLocales behavior with our own now resolved
4815
+ // locales; see https://github.com/jdorn/json-editor/issues/132
4816
+ return basePath + langData.localeFileBasePath + langs.find(l => l.code === code).locale.$ref;
4817
+ },
5841
4818
 
5842
- var replacementFormSubmit = function () {
5843
- if (!isFormMethodDialog(this)) {
5844
- return nativeFormSubmit.call(this);
5845
- }
4819
+ async callback(...args) {
4820
+ if (localeCallback && localeCallback(...args)) {
4821
+ resolve();
4822
+ return;
4823
+ }
5846
4824
 
5847
- var dialog = findNearestDialog(this);
5848
- dialog && dialog.close();
5849
- };
4825
+ await resultsCallback(...args);
4826
+ resolve();
4827
+ }
5850
4828
 
5851
- HTMLFormElement.prototype.submit = replacementFormSubmit;
4829
+ });
4830
+ });
5852
4831
  }
5853
4832
 
5854
4833
  /*
@@ -7801,7 +6780,6 @@ class Dialog {
7801
6780
  }
7802
6781
 
7803
6782
  const dialog = jml('dialog', atts, children, $$1('#main'));
7804
- dialogPolyfill.registerDialog(dialog);
7805
6783
  dialog.showModal();
7806
6784
 
7807
6785
  if (remove) {
@@ -7896,7 +6874,6 @@ class Dialog {
7896
6874
 
7897
6875
  }
7898
6876
  }, [this.localeStrings.ok]]]]] : [])], $$1('#main'));
7899
- dialogPolyfill.registerDialog(dialog);
7900
6877
  dialog.showModal();
7901
6878
  });
7902
6879
  }
@@ -7970,7 +6947,6 @@ class Dialog {
7970
6947
 
7971
6948
  }
7972
6949
  }, [this.localeStrings.cancel]]]]], $$1('#main'));
7973
- dialogPolyfill.registerDialog(dialog);
7974
6950
  dialog.showModal();
7975
6951
  });
7976
6952
  }
@@ -15472,15 +14448,6 @@ class PluginsForWork {
15472
14448
 
15473
14449
  }
15474
14450
 
15475
- let path, babelRegister;
15476
-
15477
- if (typeof process !== 'undefined') {
15478
- /* eslint-disable node/global-require */
15479
- path = require('path');
15480
- babelRegister = require('@babel/register');
15481
- /* eslint-enable node/global-require */
15482
- }
15483
-
15484
14451
  const getWorkFiles = async function getWorkFiles(files = this.files) {
15485
14452
  const filesObj = await getJSON$1(files);
15486
14453
  const dataFiles = [];
@@ -15625,20 +14592,7 @@ const getWorkData = async function ({
15625
14592
 
15626
14593
  const pluginFieldMappings = pluginFieldMappingForWork;
15627
14594
  const [schemaObj, pluginObjects] = await Promise.all([getMetadata(schemaFile, schemaProperty, basePath), getPlugins ? Promise.all(pluginPaths.map(pluginPath => {
15628
- if (typeof process !== 'undefined') {
15629
- pluginPath = path.resolve(path.join(process.cwd(), 'node_modules/textbrowser/server', pluginPath));
15630
- babelRegister({
15631
- presets: ['@babel/env']
15632
- });
15633
- return Promise.resolve().then(() => {
15634
- return require(pluginPath); // eslint-disable-line node/global-require, import/no-dynamic-require
15635
- }).catch(err => {
15636
- // E.g., with tooltips plugin
15637
- console.log('err', err);
15638
- });
15639
- } // eslint-disable-next-line no-unsanitized/method
15640
-
15641
-
14595
+ // eslint-disable-next-line no-unsanitized/method
15642
14596
  return import(pluginPath);
15643
14597
  })) : null]);
15644
14598
  const pluginsForWork = new PluginsForWork({
@@ -18288,6 +17242,9 @@ var rtlDetect_1 = {
18288
17242
  getLangDir: rtlDetect.getLangDir
18289
17243
  };
18290
17244
 
17245
+ const {
17246
+ getLangDir
17247
+ } = rtlDetect_1;
18291
17248
  const fieldValueAliasRegex = /^.* \((.*?)\)$/;
18292
17249
 
18293
17250
  const getRawFieldValue = v => {
@@ -19188,7 +18145,7 @@ const resultsDisplayServerOrClient = async function resultsDisplayServerOrClient
19188
18145
  applicableFieldIdx,
19189
18146
  applicableFieldText,
19190
18147
  fieldLang,
19191
- getLangDir: rtlDetect_1.getLangDir,
18148
+ getLangDir,
19192
18149
  meta,
19193
18150
  metaApplicableField,
19194
18151
  $p,
@@ -19199,13 +18156,13 @@ const resultsDisplayServerOrClient = async function resultsDisplayServerOrClient
19199
18156
  });
19200
18157
  }
19201
18158
 
19202
- const localeDir = rtlDetect_1.getLangDir(preferredLocale);
18159
+ const localeDir = getLangDir(preferredLocale);
19203
18160
  const fieldDirs = fieldLangs.map(langCode => {
19204
18161
  if (!langCode) {
19205
18162
  return null;
19206
18163
  }
19207
18164
 
19208
- const langDir = rtlDetect_1.getLangDir(langCode);
18165
+ const langDir = getLangDir(langCode);
19209
18166
  return langDir !== localeDir ? langDir : null;
19210
18167
  });
19211
18168
  const templateArgs = {
@@ -19427,7 +18384,7 @@ class TextBrowser {
19427
18384
  const builtinIndex = stylesheets.indexOf('@builtin');
19428
18385
 
19429
18386
  if (builtinIndex !== -1) {
19430
- stylesheets.splice(builtinIndex, 1, new URL('index.css', moduleURL).href, new URL('node_modules/textbrowser/node_modules/dialog-polyfill/dist/dialog-polyfill.css', location).href);
18387
+ stylesheets.splice(builtinIndex, 1, new URL('index.css', moduleURL).href);
19431
18388
  }
19432
18389
 
19433
18390
  this.stylesheets = stylesheets;