jsf.js_next_gen 1.0.0-beta-16 → 1.0.0-beta-18

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 (35) hide show
  1. package/dist/window/jsf-development.js +318 -212
  2. package/dist/window/jsf-development.js.map +1 -1
  3. package/dist/window/jsf.js +1 -1
  4. package/dist/window/jsf.js.br +0 -0
  5. package/dist/window/jsf.js.gz +0 -0
  6. package/dist/window/jsf.js.map +1 -1
  7. package/package.json +2 -2
  8. package/src/main/typescript/impl/AjaxImpl.ts +84 -48
  9. package/src/main/typescript/impl/util/AsyncQueue.ts +30 -17
  10. package/src/main/typescript/impl/util/AsyncRunnable.ts +5 -3
  11. package/src/main/typescript/impl/util/ExtDomQuery.ts +8 -8
  12. package/src/main/typescript/impl/xhrCore/EventData.ts +2 -2
  13. package/src/main/typescript/impl/xhrCore/RequestDataResolver.ts +3 -3
  14. package/src/main/typescript/impl/xhrCore/ResonseDataResolver.ts +3 -3
  15. package/src/main/typescript/impl/xhrCore/ResponseProcessor.ts +31 -11
  16. package/src/main/typescript/impl/xhrCore/XhrFormData.ts +86 -90
  17. package/src/main/typescript/impl/xhrCore/XhrRequest.ts +34 -28
  18. package/target/impl/AjaxImpl.js +80 -39
  19. package/target/impl/AjaxImpl.js.map +1 -1
  20. package/target/impl/util/AsyncQueue.js +28 -15
  21. package/target/impl/util/AsyncQueue.js.map +1 -1
  22. package/target/impl/util/ExtDomQuery.js +7 -7
  23. package/target/impl/util/ExtDomQuery.js.map +1 -1
  24. package/target/impl/xhrCore/EventData.js +2 -2
  25. package/target/impl/xhrCore/EventData.js.map +1 -1
  26. package/target/impl/xhrCore/RequestDataResolver.js +3 -3
  27. package/target/impl/xhrCore/RequestDataResolver.js.map +1 -1
  28. package/target/impl/xhrCore/ResonseDataResolver.js +3 -3
  29. package/target/impl/xhrCore/ResonseDataResolver.js.map +1 -1
  30. package/target/impl/xhrCore/ResponseProcessor.js +31 -9
  31. package/target/impl/xhrCore/ResponseProcessor.js.map +1 -1
  32. package/target/impl/xhrCore/XhrFormData.js +86 -88
  33. package/target/impl/xhrCore/XhrFormData.js.map +1 -1
  34. package/target/impl/xhrCore/XhrRequest.js +32 -27
  35. package/target/impl/xhrCore/XhrRequest.js.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsf.js_next_gen",
3
- "version": "1.0.0-beta-16",
3
+ "version": "1.0.0-beta-18",
4
4
  "description": "A next generation typescript reimplementation of jsf.js",
5
5
  "main": "dist/window/jsf.js",
6
6
  "scripts": {
@@ -48,6 +48,6 @@
48
48
  "webpack-dev-server": "^4.11.1"
49
49
  },
50
50
  "dependencies": {
51
- "mona-dish": "0.21.16"
51
+ "mona-dish": "0.21.17"
52
52
  }
53
53
  }
@@ -95,6 +95,54 @@ enum BlockFilter {
95
95
  * however a dedicated api makes sense for readability reasons
96
96
  */
97
97
  export module Implementation {
98
+ /*
99
+ Small internal explanation, this code is optimized for readability
100
+ and cuts off a ton of old legacy code.
101
+ Aka older browsers are not supported anymore.
102
+ We use a self written helper library to keep the number of exernal
103
+ code dependencies down.
104
+ The library is called mona-dish and started as a small sideproject of mine
105
+ it provides following
106
+
107
+ a) Monad like structures for querying because this keeps the code denser and adds abstractions
108
+ that always was the strong point of jquery and it still is better in this regard than what ecmascript provides
109
+
110
+ b) Streams and lazystreams like java has, a pull like construct, ecmascript does not have anything like Lazystreams.
111
+ Another option would have been rxjs but that would have introduced a code dependency and probably more code. We might
112
+ move to RXJS if the need arises however. But for now I would rather stick with my small self grown library which works
113
+ quite well and where I can patch quickly (I have used it in several industrial projects, so it works well
114
+ and is heavily fortified by unit tests (140 testcases as time of writing this))
115
+
116
+ c) A neutral json like configuration which allows assignments of arbitrary values with reduce code which then can be
117
+ transformed into different data representations
118
+
119
+ examples:
120
+ internalCtx.assign(MYPARAM, CTX_PARAM_SRC_FRM_ID).value = form.id.value;
121
+ passes a value into context.MYPARAM.CTX_PARAM_SRC_FRM_ID
122
+
123
+ basically an abbreviation for
124
+
125
+ internalCtxt[MYPARAM] = internalCtxt?.[MYPARAM] ? internalCtxt[MYPARAM] : {};
126
+ internalCtxt[MYPARAM][CTX_PARAM_SRC_FRM_ID] = internalCtxt?.[MYPARAM][CTX_PARAM_SRC_FRM_ID] ? internalCtxt[MYPARAM][CTX_PARAM_SRC_FRM_ID] : {};
127
+ internalCtxt[MYPARAM][CTX_PARAM_SRC_FRM_ID] = form.id.value;
128
+
129
+
130
+ internalCtx.assign(condition, MYPARAM, CTX_PARAM_SRC_FRM_ID).value = form.id.value;
131
+ passes a value into context.MYPARAM.CTX_PARAM_SRC_FRM_ID if condition === true otherwise it is ignored
132
+
133
+ abbreviates:
134
+ if(condition) {
135
+ internalCtxt[MYPARAM] = internalCtxt?.[MYPARAM] ? internalCtxt[MYPARAM] : {};
136
+ internalCtxt[MYPARAM][CTX_PARAM_SRC_FRM_ID] = internalCtxt?.[MYPARAM][CTX_PARAM_SRC_FRM_ID] ? internalCtxt[MYPARAM][CTX_PARAM_SRC_FRM_ID] : {};
137
+ internalCtxt[MYPARAM][CTX_PARAM_SRC_FRM_ID] = form.id.value;
138
+ }
139
+
140
+
141
+ d) Optional constructs, while under heavy debate we only use them lightly where the api requires it from mona-dish
142
+
143
+ Note the inclusion of this library uses a reduced build which only includes the part of it, which we really use
144
+
145
+ */
98
146
 
99
147
  import trim = Lang.trim;
100
148
  import getMessage = ExtLang.getMessage;
@@ -170,8 +218,9 @@ export module Implementation {
170
218
 
171
219
  return LazyStream.of(...funcs)
172
220
  .map(func => resolveAndExecute(source, event, func))
173
- // we use the return false == stop as an early stop
221
+ // we use the return false == stop as an early stop, onElem stops at the first false
174
222
  .onElem((opResult: boolean) => opResult)
223
+ //last ensures we run until the first false is returned
175
224
  .last().value;
176
225
  }
177
226
 
@@ -208,17 +257,27 @@ export module Implementation {
208
257
 
209
258
  Assertions.assertRequestIntegrity(options, elem);
210
259
 
211
- requestCtx.assignIf(!!windowId, P_WINDOW_ID).value = windowId;
260
+ /**
261
+ * fetch the parent form
262
+ *
263
+ * note we also add an override possibility here
264
+ * so that people can use dummy forms and work
265
+ * with detached objects
266
+ */
267
+ const form: DQ = resolveForm(requestCtx, elem, resolvedEvent);
268
+ const formId = form.id.value;
269
+ const delay: number = resolveDelay(options);
270
+ const timeout: number = resolveTimeout(options);
212
271
 
272
+ requestCtx.assignIf(!!windowId, P_WINDOW_ID).value = windowId;
213
273
  requestCtx.assign(CTX_PARAM_PASS_THR).value = filterPassthroughValues(options.value);
214
-
215
274
  requestCtx.assignIf(!!resolvedEvent, CTX_PARAM_PASS_THR, P_EVT).value = resolvedEvent?.type;
216
275
 
217
276
  /**
218
277
  * ajax pass through context with the source
219
- * onresolvedEvent and onerror
278
+ * onresolved Event and onerror Event
220
279
  */
221
- requestCtx.assign(SOURCE).value = elementId.value;
280
+ requestCtx.assign(SOURCE).value = elementId;
222
281
 
223
282
  /**
224
283
  * on resolvedEvent and onError...
@@ -232,30 +291,17 @@ export module Implementation {
232
291
  * lets drag the myfaces config params also in
233
292
  */
234
293
  requestCtx.assign(MYFACES).value = options.value?.myfaces;
235
- /**
236
- * fetch the parent form
237
- *
238
- * note we also add an override possibility here
239
- * so that people can use dummy forms and work
240
- * with detached objects
241
- */
242
- let form: DQ = resolveForm(requestCtx, elem, resolvedEvent);
243
294
 
244
295
  /**
245
296
  * binding contract the javax.faces.source must be set
246
297
  */
247
- requestCtx.assign(CTX_PARAM_PASS_THR, P_PARTIAL_SOURCE).value = elementId.value;
298
+ requestCtx.assign(CTX_PARAM_PASS_THR, P_PARTIAL_SOURCE).value = elementId;
248
299
 
249
300
  /**
250
301
  * javax.faces.partial.ajax must be set to true
251
302
  */
252
303
  requestCtx.assign(CTX_PARAM_PASS_THR, P_AJAX).value = true;
253
304
 
254
- /**
255
- * binding contract the javax.faces.source must be set
256
- */
257
- requestCtx.assign(CTX_PARAM_PASS_THR, P_PARTIAL_SOURCE).value = elementId.value;
258
-
259
305
  /**
260
306
  * if resetValues is set to true
261
307
  * then we have to set javax.faces.resetValues as well
@@ -265,27 +311,22 @@ export module Implementation {
265
311
  */
266
312
  requestCtx.assignIf(isResetValues, CTX_PARAM_PASS_THR, P_RESET_VALUES).value = true;
267
313
 
268
- //additional meta information to speed things up, note internal non jsf
269
- //pass through options are stored under _mfInternal in the context
270
- internalCtx.assign(CTX_PARAM_SRC_FRM_ID).value = form.id.value;
271
- internalCtx.assign(CTX_PARAM_SRC_CTL_ID).value = elementId.value;
314
+ // additional meta information to speed things up, note internal non jsf
315
+ // pass through options are stored under _mfInternal in the context
316
+ internalCtx.assign(CTX_PARAM_SRC_FRM_ID).value = formId;
317
+
318
+ // mojarra compatibility, mojarra is sending the form id as well
319
+ // this is not documented behavior but can be determined by running
320
+ // mojarra under blackbox conditions.
321
+ // I assume it does the same as our formId_submit=1 so leaving it out
322
+ // won't hurt but for the sake of compatibility we are going to add it
323
+ requestCtx.assign(CTX_PARAM_PASS_THR, formId).value = formId;
324
+ internalCtx.assign(CTX_PARAM_SRC_CTL_ID).value = elementId;
272
325
  internalCtx.assign(CTX_PARAM_TR_TYPE).value = REQ_TYPE_POST;
273
326
 
274
- //mojarra compatibility, mojarra is sending the form id as well
275
- //this is not documented behavior but can be determined by running
276
- //mojarra under blackbox conditions
277
- //i assume it does the same as our formId_submit=1 so leaving it out
278
- //wont hurt but for the sake of compatibility we are going to add it
279
-
280
- requestCtx.assign(CTX_PARAM_PASS_THR, form.id.value).value = form.id.value;
281
-
282
327
  assignClientWindowId(form, requestCtx);
283
-
284
- assignExecute(options, requestCtx, form, elementId.value);
285
- assignRender(options, requestCtx, form, elementId.value);
286
-
287
- let delay: number = resolveDelay(options);
288
- let timeout: number = resolveTimeout(options);
328
+ assignExecute(options, requestCtx, form, elementId);
329
+ assignRender(options, requestCtx, form, elementId);
289
330
 
290
331
  //now we enqueue the request as asynchronous runnable into our request
291
332
  //queue and let the queue take over the rest
@@ -308,7 +349,6 @@ export module Implementation {
308
349
  * @param errorListener the error listener handler
309
350
  */
310
351
  export function addOnError(errorListener: IListener<ErrorData>) {
311
- /*error handling already done in the assert of the queue*/
312
352
  errorQueue.push(errorListener);
313
353
  }
314
354
 
@@ -318,7 +358,6 @@ export module Implementation {
318
358
  * @param eventListener the event listener handler
319
359
  */
320
360
  export function addOnEvent(eventListener: IListener<EventData>) {
321
- /*error handling already done in the assert of the queue*/
322
361
  eventQueue.push(eventListener);
323
362
  }
324
363
 
@@ -480,7 +519,7 @@ export module Implementation {
480
519
 
481
520
  /**
482
521
  * this at the first sight looks like a weird construct, but we need to do it this way
483
- * for testing, we cannot proxy addRequestToQueue from the testing frameworks directly
522
+ * for testing, we cannot proxy addRequestToQueue from the testing frameworks directly,
484
523
  * but we need to keep it under unit tests.
485
524
  */
486
525
  export let queueHandler = {
@@ -572,15 +611,12 @@ export module Implementation {
572
611
  function remapDefaultConstants(targetConfig: Config, targetKey: string, userValues: string, issuingForm: DQ, issuingElementId: string): Config {
573
612
  //a cleaner implementation of the transform list method
574
613
 
575
- let iterValues = (userValues) ? trim(userValues).split(/\s+/gi) : [];
614
+ let iterValues: string[] = (userValues) ? trim(userValues).split(/\s+/gi) : [];
576
615
  let ret = [];
577
- let processed = {};
616
+ let processed: {[key: string]: boolean} = {};
578
617
 
579
- //the idea is simply to loop over all values and then replace
580
- //their generic values and filter out doubles
581
- //this is more readable than the old indexed based solution
582
- //and not really slower because we had to build up the index in our old solution
583
- //anyway
618
+ // in this case we do not use lazy stream because it wont bring any code reduction
619
+ // or speedup
584
620
  for (let cnt = 0; cnt < iterValues.length; cnt++) {
585
621
  //avoid doubles
586
622
  if (iterValues[cnt] in processed) {
@@ -649,7 +685,7 @@ export module Implementation {
649
685
  return (<Function>func).call(source, event) !== false;
650
686
  } else {
651
687
  //either a function or a string can be passed in case of a string we have to wrap it into another function
652
- //it it is not a plain executable code but a definition
688
+ //it is not a plain executable code but a definition
653
689
  let sourceCode = trim(<string>func);
654
690
  if (sourceCode.indexOf("function ") == 0) {
655
691
  sourceCode = `return ${sourceCode} (event)`;
@@ -6,7 +6,7 @@ import {AsyncRunnable} from "./AsyncRunnable";
6
6
  *
7
7
  * Every callback must be of async runnable
8
8
  * which is sort of an extended promise which has
9
- * added a decicated cancel and start point
9
+ * added a dedicated cancel and start point
10
10
  *
11
11
  * This interface can be used as wrapper contract
12
12
  * for normal promises if needed.
@@ -21,12 +21,15 @@ export class AsynchronousQueue<T extends AsyncRunnable<any>> {
21
21
  constructor() {
22
22
  }
23
23
 
24
+ /**
25
+ * simple is empty accessor, returns true if queue is empty atm
26
+ */
24
27
  get isEmpty(): boolean {
25
28
  return !this.runnableQueue.length;
26
29
  }
27
30
 
28
31
  /**
29
- * enequeues an element and starts the
32
+ * enqueues an element and starts the
30
33
  * asynchronous work loop if not already running
31
34
  *
32
35
  * @param element the element to be queued and processed
@@ -46,15 +49,39 @@ export class AsynchronousQueue<T extends AsyncRunnable<any>> {
46
49
  }
47
50
  }
48
51
 
49
- dequeue(): T {
52
+ /**
53
+ * fetches the next element from the queue (first in first out order)
54
+ */
55
+ dequeue(): T | undefined{
50
56
  return this.runnableQueue.shift();
51
57
  }
52
58
 
59
+ /**
60
+ * clears up all elements from the queue
61
+ */
53
62
  cleanup() {
54
63
  this.currentlyRunning = null;
55
64
  this.runnableQueue.length = 0;
56
65
  }
57
66
 
67
+ /**
68
+ * cancels the currently running element and then cleans up the queue
69
+ * aka cancel the queue entirely
70
+ */
71
+ cancel() {
72
+ try {
73
+ if (this.currentlyRunning) {
74
+ this.currentlyRunning.cancel();
75
+ }
76
+ } finally {
77
+ this.cleanup();
78
+ }
79
+ }
80
+
81
+ private callForNextElementToProcess() {
82
+ this.runEntry();
83
+ }
84
+
58
85
  private appendElement(element: T) {
59
86
  //only if the first element is added we start with a trigger
60
87
  //otherwise a process already is running and not finished yet at that
@@ -88,18 +115,4 @@ export class AsynchronousQueue<T extends AsyncRunnable<any>> {
88
115
  () => this.callForNextElementToProcess()
89
116
  ).start();
90
117
  }
91
-
92
- cancel() {
93
- try {
94
- if (this.currentlyRunning) {
95
- this.currentlyRunning.cancel();
96
- }
97
- } finally {
98
- this.cleanup();
99
- }
100
- }
101
-
102
- private callForNextElementToProcess() {
103
- this.runEntry();
104
- }
105
118
  }
@@ -19,7 +19,9 @@
19
19
  * Ever object in the asynchronous queue needs to implement this interface
20
20
  *
21
21
  * the usage should be similar as a Promise from the outside.
22
- * but with a dedicated start point
22
+ * but with a dedicated start point. The problem why we cannot use
23
+ * promises here, is mostly related to the needed cancel functionality
24
+ * and that the queue expects a runnable as entry.
23
25
  *
24
26
  * from the implementation side it is mostly registering callbacks
25
27
  * and calling them at the appropriate time.
@@ -36,8 +38,8 @@ export interface AsyncRunnable<T> {
36
38
  cancel();
37
39
 
38
40
  /**
39
- * callback for then functinality
40
- * triggered when the asynch run is complete
41
+ * callback for then functionality
42
+ * triggered when the async run is complete
41
43
  *
42
44
  * the async runnable must register the passed function
43
45
  * and then triggers all the registered thens
@@ -1,5 +1,5 @@
1
1
  import {Config, IValueHolder, Optional, DomQuery, DQ} from "mona-dish";
2
- import {EMPTY_STR, P_WINDOW_ID} from "../core/Const";
2
+ import {P_WINDOW_ID} from "../core/Const";
3
3
 
4
4
  declare let window: any;
5
5
 
@@ -13,9 +13,9 @@ declare let window: any;
13
13
  */
14
14
  const IS_JSF_SOURCE = (source?: string): boolean => {
15
15
  return source && !!(source?.search(/\/javax\.faces\.resource.*\/jsf\.js.*/) != -1 ||
16
- source?.search(/\/jsf\-development\.js.*/) != -1 ||
17
- source?.search(/\/jsf\-uncompressed\.js.*/) != -1 ||
18
- source?.search(/\/jsf[^\.]\.js.*ln\=javax.faces.*/gi) != -1);
16
+ source?.search(/\/jsf-development\.js.*/) != -1 ||
17
+ source?.search(/\/jsf-uncompressed\.js.*/) != -1 ||
18
+ source?.search(/\/jsf[^.]*\.js.*ln=javax.faces.*/gi) != -1);
19
19
  }
20
20
 
21
21
  /**
@@ -27,7 +27,7 @@ const IS_JSF_SOURCE = (source?: string): boolean => {
27
27
  * @constructor
28
28
  */
29
29
  const IS_INTERNAL_SOURCE = (source: string): boolean => {
30
- return source.search(/\/jsf[^\.]\.js.*ln\=myfaces.testscripts.*/gi) != -1;
30
+ return source.search(/\/jsf[^.]*\.js.*ln=myfaces.testscripts.*/gi) != -1;
31
31
  }
32
32
 
33
33
 
@@ -131,7 +131,7 @@ export class ExtDomquery extends DQ {
131
131
  }
132
132
 
133
133
  globalEval(code: string, nonce ?: string): DQ {
134
- return super.globalEval(code, nonce ?? this.nonce);
134
+ return new ExtDomquery(super.globalEval(code, nonce ?? this.nonce));
135
135
  }
136
136
 
137
137
  /**
@@ -150,12 +150,12 @@ export class ExtDomquery extends DQ {
150
150
  * byId producer
151
151
  *
152
152
  * @param selector id
153
+ * @param deep whether the search should go into embedded shadow dom elements
153
154
  * @return a DomQuery containing the found elements
154
155
  */
155
156
  static byId(selector: string | DomQuery | Element, deep = false): DomQuery {
156
157
  const ret = DomQuery.byId(selector, deep);
157
- //return new ExtDomquery(ret);
158
- return ret;
158
+ return new ExtDomquery(ret);
159
159
  }
160
160
  }
161
161
 
@@ -17,8 +17,8 @@ export class EventData {
17
17
  eventData.status = name;
18
18
 
19
19
  let sourceId: string = context.getIf(SOURCE)
20
- .orElse(context.getIf(P_PARTIAL_SOURCE).value)
21
- .orElse(context.getIf(CTX_PARAM_PASS_THR, P_PARTIAL_SOURCE).value).value;
20
+ .orElseLazy(() => context.getIf(P_PARTIAL_SOURCE).value)
21
+ .orElseLazy(() => context.getIf(CTX_PARAM_PASS_THR, P_PARTIAL_SOURCE).value).value;
22
22
  if (sourceId) {
23
23
  eventData.source = DQ.byId(sourceId, true).first().value.value;
24
24
  }
@@ -46,7 +46,7 @@ import {ExtDomquery} from "../util/ExtDomQuery";
46
46
  */
47
47
  export function resolveHandlerFunc(requestContext: Config, responseContext: Config, funcName: string) {
48
48
  return responseContext.getIf(funcName)
49
- .orElse(requestContext.getIf(funcName).value)
49
+ .orElseLazy(() =>requestContext.getIf(funcName).value)
50
50
  .orElse(EMPTY_FUNC).value;
51
51
  }
52
52
 
@@ -72,7 +72,7 @@ export function resolveFinalUrl(sourceForm: DomQuery, formData: XhrFormData, aja
72
72
  * @param event
73
73
  */
74
74
  export function resolveForm(requestCtx: Config, elem: DQ, event: Event): DQ {
75
- const configId = requestCtx.value?.myfaces?.form ?? MF_NONE; //requestCtx.getIf(MYFACES, "form").orElse(MF_NONE).value;
75
+ const configId = requestCtx.value?.myfaces?.form ?? MF_NONE;
76
76
  return DQ
77
77
  .byId(configId, true)
78
78
  .orElseLazy(() => ExtLang.getForm(elem.getAsElem(0).value, event));
@@ -142,7 +142,7 @@ export function resolveDefaults(event: Event, opts: any = {}, el: Element | stri
142
142
  const resolvedEvent = event,
143
143
  options = new Config(opts).deepCopy,
144
144
  elem = DQ.byId(el || <Element>resolvedEvent.target, true),
145
- elementId = elem.id, requestCtx = new Config({}),
145
+ elementId = elem.id.value, requestCtx = new Config({}),
146
146
  internalCtx = new Config({}), windowId = resolveWindowId(options),
147
147
  isResetValues = true === options.value?.resetValues;
148
148
 
@@ -102,9 +102,9 @@ export function resolveSourceForm(internalContext: Config, elem: DQ): DQ {
102
102
  let sourceFormId = internalContext.getIf(CTX_PARAM_SRC_FRM_ID);
103
103
  let sourceForm = new DQ(sourceFormId.isPresent() ? document.forms[sourceFormId.value] : null);
104
104
 
105
- sourceForm = sourceForm.orElse(elem.parents(TAG_FORM))
106
- .orElse(elem.querySelectorAll(TAG_FORM))
107
- .orElse(DQ.querySelectorAll(TAG_FORM));
105
+ sourceForm = sourceForm.orElseLazy(() => elem.parents(TAG_FORM))
106
+ .orElseLazy(() => elem.querySelectorAll(TAG_FORM))
107
+ .orElseLazy(() => DQ.querySelectorAll(TAG_FORM));
108
108
 
109
109
  return sourceForm;
110
110
  }
@@ -71,9 +71,13 @@ import {ExtDomquery} from "../util/ExtDomQuery";
71
71
  export class ResponseProcessor implements IResponseProcessor {
72
72
 
73
73
  constructor(private request: Config, private externalContext: Config, private internalContext: Config) {
74
-
75
74
  }
76
75
 
76
+ /**
77
+ * head replacement
78
+ * @param shadowDocument incoming shadow head data (aka cdata as xml reference or dom element)
79
+ * the data incoming must represent the html representation of the head itself one way or the other
80
+ */
77
81
  replaceHead(shadowDocument: XMLQuery | DQ) {
78
82
  let shadowHead = shadowDocument.querySelectorAll(TAG_HEAD);
79
83
  if (!shadowHead.isPresent()) {
@@ -85,6 +89,9 @@ export class ResponseProcessor implements IResponseProcessor {
85
89
  //delete all to avoid script and style overlays
86
90
  oldHead.querySelectorAll(SEL_SCRIPTS_STYLES).delete();
87
91
 
92
+ // we cannot replace new elements in the head, but we can eval the elements
93
+ // eval means the scripts will get attached (eval script attach method)
94
+ // but this is done by DomQuery not in this code
88
95
  this.storeForEval(shadowHead);
89
96
  }
90
97
 
@@ -108,6 +115,8 @@ export class ResponseProcessor implements IResponseProcessor {
108
115
  let resultingBody = <DQ>DQ.querySelectorAll(TAG_BODY).html(shadowInnerHTML);
109
116
  let updateForms = resultingBody.querySelectorAll(TAG_FORM);
110
117
 
118
+ // main difference, we cannot replace the body itself, but only its content
119
+ // we need a separate step for post processing the incoming attributes, like classes, styles etc...
111
120
  resultingBody.copyAttrs(shadowBody);
112
121
 
113
122
  this.storeForPostProcessing(updateForms, resultingBody);
@@ -157,10 +166,6 @@ export class ResponseProcessor implements IResponseProcessor {
157
166
  Implementation.sendError(errorData);
158
167
  }
159
168
 
160
- private triggerOnError(errorData: ErrorData) {
161
- this.externalContext.getIf(ON_ERROR).orElse(this.internalContext.getIf(ON_ERROR).value).orElse(EMPTY_FUNC).value(errorData);
162
- }
163
-
164
169
  /**
165
170
  * process the redirect operation
166
171
  *
@@ -182,12 +187,16 @@ export class ResponseProcessor implements IResponseProcessor {
182
187
  */
183
188
  update(node: XMLQuery, cdataBlock: string) {
184
189
  let result = ExtDomquery.byId(node.id.value, true).outerHTML(cdataBlock, false, false);
185
- let sourceForm = result?.parents(TAG_FORM).orElse(result.byTagName(TAG_FORM, true));
190
+ let sourceForm = result?.parents(TAG_FORM).orElseLazy(() => result.byTagName(TAG_FORM, true));
186
191
  if (sourceForm) {
187
192
  this.storeForPostProcessing(sourceForm, result);
188
193
  }
189
194
  }
190
195
 
196
+ /**
197
+ * Delete handler, simply deleetes the node referenced by the xml data
198
+ * @param node
199
+ */
191
200
  delete(node: XMLQuery) {
192
201
  DQ.byId(node.id.value, true).delete();
193
202
  }
@@ -214,7 +223,7 @@ export class ResponseProcessor implements IResponseProcessor {
214
223
  }
215
224
 
216
225
  /**
217
- * insert handling, either before or after
226
+ * Insert handling, either before or after
218
227
  *
219
228
  * @param node
220
229
  */
@@ -239,7 +248,7 @@ export class ResponseProcessor implements IResponseProcessor {
239
248
  }
240
249
 
241
250
  /**
242
- * handler for the case &lt;insert <&lt; before id="...
251
+ * Handler for the case &lt;insert <&lt; before id="...
243
252
  *
244
253
  * @param node the node hosting the insert data
245
254
  */
@@ -267,7 +276,7 @@ export class ResponseProcessor implements IResponseProcessor {
267
276
  }
268
277
 
269
278
  /**
270
- * process the viewState update, update the affected
279
+ * Process the viewState update, update the affected
271
280
  * forms with their respective new viewstate values
272
281
  *
273
282
  */
@@ -298,7 +307,10 @@ export class ResponseProcessor implements IResponseProcessor {
298
307
  }
299
308
 
300
309
  /**
301
- * post processing viewstate fixing
310
+ * Postprocessing view state fixing
311
+ * this appends basically the incoming view states to the forms.
312
+ * It is called from outside after all forms have been processed basically
313
+ * as last lifecycle step, before going into the next request.
302
314
  */
303
315
  fixViewStates() {
304
316
  Stream.ofAssoc<StateHolder>(this.internalContext.getIf(APPLIED_VST).orElse({}).value)
@@ -312,6 +324,10 @@ export class ResponseProcessor implements IResponseProcessor {
312
324
  });
313
325
  }
314
326
 
327
+ /**
328
+ * same as with view states before applies the incoming client windows as last step after the rest of the processing
329
+ * is done.
330
+ */
315
331
  fixClientWindow() {
316
332
  Stream.ofAssoc<StateHolder>(this.internalContext.getIf(APPLIED_CLIENT_WINDOW).orElse({}).value)
317
333
  .each((item: Array<any>) => {
@@ -331,7 +347,7 @@ export class ResponseProcessor implements IResponseProcessor {
331
347
  let eventData = EventData.createFromRequest(this.request.value, this.externalContext, SUCCESS);
332
348
 
333
349
  //because some frameworks might decorate them over the context in the response
334
- let eventHandler = this.externalContext.getIf(ON_EVENT).orElse(this.internalContext.getIf(ON_EVENT).value).orElse(EMPTY_FUNC).value;
350
+ let eventHandler = this.externalContext.getIf(ON_EVENT).orElseLazy(() => this.internalContext.getIf(ON_EVENT).value).orElse(EMPTY_FUNC).value;
335
351
  Implementation.sendEvent(eventData, eventHandler);
336
352
  }
337
353
 
@@ -441,4 +457,8 @@ export class ResponseProcessor implements IResponseProcessor {
441
457
  node?.id?.value?.indexOf([P_CLIENT_WINDOW, separatorChar].join(EMPTY_STR)) != -1);
442
458
  }
443
459
 
460
+ private triggerOnError(errorData: ErrorData) {
461
+ this.externalContext.getIf(ON_ERROR).orElse(this.internalContext.getIf(ON_ERROR).value).orElse(EMPTY_FUNC).value(errorData);
462
+ }
463
+
444
464
  }