From 698331bc77514e63171425687e895604e7bdb454 Mon Sep 17 00:00:00 2001 From: root <cosimo.volpicelli@inaf.it> Date: Tue, 23 Mar 2021 11:08:39 +0100 Subject: [PATCH] Modifiche Prima pagina --- Acquisti/settings.py | 2 + home/templates/home/primapagina.html | 51 + static/validator/parsley.css | 116 ++ static/validator/parsley.js | 2472 ++++++++++++++++++++++++++ utenti/templates/plain.html | 72 +- 5 files changed, 2709 insertions(+), 4 deletions(-) create mode 100644 static/validator/parsley.css create mode 100644 static/validator/parsley.js diff --git a/Acquisti/settings.py b/Acquisti/settings.py index 3ff9a4e9..fd7a974a 100644 --- a/Acquisti/settings.py +++ b/Acquisti/settings.py @@ -180,3 +180,5 @@ EMAIL_HOST_PASSWORD = 'caV#290957#Vac' EMAIL_PORT = 587 EMAIL_USE_TLS =True EMAIL_USE_SSL = False + +REPOSITORY_ALLEGATI = '/srv/Acquisti/allegati/' \ No newline at end of file diff --git a/home/templates/home/primapagina.html b/home/templates/home/primapagina.html index 7077726e..e33043d4 100644 --- a/home/templates/home/primapagina.html +++ b/home/templates/home/primapagina.html @@ -130,7 +130,53 @@ </div> </div> </div> +<div class="x_content"> + <div class="row"> + <div class="animated flipInY col-lg-3 col-md-3 col-sm-6 " data-href="completate"> + <div class="tile-stats"> + <div class="icon"><i class="fa fa-check"></i> + </div> + <div class="count">179</div> + + <h3>Completate</h3> + <p>Lorem ipsum psdea itgum rixt.</p> + </div> + </div> + <div class="animated flipInY col-lg-3 col-md-3 col-sm-6 " data-href="inviate"> + <div class="tile-stats"> + <div class="icon"><i class="fa fa-mail-forward"></i> + </div> + <div class="count">179</div> + + <h3>Inviate</h3> + <p>Lorem ipsum psdea itgum rixt.</p> + </div> + </div> + <div class="animated flipInY col-lg-3 col-md-3 col-sm-6 " data-href="lavorazione"> + <div class="tile-stats"> + <div class="icon"><i class="fa fa-gears"></i> + </div> + <div class="count">179</div> + + <h3>In lavorazione</h3> + <p>Lorem ipsum psdea itgum rixt.</p> + </div> + </div> + <div class="animated flipInY col-lg-3 col-md-3 col-sm-6 " data-href="create"> + <div class="tile-stats"> + <div class="icon"><i class="fa fa-comment-o"></i> + </div> + <div class="count">179</div> + + <h3>Create</h3> + <p>Lorem ipsum psdea itgum rixt.</p> + </div> + </div> + </div> + </div> + </div> + {% endblock right_col %} @@ -144,6 +190,11 @@ <script src="{% static '/DataTables/dataTables.bootstrap5.min.js' %}"></script> <script src="{% static '/datepicker/js/bootstrap-datepicker.js' %}"></script> + <script> +$('.animated').on('click',function(ev){ + alert($(this).attr('data-href')) +}) + </script> {% endblock javascripts %} diff --git a/static/validator/parsley.css b/static/validator/parsley.css new file mode 100644 index 00000000..61d3c21b --- /dev/null +++ b/static/validator/parsley.css @@ -0,0 +1,116 @@ +.validate { + margin-top: 10px; } + +.invalid-form-error-message { + margin-top: 10px; + padding: 5px; } + +.invalid-form-error-message.filled { + border-left: 2px solid #E74C3C; } + +p.parsley-success { + color: #468847; + background-color: #DFF0D8; + border: 1px solid #D6E9C6; } + +p.parsley-error { + color: #B94A48; + background-color: #F2DEDE; + border: 1px solid #EED3D7; } + +ul.parsley-errors-list { + list-style: none; + color: #E74C3C; + padding-left: 0; } + +input.parsley-error, textarea.parsley-error, select.parsley-error { + background: #FAEDEC; + border: 1px solid #E85445; } + +.btn-group .parsley-errors-list { + display: none; } + +.bad input, .bad select, .bad textarea { + border: 1px solid #CE5454; + -webkit-box-shadow: 0 0 4px -2px #CE5454; + box-shadow: 0 0 4px -2px #CE5454; + position: relative; + left: 0; + -moz-animation: .7s 1 shake linear; + -webkit-animation: 0.7s 1 shake linear; } + + .item { + display: -webkit-box; + display: -ms-flexbox; + display: flex; } + +.item input, .item textarea { + -webkit-transition: 0.42s; + transition: 0.42s; } + +/* alerts (when validation fails) */ +.item .alert { + float: left; + margin: 0 0 0 20px; + padding: 3px 10px; + color: #FFF; + border-radius: 3px 4px 4px 3px; + background-color: #CE5454; + max-width: 170px; + white-space: pre; + position: relative; + left: -15px; + opacity: 0; + z-index: 1; + -webkit-transition: 0.15s ease-out; + transition: 0.15s ease-out; } + +.item .alert::after { + content: ''; + display: block; + height: 0; + width: 0; + border-color: transparent #CE5454 transparent transparent; + border-style: solid; + border-width: 11px 7px; + position: absolute; + left: -13px; + top: 1px; } + +.item.bad .alert { + left: 0; + opacity: 1; } + +.inl-bl { + display: inline-block; } + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); } +.well .markup { + background: #fff; + color: #777; + position: relative; + padding: 45px 15px 15px; + margin: 15px 0 0 0; + background-color: #fff; + border-radius: 0 0 4px 4px; + -webkit-box-shadow: none; + box-shadow: none; } + +.well .markup::after { + content: "Example"; + position: absolute; + top: 15px; + left: 15px; + font-size: 12px; + font-weight: bold; + color: #bbb; + text-transform: uppercase; + letter-spacing: 1px; } diff --git a/static/validator/parsley.js b/static/validator/parsley.js new file mode 100644 index 00000000..0f5718d8 --- /dev/null +++ b/static/validator/parsley.js @@ -0,0 +1,2472 @@ +/*! +* Parsley.js +* Version 2.9.2 - built Tue, Dec 10th 2019, 6:18 pm +* http://parsleyjs.org +* Guillaume Potier - <guillaume@wisembly.com> +* Marc-Andre Lafortune - <petroselinum@marc-andre.ca> +* MIT Licensed +*/ + +// The source code below is generated by babel as +// Parsley is written in ECMAScript 6 +// + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) : + typeof define === 'function' && define.amd ? define(['jquery'], factory) : + (global = global || self, global.parsley = factory(global.jQuery)); +}(this, (function ($) { 'use strict'; + + function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function _extends() { + _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + return _extends.apply(this, arguments); + } + + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } + } + + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); + } + + function _iterableToArrayLimit(arr, i) { + if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { + return; + } + + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); + } + + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + + var globalID = 1; + var pastWarnings = {}; + var Utils = { + // Parsley DOM-API + // returns object from dom attributes and values + attr: function attr(element, namespace, obj) { + var i; + var attribute; + var attributes; + var regex = new RegExp('^' + namespace, 'i'); + if ('undefined' === typeof obj) obj = {};else { + // Clear all own properties. This won't affect prototype's values + for (i in obj) { + if (obj.hasOwnProperty(i)) delete obj[i]; + } + } + if (!element) return obj; + attributes = element.attributes; + + for (i = attributes.length; i--;) { + attribute = attributes[i]; + + if (attribute && attribute.specified && regex.test(attribute.name)) { + obj[this.camelize(attribute.name.slice(namespace.length))] = this.deserializeValue(attribute.value); + } + } + + return obj; + }, + checkAttr: function checkAttr(element, namespace, _checkAttr) { + return element.hasAttribute(namespace + _checkAttr); + }, + setAttr: function setAttr(element, namespace, attr, value) { + element.setAttribute(this.dasherize(namespace + attr), String(value)); + }, + getType: function getType(element) { + return element.getAttribute('type') || 'text'; + }, + generateID: function generateID() { + return '' + globalID++; + }, + + /** Third party functions **/ + deserializeValue: function deserializeValue(value) { + var num; + + try { + return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? JSON.parse(value) : value) : value; + } catch (e) { + return value; + } + }, + // Zepto camelize function + camelize: function camelize(str) { + return str.replace(/-+(.)?/g, function (match, chr) { + return chr ? chr.toUpperCase() : ''; + }); + }, + // Zepto dasherize function + dasherize: function dasherize(str) { + return str.replace(/::/g, '/').replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/_/g, '-').toLowerCase(); + }, + warn: function warn() { + var _window$console; + + if (window.console && 'function' === typeof window.console.warn) (_window$console = window.console).warn.apply(_window$console, arguments); + }, + warnOnce: function warnOnce(msg) { + if (!pastWarnings[msg]) { + pastWarnings[msg] = true; + this.warn.apply(this, arguments); + } + }, + _resetWarnings: function _resetWarnings() { + pastWarnings = {}; + }, + trimString: function trimString(string) { + return string.replace(/^\s+|\s+$/g, ''); + }, + parse: { + date: function date(string) { + var parsed = string.match(/^(\d{4,})-(\d\d)-(\d\d)$/); + if (!parsed) return null; + + var _parsed$map = parsed.map(function (x) { + return parseInt(x, 10); + }), + _parsed$map2 = _slicedToArray(_parsed$map, 4), + _ = _parsed$map2[0], + year = _parsed$map2[1], + month = _parsed$map2[2], + day = _parsed$map2[3]; + + var date = new Date(year, month - 1, day); + if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) return null; + return date; + }, + string: function string(_string) { + return _string; + }, + integer: function integer(string) { + if (isNaN(string)) return null; + return parseInt(string, 10); + }, + number: function number(string) { + if (isNaN(string)) throw null; + return parseFloat(string); + }, + 'boolean': function _boolean(string) { + return !/^\s*false\s*$/i.test(string); + }, + object: function object(string) { + return Utils.deserializeValue(string); + }, + regexp: function regexp(_regexp) { + var flags = ''; // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern + + if (/^\/.*\/(?:[gimy]*)$/.test(_regexp)) { + // Replace the regexp literal string with the first match group: ([gimy]*) + // If no flag is present, this will be a blank string + flags = _regexp.replace(/.*\/([gimy]*)$/, '$1'); // Again, replace the regexp literal string with the first match group: + // everything excluding the opening and closing slashes and the flags + + _regexp = _regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1'); + } else { + // Anchor regexp: + _regexp = '^' + _regexp + '$'; + } + + return new RegExp(_regexp, flags); + } + }, + parseRequirement: function parseRequirement(requirementType, string) { + var converter = this.parse[requirementType || 'string']; + if (!converter) throw 'Unknown requirement specification: "' + requirementType + '"'; + var converted = converter(string); + if (converted === null) throw "Requirement is not a ".concat(requirementType, ": \"").concat(string, "\""); + return converted; + }, + namespaceEvents: function namespaceEvents(events, namespace) { + events = this.trimString(events || '').split(/\s+/); + if (!events[0]) return ''; + return $.map(events, function (evt) { + return "".concat(evt, ".").concat(namespace); + }).join(' '); + }, + difference: function difference(array, remove) { + // This is O(N^2), should be optimized + var result = []; + $.each(array, function (_, elem) { + if (remove.indexOf(elem) == -1) result.push(elem); + }); + return result; + }, + // Alter-ego to native Promise.all, but for jQuery + all: function all(promises) { + // jQuery treats $.when() and $.when(singlePromise) differently; let's avoid that and add spurious elements + return $.when.apply($, _toConsumableArray(promises).concat([42, 42])); + }, + // Object.create polyfill, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill + objectCreate: Object.create || function () { + var Object = function Object() {}; + + return function (prototype) { + if (arguments.length > 1) { + throw Error('Second argument not supported'); + } + + if (_typeof(prototype) != 'object') { + throw TypeError('Argument must be an object'); + } + + Object.prototype = prototype; + var result = new Object(); + Object.prototype = null; + return result; + }; + }(), + _SubmitSelector: 'input[type="submit"], button:submit' + }; + + // All these options could be overriden and specified directly in DOM using + // `data-parsley-` default DOM-API + // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"` + // eg: `data-parsley-stop-on-first-failing-constraint="false"` + var Defaults = { + // ### General + // Default data-namespace for DOM API + namespace: 'data-parsley-', + // Supported inputs by default + inputs: 'input, textarea, select', + // Excluded inputs by default + excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]', + // Stop validating field on highest priority failing constraint + priorityEnabled: true, + // ### Field only + // identifier used to group together inputs (e.g. radio buttons...) + multiple: null, + // identifier (or array of identifiers) used to validate only a select group of inputs + group: null, + // ### UI + // Enable\Disable error messages + uiEnabled: true, + // Key events threshold before validation + validationThreshold: 3, + // Focused field on form validation error. 'first'|'last'|'none' + focus: 'first', + // event(s) that will trigger validation before first failure. eg: `input`... + trigger: false, + // event(s) that will trigger validation after first failure. + triggerAfterFailure: 'input', + // Class that would be added on every failing validation Parsley field + errorClass: 'parsley-error', + // Same for success validation + successClass: 'parsley-success', + // Return the `$element` that will receive these above success or error classes + // Could also be (and given directly from DOM) a valid selector like `'#div'` + classHandler: function classHandler(Field) {}, + // Return the `$element` where errors will be appended + // Could also be (and given directly from DOM) a valid selector like `'#div'` + errorsContainer: function errorsContainer(Field) {}, + // ul elem that would receive errors' list + errorsWrapper: '<ul class="parsley-errors-list"></ul>', + // li elem that would receive error message + errorTemplate: '<li></li>' + }; + + var Base = function Base() { + this.__id__ = Utils.generateID(); + }; + + Base.prototype = { + asyncSupport: true, + // Deprecated + _pipeAccordingToValidationResult: function _pipeAccordingToValidationResult() { + var _this = this; + + var pipe = function pipe() { + var r = $.Deferred(); + if (true !== _this.validationResult) r.reject(); + return r.resolve().promise(); + }; + + return [pipe, pipe]; + }, + actualizeOptions: function actualizeOptions() { + Utils.attr(this.element, this.options.namespace, this.domOptions); + if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions(); + return this; + }, + _resetOptions: function _resetOptions(initOptions) { + this.domOptions = Utils.objectCreate(this.parent.options); + this.options = Utils.objectCreate(this.domOptions); // Shallow copy of ownProperties of initOptions: + + for (var i in initOptions) { + if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i]; + } + + this.actualizeOptions(); + }, + _listeners: null, + // Register a callback for the given event name + // Callback is called with context as the first argument and the `this` + // The context is the current parsley instance, or window.Parsley if global + // A return value of `false` will interrupt the calls + on: function on(name, fn) { + this._listeners = this._listeners || {}; + var queue = this._listeners[name] = this._listeners[name] || []; + queue.push(fn); + return this; + }, + // Deprecated. Use `on` instead + subscribe: function subscribe(name, fn) { + $.listenTo(this, name.toLowerCase(), fn); + }, + // Unregister a callback (or all if none is given) for the given event name + off: function off(name, fn) { + var queue = this._listeners && this._listeners[name]; + + if (queue) { + if (!fn) { + delete this._listeners[name]; + } else { + for (var i = queue.length; i--;) { + if (queue[i] === fn) queue.splice(i, 1); + } + } + } + + return this; + }, + // Deprecated. Use `off` + unsubscribe: function unsubscribe(name, fn) { + $.unsubscribeTo(this, name.toLowerCase()); + }, + // Trigger an event of the given name + // A return value of `false` interrupts the callback chain + // Returns false if execution was interrupted + trigger: function trigger(name, target, extraArg) { + target = target || this; + var queue = this._listeners && this._listeners[name]; + var result; + + if (queue) { + for (var i = queue.length; i--;) { + result = queue[i].call(target, target, extraArg); + if (result === false) return result; + } + } + + if (this.parent) { + return this.parent.trigger(name, target, extraArg); + } + + return true; + }, + asyncIsValid: function asyncIsValid(group, force) { + Utils.warnOnce("asyncIsValid is deprecated; please use whenValid instead"); + return this.whenValid({ + group: group, + force: force + }); + }, + _findRelated: function _findRelated() { + return this.options.multiple ? $(this.parent.element.querySelectorAll("[".concat(this.options.namespace, "multiple=\"").concat(this.options.multiple, "\"]"))) : this.$element; + } + }; + + var convertArrayRequirement = function convertArrayRequirement(string, length) { + var m = string.match(/^\s*\[(.*)\]\s*$/); + if (!m) throw 'Requirement is not an array: "' + string + '"'; + var values = m[1].split(',').map(Utils.trimString); + if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed'; + return values; + }; + + var convertExtraOptionRequirement = function convertExtraOptionRequirement(requirementSpec, string, extraOptionReader) { + var main = null; + var extra = {}; + + for (var key in requirementSpec) { + if (key) { + var value = extraOptionReader(key); + if ('string' === typeof value) value = Utils.parseRequirement(requirementSpec[key], value); + extra[key] = value; + } else { + main = Utils.parseRequirement(requirementSpec[key], string); + } + } + + return [main, extra]; + }; // A Validator needs to implement the methods `validate` and `parseRequirements` + + + var Validator = function Validator(spec) { + $.extend(true, this, spec); + }; + + Validator.prototype = { + // Returns `true` iff the given `value` is valid according the given requirements. + validate: function validate(value, requirementFirstArg) { + if (this.fn) { + // Legacy style validator + if (arguments.length > 3) // If more args then value, requirement, instance... + requirementFirstArg = [].slice.call(arguments, 1, -1); // Skip first arg (value) and last (instance), combining the rest + + return this.fn(value, requirementFirstArg); + } + + if (Array.isArray(value)) { + if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values'; + return this.validateMultiple.apply(this, arguments); + } else { + var instance = arguments[arguments.length - 1]; + + if (this.validateDate && instance._isDateInput()) { + arguments[0] = Utils.parse.date(arguments[0]); + if (arguments[0] === null) return false; + return this.validateDate.apply(this, arguments); + } + + if (this.validateNumber) { + if (!value) // Builtin validators all accept empty strings, except `required` of course + return true; + if (isNaN(value)) return false; + arguments[0] = parseFloat(arguments[0]); + return this.validateNumber.apply(this, arguments); + } + + if (this.validateString) { + return this.validateString.apply(this, arguments); + } + + throw 'Validator `' + this.name + '` only handles multiple values'; + } + }, + // Parses `requirements` into an array of arguments, + // according to `this.requirementType` + parseRequirements: function parseRequirements(requirements, extraOptionReader) { + if ('string' !== typeof requirements) { + // Assume requirement already parsed + // but make sure we return an array + return Array.isArray(requirements) ? requirements : [requirements]; + } + + var type = this.requirementType; + + if (Array.isArray(type)) { + var values = convertArrayRequirement(requirements, type.length); + + for (var i = 0; i < values.length; i++) { + values[i] = Utils.parseRequirement(type[i], values[i]); + } + + return values; + } else if ($.isPlainObject(type)) { + return convertExtraOptionRequirement(type, requirements, extraOptionReader); + } else { + return [Utils.parseRequirement(type, requirements)]; + } + }, + // Defaults: + requirementType: 'string', + priority: 2 + }; + + var ValidatorRegistry = function ValidatorRegistry(validators, catalog) { + this.__class__ = 'ValidatorRegistry'; // Default Parsley locale is en + + this.locale = 'en'; + this.init(validators || {}, catalog || {}); + }; + + var typeTesters = { + email: /^((([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))$/, + // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers + number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i, + integer: /^-?\d+$/, + digits: /^\d+$/, + alphanum: /^\w+$/i, + date: { + test: function test(value) { + return Utils.parse.date(value) !== null; + } + }, + url: new RegExp("^" + // protocol identifier + "(?:(?:https?|ftp)://)?" + // ** mod: make scheme optional + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + "(?:" + // IP address exclusion + // private & local networks + // "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + // ** mod: allow local networks + // "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks + // "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + "|" + // host name + "(?:(?:[a-zA-Z\\u00a1-\\uffff0-9]-*)*[a-zA-Z\\u00a1-\\uffff0-9]+)" + // domain name + "(?:\\.(?:[a-zA-Z\\u00a1-\\uffff0-9]-*)*[a-zA-Z\\u00a1-\\uffff0-9]+)*" + // TLD identifier + "(?:\\.(?:[a-zA-Z\\u00a1-\\uffff]{2,}))" + ")" + // port number + "(?::\\d{2,5})?" + // resource path + "(?:/\\S*)?" + "$") + }; + typeTesters.range = typeTesters.number; // See http://stackoverflow.com/a/10454560/8279 + + var decimalPlaces = function decimalPlaces(num) { + var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/); + + if (!match) { + return 0; + } + + return Math.max(0, // Number of digits right of decimal point. + (match[1] ? match[1].length : 0) - ( // Adjust for scientific notation. + match[2] ? +match[2] : 0)); + }; // parseArguments('number', ['1', '2']) => [1, 2] + + + var parseArguments = function parseArguments(type, args) { + return args.map(Utils.parse[type]); + }; // operatorToValidator returns a validating function for an operator function, applied to the given type + + + var operatorToValidator = function operatorToValidator(type, operator) { + return function (value) { + for (var _len = arguments.length, requirementsAndInput = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + requirementsAndInput[_key - 1] = arguments[_key]; + } + + requirementsAndInput.pop(); // Get rid of `input` argument + + return operator.apply(void 0, [value].concat(_toConsumableArray(parseArguments(type, requirementsAndInput)))); + }; + }; + + var comparisonOperator = function comparisonOperator(operator) { + return { + validateDate: operatorToValidator('date', operator), + validateNumber: operatorToValidator('number', operator), + requirementType: operator.length <= 2 ? 'string' : ['string', 'string'], + // Support operators with a 1 or 2 requirement(s) + priority: 30 + }; + }; + + ValidatorRegistry.prototype = { + init: function init(validators, catalog) { + this.catalog = catalog; // Copy prototype's validators: + + this.validators = _extends({}, this.validators); + + for (var name in validators) { + this.addValidator(name, validators[name].fn, validators[name].priority); + } + + window.Parsley.trigger('parsley:validator:init'); + }, + // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n + setLocale: function setLocale(locale) { + if ('undefined' === typeof this.catalog[locale]) throw new Error(locale + ' is not available in the catalog'); + this.locale = locale; + return this; + }, + // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true` + addCatalog: function addCatalog(locale, messages, set) { + if ('object' === _typeof(messages)) this.catalog[locale] = messages; + if (true === set) return this.setLocale(locale); + return this; + }, + // Add a specific message for a given constraint in a given locale + addMessage: function addMessage(locale, name, message) { + if ('undefined' === typeof this.catalog[locale]) this.catalog[locale] = {}; + this.catalog[locale][name] = message; + return this; + }, + // Add messages for a given locale + addMessages: function addMessages(locale, nameMessageObject) { + for (var name in nameMessageObject) { + this.addMessage(locale, name, nameMessageObject[name]); + } + + return this; + }, + // Add a new validator + // + // addValidator('custom', { + // requirementType: ['integer', 'integer'], + // validateString: function(value, from, to) {}, + // priority: 22, + // messages: { + // en: "Hey, that's no good", + // fr: "Aye aye, pas bon du tout", + // } + // }) + // + // Old API was addValidator(name, function, priority) + // + addValidator: function addValidator(name, arg1, arg2) { + if (this.validators[name]) Utils.warn('Validator "' + name + '" is already defined.');else if (Defaults.hasOwnProperty(name)) { + Utils.warn('"' + name + '" is a restricted keyword and is not a valid validator name.'); + return; + } + return this._setValidator.apply(this, arguments); + }, + hasValidator: function hasValidator(name) { + return !!this.validators[name]; + }, + updateValidator: function updateValidator(name, arg1, arg2) { + if (!this.validators[name]) { + Utils.warn('Validator "' + name + '" is not already defined.'); + return this.addValidator.apply(this, arguments); + } + + return this._setValidator.apply(this, arguments); + }, + removeValidator: function removeValidator(name) { + if (!this.validators[name]) Utils.warn('Validator "' + name + '" is not defined.'); + delete this.validators[name]; + return this; + }, + _setValidator: function _setValidator(name, validator, priority) { + if ('object' !== _typeof(validator)) { + // Old style validator, with `fn` and `priority` + validator = { + fn: validator, + priority: priority + }; + } + + if (!validator.validate) { + validator = new Validator(validator); + } + + this.validators[name] = validator; + + for (var locale in validator.messages || {}) { + this.addMessage(locale, name, validator.messages[locale]); + } + + return this; + }, + getErrorMessage: function getErrorMessage(constraint) { + var message; // Type constraints are a bit different, we have to match their requirements too to find right error message + + if ('type' === constraint.name) { + var typeMessages = this.catalog[this.locale][constraint.name] || {}; + message = typeMessages[constraint.requirements]; + } else message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements); + + return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage; + }, + // Kind of light `sprintf()` implementation + formatMessage: function formatMessage(string, parameters) { + if ('object' === _typeof(parameters)) { + for (var i in parameters) { + string = this.formatMessage(string, parameters[i]); + } + + return string; + } + + return 'string' === typeof string ? string.replace(/%s/i, parameters) : ''; + }, + // Here is the Parsley default validators list. + // A validator is an object with the following key values: + // - priority: an integer + // - requirement: 'string' (default), 'integer', 'number', 'regexp' or an Array of these + // - validateString, validateMultiple, validateNumber: functions returning `true`, `false` or a promise + // Alternatively, a validator can be a function that returns such an object + // + validators: { + notblank: { + validateString: function validateString(value) { + return /\S/.test(value); + }, + priority: 2 + }, + required: { + validateMultiple: function validateMultiple(values) { + return values.length > 0; + }, + validateString: function validateString(value) { + return /\S/.test(value); + }, + priority: 512 + }, + type: { + validateString: function validateString(value, type) { + var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + _ref$step = _ref.step, + step = _ref$step === void 0 ? 'any' : _ref$step, + _ref$base = _ref.base, + base = _ref$base === void 0 ? 0 : _ref$base; + + var tester = typeTesters[type]; + + if (!tester) { + throw new Error('validator type `' + type + '` is not supported'); + } + + if (!value) return true; // Builtin validators all accept empty strings, except `required` of course + + if (!tester.test(value)) return false; + + if ('number' === type) { + if (!/^any$/i.test(step || '')) { + var nb = Number(value); + var decimals = Math.max(decimalPlaces(step), decimalPlaces(base)); + if (decimalPlaces(nb) > decimals) // Value can't have too many decimals + return false; // Be careful of rounding errors by using integers. + + var toInt = function toInt(f) { + return Math.round(f * Math.pow(10, decimals)); + }; + + if ((toInt(nb) - toInt(base)) % toInt(step) != 0) return false; + } + } + + return true; + }, + requirementType: { + '': 'string', + step: 'string', + base: 'number' + }, + priority: 256 + }, + pattern: { + validateString: function validateString(value, regexp) { + if (!value) return true; // Builtin validators all accept empty strings, except `required` of course + + return regexp.test(value); + }, + requirementType: 'regexp', + priority: 64 + }, + minlength: { + validateString: function validateString(value, requirement) { + if (!value) return true; // Builtin validators all accept empty strings, except `required` of course + + return value.length >= requirement; + }, + requirementType: 'integer', + priority: 30 + }, + maxlength: { + validateString: function validateString(value, requirement) { + return value.length <= requirement; + }, + requirementType: 'integer', + priority: 30 + }, + length: { + validateString: function validateString(value, min, max) { + if (!value) return true; // Builtin validators all accept empty strings, except `required` of course + + return value.length >= min && value.length <= max; + }, + requirementType: ['integer', 'integer'], + priority: 30 + }, + mincheck: { + validateMultiple: function validateMultiple(values, requirement) { + return values.length >= requirement; + }, + requirementType: 'integer', + priority: 30 + }, + maxcheck: { + validateMultiple: function validateMultiple(values, requirement) { + return values.length <= requirement; + }, + requirementType: 'integer', + priority: 30 + }, + check: { + validateMultiple: function validateMultiple(values, min, max) { + return values.length >= min && values.length <= max; + }, + requirementType: ['integer', 'integer'], + priority: 30 + }, + min: comparisonOperator(function (value, requirement) { + return value >= requirement; + }), + max: comparisonOperator(function (value, requirement) { + return value <= requirement; + }), + range: comparisonOperator(function (value, min, max) { + return value >= min && value <= max; + }), + equalto: { + validateString: function validateString(value, refOrValue) { + if (!value) return true; // Builtin validators all accept empty strings, except `required` of course + + var $reference = $(refOrValue); + if ($reference.length) return value === $reference.val();else return value === refOrValue; + }, + priority: 256 + }, + euvatin: { + validateString: function validateString(value, refOrValue) { + if (!value) { + return true; // Builtin validators all accept empty strings, except `required` of course + } + + var re = /^[A-Z][A-Z][A-Za-z0-9 -]{2,}$/; + return re.test(value); + }, + priority: 30 + } + } + }; + + var UI = {}; + + var diffResults = function diffResults(newResult, oldResult, deep) { + var added = []; + var kept = []; + + for (var i = 0; i < newResult.length; i++) { + var found = false; + + for (var j = 0; j < oldResult.length; j++) { + if (newResult[i].assert.name === oldResult[j].assert.name) { + found = true; + break; + } + } + + if (found) kept.push(newResult[i]);else added.push(newResult[i]); + } + + return { + kept: kept, + added: added, + removed: !deep ? diffResults(oldResult, newResult, true).added : [] + }; + }; + + UI.Form = { + _actualizeTriggers: function _actualizeTriggers() { + var _this = this; + + this.$element.on('submit.Parsley', function (evt) { + _this.onSubmitValidate(evt); + }); + this.$element.on('click.Parsley', Utils._SubmitSelector, function (evt) { + _this.onSubmitButton(evt); + }); // UI could be disabled + + if (false === this.options.uiEnabled) return; + this.element.setAttribute('novalidate', ''); + }, + focus: function focus() { + this._focusedField = null; + if (true === this.validationResult || 'none' === this.options.focus) return null; + + for (var i = 0; i < this.fields.length; i++) { + var field = this.fields[i]; + + if (true !== field.validationResult && field.validationResult.length > 0 && 'undefined' === typeof field.options.noFocus) { + this._focusedField = field.$element; + if ('first' === this.options.focus) break; + } + } + + if (null === this._focusedField) return null; + return this._focusedField.focus(); + }, + _destroyUI: function _destroyUI() { + // Reset all event listeners + this.$element.off('.Parsley'); + } + }; + UI.Field = { + _reflowUI: function _reflowUI() { + this._buildUI(); // If this field doesn't have an active UI don't bother doing something + + + if (!this._ui) return; // Diff between two validation results + + var diff = diffResults(this.validationResult, this._ui.lastValidationResult); // Then store current validation result for next reflow + + this._ui.lastValidationResult = this.validationResult; // Handle valid / invalid / none field class + + this._manageStatusClass(); // Add, remove, updated errors messages + + + this._manageErrorsMessages(diff); // Triggers impl + + + this._actualizeTriggers(); // If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user + + + if ((diff.kept.length || diff.added.length) && !this._failedOnce) { + this._failedOnce = true; + + this._actualizeTriggers(); + } + }, + // Returns an array of field's error message(s) + getErrorsMessages: function getErrorsMessages() { + // No error message, field is valid + if (true === this.validationResult) return []; + var messages = []; + + for (var i = 0; i < this.validationResult.length; i++) { + messages.push(this.validationResult[i].errorMessage || this._getErrorMessage(this.validationResult[i].assert)); + } + + return messages; + }, + // It's a goal of Parsley that this method is no longer required [#1073] + addError: function addError(name) { + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + message = _ref.message, + assert = _ref.assert, + _ref$updateClass = _ref.updateClass, + updateClass = _ref$updateClass === void 0 ? true : _ref$updateClass; + + this._buildUI(); + + this._addError(name, { + message: message, + assert: assert + }); + + if (updateClass) this._errorClass(); + }, + // It's a goal of Parsley that this method is no longer required [#1073] + updateError: function updateError(name) { + var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + message = _ref2.message, + assert = _ref2.assert, + _ref2$updateClass = _ref2.updateClass, + updateClass = _ref2$updateClass === void 0 ? true : _ref2$updateClass; + + this._buildUI(); + + this._updateError(name, { + message: message, + assert: assert + }); + + if (updateClass) this._errorClass(); + }, + // It's a goal of Parsley that this method is no longer required [#1073] + removeError: function removeError(name) { + var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref3$updateClass = _ref3.updateClass, + updateClass = _ref3$updateClass === void 0 ? true : _ref3$updateClass; + + this._buildUI(); + + this._removeError(name); // edge case possible here: remove a standard Parsley error that is still failing in this.validationResult + // but highly improbable cuz' manually removing a well Parsley handled error makes no sense. + + + if (updateClass) this._manageStatusClass(); + }, + _manageStatusClass: function _manageStatusClass() { + if (this.hasConstraints() && this.needsValidation() && true === this.validationResult) this._successClass();else if (this.validationResult.length > 0) this._errorClass();else this._resetClass(); + }, + _manageErrorsMessages: function _manageErrorsMessages(diff) { + if ('undefined' !== typeof this.options.errorsMessagesDisabled) return; // Case where we have errorMessage option that configure an unique field error message, regardless failing validators + + if ('undefined' !== typeof this.options.errorMessage) { + if (diff.added.length || diff.kept.length) { + this._insertErrorWrapper(); + + if (0 === this._ui.$errorsWrapper.find('.parsley-custom-error-message').length) this._ui.$errorsWrapper.append($(this.options.errorTemplate).addClass('parsley-custom-error-message')); + + this._ui.$errorClassHandler.attr('aria-describedby', this._ui.errorsWrapperId); + + return this._ui.$errorsWrapper.addClass('filled').attr('aria-hidden', 'false').find('.parsley-custom-error-message').html(this.options.errorMessage); + } + + this._ui.$errorClassHandler.removeAttr('aria-describedby'); + + return this._ui.$errorsWrapper.removeClass('filled').attr('aria-hidden', 'true').find('.parsley-custom-error-message').remove(); + } // Show, hide, update failing constraints messages + + + for (var i = 0; i < diff.removed.length; i++) { + this._removeError(diff.removed[i].assert.name); + } + + for (i = 0; i < diff.added.length; i++) { + this._addError(diff.added[i].assert.name, { + message: diff.added[i].errorMessage, + assert: diff.added[i].assert + }); + } + + for (i = 0; i < diff.kept.length; i++) { + this._updateError(diff.kept[i].assert.name, { + message: diff.kept[i].errorMessage, + assert: diff.kept[i].assert + }); + } + }, + _addError: function _addError(name, _ref4) { + var message = _ref4.message, + assert = _ref4.assert; + + this._insertErrorWrapper(); + + this._ui.$errorClassHandler.attr('aria-describedby', this._ui.errorsWrapperId); + + this._ui.$errorsWrapper.addClass('filled').attr('aria-hidden', 'false').append($(this.options.errorTemplate).addClass('parsley-' + name).html(message || this._getErrorMessage(assert))); + }, + _updateError: function _updateError(name, _ref5) { + var message = _ref5.message, + assert = _ref5.assert; + + this._ui.$errorsWrapper.addClass('filled').find('.parsley-' + name).html(message || this._getErrorMessage(assert)); + }, + _removeError: function _removeError(name) { + this._ui.$errorClassHandler.removeAttr('aria-describedby'); + + this._ui.$errorsWrapper.removeClass('filled').attr('aria-hidden', 'true').find('.parsley-' + name).remove(); + }, + _getErrorMessage: function _getErrorMessage(constraint) { + var customConstraintErrorMessage = constraint.name + 'Message'; + if ('undefined' !== typeof this.options[customConstraintErrorMessage]) return window.Parsley.formatMessage(this.options[customConstraintErrorMessage], constraint.requirements); + return window.Parsley.getErrorMessage(constraint); + }, + _buildUI: function _buildUI() { + // UI could be already built or disabled + if (this._ui || false === this.options.uiEnabled) return; + var _ui = {}; // Give field its Parsley id in DOM + + this.element.setAttribute(this.options.namespace + 'id', this.__id__); + /** Generate important UI elements and store them in this **/ + // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes + + _ui.$errorClassHandler = this._manageClassHandler(); // $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer + + _ui.errorsWrapperId = 'parsley-id-' + (this.options.multiple ? 'multiple-' + this.options.multiple : this.__id__); + _ui.$errorsWrapper = $(this.options.errorsWrapper).attr('id', _ui.errorsWrapperId); // ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly + + _ui.lastValidationResult = []; + _ui.validationInformationVisible = false; // Store it in this for later + + this._ui = _ui; + }, + // Determine which element will have `parsley-error` and `parsley-success` classes + _manageClassHandler: function _manageClassHandler() { + // Class handled could also be determined by function given in Parsley options + if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length) return $(this.options.classHandler); // Class handled could also be determined by function given in Parsley options + + var $handlerFunction = this.options.classHandler; // It might also be the function name of a global function + + if ('string' === typeof this.options.classHandler && 'function' === typeof window[this.options.classHandler]) $handlerFunction = window[this.options.classHandler]; + + if ('function' === typeof $handlerFunction) { + var $handler = $handlerFunction.call(this, this); // If this function returned a valid existing DOM element, go for it + + if ('undefined' !== typeof $handler && $handler.length) return $handler; + } else if ('object' === _typeof($handlerFunction) && $handlerFunction instanceof jQuery && $handlerFunction.length) { + return $handlerFunction; + } else if ($handlerFunction) { + Utils.warn('The class handler `' + $handlerFunction + '` does not exist in DOM nor as a global JS function'); + } + + return this._inputHolder(); + }, + _inputHolder: function _inputHolder() { + // if simple element (input, texatrea, select...) it will perfectly host the classes and precede the error container + if (!this.options.multiple || this.element.nodeName === 'SELECT') return this.$element; // But if multiple element (radio, checkbox), that would be their parent + + return this.$element.parent(); + }, + _insertErrorWrapper: function _insertErrorWrapper() { + var $errorsContainer = this.options.errorsContainer; // Nothing to do if already inserted + + if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent(); + + if ('string' === typeof $errorsContainer) { + if ($($errorsContainer).length) return $($errorsContainer).append(this._ui.$errorsWrapper);else if ('function' === typeof window[$errorsContainer]) $errorsContainer = window[$errorsContainer];else Utils.warn('The errors container `' + $errorsContainer + '` does not exist in DOM nor as a global JS function'); + } + + if ('function' === typeof $errorsContainer) $errorsContainer = $errorsContainer.call(this, this); + if ('object' === _typeof($errorsContainer) && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper); + return this._inputHolder().after(this._ui.$errorsWrapper); + }, + _actualizeTriggers: function _actualizeTriggers() { + var _this2 = this; + + var $toBind = this._findRelated(); + + var trigger; // Remove Parsley events already bound on this field + + $toBind.off('.Parsley'); + if (this._failedOnce) $toBind.on(Utils.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () { + _this2._validateIfNeeded(); + });else if (trigger = Utils.namespaceEvents(this.options.trigger, 'Parsley')) { + $toBind.on(trigger, function (event) { + _this2._validateIfNeeded(event); + }); + } + }, + _validateIfNeeded: function _validateIfNeeded(event) { + var _this3 = this; + + // For keyup, keypress, keydown, input... events that could be a little bit obstrusive + // do not validate if val length < min threshold on first validation. Once field have been validated once and info + // about success or failure have been displayed, always validate with this trigger to reflect every yalidation change. + if (event && /key|input/.test(event.type)) if (!(this._ui && this._ui.validationInformationVisible) && this.getValue().length <= this.options.validationThreshold) return; + + if (this.options.debounce) { + window.clearTimeout(this._debounced); + this._debounced = window.setTimeout(function () { + return _this3.validate(); + }, this.options.debounce); + } else this.validate(); + }, + _resetUI: function _resetUI() { + // Reset all event listeners + this._failedOnce = false; + + this._actualizeTriggers(); // Nothing to do if UI never initialized for this field + + + if ('undefined' === typeof this._ui) return; // Reset all errors' li + + this._ui.$errorsWrapper.removeClass('filled').children().remove(); // Reset validation class + + + this._resetClass(); // Reset validation flags and last validation result + + + this._ui.lastValidationResult = []; + this._ui.validationInformationVisible = false; + }, + _destroyUI: function _destroyUI() { + this._resetUI(); + + if ('undefined' !== typeof this._ui) this._ui.$errorsWrapper.remove(); + delete this._ui; + }, + _successClass: function _successClass() { + this._ui.validationInformationVisible = true; + + this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass); + }, + _errorClass: function _errorClass() { + this._ui.validationInformationVisible = true; + + this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass); + }, + _resetClass: function _resetClass() { + this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass); + } + }; + + var Form = function Form(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 onSubmitValidate(event) { + var _this = this; + + // 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: event + }); + + if ('resolved' === promise.state() && false !== this._trigger('submit')) ; else { + // Rejected or pending: cancel this submit + event.stopImmediatePropagation(); + event.preventDefault(); + if ('pending' === promise.state()) promise.done(function () { + _this._submit(submitSource); + }); + } + }, + onSubmitButton: function onSubmitButton(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 _submit(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(_extends($.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 validate(options) { + if (arguments.length >= 1 && !$.isPlainObject(options)) { + Utils.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.'); + + var _arguments = Array.prototype.slice.call(arguments), + group = _arguments[0], + force = _arguments[1], + event = _arguments[2]; + + options = { + group: group, + force: force, + event: event + }; + } + + return statusMapping[this.whenValidate(options).state()]; + }, + whenValidate: function whenValidate() { + var _this2 = this, + _Utils$all$done$fail$; + + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + group = _ref.group, + force = _ref.force, + event = _ref.event; + + this.submitEvent = event; + + if (event) { + this.submitEvent = _extends({}, event, { + preventDefault: function preventDefault() { + Utils.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`"); + _this2.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(function () { + return $.map(_this2.fields, function (field) { + return field.whenValidate({ + force: force, + group: group + }); + }); + }); + + return (_Utils$all$done$fail$ = Utils.all(promises).done(function () { + _this2._trigger('success'); + }).fail(function () { + _this2.validationResult = false; + + _this2.focus(); + + _this2._trigger('error'); + }).always(function () { + _this2._trigger('validated'); + })).pipe.apply(_Utils$all$done$fail$, _toConsumableArray(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 isValid(options) { + if (arguments.length >= 1 && !$.isPlainObject(options)) { + Utils.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.'); + + var _arguments2 = Array.prototype.slice.call(arguments), + group = _arguments2[0], + force = _arguments2[1]; + + options = { + group: group, + force: 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 whenValid() { + var _this3 = this; + + var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + group = _ref2.group, + force = _ref2.force; + + this._refreshFields(); + + var promises = this._withoutReactualizingFormOptions(function () { + return $.map(_this3.fields, function (field) { + return field.whenValid({ + group: group, + force: force + }); + }); + }); + + return Utils.all(promises); + }, + refresh: function refresh() { + this._refreshFields(); + + return this; + }, + // Reset UI + reset: function reset() { + // 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 destroy() { + // 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 _refreshFields() { + return this.actualizeOptions()._bindFields(); + }, + _bindFields: function _bindFields() { + var _this4 = this; + + var oldFields = this.fields; + this.fields = []; + this.fieldsMappedById = {}; + + this._withoutReactualizingFormOptions(function () { + _this4.$element.find(_this4.options.inputs).not(_this4.options.excluded).not("[".concat(_this4.options.namespace, "excluded=true]")).each(function (_, element) { + var fieldInstance = new window.Parsley.Factory(element, {}, _this4); // Only add valid and not excluded `Field` and `FieldMultiple` children + + if ('Field' === fieldInstance.__class__ || 'FieldMultiple' === fieldInstance.__class__) { + var uniqueId = fieldInstance.__class__ + '-' + fieldInstance.__id__; + + if ('undefined' === typeof _this4.fieldsMappedById[uniqueId]) { + _this4.fieldsMappedById[uniqueId] = fieldInstance; + + _this4.fields.push(fieldInstance); + } + } + }); + + $.each(Utils.difference(oldFields, _this4.fields), function (_, 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 _withoutReactualizingFormOptions(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 _trigger(eventName) { + return this.trigger('form:' + eventName); + } + }; + + var Constraint = function Constraint(parsleyField, name, requirements, priority, isDomConstraint) { + var validatorSpec = window.Parsley._validatorRegistry.validators[name]; + var validator = new Validator(validatorSpec); + priority = priority || parsleyField.options[name + 'Priority'] || validator.priority; + isDomConstraint = true === isDomConstraint; + + _extends(this, { + validator: validator, + name: name, + requirements: requirements, + priority: priority, + isDomConstraint: isDomConstraint + }); + + this._parseRequirements(parsleyField.options); + }; + + var capitalize = function capitalize(str) { + var cap = str[0].toUpperCase(); + return cap + str.slice(1); + }; + + Constraint.prototype = { + validate: function validate(value, instance) { + var _this$validator; + + return (_this$validator = this.validator).validate.apply(_this$validator, [value].concat(_toConsumableArray(this.requirementList), [instance])); + }, + _parseRequirements: function _parseRequirements(options) { + var _this = this; + + this.requirementList = this.validator.parseRequirements(this.requirements, function (key) { + return options[_this.name + capitalize(key)]; + }); + } + }; + + var Field = function Field(field, domOptions, options, parsleyFormInstance) { + this.__class__ = 'Field'; + this.element = field; + this.$element = $(field); // Set parent if we have one + + if ('undefined' !== typeof parsleyFormInstance) { + this.parent = parsleyFormInstance; + } + + this.options = options; + this.domOptions = domOptions; // Initialize some properties + + this.constraints = []; + this.constraintsByName = {}; + this.validationResult = true; // Bind constraints + + this._bindConstraints(); + }; + + var statusMapping$1 = { + pending: null, + resolved: true, + rejected: false + }; + Field.prototype = { + // # Public API + // Validate field and trigger some events for mainly `UI` + // @returns `true`, an array of the validators that failed, or + // `null` if validation is not finished. Prefer using whenValidate + validate: function validate(options) { + if (arguments.length >= 1 && !$.isPlainObject(options)) { + Utils.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.'); + options = { + options: options + }; + } + + var promise = this.whenValidate(options); + if (!promise) // If excluded with `group` option + return true; + + switch (promise.state()) { + case 'pending': + return null; + + case 'resolved': + return true; + + case 'rejected': + return this.validationResult; + } + }, + // Validate field and trigger some events for mainly `UI` + // @returns a promise that succeeds only when all validations do + // or `undefined` if field is not in the given `group`. + whenValidate: function whenValidate() { + var _this$whenValid$alway, + _this = this; + + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + force = _ref.force, + group = _ref.group; + + // do not validate a field if not the same as given validation group + this.refresh(); + if (group && !this._isInGroup(group)) return; + this.value = this.getValue(); // Field Validate event. `this.value` could be altered for custom needs + + this._trigger('validate'); + + return (_this$whenValid$alway = this.whenValid({ + force: force, + value: this.value, + _refreshed: true + }).always(function () { + _this._reflowUI(); + }).done(function () { + _this._trigger('success'); + }).fail(function () { + _this._trigger('error'); + }).always(function () { + _this._trigger('validated'); + })).pipe.apply(_this$whenValid$alway, _toConsumableArray(this._pipeAccordingToValidationResult())); + }, + hasConstraints: function hasConstraints() { + return 0 !== this.constraints.length; + }, + // An empty optional field does not need validation + needsValidation: function needsValidation(value) { + if ('undefined' === typeof value) value = this.getValue(); // If a field is empty and not required, it is valid + // Except if `data-parsley-validate-if-empty` explicitely added, useful for some custom validators + + if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty) return false; + return true; + }, + _isInGroup: function _isInGroup(group) { + if (Array.isArray(this.options.group)) return -1 !== $.inArray(group, this.options.group); + return this.options.group === group; + }, + // Just validate field. Do not trigger any event. + // Returns `true` iff all constraints pass, `false` if there are failures, + // or `null` if the result can not be determined yet (depends on a promise) + // See also `whenValid`. + isValid: function isValid(options) { + if (arguments.length >= 1 && !$.isPlainObject(options)) { + Utils.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.'); + + var _arguments = Array.prototype.slice.call(arguments), + force = _arguments[0], + value = _arguments[1]; + + options = { + force: force, + value: value + }; + } + + var promise = this.whenValid(options); + if (!promise) // Excluded via `group` + return true; + return statusMapping$1[promise.state()]; + }, + // Just validate field. Do not trigger any event. + // @returns a promise that succeeds only when all validations do + // or `undefined` if the field is not in the given `group`. + // The argument `force` will force validation of empty fields. + // If a `value` is given, it will be validated instead of the value of the input. + whenValid: function whenValid() { + var _this2 = this; + + var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref2$force = _ref2.force, + force = _ref2$force === void 0 ? false : _ref2$force, + value = _ref2.value, + group = _ref2.group, + _refreshed = _ref2._refreshed; + + // Recompute options and rebind constraints to have latest changes + if (!_refreshed) this.refresh(); // do not validate a field if not the same as given validation group + + if (group && !this._isInGroup(group)) return; + this.validationResult = true; // A field without constraint is valid + + if (!this.hasConstraints()) return $.when(); // Value could be passed as argument, needed to add more power to 'field:validate' + + if ('undefined' === typeof value || null === value) value = this.getValue(); + if (!this.needsValidation(value) && true !== force) return $.when(); + + var groupedConstraints = this._getGroupedConstraints(); + + var promises = []; + $.each(groupedConstraints, function (_, constraints) { + // Process one group of constraints at a time, we validate the constraints + // and combine the promises together. + var promise = Utils.all($.map(constraints, function (constraint) { + return _this2._validateConstraint(value, constraint); + })); + promises.push(promise); + if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed + }); + return Utils.all(promises); + }, + // @returns a promise + _validateConstraint: function _validateConstraint(value, constraint) { + var _this3 = this; + + var result = constraint.validate(value, this); // Map false to a failed promise + + if (false === result) result = $.Deferred().reject(); // Make sure we return a promise and that we record failures + + return Utils.all([result]).fail(function (errorMessage) { + if (!(_this3.validationResult instanceof Array)) _this3.validationResult = []; + + _this3.validationResult.push({ + assert: constraint, + errorMessage: 'string' === typeof errorMessage && errorMessage + }); + }); + }, + // @returns Parsley field computed value that could be overrided or configured in DOM + getValue: function getValue() { + var value; // Value could be overriden in DOM or with explicit options + + if ('function' === typeof this.options.value) value = this.options.value(this);else if ('undefined' !== typeof this.options.value) value = this.options.value;else value = this.$element.val(); // Handle wrong DOM or configurations + + if ('undefined' === typeof value || null === value) return ''; + return this._handleWhitespace(value); + }, + // Reset UI + reset: function reset() { + this._resetUI(); + + return this._trigger('reset'); + }, + // Destroy Parsley instance (+ UI) + destroy: function destroy() { + // Field case: emit destroy event to clean UI and then destroy stored instance + this._destroyUI(); + + this.$element.removeData('Parsley'); + this.$element.removeData('FieldMultiple'); + + this._trigger('destroy'); + }, + // Actualize options and rebind constraints + refresh: function refresh() { + this._refreshConstraints(); + + return this; + }, + _refreshConstraints: function _refreshConstraints() { + return this.actualizeOptions()._bindConstraints(); + }, + refreshConstraints: function refreshConstraints() { + Utils.warnOnce("Parsley's refreshConstraints is deprecated. Please use refresh"); + return this.refresh(); + }, + + /** + * Add a new constraint to a field + * + * @param {String} name + * @param {Mixed} requirements optional + * @param {Number} priority optional + * @param {Boolean} isDomConstraint optional + */ + addConstraint: function addConstraint(name, requirements, priority, isDomConstraint) { + if (window.Parsley._validatorRegistry.validators[name]) { + var constraint = new Constraint(this, name, requirements, priority, isDomConstraint); // if constraint already exist, delete it and push new version + + if ('undefined' !== this.constraintsByName[constraint.name]) this.removeConstraint(constraint.name); + this.constraints.push(constraint); + this.constraintsByName[constraint.name] = constraint; + } + + return this; + }, + // Remove a constraint + removeConstraint: function removeConstraint(name) { + for (var i = 0; i < this.constraints.length; i++) { + if (name === this.constraints[i].name) { + this.constraints.splice(i, 1); + break; + } + } + + delete this.constraintsByName[name]; + return this; + }, + // Update a constraint (Remove + re-add) + updateConstraint: function updateConstraint(name, parameters, priority) { + return this.removeConstraint(name).addConstraint(name, parameters, priority); + }, + // # Internals + // Internal only. + // Bind constraints from config + options + DOM + _bindConstraints: function _bindConstraints() { + var constraints = []; + var constraintsByName = {}; // clean all existing DOM constraints to only keep javascript user constraints + + for (var i = 0; i < this.constraints.length; i++) { + if (false === this.constraints[i].isDomConstraint) { + constraints.push(this.constraints[i]); + constraintsByName[this.constraints[i].name] = this.constraints[i]; + } + } + + this.constraints = constraints; + this.constraintsByName = constraintsByName; // then re-add Parsley DOM-API constraints + + for (var name in this.options) { + this.addConstraint(name, this.options[name], undefined, true); + } // finally, bind special HTML5 constraints + + + return this._bindHtml5Constraints(); + }, + // Internal only. + // Bind specific HTML5 constraints to be HTML5 compliant + _bindHtml5Constraints: function _bindHtml5Constraints() { + // html5 required + if (null !== this.element.getAttribute('required')) this.addConstraint('required', true, undefined, true); // html5 pattern + + if (null !== this.element.getAttribute('pattern')) this.addConstraint('pattern', this.element.getAttribute('pattern'), undefined, true); // range + + var min = this.element.getAttribute('min'); + var max = this.element.getAttribute('max'); + if (null !== min && null !== max) this.addConstraint('range', [min, max], undefined, true); // HTML5 min + else if (null !== min) this.addConstraint('min', min, undefined, true); // HTML5 max + else if (null !== max) this.addConstraint('max', max, undefined, true); // length + + if (null !== this.element.getAttribute('minlength') && null !== this.element.getAttribute('maxlength')) this.addConstraint('length', [this.element.getAttribute('minlength'), this.element.getAttribute('maxlength')], undefined, true); // HTML5 minlength + else if (null !== this.element.getAttribute('minlength')) this.addConstraint('minlength', this.element.getAttribute('minlength'), undefined, true); // HTML5 maxlength + else if (null !== this.element.getAttribute('maxlength')) this.addConstraint('maxlength', this.element.getAttribute('maxlength'), undefined, true); // html5 types + + var type = Utils.getType(this.element); // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise + + if ('number' === type) { + return this.addConstraint('type', ['number', { + step: this.element.getAttribute('step') || '1', + base: min || this.element.getAttribute('value') + }], undefined, true); // Regular other HTML5 supported types + } else if (/^(email|url|range|date)$/i.test(type)) { + return this.addConstraint('type', type, undefined, true); + } + + return this; + }, + // Internal only. + // Field is required if have required constraint without `false` value + _isRequired: function _isRequired() { + if ('undefined' === typeof this.constraintsByName.required) return false; + return false !== this.constraintsByName.required.requirements; + }, + // Internal only. + // Shortcut to trigger an event + _trigger: function _trigger(eventName) { + return this.trigger('field:' + eventName); + }, + // Internal only + // Handles whitespace in a value + // Use `data-parsley-whitespace="squish"` to auto squish input value + // Use `data-parsley-whitespace="trim"` to auto trim input value + _handleWhitespace: function _handleWhitespace(value) { + if (true === this.options.trimValue) Utils.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"'); + if ('squish' === this.options.whitespace) value = value.replace(/\s{2,}/g, ' '); + if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) value = Utils.trimString(value); + return value; + }, + _isDateInput: function _isDateInput() { + var c = this.constraintsByName.type; + return c && c.requirements === 'date'; + }, + // Internal only. + // Returns the constraints, grouped by descending priority. + // The result is thus an array of arrays of constraints. + _getGroupedConstraints: function _getGroupedConstraints() { + if (false === this.options.priorityEnabled) return [this.constraints]; + var groupedConstraints = []; + var index = {}; // Create array unique of priorities + + for (var i = 0; i < this.constraints.length; i++) { + var p = this.constraints[i].priority; + if (!index[p]) groupedConstraints.push(index[p] = []); + index[p].push(this.constraints[i]); + } // Sort them by priority DESC + + + groupedConstraints.sort(function (a, b) { + return b[0].priority - a[0].priority; + }); + return groupedConstraints; + } + }; + + var Multiple = function Multiple() { + this.__class__ = 'FieldMultiple'; + }; + + Multiple.prototype = { + // Add new `$element` sibling for multiple field + addElement: function addElement($element) { + this.$elements.push($element); + return this; + }, + // See `Field._refreshConstraints()` + _refreshConstraints: function _refreshConstraints() { + var fieldConstraints; + this.constraints = []; // Select multiple special treatment + + if (this.element.nodeName === 'SELECT') { + this.actualizeOptions()._bindConstraints(); + + return this; + } // Gather all constraints for each input in the multiple group + + + for (var i = 0; i < this.$elements.length; i++) { + // Check if element have not been dynamically removed since last binding + if (!$('html').has(this.$elements[i]).length) { + this.$elements.splice(i, 1); + continue; + } + + fieldConstraints = this.$elements[i].data('FieldMultiple')._refreshConstraints().constraints; + + for (var j = 0; j < fieldConstraints.length; j++) { + this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint); + } + } + + return this; + }, + // See `Field.getValue()` + getValue: function getValue() { + // Value could be overriden in DOM + if ('function' === typeof this.options.value) return this.options.value(this);else if ('undefined' !== typeof this.options.value) return this.options.value; // Radio input case + + if (this.element.nodeName === 'INPUT') { + var type = Utils.getType(this.element); + if (type === 'radio') return this._findRelated().filter(':checked').val() || ''; // checkbox input case + + if (type === 'checkbox') { + var values = []; + + this._findRelated().filter(':checked').each(function () { + values.push($(this).val()); + }); + + return values; + } + } // Select multiple case + + + if (this.element.nodeName === 'SELECT' && null === this.$element.val()) return []; // Default case that should never happen + + return this.$element.val(); + }, + _init: function _init() { + this.$elements = [this.$element]; + return this; + } + }; + + var Factory = function Factory(element, options, parsleyFormInstance) { + this.element = element; + this.$element = $(element); // If the element has already been bound, returns its saved Parsley instance + + var savedparsleyFormInstance = this.$element.data('Parsley'); + + if (savedparsleyFormInstance) { + // If the saved instance has been bound without a Form parent and there is one given in this call, add it + if ('undefined' !== typeof parsleyFormInstance && savedparsleyFormInstance.parent === window.Parsley) { + savedparsleyFormInstance.parent = parsleyFormInstance; + + savedparsleyFormInstance._resetOptions(savedparsleyFormInstance.options); + } + + if ('object' === _typeof(options)) { + _extends(savedparsleyFormInstance.options, options); + } + + return savedparsleyFormInstance; + } // Parsley must be instantiated with a DOM element or jQuery $element + + + if (!this.$element.length) throw new Error('You must bind Parsley on an existing element.'); + if ('undefined' !== typeof parsleyFormInstance && 'Form' !== parsleyFormInstance.__class__) throw new Error('Parent instance must be a Form instance'); + this.parent = parsleyFormInstance || window.Parsley; + return this.init(options); + }; + + Factory.prototype = { + init: function init(options) { + this.__class__ = 'Parsley'; + this.__version__ = '2.9.2'; + this.__id__ = Utils.generateID(); // Pre-compute options + + this._resetOptions(options); // A Form instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute + + + if (this.element.nodeName === 'FORM' || Utils.checkAttr(this.element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm'); // Every other element is bound as a `Field` or `FieldMultiple` + + return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField'); + }, + isMultiple: function isMultiple() { + var type = Utils.getType(this.element); + return type === 'radio' || type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple'); + }, + // Multiples fields are a real nightmare :( + // Maybe some refactoring would be appreciated here... + handleMultiple: function handleMultiple() { + var _this = this; + + var name; + var parsleyMultipleInstance; // Handle multiple name + + this.options.multiple = this.options.multiple || (name = this.element.getAttribute('name')) || this.element.getAttribute('id'); // Special select multiple input + + if (this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple')) { + this.options.multiple = this.options.multiple || this.__id__; + return this.bind('parsleyFieldMultiple'); // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it + } else if (!this.options.multiple) { + Utils.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element); + return this; + } // Remove special chars + + + this.options.multiple = this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, ''); // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name + + if (name) { + $('input[name="' + name + '"]').each(function (i, input) { + var type = Utils.getType(input); + if (type === 'radio' || type === 'checkbox') input.setAttribute(_this.options.namespace + 'multiple', _this.options.multiple); + }); + } // Check here if we don't already have a related multiple instance saved + + + var $previouslyRelated = this._findRelated(); + + for (var i = 0; i < $previouslyRelated.length; i++) { + parsleyMultipleInstance = $($previouslyRelated.get(i)).data('Parsley'); + + if ('undefined' !== typeof parsleyMultipleInstance) { + if (!this.$element.data('FieldMultiple')) { + parsleyMultipleInstance.addElement(this.$element); + } + + break; + } + } // Create a secret Field instance for every multiple field. It will be stored in `data('FieldMultiple')` + // And will be useful later to access classic `Field` stuff while being in a `FieldMultiple` instance + + + this.bind('parsleyField', true); + return parsleyMultipleInstance || this.bind('parsleyFieldMultiple'); + }, + // Return proper `Form`, `Field` or `FieldMultiple` + bind: function bind(type, doNotStore) { + var parsleyInstance; + + switch (type) { + case 'parsleyForm': + parsleyInstance = $.extend(new Form(this.element, this.domOptions, this.options), new Base(), window.ParsleyExtend)._bindFields(); + break; + + case 'parsleyField': + parsleyInstance = $.extend(new Field(this.element, this.domOptions, this.options, this.parent), new Base(), window.ParsleyExtend); + break; + + case 'parsleyFieldMultiple': + parsleyInstance = $.extend(new Field(this.element, this.domOptions, this.options, this.parent), new Multiple(), new Base(), window.ParsleyExtend)._init(); + break; + + default: + throw new Error(type + 'is not a supported Parsley type'); + } + + if (this.options.multiple) Utils.setAttr(this.element, this.options.namespace, 'multiple', this.options.multiple); + + if ('undefined' !== typeof doNotStore) { + this.$element.data('FieldMultiple', parsleyInstance); + return parsleyInstance; + } // Store the freshly bound instance in a DOM element for later access using jQuery `data()` + + + this.$element.data('Parsley', parsleyInstance); // Tell the world we have a new Form or Field instance! + + parsleyInstance._actualizeTriggers(); + + parsleyInstance._trigger('init'); + + return parsleyInstance; + } + }; + + var vernums = $.fn.jquery.split('.'); + + if (parseInt(vernums[0]) <= 1 && parseInt(vernums[1]) < 8) { + throw "The loaded version of jQuery is too old. Please upgrade to 1.8.x or better."; + } + + if (!vernums.forEach) { + Utils.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim'); + } // Inherit `on`, `off` & `trigger` to Parsley: + + + var Parsley = _extends(new Base(), { + element: document, + $element: $(document), + actualizeOptions: null, + _resetOptions: null, + Factory: Factory, + version: '2.9.2' + }); // Supplement Field and Form with Base + // This way, the constructors will have access to those methods + + + _extends(Field.prototype, UI.Field, Base.prototype); + + _extends(Form.prototype, UI.Form, Base.prototype); // Inherit actualizeOptions and _resetOptions: + + + _extends(Factory.prototype, Base.prototype); // ### jQuery API + // `$('.elem').parsley(options)` or `$('.elem').psly(options)` + + + $.fn.parsley = $.fn.psly = function (options) { + if (this.length > 1) { + var instances = []; + this.each(function () { + instances.push($(this).parsley(options)); + }); + return instances; + } // Return undefined if applied to non existing DOM element + + + if (this.length == 0) { + return; + } + + return new Factory(this[0], options); + }; // ### Field and Form extension + // Ensure the extension is now defined if it wasn't previously + + + if ('undefined' === typeof window.ParsleyExtend) window.ParsleyExtend = {}; // ### Parsley config + // Inherit from ParsleyDefault, and copy over any existing values + + Parsley.options = _extends(Utils.objectCreate(Defaults), window.ParsleyConfig); + window.ParsleyConfig = Parsley.options; // Old way of accessing global options + // ### Globals + + window.Parsley = window.psly = Parsley; + Parsley.Utils = Utils; + window.ParsleyUtils = {}; + $.each(Utils, function (key, value) { + if ('function' === typeof value) { + window.ParsleyUtils[key] = function () { + Utils.warnOnce('Accessing `window.ParsleyUtils` is deprecated. Use `window.Parsley.Utils` instead.'); + return Utils[key].apply(Utils, arguments); + }; + } + }); // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley + + var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n); + window.ParsleyValidator = {}; + $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator hasValidator'.split(' '), function (i, method) { + window.Parsley[method] = function () { + return registry[method].apply(registry, arguments); + }; + + window.ParsleyValidator[method] = function () { + var _window$Parsley; + + Utils.warnOnce("Accessing the method '".concat(method, "' through Validator is deprecated. Simply call 'window.Parsley.").concat(method, "(...)'")); + return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments); + }; + }); // ### UI + // Deprecated global object + + window.Parsley.UI = UI; + window.ParsleyUI = { + removeError: function removeError(instance, name, doNotUpdateClass) { + var updateClass = true !== doNotUpdateClass; + Utils.warnOnce("Accessing UI is deprecated. Call 'removeError' on the instance directly. Please comment in issue 1073 as to your need to call this method."); + return instance.removeError(name, { + updateClass: updateClass + }); + }, + getErrorsMessages: function getErrorsMessages(instance) { + Utils.warnOnce("Accessing UI is deprecated. Call 'getErrorsMessages' on the instance directly."); + return instance.getErrorsMessages(); + } + }; + $.each('addError updateError'.split(' '), function (i, method) { + window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) { + var updateClass = true !== doNotUpdateClass; + Utils.warnOnce("Accessing UI is deprecated. Call '".concat(method, "' on the instance directly. Please comment in issue 1073 as to your need to call this method.")); + return instance[method](name, { + message: message, + assert: assert, + updateClass: updateClass + }); + }; + }); // ### PARSLEY auto-binding + // Prevent it by setting `ParsleyConfig.autoBind` to `false` + + if (false !== window.ParsleyConfig.autoBind) { + $(function () { + // Works only on `data-parsley-validate`. + if ($('[data-parsley-validate]').length) $('[data-parsley-validate]').parsley(); + }); + } + + var o = $({}); + + var deprecated = function deprecated() { + Utils.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley"); + }; // Returns an event handler that calls `fn` with the arguments it expects + + + function adapt(fn, context) { + // Store to allow unbinding + if (!fn.parsleyAdaptedCallback) { + fn.parsleyAdaptedCallback = function () { + var args = Array.prototype.slice.call(arguments, 0); + args.unshift(this); + fn.apply(context || o, args); + }; + } + + return fn.parsleyAdaptedCallback; + } + + var eventPrefix = 'parsley:'; // Converts 'parsley:form:validate' into 'form:validate' + + function eventName(name) { + if (name.lastIndexOf(eventPrefix, 0) === 0) return name.substr(eventPrefix.length); + return name; + } // $.listen is deprecated. Use Parsley.on instead. + + + $.listen = function (name, callback) { + var context; + deprecated(); + + if ('object' === _typeof(arguments[1]) && 'function' === typeof arguments[2]) { + context = arguments[1]; + callback = arguments[2]; + } + + if ('function' !== typeof callback) throw new Error('Wrong parameters'); + window.Parsley.on(eventName(name), adapt(callback, context)); + }; + + $.listenTo = function (instance, name, fn) { + deprecated(); + if (!(instance instanceof Field) && !(instance instanceof Form)) throw new Error('Must give Parsley instance'); + if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong parameters'); + instance.on(eventName(name), adapt(fn)); + }; + + $.unsubscribe = function (name, fn) { + deprecated(); + if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong arguments'); + window.Parsley.off(eventName(name), fn.parsleyAdaptedCallback); + }; + + $.unsubscribeTo = function (instance, name) { + deprecated(); + if (!(instance instanceof Field) && !(instance instanceof Form)) throw new Error('Must give Parsley instance'); + instance.off(eventName(name)); + }; + + $.unsubscribeAll = function (name) { + deprecated(); + window.Parsley.off(eventName(name)); + $('form,input,textarea,select').each(function () { + var instance = $(this).data('Parsley'); + + if (instance) { + instance.off(eventName(name)); + } + }); + }; // $.emit is deprecated. Use jQuery events instead. + + + $.emit = function (name, instance) { + var _instance; + + deprecated(); + var instanceGiven = instance instanceof Field || instance instanceof Form; + var args = Array.prototype.slice.call(arguments, instanceGiven ? 2 : 1); + args.unshift(eventName(name)); + + if (!instanceGiven) { + instance = window.Parsley; + } + + (_instance = instance).trigger.apply(_instance, _toConsumableArray(args)); + }; + + $.extend(true, Parsley, { + asyncValidators: { + 'default': { + fn: function fn(xhr) { + // By default, only status 2xx are deemed successful. + // Note: we use status instead of state() because responses with status 200 + // but invalid messages (e.g. an empty body for content type set to JSON) will + // result in state() === 'rejected'. + return xhr.status >= 200 && xhr.status < 300; + }, + url: false + }, + reverse: { + fn: function fn(xhr) { + // If reverse option is set, a failing ajax request is considered successful + return xhr.status < 200 || xhr.status >= 300; + }, + url: false + } + }, + addAsyncValidator: function addAsyncValidator(name, fn, url, options) { + Parsley.asyncValidators[name] = { + fn: fn, + url: url || false, + options: options || {} + }; + return this; + } + }); + Parsley.addValidator('remote', { + requirementType: { + '': 'string', + 'validator': 'string', + 'reverse': 'boolean', + 'options': 'object' + }, + validateString: function validateString(value, url, options, instance) { + var data = {}; + var ajaxOptions; + var csr; + var validator = options.validator || (true === options.reverse ? 'reverse' : 'default'); + if ('undefined' === typeof Parsley.asyncValidators[validator]) throw new Error('Calling an undefined async validator: `' + validator + '`'); + url = Parsley.asyncValidators[validator].url || url; // Fill current value + + if (url.indexOf('{value}') > -1) { + url = url.replace('{value}', encodeURIComponent(value)); + } else { + data[instance.element.getAttribute('name') || instance.element.getAttribute('id')] = value; + } // Merge options passed in from the function with the ones in the attribute + + + var remoteOptions = $.extend(true, options.options || {}, Parsley.asyncValidators[validator].options); // All `$.ajax(options)` could be overridden or extended directly from DOM in `data-parsley-remote-options` + + ajaxOptions = $.extend(true, {}, { + url: url, + data: data, + type: 'GET' + }, remoteOptions); // Generate store key based on ajax options + + instance.trigger('field:ajaxoptions', instance, ajaxOptions); + csr = $.param(ajaxOptions); // Initialise querry cache + + if ('undefined' === typeof Parsley._remoteCache) Parsley._remoteCache = {}; // Try to retrieve stored xhr + + var xhr = Parsley._remoteCache[csr] = Parsley._remoteCache[csr] || $.ajax(ajaxOptions); + + var handleXhr = function handleXhr() { + var result = Parsley.asyncValidators[validator].fn.call(instance, xhr, url, options); + if (!result) // Map falsy results to rejected promise + result = $.Deferred().reject(); + return $.when(result); + }; + + return xhr.then(handleXhr, handleXhr); + }, + priority: -1 + }); + Parsley.on('form:submit', function () { + Parsley._remoteCache = {}; + }); + + Base.prototype.addAsyncValidator = function () { + Utils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`'); + return Parsley.addAsyncValidator.apply(Parsley, arguments); + }; + + // This is included with the Parsley library itself, + Parsley.addMessages('en', { + defaultMessage: "This value seems to be invalid.", + type: { + email: "This value should be a valid email.", + url: "This value should be a valid url.", + number: "This value should be a valid number.", + integer: "This value should be a valid integer.", + digits: "This value should be digits.", + alphanum: "This value should be alphanumeric." + }, + notblank: "This value should not be blank.", + required: "This value is required.", + pattern: "This value seems to be invalid.", + min: "This value should be greater than or equal to %s.", + max: "This value should be lower than or equal to %s.", + range: "This value should be between %s and %s.", + minlength: "This value is too short. It should have %s characters or more.", + maxlength: "This value is too long. It should have %s characters or fewer.", + length: "This value length is invalid. It should be between %s and %s characters long.", + mincheck: "You must select at least %s choices.", + maxcheck: "You must select %s choices or fewer.", + check: "You must select between %s and %s choices.", + equalto: "This value should be the same.", + euvatin: "It's not a valid VAT Identification Number." + }); + Parsley.setLocale('en'); + + function InputEvent() { + var _this = this; + + var globals = window || global; // Slightly odd way construct our object. This way methods are force bound. + // Used to test for duplicate library. + + _extends(this, { + // For browsers that do not support isTrusted, assumes event is native. + isNativeEvent: function isNativeEvent(evt) { + return evt.originalEvent && evt.originalEvent.isTrusted !== false; + }, + fakeInputEvent: function fakeInputEvent(evt) { + if (_this.isNativeEvent(evt)) { + $(evt.target).trigger('input'); + } + }, + misbehaves: function misbehaves(evt) { + if (_this.isNativeEvent(evt)) { + _this.behavesOk(evt); + + $(document).on('change.inputevent', evt.data.selector, _this.fakeInputEvent); + + _this.fakeInputEvent(evt); + } + }, + behavesOk: function behavesOk(evt) { + if (_this.isNativeEvent(evt)) { + $(document) // Simply unbinds the testing handler + .off('input.inputevent', evt.data.selector, _this.behavesOk).off('change.inputevent', evt.data.selector, _this.misbehaves); + } + }, + // Bind the testing handlers + install: function install() { + if (globals.inputEventPatched) { + return; + } + + globals.inputEventPatched = '0.0.3'; + + for (var _i = 0, _arr = ['select', 'input[type="checkbox"]', 'input[type="radio"]', 'input[type="file"]']; _i < _arr.length; _i++) { + var selector = _arr[_i]; + $(document).on('input.inputevent', selector, { + selector: selector + }, _this.behavesOk).on('change.inputevent', selector, { + selector: selector + }, _this.misbehaves); + } + }, + uninstall: function uninstall() { + delete globals.inputEventPatched; + $(document).off('.inputevent'); + } + }); + } + var inputevent = new InputEvent(); + + inputevent.install(); + + return Parsley; + +}))); +//# sourceMappingURL=parsley.js.map diff --git a/utenti/templates/plain.html b/utenti/templates/plain.html index 51d09531..831ac8ed 100644 --- a/utenti/templates/plain.html +++ b/utenti/templates/plain.html @@ -9,6 +9,7 @@ <link href="{% static '/datepicker/css/datepicker.css' %}" rel="stylesheet"> <link href="{% static '/smartwizard/css/smart_wizard_all.min.css' %}" rel="stylesheet"> + <link href="{% static '/validator/parsley.css' %}" rel="stylesheet"> <!-- <link href="https://unpkg.com/smartwizard@5/dist/css/smart_wizard_all.min.css" rel="stylesheet" type="text/css" /> @@ -122,7 +123,7 @@ </span> </a> </li> </ul> - <form action="/utenti/save/richiesta" method="POST"> + <form action="/utenti/save/richiesta" method="POST" data-parsley-validate> {% csrf_token %} <div class="tab-content"> @@ -135,7 +136,7 @@ <div class="form-group"> <button style="z-index:100" id="pollastro" type="button" data-toggle="popover" title="Info" data-html="true" data-content="Inserire parole chiave per agevolare la tracciabilità e la ricerca della richiesta di acquisto" data-original-title="Info"><span class="fa fa-1x fa-info-circle" aria-hidden="true"></span></button> <label>Specificare un titolo breve per questo acquisto in modo da poter essere facilmente ricercato</label> - <input id="titolobreve" name="titolobreve" type="text" class="form-control required="required""> + <input id="titolobreve" name="titolobreve" type="text" class="form-control" required> </div> <div class="form-group "> <label>Pino Torinese, il 30-05-2020 <br> @@ -492,7 +493,7 @@ <script src="{% static '/smartwizard/js/jquery.smartWizard.min.js' %}"></script> <script src="{% static '/validator/multifield.js' %}"></script> - <script src="{% static '/validator/validator.js' %}"></script> + <script src="{% static '/validator/parsley.js' %}"></script> <!-- <script src="https://unpkg.com/smartwizard@5/dist/js/jquery.smartWizard.min.js" type="text/javascript"></script> --> @@ -548,6 +549,7 @@ </div> </script> <script> +/* var validator = new FormValidator(); document.forms[0].addEventListener('blur', function(e){ validator.checkField(e.target) @@ -555,6 +557,7 @@ var validator = new FormValidator(); document.forms[0].addEventListener('input', function(e){ validator.checkField(e.target); }, true); +*/ var app3 = new Vue({ el: '#informaticiPlus', data: { @@ -763,10 +766,68 @@ $('#smartwizard').smartWizard({ errorSteps: [], // Highlight step with errors hiddenSteps: [] // Hidden steps }); - + /* PARSLEY */ + var validateFront = function () { + if (true === $('form').parsley().isValid()) { + $('.bs-callout-info').removeClass('hidden'); + $('.bs-callout-warning').addClass('hidden'); + } else { + $('.bs-callout-info').addClass('hidden'); + $('.bs-callout-warning').removeClass('hidden'); + } + }; +function init_parsley() { + + if (typeof (parsley) === 'undefined') { return; } + console.log('init_parsley'); + + $/*.listen*/('parsley:field:validate', function () { + validateFront(); + }); + $('#demo-form .btn').on('click', function () { + $('#demo-form').parsley().validate(); + validateFront(); + }); + var validateFront = function () { + if (true === $('#demo-form').parsley().isValid()) { + $('.bs-callout-info').removeClass('hidden'); + $('.bs-callout-warning').addClass('hidden'); + } else { + $('.bs-callout-info').addClass('hidden'); + $('.bs-callout-warning').removeClass('hidden'); + } + }; + + $/*.listen*/('parsley:field:validate', function () { + validateFront(); + }); + $('#demo-form2 .btn').on('click', function () { + $('#demo-form2').parsley().validate(); + validateFront(); + }); + var validateFront = function () { + if (true === $('form').parsley().isValid()) { + $('.bs-callout-info').removeClass('hidden'); + $('.bs-callout-warning').addClass('hidden'); + } else { + $('.bs-callout-info').addClass('hidden'); + $('.bs-callout-warning').removeClass('hidden'); + } + }; + + try { + hljs.initHighlightingOnLoad(); + } catch (err) { } + +}; +init_parsley(); + // Initialize the leaveStep event $("#smartwizard").on("leaveStep", function(e, anchorObject, currentStepIndex, nextStepIndex, stepDirection) { //console.log("get", $("#smartwizard").steps("getCurrentStep") ); + $('form').parsley().validate(); + validateFront(); + console.log("parsley:", $('form').parsley().isValid()); if ($('form').valid()) { return true; } else { @@ -849,6 +910,9 @@ $("#smartwizard").on("showStep", function(e, anchorObject, stepIndex, stepDirect } console.log(stepDirection); }); + + + var obiettivifun=[] {% for one in ob_fun %} j={'id':{{one.id}},'of':'{{one.obiettivofunzione}}','descr': '{{one.descrizione}}', -- GitLab