jsf.js_next_gen 4.0.0-RC.1 → 4.0.0-RC.11

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.
Files changed (102) hide show
  1. package/dist/docs/assets/main.js +1 -1
  2. package/dist/docs/functions/faces.push.init.html +5 -1
  3. package/dist/docs/functions/myfaces.ab.html +2 -2
  4. package/dist/window/faces-development.js +403 -141
  5. package/dist/window/faces-development.js.br +0 -0
  6. package/dist/window/faces-development.js.gz +0 -0
  7. package/dist/window/faces-development.js.map +1 -1
  8. package/dist/window/faces.js +1 -1
  9. package/dist/window/faces.js.br +0 -0
  10. package/dist/window/faces.js.gz +0 -0
  11. package/dist/window/faces.js.map +1 -1
  12. package/dist/window/jsf-development.js +414 -141
  13. package/dist/window/jsf-development.js.br +0 -0
  14. package/dist/window/jsf-development.js.gz +0 -0
  15. package/dist/window/jsf-development.js.map +1 -1
  16. package/dist/window/jsf.js +1 -1
  17. package/dist/window/jsf.js.br +0 -0
  18. package/dist/window/jsf.js.gz +0 -0
  19. package/dist/window/jsf.js.map +1 -1
  20. package/package.json +11 -11
  21. package/src/main/typescript/@types/definitions/index.d.ts +17 -2
  22. package/src/main/typescript/api/_api.ts +4 -2
  23. package/src/main/typescript/api/jsf.ts +18 -0
  24. package/src/main/typescript/impl/AjaxImpl.ts +22 -2
  25. package/src/main/typescript/impl/PushImpl.ts +38 -12
  26. package/src/main/typescript/impl/core/Const.ts +9 -5
  27. package/src/main/typescript/impl/util/Assertions.ts +14 -6
  28. package/src/main/typescript/impl/util/AsyncQueue.ts +1 -1
  29. package/src/main/typescript/impl/util/ExtDomQuery.ts +4 -1
  30. package/src/main/typescript/impl/util/Lang.ts +3 -3
  31. package/src/main/typescript/impl/xhrCore/IResponseProcessor.ts +8 -1
  32. package/src/main/typescript/impl/xhrCore/RequestDataResolver.ts +13 -3
  33. package/src/main/typescript/impl/xhrCore/ResonseDataResolver.ts +1 -1
  34. package/src/main/typescript/impl/xhrCore/ResponseProcessor.ts +92 -30
  35. package/src/main/typescript/impl/xhrCore/XhrFormData.ts +24 -12
  36. package/src/main/typescript/myfaces/OamSubmit.ts +15 -10
  37. package/src/main/typescript/test/frameworkBase/_ext/monadish/DomQueryTest.spec.ts +1 -1
  38. package/src/main/typescript/test/frameworkBase/_ext/shared/XmlResponses.ts +40 -1
  39. package/src/main/typescript/test/xhrCore/OamSubmitTest.spec.ts +177 -0
  40. package/src/main/typescript/test/xhrCore/RequestTest.spec.ts +237 -8
  41. package/src/main/typescript/test/xhrCore/ResponseTest.spec.ts +174 -10
  42. package/src/main/typescript/test/xhrCore/ResponseTest23.spec.ts +8 -6
  43. package/src/main/typescript/test.xml +6 -0
  44. package/target/api/_api.js +3 -2
  45. package/target/api/_api.js.map +1 -1
  46. package/target/api/jsf.js +11 -0
  47. package/target/api/jsf.js.map +1 -1
  48. package/target/impl/AjaxImpl.js +18 -0
  49. package/target/impl/AjaxImpl.js.map +1 -1
  50. package/target/impl/PushImpl.js +44 -14
  51. package/target/impl/PushImpl.js.map +1 -1
  52. package/target/impl/core/Const.js +10 -8
  53. package/target/impl/core/Const.js.map +1 -1
  54. package/target/impl/util/Assertions.js +11 -6
  55. package/target/impl/util/Assertions.js.map +1 -1
  56. package/target/impl/util/AsyncQueue.js.map +1 -1
  57. package/target/impl/util/ExtDomQuery.js +3 -0
  58. package/target/impl/util/ExtDomQuery.js.map +1 -1
  59. package/target/impl/util/Lang.js +3 -3
  60. package/target/impl/util/Lang.js.map +1 -1
  61. package/target/impl/xhrCore/RequestDataResolver.js +11 -2
  62. package/target/impl/xhrCore/RequestDataResolver.js.map +1 -1
  63. package/target/impl/xhrCore/ResonseDataResolver.js +1 -1
  64. package/target/impl/xhrCore/ResonseDataResolver.js.map +1 -1
  65. package/target/impl/xhrCore/ResponseProcessor.js +85 -24
  66. package/target/impl/xhrCore/ResponseProcessor.js.map +1 -1
  67. package/target/impl/xhrCore/XhrFormData.js +18 -7
  68. package/target/impl/xhrCore/XhrFormData.js.map +1 -1
  69. package/target/myfaces/OamSubmit.js +13 -11
  70. package/target/myfaces/OamSubmit.js.map +1 -1
  71. package/target/test/frameworkBase/_ext/monadish/DomQueryTest.spec.js +1 -1
  72. package/target/test/frameworkBase/_ext/monadish/DomQueryTest.spec.js.map +1 -1
  73. package/target/test/frameworkBase/_ext/shared/XmlResponses.js +37 -1
  74. package/target/test/frameworkBase/_ext/shared/XmlResponses.js.map +1 -1
  75. package/target/test/xhrCore/OamSubmitTest.spec.js +180 -0
  76. package/target/test/xhrCore/OamSubmitTest.spec.js.map +1 -0
  77. package/target/test/xhrCore/RequestTest.spec.js +214 -7
  78. package/target/test/xhrCore/RequestTest.spec.js.map +1 -1
  79. package/target/test/xhrCore/ResponseTest.spec.js +139 -8
  80. package/target/test/xhrCore/ResponseTest.spec.js.map +1 -1
  81. package/target/test/xhrCore/ResponseTest23.spec.js +5 -5
  82. package/target/test/xhrCore/ResponseTest23.spec.js.map +1 -1
  83. package/target/classes/com/example/jsfs_js_ts/DecoratedFacesJS.class +0 -0
  84. package/target/classes/com/example/jsfs_js_ts/DecoratingResourceHandlerWrapper.class +0 -0
  85. package/target/classes/com/example/jsfs_js_ts/FacesJSMapFileResourceWrapper.class +0 -0
  86. package/target/classes/com/example/jsfs_js_ts/FacesJSMappingDecorator.class +0 -0
  87. package/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +0 -4
  88. package/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +0 -4
  89. package/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +0 -1
  90. package/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst +0 -1
  91. package/target/surefire-reports/TEST-com.example.jsfs_js_ts.JsfsJsTsApplicationTests.xml +0 -78
  92. package/target/surefire-reports/com.example.jsfs_js_ts.JsfsJsTsApplicationTests.txt +0 -7
  93. package/target/test-classes/.gz +0 -0
  94. package/target/test-classes/com/example/jsfs_js_ts/JsfsJsTsApplicationTests.class +0 -0
  95. package/target/test-classes/fileuploadtest.html +0 -24
  96. package/target/test-classes/jsf-development.js +0 -3559
  97. package/target/test-classes/jsf-development.js.br +0 -0
  98. package/target/test-classes/jsf-development.js.gz +0 -0
  99. package/target/test-classes/jsf-development.js.map +0 -1
  100. package/target/test-classes/jsf.js +0 -3
  101. package/target/test-classes/jsf.js.br +0 -0
  102. package/target/test-classes/jsf.js.gz +0 -0
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import {Config, DomQuery, DQ, Lang, Stream, XMLQuery} from "mona-dish";
17
+ import {Config, DomQueryCollector, DQ, DQ$, Lang, LazyStream, Stream, XMLQuery} from "mona-dish";
18
18
  import {Implementation} from "../AjaxImpl";
19
19
  import {Assertions} from "../util/Assertions";
20
20
  import {IResponseProcessor} from "./IResponseProcessor";
@@ -40,7 +40,6 @@ import {
40
40
  P_PARTIAL_SOURCE,
41
41
  P_VIEWSTATE,
42
42
  RESPONSE_XML, SEL_CLIENT_WINDOW_ELEM,
43
- SEL_SCRIPTS_STYLES,
44
43
  SEL_VIEWSTATE_ELEM,
45
44
  SOURCE,
46
45
  SUCCESS,
@@ -52,7 +51,7 @@ import {
52
51
  TAG_HEAD,
53
52
  UPDATE_ELEMS,
54
53
  UPDATE_FORMS,
55
- DEFERRED_HEAD_INSERTS
54
+ DEFERRED_HEAD_INSERTS, PARTIAL_ID, P_EXECUTE, P_RENDER, HTML_CLIENT_WINDOW
56
55
  } from "../core/Const";
57
56
  import trim = Lang.trim;
58
57
  import {ExtConfig, ExtDomQuery} from "../util/ExtDomQuery";
@@ -86,27 +85,31 @@ export class ResponseProcessor implements IResponseProcessor {
86
85
  if (!shadowHead.isPresent()) {
87
86
  return;
88
87
  }
88
+ let head = ExtDomQuery.querySelectorAll(TAG_HEAD);
89
+ // full replace we delete everything
90
+ head.childNodes.delete();
91
+ this.addToHead(shadowHead);
92
+ }
89
93
 
90
- let oldHead = ExtDomQuery.querySelectorAll(TAG_HEAD);
91
-
92
- //delete all to avoid script and style overlays
93
- oldHead.querySelectorAll(SEL_SCRIPTS_STYLES).delete();
94
+ addToHead(shadowHead: XMLQuery | DQ) {
95
+ const mappedHeadData = new ExtDomQuery(shadowHead);
96
+ const postProcessTags = ["STYLE", "LINK", "SCRIPT"];
97
+ const nonExecutables = mappedHeadData.filter(item => postProcessTags.indexOf(item.tagName.orElse("").value) == -1);
98
+ nonExecutables.runHeadInserts(true);
94
99
 
95
- // we cannot replace new elements in the head, but we can eval the elements
96
- // eval means the scripts will get attached (eval script attach method)
97
- // but this is done by DomQuery not in this code
98
- this.storeForEval(shadowHead);
99
100
  //incoming either the outer head tag or its children
100
- //shadowHead = (shadowHead.tagName.value === "HEAD") ? shadowHead.childNodes : shadowHead;
101
- //this.addToHead(shadowHead);
101
+ const nodesToAdd = (shadowHead.tagName.value === "HEAD") ? shadowHead.childNodes : shadowHead;
102
+ // this is stored for post processing
103
+ // after the rest of the "pyhsical build up", head before body
104
+ const evalElements = nodesToAdd.stream
105
+ .filter(item => postProcessTags.indexOf(item.tagName.orElse("").value) != -1).collect(new DomQueryCollector());
106
+ this.addToHeadDeferred(evalElements);
102
107
  }
103
108
 
104
- addToHead(newElements: XMLQuery | DQ) {
109
+ addToHeadDeferred(newElements: XMLQuery | DQ) {
105
110
  this.internalContext.assign(DEFERRED_HEAD_INSERTS).value.push(newElements);
106
111
  }
107
112
 
108
-
109
-
110
113
  /**
111
114
  * replaces the body in the expected manner
112
115
  * which means the entire body content is refreshed
@@ -200,7 +203,7 @@ export class ResponseProcessor implements IResponseProcessor {
200
203
  */
201
204
  update(node: XMLQuery, cdataBlock: string) {
202
205
  let result = ExtDomQuery.byId(node.id.value, true).outerHTML(cdataBlock, false, false);
203
- let sourceForm = result?.parents(TAG_FORM).orElseLazy(() => result.byTagName(TAG_FORM, true));
206
+ let sourceForm = result?.firstParent(TAG_FORM).orElseLazy(() => result.byTagName(TAG_FORM, true));
204
207
  if (sourceForm) {
205
208
  this.storeForPostProcessing(sourceForm, result);
206
209
  }
@@ -335,14 +338,18 @@ export class ResponseProcessor implements IResponseProcessor {
335
338
  Stream.ofAssoc<StateHolder>(this.internalContext.getIf(APPLIED_VST).orElse({}).value)
336
339
  .each((item: Array<any>) => {
337
340
  let value: StateHolder = item[1];
338
- let nameSpace = DQ.byId(value.nameSpace, true).orElse(document.body);
339
- let affectedForms = nameSpace.byTagName(TAG_FORM);
340
- let affectedForms2 = nameSpace.filter(item => item.tagName.orElse(EMPTY_STR).value.toLowerCase() == TAG_FORM);
341
+ let namingContainerId = this.internalContext.getIf(PARTIAL_ID);
342
+ let affectedForms;
341
343
 
342
- this.appendViewStateToForms(new DomQuery(affectedForms, affectedForms2), value.value);
344
+ affectedForms = this.getContainerForms(namingContainerId)
345
+ .filter(affectedForm => this.executeOrRenderFilter(affectedForm));
346
+
347
+ this.appendViewStateToForms(affectedForms, value.value);
343
348
  });
344
349
  }
345
350
 
351
+
352
+
346
353
  /**
347
354
  * same as with view states before applies the incoming client windows as last step after the rest of the processing
348
355
  * is done.
@@ -350,12 +357,14 @@ export class ResponseProcessor implements IResponseProcessor {
350
357
  fixClientWindow() {
351
358
  Stream.ofAssoc<StateHolder>(this.internalContext.getIf(APPLIED_CLIENT_WINDOW).orElse({}).value)
352
359
  .each((item: Array<any>) => {
353
- let value: StateHolder = item[1];
354
- let nameSpace = DQ.byId(value.nameSpace, true).orElse(document.body);
355
- let affectedForms = nameSpace.byTagName(TAG_FORM);
356
- let affectedForms2 = nameSpace.filter(item => item.tagName.orElse(EMPTY_STR).value.toLowerCase() == TAG_FORM);
360
+ const value: StateHolder = item[1];
361
+ const namingContainerId = this.internalContext.getIf(PARTIAL_ID);
362
+ let affectedForms;
357
363
 
358
- this.appendClientWindowToForms(new DomQuery(affectedForms, affectedForms2), value.value);
364
+ affectedForms = this.getContainerForms(namingContainerId)
365
+ .filter(affectedForm => this.executeOrRenderFilter(affectedForm));
366
+
367
+ this.appendClientWindowToForms(affectedForms, value.value);
359
368
  });
360
369
  }
361
370
 
@@ -403,7 +412,11 @@ export class ResponseProcessor implements IResponseProcessor {
403
412
  private assignState(forms: DQ, selector: string, state: string) {
404
413
  forms.each((form: DQ) => {
405
414
  let stateHolders = form.querySelectorAll(selector)
406
- .orElseLazy(() => ResponseProcessor.newViewStateElement(form));
415
+ .orElseLazy(() => {
416
+ return selector.indexOf("ViewState") != -1 ?
417
+ ResponseProcessor.newViewStateElement(form):
418
+ ResponseProcessor.newClientWindowElement(form);
419
+ });
407
420
 
408
421
  stateHolders.attr("value").value = state;
409
422
  });
@@ -416,9 +429,21 @@ export class ResponseProcessor implements IResponseProcessor {
416
429
  * (usually a form node)
417
430
  */
418
431
  private static newViewStateElement(parent: DQ): DQ {
419
- let newViewState = DQ.fromMarkup($nsp(HTML_VIEWSTATE));
420
- newViewState.appendTo(parent);
421
- return newViewState;
432
+ let newElement = DQ.fromMarkup($nsp(HTML_VIEWSTATE));
433
+ newElement.appendTo(parent);
434
+ return newElement;
435
+ }
436
+
437
+ /**
438
+ * Helper to Create a new JSF ViewState Element
439
+ *
440
+ * @param parent, the parent node to attach the viewState element to
441
+ * (usually a form node)
442
+ */
443
+ private static newClientWindowElement(parent: DQ): DQ {
444
+ let newElement = DQ.fromMarkup($nsp(HTML_CLIENT_WINDOW));
445
+ newElement.appendTo(parent);
446
+ return newElement;
422
447
  }
423
448
 
424
449
  /**
@@ -480,5 +505,42 @@ export class ResponseProcessor implements IResponseProcessor {
480
505
  this.externalContext.getIf(ON_ERROR).orElse(this.internalContext.getIf(ON_ERROR).value).orElse(EMPTY_FUNC).value(errorData);
481
506
  }
482
507
 
508
+ /**
509
+ * filters the forms according to being in the execute or render cycle
510
+ * @param affectedForm
511
+ * @private
512
+ */
513
+ private executeOrRenderFilter(affectedForm) {
514
+ let executes = this.externalContext.getIf($nsp(P_EXECUTE)).orElse("@none").value.split(/\s+/gi);
515
+ let renders = this.externalContext.getIf($nsp(P_RENDER)).orElse("@none").value.split(/\s+/gi);
516
+ let executeAndRenders = executes.concat(...renders);
517
+ return LazyStream.of(...executeAndRenders).filter(nameOrId => {
518
+ if (nameOrId == "@all") {
519
+ return true;
520
+ }
521
+ if (nameOrId == "@none") {
522
+ return true;
523
+ }
524
+
525
+ const nameOrIdSelector = `[id='${nameOrId}'], [name='#${nameOrId}']`;
526
+ //either the form directly is in execute or render or one of its children or one of its parents
527
+ return affectedForm.matchesSelector(nameOrIdSelector) ||
528
+ affectedForm.querySelectorAll(nameOrIdSelector).isPresent() ||
529
+ affectedForm.firstParent(nameOrIdSelector).isPresent();
530
+ }).first().isPresent();
531
+ }
483
532
 
533
+ /**
534
+ * gets all forms under a single naming container id
535
+ * @param namingContainerId
536
+ * @private
537
+ */
538
+ private getContainerForms(namingContainerId: Config) {
539
+ if (namingContainerId.isPresent()) {
540
+ //naming container mode, all forms under naming container id must be processed
541
+ return DQ.byId(namingContainerId.value).orElse(DQ$(`form[name='${namingContainerId.value}']`)).byTagName(TAG_FORM, true);
542
+ } else {
543
+ return DQ.byTagName(TAG_FORM);
544
+ }
545
+ }
484
546
  }
@@ -16,7 +16,7 @@
16
16
  import {ArrayCollector, Config, DQ, Lang, LazyStream, Stream} from "mona-dish";
17
17
  import {EMPTY_STR, IDENT_ALL, IDENT_FORM, P_VIEWSTATE} from "../core/Const";
18
18
  import isString = Lang.isString;
19
- import {ExtConfig} from "../util/ExtDomQuery";
19
+ import {ExtConfig, ExtDomQuery} from "../util/ExtDomQuery";
20
20
 
21
21
 
22
22
  /**
@@ -54,15 +54,20 @@ export class XhrFormData extends Config {
54
54
  //a call to getViewState before must pass the encoded line
55
55
  //a call from getViewState passes the form element as datasource,
56
56
  //so we have two call points
57
+ // atm we basically encode twice, to keep the code leaner
58
+ // this will be later optmized, practically elements
59
+ // which are already covered by an external viewstate do not need
60
+ // the encoding a second time, because they are overwritten by the viewstate again
57
61
  if (isString(dataSource)) {
58
62
  this.assignEncodedString(<string>this.dataSource);
59
63
  } else {
60
64
  this.applyFormDataToConfig();
61
65
  }
62
- if('undefined' != typeof viewState) {
66
+ //now assign the external viewstate overrides
67
+ if ('undefined' != typeof viewState) {
63
68
  this.assignEncodedString(viewState)
64
69
  }
65
- if(executes) {
70
+ if (executes) {
66
71
  this.postInit(...executes);
67
72
  }
68
73
  }
@@ -73,14 +78,17 @@ export class XhrFormData extends Config {
73
78
  * in our ajax request
74
79
  */
75
80
  postInit(...executes: Array<string>) {
76
- let fetchInput = (id: string): DQ => {
81
+ let fetchFileInputs = (id: string): DQ => {
82
+ const INPUT_FILE = "input[type='file']";
77
83
  if (id == IDENT_ALL) {
78
- return DQ.querySelectorAllDeep("input[type='file']");
84
+ return DQ.querySelectorAllDeep(INPUT_FILE);
79
85
  } else if (id == IDENT_FORM) {
80
- return (<DQ>this.dataSource).querySelectorAllDeep("input[type='file']");
86
+ return (<DQ>this.dataSource).matchesSelector(INPUT_FILE) ?
87
+ (<DQ>this.dataSource) :
88
+ (<DQ>this.dataSource).querySelectorAllDeep(INPUT_FILE);
81
89
  } else {
82
90
  let element = DQ.byId(id, true);
83
- return this.getFileInputs(element);
91
+ return element.matchesSelector(INPUT_FILE) ? element : this.getFileInputs(element);
84
92
  }
85
93
  };
86
94
 
@@ -90,7 +98,7 @@ export class XhrFormData extends Config {
90
98
 
91
99
 
92
100
  this.isMultipartRequest = LazyStream.of(...executes)
93
- .map(fetchInput)
101
+ .map(fetchFileInputs)
94
102
  .filter(inputExists)
95
103
  .first().isPresent();
96
104
  }
@@ -113,8 +121,8 @@ export class XhrFormData extends Config {
113
121
  assignEncodedString(encoded: string) {
114
122
  // this code filters out empty strings as key value pairs
115
123
  let keyValueEntries = decodeURIComponent(encoded).split(/&/gi)
116
- .filter(item => !!(item || '')
117
- .replace(/\s+/g,''));
124
+ .filter(item => !!(item || '')
125
+ .replace(/\s+/g, ''));
118
126
  this.assignString(keyValueEntries);
119
127
  }
120
128
 
@@ -133,8 +141,8 @@ export class XhrFormData extends Config {
133
141
  return keyVal.length < 3 ? [keyVal?.[0] ?? [], keyVal?.[1] ?? []] : keyVal;
134
142
  }
135
143
 
144
+ //TODO fix files...
136
145
  Stream.of(...keyValueEntries)
137
- //split only the first =
138
146
  .map(line => splitToKeyVal(line))
139
147
  //special case of having keys without values
140
148
  .map(keyVal => fixKeyWithoutVal(keyVal))
@@ -171,7 +179,11 @@ export class XhrFormData extends Config {
171
179
  }
172
180
  let entries = LazyStream.of(...Object.keys(this.value))
173
181
  .filter(key => this.value.hasOwnProperty(key))
174
- .flatMap(key => Stream.of(...this.value[key]).map(val => [key, val]).collect(new ArrayCollector()))
182
+ .flatMap(key => Stream.of(...this.value[key]).map(val => [key, val])
183
+ //we cannot encode file elements that is handled by multipart requests anyway
184
+ .filter(([, value]) => !(value instanceof ExtDomQuery.global().File))
185
+ .collect(new ArrayCollector()))
186
+
175
187
  .map(keyVal => {
176
188
  return `${encodeURIComponent(keyVal[0])}=${encodeURIComponent(keyVal[1])}`;
177
189
  })
@@ -62,18 +62,22 @@ export module oam {
62
62
  DQ.byId(element).delete();
63
63
  };
64
64
 
65
- // noinspection JSUnusedGlobalSymbols
65
+ // noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols
66
66
  /**
67
67
  * does special form submit remapping
68
68
  * re-maps the issuing command link into something,
69
- * a decode of the command link on the server can understand
69
+ * the "decode" of the command link on the server can understand
70
70
  *
71
71
  * @param formName
72
72
  * @param linkId
73
73
  * @param target
74
74
  * @param params
75
75
  */
76
- export const submitForm = function (formName: string, linkId: string, target: string, params: { [key: string]: any }): boolean {
76
+ export const submitForm = function (formName: string, linkId: string | null = null, target: string |null = null, params: AssocArr<any> | Tuples<string, any> | null = {} ): boolean {
77
+
78
+ //handle a possible incoming null, not sure if this is used that way anywhere, but we allow it
79
+ params = (!params) ? {} : params;
80
+
77
81
  let clearFn = 'clearFormHiddenParams_' + formName.replace(/-/g, '\$:').replace(/:/g, '_');
78
82
  window?.[clearFn]?.(formName);
79
83
 
@@ -81,14 +85,14 @@ export module oam {
81
85
  if (window?.myfaces?.core?.config?.autoScroll && (window as any)?.getScrolling) {
82
86
  myfaces.oam.setHiddenInput(formName, 'autoScroll', (window as any)?.getScrolling());
83
87
  }
84
- Stream.ofAssoc(params).each((param: [string, any]) => {
85
- myfaces.oam.setHiddenInput(formName, param[0], param[1]);
86
- });
88
+ let paramsStream: Stream<[string, any]> = Array.isArray(params) ? Stream.of(...params) : Stream.ofAssoc(params);
89
+ paramsStream.each(([key, data]) => myfaces.oam.setHiddenInput(formName, key, data));
87
90
 
88
91
  //we call the namespaced function, to allow decoration, via a direct call we would
89
- myfaces.oam.setHiddenInput(formName, `${formName}:_idcl`, linkId);
92
+ myfaces.oam.setHiddenInput(formName, `${formName}:_idcl`, linkId ?? '');
93
+
90
94
 
91
- DQ.byId(document.forms[formName]).each(form => {
95
+ DQ.byId(document.forms?.[formName] ?? document.getElementById(formName)).each(form => {
92
96
  const ATTR_TARGET = "target";
93
97
  const formElement = form.getAsElem(0).value as HTMLFormElement;
94
98
  const oldTarget = form.attr(ATTR_TARGET).value;
@@ -104,8 +108,9 @@ export module oam {
104
108
  window?.console.error(e);
105
109
  } finally {
106
110
  form.attr(ATTR_TARGET).value = oldTarget;
107
- Stream.ofAssoc(params).each((param: [string, any]) => {
108
- myfaces.oam.clearHiddenInput(formName, param[0]);
111
+ // noinspection JSUnusedLocalSymbols
112
+ paramsStream.each(([key, data]) => {
113
+ myfaces.oam.clearHiddenInput(formName, key);
109
114
  });
110
115
  myfaces.oam.clearHiddenInput(formName, `${formName}:_idcl`);
111
116
  }
@@ -319,7 +319,7 @@ describe('DOMQuery tests', function () {
319
319
 
320
320
  it('it must have parents', function () {
321
321
  let probe1 = new DomQuery(document).querySelectorAll("div");
322
- let coll: Array<any> = probe1.parents("body").stream.collect(new ArrayCollector());
322
+ let coll: Array<any> = probe1.firstParent("body").stream.collect(new ArrayCollector());
323
323
  expect(coll.length == 1).to.be.true;
324
324
 
325
325
  });
@@ -194,7 +194,7 @@ export class XmlResponses {
194
194
  <partial-response id="j_id__v_0"><changes><update id="jakarta.faces.Resource">
195
195
  <![CDATA[
196
196
  <script src="../../../xhrCore/fixtures/addedViewHead3.js"></script>
197
- <style type="text/css" rel="../../../xhrCore/fixtures/addedViewHead2.css"></style>
197
+ <link rel="stylesheet" href="../../../xhrCore/fixtures/addedViewHead2.css"></link>
198
198
  <script type="text/javascript">
199
199
  document.getElementById('resource_area_1').innerHTML = 'booga';
200
200
  </script>
@@ -204,6 +204,45 @@ export class XmlResponses {
204
204
  </partial-response>
205
205
  `
206
206
 
207
+ static HEAD_REPLACE = `
208
+ <partial-response id="j_id__v_0"><changes><update id="jakarta.faces.ViewHead">
209
+ <![CDATA[
210
+ <head>
211
+ <script type="text/javascript" src="../../../xhrCore/fixtures/addedViewHead3.js"></script>
212
+ <link rel="stylesheet" href="../../../xhrCore/fixtures/addedViewHead2.css"></link>
213
+ <script type="text/javascript">
214
+ setTimeout(() => document.getElementById('resource_area_1').innerHTML = 'booga', 100);
215
+ </script>
216
+ </head>
217
+ ]]>
218
+ </update>
219
+ </changes>
220
+ </partial-response>
221
+ `
222
+
223
+ static HEAD_REPLACE2 = `
224
+ <partial-response id="j_id__v_0"><changes><update id="jakarta.faces.ViewHead">
225
+ <![CDATA[
226
+ <head>
227
+ <title>After Update</title>
228
+ <meta charset="UTF-8">
229
+ <meta name="description" content="Free Web tutorials">
230
+ <meta name="keywords" content="HTML, CSS, JavaScript, JSF">
231
+ <meta name="viewport" content="width=device-width, initial-scale=0.8">
232
+ <meta name="author" content="Whoever">
233
+ <script type="text/javascript" src="../../../xhrCore/fixtures/addedViewHead3.js"></script>
234
+ <link rel="stylesheet" href="../../../xhrCore/fixtures/addedViewHead2.css"></link>
235
+ <script type="text/javascript">
236
+ setTimeout(() => document.getElementById('resource_area_1').innerHTML = 'booga', 100);
237
+ </script>
238
+ </head>
239
+ ]]>
240
+ </update>
241
+ </changes>
242
+ </partial-response>
243
+ `
244
+
245
+
207
246
  static NONCE_REPLY = `
208
247
  <partial-response><changes><update id='nonce_result'>
209
248
  <![CDATA[<script nonce='test12d3' type='text/javascript' src='http://foobaz/nonce_script.js'></script>]]>
@@ -0,0 +1,177 @@
1
+ /*! Licensed to the Apache Software Foundation (ASF) under one or more
2
+ * contributor license agreements. See the NOTICE file distributed with
3
+ * this work for additional information regarding copyright ownership.
4
+ * The ASF licenses this file to you under the Apache License, Version 2.0
5
+ * (the "License"); you may not use this file except in compliance with
6
+ * the License. You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import {describe} from "mocha";
18
+ import * as sinon from "sinon";
19
+ import {Implementation} from "../../impl/AjaxImpl";
20
+ import {StandardInits} from "../frameworkBase/_ext/shared/StandardInits";
21
+ import defaultMyFaces = StandardInits.defaultMyFaces;
22
+ import {DQ, DQ$} from "mona-dish";
23
+ import {expect} from "chai";
24
+
25
+ describe('Tests for the MyFaces specifig oam submit', function () {
26
+
27
+ beforeEach(async function () {
28
+
29
+ let waitForResult = defaultMyFaces();
30
+
31
+ return waitForResult.then((close) => {
32
+
33
+ this.xhr = sinon.useFakeXMLHttpRequest();
34
+ this.requests = [];
35
+ this.xhr.onCreate = (xhr) => {
36
+ this.requests.push(xhr);
37
+ };
38
+ (<any>global).XMLHttpRequest = this.xhr;
39
+ window.XMLHttpRequest = this.xhr;
40
+
41
+ this.jsfAjaxResponse = sinon.spy((<any>global).faces.ajax, "response");
42
+
43
+ this.closeIt = () => {
44
+ (<any>global).XMLHttpRequest = window.XMLHttpRequest = this.xhr.restore();
45
+ this.jsfAjaxResponse.restore();
46
+ Implementation.reset();
47
+ close();
48
+ }
49
+ });
50
+ });
51
+
52
+ afterEach(function () {
53
+ this.closeIt();
54
+ });
55
+
56
+ it(("must handle oam submit correctly, tuples"), (done) => {
57
+
58
+ let options = [["booga1", "value1"], ["booga2", "value2"]];
59
+
60
+ (DQ.byId("blarg")
61
+ .getAsElem(0).value as HTMLFormElement).onsubmit = (evt) => {
62
+ expect(DQ$("#blarg #booga1").inputValue.value).to.eq("value1");
63
+ expect(DQ$("#blarg #booga2").inputValue.value).to.eq("value2");
64
+ done();
65
+ return false;
66
+ };
67
+
68
+ myfaces.oam.submitForm("blarg", null, null, options);
69
+
70
+ });
71
+ it(("must handle oam submit correctly, associative array"), (done) => {
72
+
73
+ let options = {"booga1": "value1", "booga2": "value2"};
74
+
75
+ (DQ.byId("blarg")
76
+ .getAsElem(0).value as HTMLFormElement).onsubmit = (evt) => {
77
+ expect(DQ$("#blarg #booga1").inputValue.value).to.eq("value1");
78
+ expect(DQ$("#blarg #booga2").inputValue.value).to.eq("value2");
79
+ done();
80
+ return false;
81
+ };
82
+
83
+ myfaces.oam.submitForm("blarg", null, null, options);
84
+
85
+ });
86
+
87
+ it(("all hidden inputs must be cleared post submit"), (done) => {
88
+
89
+ let options = {"booga1": "value1", "booga2": "value2"};
90
+
91
+ (DQ.byId("blarg")
92
+ .getAsElem(0).value as HTMLFormElement).onsubmit = (evt) => {
93
+ expect(DQ$("#blarg #booga1").length).to.eq(1);
94
+ expect(DQ$("#blarg #booga2").length).to.eq(1);
95
+ return false;
96
+ };
97
+
98
+ myfaces.oam.submitForm("blarg", null, null, options);
99
+
100
+ expect(DQ$("#blarg #booga1").length).to.eq(0);
101
+ expect(DQ$("#blarg #booga2").length).to.eq(0);
102
+ done();
103
+ });
104
+
105
+ it(("must handle linkid correctly, associative array"), (done) => {
106
+
107
+ let options = {"booga1": "value1", "booga2": "value2"};
108
+
109
+ (DQ.byId("blarg")
110
+ .getAsElem(0).value as HTMLFormElement).onsubmit = (evt) => {
111
+ expect(DQ.byId(`blarg:_idcl`).inputValue.value).to.eq("bla");
112
+ done();
113
+ return false;
114
+ };
115
+
116
+ myfaces.oam.submitForm("blarg", "bla", null, options);
117
+
118
+ });
119
+
120
+ it(("must handle target correctly, associative array"), (done) => {
121
+
122
+ let options = {"booga1": "value1", "booga2": "value2"};
123
+ (DQ.byId("blarg")
124
+ .getAsElem(0).value as HTMLFormElement).onsubmit = (evt) => {
125
+ expect(DQ$(`#blarg`).attr("target").value).to.eq("target1");
126
+ done();
127
+ return false;
128
+ };
129
+ myfaces.oam.submitForm("blarg", "bla", "target1", options);
130
+
131
+ });
132
+
133
+ it(("must handle limited parameters"), (done) => {
134
+
135
+ (DQ.byId("blarg")
136
+ .getAsElem(0).value as HTMLFormElement).onsubmit = (evt) => {
137
+ expect(DQ.byId(`blarg:_idcl`).inputValue.value).to.eq("bla");
138
+ done();
139
+ return false;
140
+ };
141
+ try {
142
+ myfaces.oam.submitForm("blarg", "bla");
143
+ } catch(e) {
144
+ done(e);
145
+ }
146
+
147
+ });
148
+ it(("must handle limited parameters 2"), (done) => {
149
+
150
+ (DQ.byId("blarg")
151
+ .getAsElem(0).value as HTMLFormElement).onsubmit = (evt) => {
152
+ expect(DQ.byId(`blarg:_idcl`).inputValue.value).to.eq("bla");
153
+ done();
154
+ return false;
155
+ };
156
+ try {
157
+ myfaces.oam.submitForm("blarg", "bla", null);
158
+ } catch(e) {
159
+ done(e);
160
+ }
161
+ });
162
+ it(("must handle limited parameters 3"), (done) => {
163
+
164
+ (DQ.byId("blarg")
165
+ .getAsElem(0).value as HTMLFormElement).onsubmit = (evt) => {
166
+ expect(DQ.byId(`blarg:_idcl`).inputValue.value).to.eq("bla");
167
+ done();
168
+ return false;
169
+ };
170
+ try {
171
+ myfaces.oam.submitForm("blarg", "bla", null, null);
172
+ } catch(e) {
173
+ done(e);
174
+ }
175
+ });
176
+
177
+ });