formiojs
Version:
Common js library for client side interaction with <form.io>
613 lines (489 loc) • 19.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
require("core-js/modules/es7.symbol.async-iterator");
require("core-js/modules/es6.symbol");
require("core-js/modules/es6.reflect.get");
require("core-js/modules/es6.function.name");
require("core-js/modules/es7.array.includes");
require("core-js/modules/es6.string.includes");
require("core-js/modules/es6.array.iterator");
require("core-js/modules/es6.string.iterator");
require("core-js/modules/web.dom.iterable");
require("core-js/modules/es6.object.assign");
var _nativePromiseOnly = _interopRequireDefault(require("native-promise-only"));
var _lodash = _interopRequireDefault(require("lodash"));
var _Webform2 = _interopRequireDefault(require("./Webform"));
var _Formio = _interopRequireDefault(require("./Formio"));
var _utils = require("./utils/utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
var Wizard =
/*#__PURE__*/
function (_Webform) {
_inherits(Wizard, _Webform);
/**
* Constructor for wizard based forms
* @param element Dom element to place this wizard.
* @param {Object} options Options object, supported options are:
* - breadcrumbSettings.clickable: true (default) determines if the breadcrumb bar is clickable or not
* - buttonSettings.show*(Previous, Next, Cancel): true (default) determines if the button is shown or not
*/
function Wizard(element, options) {
var _this;
_classCallCheck(this, Wizard);
_this = _possibleConstructorReturn(this, _getPrototypeOf(Wizard).call(this, element, options));
_this.wizard = null;
_this.pages = [];
_this.globalComponents = [];
_this.page = 0;
_this.history = [];
_this._nextPage = 0;
return _this;
}
_createClass(Wizard, [{
key: "getPages",
value: function getPages() {
var _this2 = this;
var pageOptions = _lodash.default.clone(this.options);
var components = _lodash.default.clone(this.components); // We shouldn't recreate a components on the page we currently on to avoid duplicate inputs desync.
return this.pages.map(function (page, index) {
return _this2.createComponent(page, Object.assign({}, pageOptions, {
components: index === _this2.page ? components : null
}));
});
}
}, {
key: "getComponents",
value: function getComponents() {
return this.submitting ? this.getPages() : _get(_getPrototypeOf(Wizard.prototype), "getComponents", this).call(this);
}
}, {
key: "resetValue",
value: function resetValue() {
this.getPages().forEach(function (page) {
return page.resetValue();
});
this.setPristine(true);
}
}, {
key: "setPage",
value: function setPage(num) {
if (!this.wizard.full && num >= 0 && num < this.pages.length) {
this.page = num;
return _get(_getPrototypeOf(Wizard.prototype), "setForm", this).call(this, this.currentPage());
} else if (this.wizard.full || !this.pages.length) {
return _get(_getPrototypeOf(Wizard.prototype), "setForm", this).call(this, this.getWizard());
}
return _nativePromiseOnly.default.reject('Page not found');
}
}, {
key: "getNextPage",
value: function getNextPage(data, currentPage) {
var form = this.pages[currentPage]; // Check conditional nextPage
if (form) {
var page = ++currentPage;
if (form.nextPage) {
var next = this.evaluate(form.nextPage, {
next: page,
data: data,
page: page,
form: form
}, 'next');
if (next === null) {
return null;
}
var pageNum = parseInt(next, 10);
if (!isNaN(parseInt(pageNum, 10)) && isFinite(pageNum)) {
return pageNum;
}
return this.getPageIndexByKey(next);
}
return page;
}
return null;
}
}, {
key: "getPreviousPage",
value: function getPreviousPage() {
var prev = this.history.pop();
if (typeof prev !== 'undefined') {
return prev;
}
return this.page - 1;
}
}, {
key: "beforeSubmit",
value: function beforeSubmit() {
return _nativePromiseOnly.default.all(this.getPages().map(function (page) {
page.options.beforeSubmit = true;
return page.beforeSubmit();
}));
}
}, {
key: "nextPage",
value: function nextPage() {
var _this3 = this;
// Read-only forms should not worry about validation before going to next page, nor should they submit.
if (this.options.readOnly) {
this.history.push(this.page);
return this.setPage(this.getNextPage(this.submission.data, this.page)).then(function () {
_this3._nextPage = _this3.getNextPage(_this3.submission.data, _this3.page);
_this3.emit('nextPage', {
page: _this3.page,
submission: _this3.submission
});
});
} // Validate the form builed, before go to the next page
if (this.checkValidity(this.submission.data, true)) {
this.checkData(this.submission.data, {
noValidate: true
});
return this.beforeNext().then(function () {
_this3.history.push(_this3.page);
return _this3.setPage(_this3.getNextPage(_this3.submission.data, _this3.page)).then(function () {
_this3._nextPage = _this3.getNextPage(_this3.submission.data, _this3.page);
_this3.emit('nextPage', {
page: _this3.page,
submission: _this3.submission
});
});
});
} else {
return _nativePromiseOnly.default.reject(this.showErrors(null, true));
}
}
}, {
key: "prevPage",
value: function prevPage() {
var _this4 = this;
var prevPage = this.getPreviousPage();
return this.setPage(prevPage).then(function () {
_this4.emit('prevPage', {
page: _this4.page,
submission: _this4.submission
});
});
}
}, {
key: "cancel",
value: function cancel(noconfirm) {
if (_get(_getPrototypeOf(Wizard.prototype), "cancel", this).call(this, noconfirm)) {
this.history = [];
return this.setPage(0);
} else {
return this.setPage();
}
}
}, {
key: "getPageIndexByKey",
value: function getPageIndexByKey(key) {
var pageIndex = 0;
this.pages.forEach(function (page, index) {
if (page.key === key) {
pageIndex = index;
return false;
}
});
return pageIndex;
}
}, {
key: "addGlobalComponents",
value: function addGlobalComponents(page) {
// If there are non-page components, then add them here. This is helpful to allow for hidden fields that
// can propogate between pages.
if (this.globalComponents.length) {
page.components = this.globalComponents.concat(page.components);
}
return page;
}
}, {
key: "getPage",
value: function getPage(pageNum) {
if (pageNum >= 0 && pageNum < this.pages.length) {
return this.addGlobalComponents(this.pages[pageNum]);
}
return null;
}
}, {
key: "getWizard",
value: function getWizard() {
var pageIndex = 0;
var page = null;
var wizard = _lodash.default.clone(this.wizard);
wizard.components = [];
do {
page = this.getPage(pageIndex);
if (page) {
wizard.components.push(page);
}
pageIndex = this.getNextPage(this.submission.data, pageIndex);
} while (pageIndex); // Add all other components.
this.wizard.components.forEach(function (component) {
if (component.type !== 'panel') {
wizard.components.push(component);
}
});
return wizard;
}
}, {
key: "currentPage",
value: function currentPage() {
return this.getPage(this.page);
}
}, {
key: "buildPages",
value: function buildPages(form) {
var _this5 = this;
this.pages = [];
form.components.forEach(function (component) {
if (component.type === 'panel') {
// Ensure that this page can be seen.
if ((0, _utils.checkCondition)(component, _this5.data, _this5.data, _this5.wizard, _this5)) {
_this5.pages.push(component);
}
} else if (component.type === 'hidden') {
// Global components are hidden components that can propagate between pages.
_this5.globalComponents.push(component);
}
});
this.buildWizardHeader();
this.buildWizardNav();
}
}, {
key: "setForm",
value: function setForm(form) {
if (!form) {
return;
}
this.wizard = form;
this.buildPages(this.wizard);
return this.setPage(this.page);
}
}, {
key: "build",
value: function build() {
var _this6 = this;
_get(_getPrototypeOf(Wizard.prototype), "build", this).call(this);
this.formReady.then(function () {
_this6.buildWizardHeader();
_this6.buildWizardNav();
});
}
}, {
key: "hasButton",
value: function hasButton(name, nextPage) {
// Check for and initlize button settings object
this.options.buttonSettings = _lodash.default.defaults(this.options.buttonSettings, {
showPrevious: true,
showNext: true,
showCancel: !this.options.readOnly
});
if (name === 'previous') {
return this.page > 0 && this.options.buttonSettings.showPrevious;
}
nextPage = nextPage === undefined ? this.getNextPage(this.submission.data, this.page) : nextPage;
if (name === 'next') {
return nextPage !== null && nextPage < this.pages.length && this.options.buttonSettings.showNext;
}
if (name === 'cancel') {
return this.options.buttonSettings.showCancel;
}
if (name === 'submit') {
return !this.options.readOnly && (nextPage === null || this.page === this.pages.length - 1);
}
return true;
}
}, {
key: "buildWizardHeader",
value: function buildWizardHeader() {
var _this7 = this;
if (this.wizardHeader) {
this.wizardHeader.innerHTML = '';
}
var currentPage = this.currentPage();
if (!currentPage || this.wizard.full) {
return;
}
currentPage.breadcrumb = currentPage.breadcrumb || 'default';
if (currentPage.breadcrumb.toLowerCase() === 'none') {
return;
} // Check for and initlize breadcrumb settings object
this.options.breadcrumbSettings = _lodash.default.defaults(this.options.breadcrumbSettings, {
clickable: true
});
this.wizardHeader = this.ce('nav', {
'aria-label': 'navigation'
});
this.wizardHeaderList = this.ce('ul', {
class: 'pagination'
});
this.wizardHeader.appendChild(this.wizardHeaderList); // Add the header to the beginning.
this.prepend(this.wizardHeader);
var showHistory = currentPage.breadcrumb.toLowerCase() === 'history';
this.pages.forEach(function (page, i) {
// See if this page is in our history.
if (showHistory && _this7.page !== i && !_this7.history.includes(i)) {
return;
} // Set clickable based on breadcrumb settings
var clickable = _this7.page !== i && _this7.options.breadcrumbSettings.clickable;
var pageClass = 'page-item ';
pageClass += i === _this7.page ? 'active' : clickable ? '' : 'disabled';
var pageButton = _this7.ce('li', {
class: pageClass,
style: clickable ? 'cursor: pointer;' : ''
}); // Navigate to the page as they click on it.
if (clickable) {
_this7.addEventListener(pageButton, 'click', function (event) {
event.preventDefault();
_this7.setPage(i);
});
}
var pageLabel = _this7.ce('span', {
class: 'page-link'
});
var pageTitle = page.title;
if (currentPage.breadcrumb.toLowerCase() === 'condensed') {
pageTitle = i === _this7.page || showHistory ? page.title : i + 1;
if (!pageTitle) {
pageTitle = i + 1;
}
}
pageLabel.appendChild(_this7.text(pageTitle));
pageButton.appendChild(pageLabel);
_this7.wizardHeaderList.appendChild(pageButton);
});
}
}, {
key: "pageId",
value: function pageId(page) {
if (page.key) {
return page.key;
} else if (page.components && page.components.length > 0) {
return this.pageId(page.components[0]);
} else {
return page.title;
}
}
}, {
key: "onChange",
value: function onChange(flags, changed) {
var _this8 = this;
_get(_getPrototypeOf(Wizard.prototype), "onChange", this).call(this, flags, changed); // Only rebuild if there is a page change.
var pageIndex = 0;
var rebuild = false;
this.wizard.components.forEach(function (component) {
if (component.type !== 'panel') {
return;
}
if ((0, _utils.hasCondition)(component)) {
var hasPage = _this8.pages && _this8.pages[pageIndex] && _this8.pageId(_this8.pages[pageIndex]) === _this8.pageId(component);
var shouldShow = (0, _utils.checkCondition)(component, _this8.data, _this8.data, _this8.wizard, _this8);
if (shouldShow && !hasPage || !shouldShow && hasPage) {
rebuild = true;
return false;
}
if (shouldShow) {
pageIndex++;
}
} else {
pageIndex++;
}
});
if (rebuild) {
this.setForm(this.wizard);
} // Update Wizard Nav
var nextPage = this.getNextPage(this.submission.data, this.page);
if (this._nextPage !== nextPage) {
this.buildWizardNav(nextPage);
this.emit('updateWizardNav', {
oldpage: this._nextPage,
newpage: nextPage,
submission: this.submission
});
this._nextPage = nextPage;
}
}
}, {
key: "buildWizardNav",
value: function buildWizardNav(nextPage) {
var _this9 = this;
if (this.wizardNav) {
this.wizardNav.innerHTML = '';
this.removeChild(this.wizardNav);
}
if (this.wizard.full) {
return;
}
this.wizardNav = this.ce('ul', {
class: 'list-inline'
});
this.element.appendChild(this.wizardNav);
[{
name: 'cancel',
method: 'cancel',
class: 'btn btn-default btn-secondary'
}, {
name: 'previous',
method: 'prevPage',
class: 'btn btn-primary'
}, {
name: 'next',
method: 'nextPage',
class: 'btn btn-primary'
}, {
name: 'submit',
method: 'submit',
class: 'btn btn-primary'
}].forEach(function (button) {
if (!_this9.hasButton(button.name, nextPage)) {
return;
}
var buttonWrapper = _this9.ce('li', {
class: 'list-inline-item'
});
var buttonProp = "".concat(button.name, "Button");
var buttonElement = _this9[buttonProp] = _this9.ce('button', {
class: "".concat(button.class, " btn-wizard-nav-").concat(button.name)
});
buttonElement.appendChild(_this9.text(_this9.t(button.name)));
_this9.addEventListener(_this9[buttonProp], 'click', function (event) {
event.preventDefault(); // Disable the button until done.
buttonElement.setAttribute('disabled', 'disabled');
_this9.setLoading(buttonElement, true); // Call the button method, then re-enable the button.
_this9[button.method]().then(function () {
buttonElement.removeAttribute('disabled');
_this9.setLoading(buttonElement, false);
}).catch(function () {
buttonElement.removeAttribute('disabled');
_this9.setLoading(buttonElement, false);
});
});
buttonWrapper.appendChild(_this9[buttonProp]);
_this9.wizardNav.appendChild(buttonWrapper);
});
}
}, {
key: "schema",
get: function get() {
return this.wizard;
}
}]);
return Wizard;
}(_Webform2.default);
exports.default = Wizard;
Wizard.setBaseUrl = _Formio.default.setBaseUrl;
Wizard.setApiUrl = _Formio.default.setApiUrl;
Wizard.setAppUrl = _Formio.default.setAppUrl;