jsf.js_next_gen
Version:
A next generation typescript reimplementation of jsf.js
163 lines • 6.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.XhrFormData = void 0;
/*! Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const mona_dish_1 = require("mona-dish");
const Const_1 = require("../core/Const");
const FileUtils_1 = require("../util/FileUtils");
const Lang_1 = require("../util/Lang");
var ofAssoc = Lang_1.ExtLang.ofAssoc;
const mona_dish_2 = require("mona-dish");
const defaultParamsMapper = (key, item) => [key, item];
/**
* A unified form data class
* which builds upon our configuration.
*
* We cannot use standard html5 forms everywhere
* due to api constraints on the HTML Form object in IE11
* and due to the url encoding constraint given by the faces.js spec
*
*
* internal storage format
* every value is stored as an array
* even scalar ones!
*/
class XhrFormData extends mona_dish_1.Config {
/**
* data collector from a given form
*
* @param dataSource either a form as DomQuery object or an encoded url string
* @param paramsMapper a remapper for the params keys and values
* @param executes the executes id list for the elements to being processed
* @param partialIds partial ids to collect, to reduce the data sent down
*/
constructor(dataSource, paramsMapper = defaultParamsMapper, executes, partialIds) {
super({});
this.dataSource = dataSource;
this.paramsMapper = paramsMapper;
this.partialIds = partialIds;
/**
* Checks if the given datasource is a multipart request source
* multipart is only needed if one of the executes is a file input
* since file inputs are stateless, they fall out of the view state
* and need special handling. With file submits we have to send a formData object
* instead of an encoded string files cannot be sent that way
*/
this.isMultipartRequest = false;
//encode and append the issuing item if not a partial ids array of ids is passed
/*
* Spec. 13.3.1
* Collect and encode input elements.
* Additionally the hidden element jakarta.faces.ViewState
* Enhancement partial page submit
*/
this.resolveRequestType(this.dataSource, executes);
this.encodeSubmittableFields(this.dataSource, this.partialIds);
this.applyViewState(this.dataSource);
}
/**
* @returns a Form data representation, this is needed for file submits
*/
toFormData() {
/*
* expands key: [item1, item2]
* to: [{key: key, value: item1}, {key: key, value: item2}]
*/
let expandValueArrays = ([key, item]) => {
if (Array.isArray(item)) {
return new mona_dish_2.Es2019Array(...item).map(value => {
return { key, value };
});
}
return [{ key, value: item }];
};
/*
* remaps the incoming {key, value} tuples
* to naming container prefixed keys and values
*/
let remapForNamingContainer = ({ key, value }) => {
key = this.remapKeyForNamingContainer(key);
return { key, value };
};
/*
* collects everything into a FormData object
*/
return ofAssoc(this.value)
.flatMap(expandValueArrays)
.map(remapForNamingContainer)
.reduce((formData, { key, value }) => {
formData.append(key, value);
return formData;
}, new FormData());
}
/**
* returns an encoded string representation of our xhr form data
*
* @param defaultStr optional default value if nothing is there to encode
*/
toString(defaultStr = Const_1.EMPTY_STR) {
return (0, FileUtils_1.encodeFormData)(this, this.paramsMapper, defaultStr);
}
/**
* generic post init code, for now, this performs some post assign data post-processing
* @param rootElement the root element which knows the request type (usually a form)
* @param executes the executable dom nodes which need to be processed into the form data, which we can send
* in our ajax request
*/
resolveRequestType(rootElement, executes) {
if (!executes || executes.indexOf(Const_1.IDENT_NONE) != -1) {
return;
}
this.isMultipartRequest = rootElement.isMultipartCandidate(true);
}
/**
* special case view state handling
*
* @param form the form holding the view state value
*/
applyViewState(form) {
if (this.getIf((0, Const_1.$nsp)(Const_1.P_VIEWSTATE)).isPresent()) {
return;
}
let viewStateElement = form.querySelectorAllDeep(`[name*='${(0, Const_1.$nsp)(Const_1.P_VIEWSTATE)}'`);
let viewState = viewStateElement.inputValue;
this.appendIf(viewState.isPresent(), this.remapKeyForNamingContainer(viewStateElement.name.value)).value = viewState.value;
}
/**
* determines fields to submit
* @param {Node} parentItem - form element item is nested in
* @param {Array} partialIds - ids fo PPS
*/
encodeSubmittableFields(parentItem, partialIds = []) {
const mergeIntoThis = ([key, value]) => this.append(key).value = value;
const namingContainerRemap = ([key, value]) => this.paramsMapper(key, value);
const remappedPartialIds = partialIds.map(partialId => this.remapKeyForNamingContainer(partialId));
const partialIdsFilter = ([key, value]) => (!remappedPartialIds.length || key.indexOf("@") == 0) ? true :
remappedPartialIds.indexOf(key) != -1;
let inputs = (0, FileUtils_1.getFormInputsAsArr)(parentItem);
inputs
.map(FileUtils_1.fixEmptyParameters)
.map(namingContainerRemap)
.filter(partialIdsFilter)
.forEach(mergeIntoThis);
}
remapKeyForNamingContainer(key) {
return this.paramsMapper(key, "")[0];
}
}
exports.XhrFormData = XhrFormData;
//# sourceMappingURL=XhrFormData.js.map