jsf.js_next_gen 1.0.0-beta-17 → 1.0.0-beta-19
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/docs/assets/search.js +1 -1
- package/dist/docs/functions/myfaces.ab.html +1 -0
- package/dist/docs/modules/myfaces.html +5 -0
- package/dist/docs/variables/myfaces.oam.html +50 -0
- package/dist/window/jsf-development.js +500 -205
- package/dist/window/jsf-development.js.map +1 -1
- package/dist/window/jsf.js +2 -2
- package/dist/window/jsf.js.br +0 -0
- package/dist/window/jsf.js.gz +0 -0
- package/dist/window/jsf.js.map +1 -1
- package/package.json +1 -1
- package/remap.js +1 -1
- package/remap.js.map +1 -1
- package/remap.ts +1 -1
- package/src/main/typescript/api/Jsf.ts +8 -10
- package/src/main/typescript/impl/AjaxImpl.ts +85 -49
- package/src/main/typescript/impl/PushImpl.ts +16 -0
- package/src/main/typescript/impl/util/Assertions.ts +15 -0
- package/src/main/typescript/impl/util/AsyncQueue.ts +45 -17
- package/src/main/typescript/impl/util/AsyncRunnable.ts +5 -3
- package/src/main/typescript/impl/util/ExtDomQuery.ts +23 -8
- package/src/main/typescript/impl/util/IListener.ts +18 -0
- package/src/main/typescript/impl/xhrCore/ErrorData.ts +15 -0
- package/src/main/typescript/impl/xhrCore/EventData.ts +17 -2
- package/src/main/typescript/impl/xhrCore/IResponseProcessor.ts +15 -0
- package/src/main/typescript/impl/xhrCore/RequestDataResolver.ts +3 -3
- package/src/main/typescript/impl/xhrCore/ResonseDataResolver.ts +3 -3
- package/src/main/typescript/impl/xhrCore/Response.ts +5 -6
- package/src/main/typescript/impl/xhrCore/ResponseProcessor.ts +31 -11
- package/src/main/typescript/impl/xhrCore/XhrFormData.ts +86 -90
- package/src/main/typescript/impl/xhrCore/XhrRequest.ts +34 -28
- package/src/main/typescript/myfaces/OamSubmit.ts +151 -0
- package/src/main/typescript/test/frameworkBase/_ext/shared/StandardInits.ts +4 -0
- package/src/main/typescript/test/myfaces/OamSubmit.spec.ts +50 -0
- package/src/main/typescript/test/xhrCore/FakeWebsocket.ts +15 -0
- package/src/main/typescript/test/xhrCore/FileUploadTest.spec.ts +15 -0
- package/src/main/typescript/test/xhrCore/RequestParamsTest.spec.ts +15 -0
- package/src/main/typescript/test/xhrCore/WebsocketTest.ts +15 -0
- package/target/api/Jsf.js +6 -5
- package/target/api/Jsf.js.map +1 -1
- package/target/impl/AjaxImpl.js +80 -39
- package/target/impl/AjaxImpl.js.map +1 -1
- package/target/impl/PushImpl.js +17 -2
- package/target/impl/PushImpl.js.map +1 -1
- package/target/impl/util/Assertions.js +15 -0
- package/target/impl/util/Assertions.js.map +1 -1
- package/target/impl/util/AsyncQueue.js +28 -15
- package/target/impl/util/AsyncQueue.js.map +1 -1
- package/target/impl/util/ExtDomQuery.js +22 -7
- package/target/impl/util/ExtDomQuery.js.map +1 -1
- package/target/impl/util/IListener.js +3 -0
- package/target/impl/util/IListener.js.map +1 -0
- package/target/impl/xhrCore/ErrorData.js +15 -0
- package/target/impl/xhrCore/ErrorData.js.map +1 -1
- package/target/impl/xhrCore/EventData.js +17 -2
- package/target/impl/xhrCore/EventData.js.map +1 -1
- package/target/impl/xhrCore/RequestDataResolver.js +3 -3
- package/target/impl/xhrCore/RequestDataResolver.js.map +1 -1
- package/target/impl/xhrCore/ResonseDataResolver.js +3 -3
- package/target/impl/xhrCore/ResonseDataResolver.js.map +1 -1
- package/target/impl/xhrCore/Response.js +5 -5
- package/target/impl/xhrCore/Response.js.map +1 -1
- package/target/impl/xhrCore/ResponseProcessor.js +31 -9
- package/target/impl/xhrCore/ResponseProcessor.js.map +1 -1
- package/target/impl/xhrCore/XhrFormData.js +86 -88
- package/target/impl/xhrCore/XhrFormData.js.map +1 -1
- package/target/impl/xhrCore/XhrRequest.js +32 -27
- package/target/impl/xhrCore/XhrRequest.js.map +1 -1
- package/target/myfaces/OamSubmit.js +128 -0
- package/target/myfaces/OamSubmit.js.map +1 -0
- package/target/test/frameworkBase/_ext/shared/StandardInits.js +3 -0
- package/target/test/frameworkBase/_ext/shared/StandardInits.js.map +1 -1
- package/target/test/myfaces/OamSubmit.spec.js +46 -0
- package/target/test/myfaces/OamSubmit.spec.js.map +1 -0
- package/target/test/xhrCore/FakeWebsocket.js +15 -0
- package/target/test/xhrCore/FakeWebsocket.js.map +1 -1
- package/target/test/xhrCore/FileUploadTest.spec.js +15 -0
- package/target/test/xhrCore/FileUploadTest.spec.js.map +1 -1
- package/target/test/xhrCore/RequestParamsTest.spec.js +15 -0
- package/target/test/xhrCore/RequestParamsTest.spec.js.map +1 -1
- package/target/test/xhrCore/WebsocketTest.js +15 -0
- package/target/test/xhrCore/WebsocketTest.js.map +1 -1
- package/webpack.config.js +0 -7
- package/webpack.config.js.map +1 -1
- package/webpack.config.ts +0 -7
- package/src/main/typescript/impl/util/ListenerQueue.ts +0 -3
|
@@ -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.
|
|
106
|
-
.
|
|
107
|
-
.
|
|
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
|
}
|
|
@@ -52,7 +52,7 @@ export module Response {
|
|
|
52
52
|
* and processing its tags
|
|
53
53
|
*
|
|
54
54
|
* @param {XMLHttpRequest} request (xhrRequest) - xhr request object
|
|
55
|
-
* @param
|
|
55
|
+
* @param context {Context} context (Map) - AJAX context
|
|
56
56
|
*
|
|
57
57
|
*/
|
|
58
58
|
export function processResponse(request: XMLHttpRequest, context: Context) {
|
|
@@ -90,7 +90,7 @@ export module Response {
|
|
|
90
90
|
const SEL_SUB_TAGS = [CMD_ERROR, CMD_REDIRECT, CMD_CHANGES].join(",");
|
|
91
91
|
|
|
92
92
|
//now we can process the main operations
|
|
93
|
-
node.
|
|
93
|
+
node.querySelectorAll(SEL_SUB_TAGS).each((node: XMLQuery) => {
|
|
94
94
|
switch (node.tagName.value) {
|
|
95
95
|
case CMD_ERROR:
|
|
96
96
|
responseProcessor.error(node);
|
|
@@ -123,8 +123,8 @@ export module Response {
|
|
|
123
123
|
* @param responseProcessor
|
|
124
124
|
*/
|
|
125
125
|
function processChangesTag(node: XMLQuery, responseProcessor: IResponseProcessor): boolean {
|
|
126
|
-
const ALLOWED_TAGS = [CMD_UPDATE, CMD_EVAL, CMD_INSERT, CMD_DELETE, CMD_ATTRIBUTES, CMD_EXTENSION].join(",");
|
|
127
|
-
node.
|
|
126
|
+
const ALLOWED_TAGS = [CMD_UPDATE, CMD_EVAL, CMD_INSERT, CMD_DELETE, CMD_ATTRIBUTES, CMD_EXTENSION].join(", ");
|
|
127
|
+
node.querySelectorAll(ALLOWED_TAGS).each(
|
|
128
128
|
(node: XMLQuery) => {
|
|
129
129
|
switch (node.tagName.value) {
|
|
130
130
|
case CMD_UPDATE:
|
|
@@ -168,7 +168,7 @@ export module Response {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
|
-
* branch tag update
|
|
171
|
+
* branch tag update. drill further down into the updates
|
|
172
172
|
* special case viewstate in that case it is a leaf
|
|
173
173
|
* and the viewstate must be processed
|
|
174
174
|
*
|
|
@@ -206,7 +206,6 @@ export module Response {
|
|
|
206
206
|
default://htmlItem replacement
|
|
207
207
|
responseProcessor.update(node, cdataBlock);
|
|
208
208
|
break;
|
|
209
|
-
|
|
210
209
|
}
|
|
211
210
|
}
|
|
212
211
|
}
|
|
@@ -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).
|
|
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
|
-
*
|
|
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
|
-
*
|
|
251
|
+
* Handler for the case <insert << 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
|
-
*
|
|
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
|
-
*
|
|
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).
|
|
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
|
}
|
|
@@ -13,11 +13,9 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import {ArrayCollector, Config,
|
|
17
|
-
|
|
18
|
-
import {Stream, DQ} from "mona-dish";
|
|
16
|
+
import {ArrayCollector, Config, DQ, Lang, LazyStream, Stream} from "mona-dish";
|
|
17
|
+
import {EMPTY_STR, IDENT_ALL, IDENT_FORM, P_VIEWSTATE} from "../core/Const";
|
|
19
18
|
import isString = Lang.isString;
|
|
20
|
-
import {EMPTY_STR, P_VIEWSTATE} from "../core/Const";
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
/**
|
|
@@ -28,43 +26,55 @@ import {EMPTY_STR, P_VIEWSTATE} from "../core/Const";
|
|
|
28
26
|
* due to api constraints on the HTML Form object in IE11
|
|
29
27
|
* and due to the url encoding constraint given by the jsf.js spec
|
|
30
28
|
*
|
|
31
|
-
* TODO not ideal. too many encoding calls
|
|
32
29
|
* probably only one needed and one overlay!
|
|
33
|
-
* the entire
|
|
34
|
-
* that
|
|
30
|
+
* the entire file input storing probably is redundant now
|
|
31
|
+
* that dom query has been fixed //TODO check this
|
|
35
32
|
*/
|
|
36
33
|
export class XhrFormData extends Config {
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Checks if the given datasource is a multipart request source
|
|
36
|
+
* multipart is only needed if one of the executes is a file input
|
|
37
|
+
* since file inputs are stateless, they fall out of the view state
|
|
38
|
+
* and need special handling. With file submits we have to send a formData object
|
|
39
|
+
* instead of an encoded string files cannot be sent that way
|
|
40
|
+
*/
|
|
41
|
+
isMultipartRequest: boolean = false;
|
|
39
42
|
|
|
40
43
|
/**
|
|
41
44
|
* data collector from a given form
|
|
42
45
|
*
|
|
43
46
|
* @param dataSource either a form as DomQuery object or an encoded url string
|
|
44
|
-
* @param
|
|
47
|
+
* @param viewState the form view state or an external viewstate coming in as string
|
|
48
|
+
* @param executes the executes id list for the elements to being processed
|
|
49
|
+
* @param partialIds partial ids to collect, to reduce the data sent down
|
|
45
50
|
*/
|
|
46
|
-
constructor(private dataSource: DQ | string, private
|
|
51
|
+
constructor(private dataSource: DQ | string, viewState?: string, executes?: string[], private partialIds?: string[]) {
|
|
47
52
|
super({});
|
|
48
53
|
//a call to getViewState before must pass the encoded line
|
|
49
|
-
//a call from getViewState passes the form element as datasource
|
|
54
|
+
//a call from getViewState passes the form element as datasource,
|
|
50
55
|
//so we have two call points
|
|
51
56
|
if (isString(dataSource)) {
|
|
52
57
|
this.assignEncodedString(<string>this.dataSource);
|
|
53
58
|
} else {
|
|
54
|
-
this.
|
|
59
|
+
this.applyFormDataToConfig();
|
|
60
|
+
}
|
|
61
|
+
if('undefined' != typeof viewState) {
|
|
62
|
+
this.assignEncodedString(viewState)
|
|
63
|
+
}
|
|
64
|
+
if(executes) {
|
|
65
|
+
this.postInit(...executes);
|
|
55
66
|
}
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
/**
|
|
59
|
-
* generic
|
|
70
|
+
* generic post init code, for now, this peforms some post assign data post processing
|
|
60
71
|
* @param executes
|
|
61
72
|
*/
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
postInit(...executes: Array<string>) {
|
|
64
74
|
let fetchInput = (id: string): DQ => {
|
|
65
|
-
if (id ==
|
|
75
|
+
if (id == IDENT_ALL) {
|
|
66
76
|
return DQ.querySelectorAllDeep("input[type='file']");
|
|
67
|
-
} else if (id ==
|
|
77
|
+
} else if (id == IDENT_FORM) {
|
|
68
78
|
return (<DQ>this.dataSource).querySelectorAllDeep("input[type='file']");
|
|
69
79
|
} else {
|
|
70
80
|
let element = DQ.byId(id, true);
|
|
@@ -76,48 +86,17 @@ export class XhrFormData extends Config {
|
|
|
76
86
|
return item.isPresent();
|
|
77
87
|
};
|
|
78
88
|
|
|
79
|
-
let applyInput = (item: DQ) => {
|
|
80
|
-
this.fileInputs[this.resolveSubmitIdentifier(<HTMLInputElement>item.getAsElem(0).value)] = true;
|
|
81
|
-
};
|
|
82
89
|
|
|
83
|
-
LazyStream.of(...executes)
|
|
90
|
+
this.isMultipartRequest = LazyStream.of(...executes)
|
|
84
91
|
.map(fetchInput)
|
|
85
92
|
.filter(inputExists)
|
|
86
|
-
.
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private getFileInputs(rootElment: DQ): DQ {
|
|
90
|
-
const rootFileInputs = rootElment
|
|
91
|
-
.filter(elem => elem.matchesSelector("input[type='file']"))
|
|
92
|
-
const childFileInputs = rootElment
|
|
93
|
-
.querySelectorAll("input[type='file']");
|
|
94
|
-
|
|
95
|
-
let ret = rootFileInputs.concat(childFileInputs);
|
|
96
|
-
return ret;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private handleFormSource() {
|
|
100
|
-
//encode and append the issuing item if not a partial ids array of ids is passed
|
|
101
|
-
/*
|
|
102
|
-
* Spec. 13.3.1
|
|
103
|
-
* Collect and encode input elements.
|
|
104
|
-
* Additionally the hidden element javax.faces.ViewState
|
|
105
|
-
* Enhancement partial page submit
|
|
106
|
-
*
|
|
107
|
-
*/
|
|
108
|
-
this.encodeSubmittableFields(this, <DQ>this.dataSource, this.partialIdsArray);
|
|
109
|
-
|
|
110
|
-
if (this.getIf(P_VIEWSTATE).isPresent()) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
this.applyViewState(<DQ>this.dataSource);
|
|
93
|
+
.first().isPresent();
|
|
115
94
|
}
|
|
116
95
|
|
|
117
96
|
/**
|
|
118
|
-
* special case
|
|
97
|
+
* special case view state handling
|
|
119
98
|
*
|
|
120
|
-
* @param form the form holding the
|
|
99
|
+
* @param form the form holding the view state value
|
|
121
100
|
*/
|
|
122
101
|
private applyViewState(form: DQ) {
|
|
123
102
|
let viewState = form.byId(P_VIEWSTATE, true).inputValue;
|
|
@@ -125,19 +104,22 @@ export class XhrFormData extends Config {
|
|
|
125
104
|
}
|
|
126
105
|
|
|
127
106
|
/**
|
|
128
|
-
*
|
|
107
|
+
* assigns an url encoded string to this xhrFormData object
|
|
129
108
|
* as key value entry
|
|
130
109
|
* @param encoded
|
|
131
110
|
*/
|
|
132
111
|
assignEncodedString(encoded: string) {
|
|
133
|
-
//
|
|
134
|
-
//this code filters out empty strings as key value pairs
|
|
112
|
+
// this code filters out empty strings as key value pairs
|
|
135
113
|
let keyValueEntries = decodeURIComponent(encoded).split(/&/gi)
|
|
136
114
|
.filter(item => !!(item || '')
|
|
137
115
|
.replace(/\s+/g,''));
|
|
138
116
|
this.assignString(keyValueEntries);
|
|
139
117
|
}
|
|
140
118
|
|
|
119
|
+
/**
|
|
120
|
+
* assign a set of key value pairs passed as array ['key=val1', 'key2=val2']
|
|
121
|
+
* @param keyValueEntries
|
|
122
|
+
*/
|
|
141
123
|
assignString(keyValueEntries: string[]) {
|
|
142
124
|
let toMerge = new Config({});
|
|
143
125
|
|
|
@@ -161,29 +143,12 @@ export class XhrFormData extends Config {
|
|
|
161
143
|
this.shallowMerge(toMerge);
|
|
162
144
|
}
|
|
163
145
|
|
|
164
|
-
// noinspection JSUnusedGlobalSymbols
|
|
165
146
|
/**
|
|
166
|
-
* @returns a Form data representation
|
|
147
|
+
* @returns a Form data representation, this is needed for file submits
|
|
167
148
|
*/
|
|
168
149
|
toFormData(): FormData {
|
|
169
150
|
let ret: any = new FormData();
|
|
170
|
-
|
|
171
|
-
LazyStream.of(...Object.keys(this.value))
|
|
172
|
-
.filter(key => !(key in this.fileInputs))
|
|
173
|
-
.each(key => {
|
|
174
|
-
Stream.of(...this.value[key]).each(item => ret.append(key, item));
|
|
175
|
-
});
|
|
176
|
-
Stream.of<string>(...Object.keys(this.fileInputs)).each((key: string) => {
|
|
177
|
-
DQ.querySelectorAllDeep(`[name='${key}'], [id="${key}"]`).eachElem((elem: HTMLInputElement) => {
|
|
178
|
-
let identifier = this.resolveSubmitIdentifier(elem);
|
|
179
|
-
if (!elem?.files?.length) {
|
|
180
|
-
ret.append(identifier, elem.value);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
ret.append(identifier, elem.files[0]);
|
|
185
|
-
})
|
|
186
|
-
});
|
|
151
|
+
this.appendInputs(ret);
|
|
187
152
|
return ret;
|
|
188
153
|
}
|
|
189
154
|
|
|
@@ -213,6 +178,42 @@ export class XhrFormData extends Config {
|
|
|
213
178
|
return entries.join("&")
|
|
214
179
|
}
|
|
215
180
|
|
|
181
|
+
/**
|
|
182
|
+
* helper to fetch all file inputs from as given root element
|
|
183
|
+
* @param rootElement
|
|
184
|
+
* @private
|
|
185
|
+
*/
|
|
186
|
+
private getFileInputs(rootElement: DQ): DQ {
|
|
187
|
+
const rootFileInputs = rootElement
|
|
188
|
+
.filter(elem => elem.matchesSelector("input[type='file']"))
|
|
189
|
+
const childFileInputs = rootElement
|
|
190
|
+
.querySelectorAll("input[type='file']");
|
|
191
|
+
|
|
192
|
+
return rootFileInputs.concat(childFileInputs);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* encode the given fields and apply the view state
|
|
197
|
+
* @private
|
|
198
|
+
*/
|
|
199
|
+
private applyFormDataToConfig() {
|
|
200
|
+
//encode and append the issuing item if not a partial ids array of ids is passed
|
|
201
|
+
/*
|
|
202
|
+
* Spec. 13.3.1
|
|
203
|
+
* Collect and encode input elements.
|
|
204
|
+
* Additionally the hidden element javax.faces.ViewState
|
|
205
|
+
* Enhancement partial page submit
|
|
206
|
+
*
|
|
207
|
+
*/
|
|
208
|
+
this.encodeSubmittableFields(this, <DQ>this.dataSource, this.partialIds);
|
|
209
|
+
|
|
210
|
+
if (this.getIf(P_VIEWSTATE).isPresent()) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
this.applyViewState(<DQ>this.dataSource);
|
|
215
|
+
}
|
|
216
|
+
|
|
216
217
|
/**
|
|
217
218
|
* determines fields to submit
|
|
218
219
|
* @param {Object} targetBuf - the target form buffer receiving the data
|
|
@@ -222,30 +223,25 @@ export class XhrFormData extends Config {
|
|
|
222
223
|
private encodeSubmittableFields(targetBuf: Config,
|
|
223
224
|
parentItem: DQ, partialIds ?: string[]) {
|
|
224
225
|
let toEncode = null;
|
|
225
|
-
if (this.
|
|
226
|
-
//in case of our myfaces reduced ppr we
|
|
227
|
-
//only submit the partials
|
|
226
|
+
if (this.partialIds && this.partialIds.length) {
|
|
227
|
+
// in case of our myfaces reduced ppr we
|
|
228
|
+
// only submit the partials
|
|
228
229
|
this._value = {};
|
|
229
|
-
toEncode = new DQ(...this.
|
|
230
|
+
toEncode = new DQ(...this.partialIds);
|
|
230
231
|
|
|
231
232
|
} else {
|
|
232
|
-
if (parentItem.isAbsent()) throw
|
|
233
|
+
if (parentItem.isAbsent()) throw 'NO_PAR_ITEM';
|
|
233
234
|
toEncode = parentItem;
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
//lets encode the form elements
|
|
237
|
-
|
|
238
238
|
this.shallowMerge(toEncode.deepElements.encodeFormElement());
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
*/
|
|
247
|
-
get isMultipartRequest(): boolean {
|
|
248
|
-
return !!Object.keys(this.fileInputs).length;
|
|
241
|
+
private appendInputs(ret: any) {
|
|
242
|
+
Stream.of(...Object.keys(this.value))
|
|
243
|
+
.each(key => {
|
|
244
|
+
Stream.of(...this.value[key]).each(item => ret.append(key, item));
|
|
245
|
+
});
|
|
249
246
|
}
|
|
250
|
-
|
|
251
247
|
}
|
|
@@ -78,6 +78,7 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
78
78
|
*
|
|
79
79
|
* Optional Parameters
|
|
80
80
|
*
|
|
81
|
+
* @param internalContext internal context with internal info which is passed through, not used by the user
|
|
81
82
|
* @param partialIdsArray an optional restricting partial ids array for encoding
|
|
82
83
|
* @param timeout optional xhr timeout
|
|
83
84
|
* @param ajaxType optional request type, default "POST"
|
|
@@ -120,19 +121,24 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
120
121
|
let viewState = jsf.getViewState(formElement);
|
|
121
122
|
//encoded we need to decode
|
|
122
123
|
//We generated a base representation of the current form
|
|
123
|
-
let formData: XhrFormData = new XhrFormData(this.sourceForm);
|
|
124
124
|
//in case someone has overloaded the viewstate with addtional decorators we merge
|
|
125
125
|
//that in, there is no way around it, the spec allows it and getViewState
|
|
126
126
|
//must be called, so whatever getViewState delivers has higher priority then
|
|
127
127
|
//whatever the formData object delivers
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
//the partialIdsArray arr is almost deprecated legacy code where we allowed to send a separate list of partial
|
|
129
|
+
//ids for reduced load and server processing, this will be removed soon, we can handle the same via execute
|
|
130
|
+
//anyway TODO remove the partial ids array
|
|
131
|
+
let formData: XhrFormData = new XhrFormData(this.sourceForm, viewState, executesArr(), this.partialIdsArray);
|
|
130
132
|
|
|
131
133
|
this.contentType = formData.isMultipartRequest ? "undefined" : this.contentType;
|
|
132
134
|
|
|
133
135
|
//next step the pass through parameters are merged in for post params
|
|
134
136
|
let requestContext = this.requestContext;
|
|
135
137
|
let passThroughParams = requestContext.getIf(CTX_PARAM_PASS_THR);
|
|
138
|
+
|
|
139
|
+
// this is an extension where we allow pass through parameters to be sent down additionally
|
|
140
|
+
// this can be used and is used in the impl to enrich the post request parameters with additional
|
|
141
|
+
// information
|
|
136
142
|
formData.shallowMerge(passThroughParams, true, true);
|
|
137
143
|
|
|
138
144
|
this.responseContext = passThroughParams.deepCopy;
|
|
@@ -162,7 +168,7 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
162
168
|
|
|
163
169
|
//probably not needed anymore, will test this
|
|
164
170
|
//some webkit based mobile browsers do not follow the w3c spec of
|
|
165
|
-
// setting
|
|
171
|
+
// setting, they accept headers automatically
|
|
166
172
|
ignoreErr(() => xhrObject.setRequestHeader(REQ_ACCEPT, STD_ACCEPT));
|
|
167
173
|
|
|
168
174
|
this.sendEvent(BEGIN);
|
|
@@ -223,23 +229,23 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
223
229
|
* @param resolve
|
|
224
230
|
* @param reject
|
|
225
231
|
*/
|
|
226
|
-
|
|
232
|
+
private registerXhrCallbacks(resolve: Consumer<any>, reject: Consumer<any>) {
|
|
227
233
|
let xhrObject = this.xhrObject;
|
|
228
234
|
|
|
229
235
|
xhrObject.onabort = () => {
|
|
230
|
-
this.onAbort(
|
|
236
|
+
this.onAbort(reject);
|
|
231
237
|
};
|
|
232
238
|
xhrObject.ontimeout = () => {
|
|
233
|
-
this.onTimeout(
|
|
239
|
+
this.onTimeout(reject);
|
|
234
240
|
};
|
|
235
241
|
xhrObject.onload = () => {
|
|
236
|
-
this.onSuccess(
|
|
242
|
+
this.onSuccess(resolve)
|
|
237
243
|
};
|
|
238
244
|
xhrObject.onloadend = () => {
|
|
239
|
-
this.onDone(this.xhrObject, resolve
|
|
245
|
+
this.onDone(this.xhrObject, resolve);
|
|
240
246
|
};
|
|
241
247
|
xhrObject.onerror = (errorData: any) => {
|
|
242
|
-
this.onError(errorData,
|
|
248
|
+
this.onError(errorData, reject);
|
|
243
249
|
};
|
|
244
250
|
}
|
|
245
251
|
|
|
@@ -250,29 +256,29 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
250
256
|
* the xhr object depending on its own state
|
|
251
257
|
*/
|
|
252
258
|
|
|
253
|
-
|
|
259
|
+
private onAbort(reject: Consumer<any>) {
|
|
254
260
|
reject();
|
|
255
261
|
}
|
|
256
262
|
|
|
257
|
-
|
|
263
|
+
private onTimeout(reject: Consumer<any>) {
|
|
258
264
|
this.sendEvent(STATE_EVT_TIMEOUT);
|
|
259
265
|
reject();
|
|
260
266
|
}
|
|
261
267
|
|
|
262
|
-
|
|
268
|
+
private onSuccess(resolve: Consumer<any>) {
|
|
263
269
|
|
|
264
270
|
this.sendEvent(COMPLETE);
|
|
265
271
|
|
|
266
272
|
//malforms always result in empty response xml
|
|
267
273
|
if (!this?.xhrObject?.responseXML) {
|
|
268
|
-
this.handleMalFormedXML(resolve
|
|
274
|
+
this.handleMalFormedXML(resolve);
|
|
269
275
|
return;
|
|
270
276
|
}
|
|
271
277
|
|
|
272
278
|
jsf.ajax.response(this.xhrObject, this.responseContext.value ?? {});
|
|
273
279
|
}
|
|
274
280
|
|
|
275
|
-
private handleMalFormedXML(resolve: Function
|
|
281
|
+
private handleMalFormedXML(resolve: Function) {
|
|
276
282
|
this.stopProgress = true;
|
|
277
283
|
let errorData = {
|
|
278
284
|
type: ERROR,
|
|
@@ -293,18 +299,29 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
293
299
|
//non blocking non clearing
|
|
294
300
|
}
|
|
295
301
|
|
|
296
|
-
|
|
302
|
+
private onDone(data: any, resolve: Consumer<any>) {
|
|
297
303
|
if (this.stopProgress) {
|
|
298
304
|
return;
|
|
299
305
|
}
|
|
300
306
|
resolve(data);
|
|
301
307
|
}
|
|
302
308
|
|
|
303
|
-
|
|
309
|
+
private onError(errorData: any, reject: Consumer<any>) {
|
|
304
310
|
this.handleError(errorData);
|
|
305
311
|
reject();
|
|
306
312
|
}
|
|
307
313
|
|
|
314
|
+
private sendRequest(formData: XhrFormData) {
|
|
315
|
+
let isPost = this.ajaxType != REQ_TYPE_GET;
|
|
316
|
+
if (formData.isMultipartRequest) {
|
|
317
|
+
//in case of a multipart request we send in a formData object as body
|
|
318
|
+
this.xhrObject.send((isPost) ? formData.toFormData() : null);
|
|
319
|
+
} else {
|
|
320
|
+
//in case of a normal request we send it normally
|
|
321
|
+
this.xhrObject.send((isPost) ? formData.toString() : null);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
308
325
|
/*
|
|
309
326
|
* other helpers
|
|
310
327
|
*/
|
|
@@ -331,15 +348,4 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
331
348
|
Implementation.sendError(errorData, eventHandler);
|
|
332
349
|
}
|
|
333
350
|
|
|
334
|
-
protected sendRequest(formData: XhrFormData) {
|
|
335
|
-
let isPost = this.ajaxType != REQ_TYPE_GET;
|
|
336
|
-
if (formData.isMultipartRequest) {
|
|
337
|
-
//in case of a multipart request we send in a formData object as body
|
|
338
|
-
this.xhrObject.send((isPost) ? formData.toFormData() : null);
|
|
339
|
-
} else {
|
|
340
|
-
//in case of a normal request we send it normally
|
|
341
|
-
this.xhrObject.send((isPost) ? formData.toString() : null);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
351
|
}
|