UNPKG

gentelella-rtl

Version:

Gentelella RTL Admin is a free to use Bootstrap admin template

228 lines (191 loc) 7.89 kB
import $ from 'jquery'; import Base from './base'; import Utils from './utils'; var Form = function (element, domOptions, options) { this.__class__ = 'Form'; this.element = element; this.$element = $(element); this.domOptions = domOptions; this.options = options; this.parent = window.Parsley; this.fields = []; this.validationResult = null; }; var statusMapping = {pending: null, resolved: true, rejected: false}; Form.prototype = { onSubmitValidate: function (event) { // This is a Parsley generated submit event, do not validate, do not prevent, simply exit and keep normal behavior if (true === event.parsley) return; // If we didn't come here through a submit button, use the first one in the form var submitSource = this._submitSource || this.$element.find(Utils._SubmitSelector)[0]; this._submitSource = null; this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true); if (submitSource && null !== submitSource.getAttribute('formnovalidate')) return; window.Parsley._remoteCache = {}; var promise = this.whenValidate({event}); if ('resolved' === promise.state() && false !== this._trigger('submit')) { // All good, let event go through. We make this distinction because browsers // differ in their handling of `submit` being called from inside a submit event [#1047] } else { // Rejected or pending: cancel this submit event.stopImmediatePropagation(); event.preventDefault(); if ('pending' === promise.state()) promise.done(() => { this._submit(submitSource); }); } }, onSubmitButton: function(event) { this._submitSource = event.currentTarget; }, // internal // _submit submits the form, this time without going through the validations. // Care must be taken to "fake" the actual submit button being clicked. _submit: function (submitSource) { if (false === this._trigger('submit')) return; // Add submit button's data if (submitSource) { var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false); if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element); $synthetic.attr({ name: submitSource.getAttribute('name'), value: submitSource.getAttribute('value') }); } this.$element.trigger(Object.assign($.Event('submit'), {parsley: true})); }, // Performs validation on fields while triggering events. // @returns `true` if all validations succeeds, `false` // if a failure is immediately detected, or `null` // if dependant on a promise. // Consider using `whenValidate` instead. validate: function (options) { if (arguments.length >= 1 && !$.isPlainObject(options)) { Utils.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.'); var [group, force, event] = arguments; options = {group, force, event}; } return statusMapping[ this.whenValidate(options).state() ]; }, whenValidate: function ({group, force, event} = {}) { this.submitEvent = event; if (event) { this.submitEvent = Object.assign({}, event, {preventDefault: () => { Utils.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`"); this.validationResult = false; }}); } this.validationResult = true; // fire validate event to eventually modify things before every validation this._trigger('validate'); // Refresh form DOM options and form's fields that could have changed this._refreshFields(); var promises = this._withoutReactualizingFormOptions(() => { return $.map(this.fields, field => field.whenValidate({force, group})); }); return Utils.all(promises) .done( () => { this._trigger('success'); }) .fail( () => { this.validationResult = false; this.focus(); this._trigger('error'); }) .always(() => { this._trigger('validated'); }) .pipe(...this._pipeAccordingToValidationResult()); }, // Iterate over refreshed fields, and stop on first failure. // Returns `true` if all fields are valid, `false` if a failure is detected // or `null` if the result depends on an unresolved promise. // Prefer using `whenValid` instead. isValid: function (options) { if (arguments.length >= 1 && !$.isPlainObject(options)) { Utils.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.'); var [group, force] = arguments; options = {group, force}; } return statusMapping[ this.whenValid(options).state() ]; }, // Iterate over refreshed fields and validate them. // Returns a promise. // A validation that immediately fails will interrupt the validations. whenValid: function ({group, force} = {}) { this._refreshFields(); var promises = this._withoutReactualizingFormOptions(() => { return $.map(this.fields, field => field.whenValid({group, force})); }); return Utils.all(promises); }, refresh: function() { this._refreshFields(); return this; }, // Reset UI reset: function () { // Form case: emit a reset event for each field for (var i = 0; i < this.fields.length; i++) this.fields[i].reset(); this._trigger('reset'); }, // Destroy Parsley instance (+ UI) destroy: function () { // Field case: emit destroy event to clean UI and then destroy stored instance this._destroyUI(); // Form case: destroy all its fields and then destroy stored instance for (var i = 0; i < this.fields.length; i++) this.fields[i].destroy(); this.$element.removeData('Parsley'); this._trigger('destroy'); }, _refreshFields: function () { return this.actualizeOptions()._bindFields(); }, _bindFields: function () { var oldFields = this.fields; this.fields = []; this.fieldsMappedById = {}; this._withoutReactualizingFormOptions(() => { this.$element .find(this.options.inputs) .not(this.options.excluded) .each((_, element) => { var fieldInstance = new window.Parsley.Factory(element, {}, this); // Only add valid and not excluded `Field` and `FieldMultiple` children if (('Field' === fieldInstance.__class__ || 'FieldMultiple' === fieldInstance.__class__) && (true !== fieldInstance.options.excluded)) { let uniqueId = fieldInstance.__class__ + '-' + fieldInstance.__id__; if ('undefined' === typeof this.fieldsMappedById[uniqueId]) { this.fieldsMappedById[uniqueId] = fieldInstance; this.fields.push(fieldInstance); } } }); $.each(Utils.difference(oldFields, this.fields), (_, field) => { field.reset(); }); }); return this; }, // Internal only. // Looping on a form's fields to do validation or similar // will trigger reactualizing options on all of them, which // in turn will reactualize the form's options. // To avoid calling actualizeOptions so many times on the form // for nothing, _withoutReactualizingFormOptions temporarily disables // the method actualizeOptions on this form while `fn` is called. _withoutReactualizingFormOptions: function (fn) { var oldActualizeOptions = this.actualizeOptions; this.actualizeOptions = function () { return this; }; var result = fn(); this.actualizeOptions = oldActualizeOptions; return result; }, // Internal only. // Shortcut to trigger an event // Returns true iff event is not interrupted and default not prevented. _trigger: function (eventName) { return this.trigger('form:' + eventName); } }; export default Form;