diff --git a/demo/demo.css b/demo/demo.css index 87f5300..ff0c798 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -1 +1,160 @@ -/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none} +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +html { + line-height: 1.15; + -webkit-text-size-adjust: 100%; +} + +body { + margin: 0; +} + +main { + display: block; +} + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +pre { + font-family: monospace, monospace; + font-size: 1em; +} + +a { + background-color: transparent; +} + +abbr[title] { + border-bottom: none; + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +b, strong { + font-weight: bolder; +} + +code, kbd, samp { + font-family: monospace, monospace; + font-size: 1em; +} + +small { + font-size: 80%; +} + +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +img { + border-style: none; +} + +button, input, optgroup, select, textarea { + font-family: inherit; + font-size: 100%; + line-height: 1.15; + margin: 0; +} + +button, input { + overflow: visible; +} + +button, select { + text-transform: none; +} + +[type=button], [type=reset], [type=submit], button { + -webkit-appearance: button; +} + +[type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner, button::-moz-focus-inner { + border-style: none; + padding: 0; +} + +[type=button]:-moz-focusring, [type=reset]:-moz-focusring, [type=submit]:-moz-focusring, button:-moz-focusring { + outline: 1px dotted ButtonText; +} + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +legend { + box-sizing: border-box; + color: inherit; + display: table; + max-width: 100%; + padding: 0; + white-space: normal; +} + +progress { + vertical-align: baseline; +} + +textarea { + overflow: auto; +} + +[type=checkbox], [type=radio] { + box-sizing: border-box; + padding: 0; +} + +[type=number]::-webkit-inner-spin-button, [type=number]::-webkit-outer-spin-button { + height: auto; +} + +[type=search] { + -webkit-appearance: textfield; + outline-offset: -2px; +} + +[type=search]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} + +details { + display: block; +} + +summary { + display: list-item; +} + +template { + display: none; +} + +[hidden] { + display: none; +} diff --git a/demo/demo.js b/demo/demo.js index ae699d7..f5535be 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -1,6 +1,3038 @@ -(()=>{var e={619:(e,t,n)=>{"use strict";function r(e){return e.replace(/-(\w)/g,((e,t)=>t.toUpperCase()))}function i(e,t){e.firstChild&&(t.appendChild(e.firstChild),i(e,t))}function o(e){Array.from(e).forEach(s)}const s=e=>e&&e.parentNode&&e.parentNode.removeChild(e),a=(e,t)=>t&&t.parentNode&&t.parentNode.insertBefore(e,t),u=new Map,l=Symbol("riot-component"),c=new Set,f="is",p="mount",d="update",h="unmount",m="shouldUpdate",g="onBeforeMount",b="onMounted",v="onBeforeUpdate",y="onUpdated",E="onBeforeUnmount",x="onUnmounted",O="props",N="state",T="slots",w="root",A=Symbol.for("pure"),j=Symbol("parent"),_=Symbol("attributes"),S=Symbol("template");var M=Object.freeze({__proto__:null,COMPONENTS_IMPLEMENTATION_MAP:u,DOM_COMPONENT_INSTANCE_PROPERTY:l,PLUGINS_SET:c,IS_DIRECTIVE:f,VALUE_ATTRIBUTE:"value",MOUNT_METHOD_KEY:p,UPDATE_METHOD_KEY:d,UNMOUNT_METHOD_KEY:h,SHOULD_UPDATE_KEY:m,ON_BEFORE_MOUNT_KEY:g,ON_MOUNTED_KEY:b,ON_BEFORE_UPDATE_KEY:v,ON_UPDATED_KEY:y,ON_BEFORE_UNMOUNT_KEY:E,ON_UNMOUNTED_KEY:x,PROPS_KEY:O,STATE_KEY:N,SLOTS_KEY:T,ROOT_KEY:w,IS_PURE_SYMBOL:A,PARENT_KEY_SYMBOL:j,ATTRIBUTES_KEY_SYMBOL:_,TEMPLATE_KEY_SYMBOL:S});var D={EACH:0,IF:1,SIMPLE:2,TAG:3,SLOT:4};var P={ATTRIBUTE:0,EVENT:1,TEXT:2,VALUE:3};function I(e,t){return typeof e===t}function U(e){const t=e.ownerSVGElement;return!!t||null===t}function C(e){return!L(e.content)}function k(e){return I(e,"function")}function R(e){return!L(e)&&I(e,"object")}function L(e){return null==e}const z=Symbol("unmount"),V={nodes:[],mount(e,t){return this.update(e,t)},update(e,t){const{placeholder:n,nodes:r,childrenMap:i}=this,o=e===z?null:this.evaluate(e),u=o?Array.from(o):[],{newChildrenMap:l,batches:c,futureNodes:f}=(n.parentNode,function(e,t,n,r){const{condition:i,template:o,childrenMap:s,itemName:a,getKey:u,indexName:l,root:c,isTemplateTag:f}=r,p=new Map,d=[],h=[];return e.forEach(((e,r)=>{const m=function(e,t){let{itemName:n,indexName:r,index:i,item:o}=t;e[n]=o,r&&(e[r]=i);return e}(Object.create(t),{itemName:a,indexName:l,index:r,item:e}),g=u?u(m):r,b=s.get(g);if(function(e,t){return!!e&&!1===Boolean(e(t))}(i,m))return;const v=b?b.template:o.clone(),y=b?v.el:c.cloneNode(),E=!b,x=f&&E?function(e){const t=e.dom.cloneNode(!0);return{avoidDOMInjection:!0,fragment:t,children:Array.from(t.childNodes)}}(v):{};if(E?d.push((()=>v.mount(y,m,n,x))):d.push((()=>v.update(m,n))),f){const e=x.children||v.children;h.push(...e)}else h.push(y);s.delete(g),p.set(g,{template:v,context:m,index:r})})),{newChildrenMap:p,batches:d,futureNodes:h}}(u,e,t,this));return((e,t,n,r,i)=>{const o=n.length;let u=t.length,l=o,c=0,f=0,p=null;for(;ce-f){const i=r(t[c],0);for(;f{if(r<0){const n=e.pop();if(n){const{template:e,context:r}=n;e.unmount(r,t,null)}}return n}}(Array.from(i.values()),t),n),c.forEach((e=>e())),this.childrenMap=l,this.nodes=f,this},unmount(e,t){return this.update(z,t),this}};const B={mount(e,t){return this.update(e,t)},update(e,t){const n=!!this.evaluate(e),r=!this.value&&n,i=this.value&&!n,o=()=>{const n=this.node.cloneNode();a(n,this.placeholder),this.template=this.template.clone(),this.template.mount(n,e,t)};switch(!0){case r:o();break;case i:this.unmount(e);break;default:n&&this.template.update(e,t)}return this.value=n,this},unmount(e,t){return this.template.unmount(e,t,!0),this}};function F(e){throw new Error(e)}function K(e){return e.reduce(((e,t)=>{const{value:n,type:i}=t;switch(!0){case!t.name&&0===i:return Object.assign({},e,n);case 3===i:e.value=t.value;break;default:e[r(t.name)]=t.value}return e}),{})}const Y="removeAttribute",$="setAttribute",q="undefined"==typeof Element?{}:Element.prototype,G=function(e){const t=new Map,n=n=>(t.has(n)||t.set(n,e.call(this,n)))&&t.get(n);return n.cache=t,n}((e=>q.hasOwnProperty(e)));function H(e,t,n,r){let{name:i}=t;if(!i)return r&&function(e,t,n){const r=t?Object.keys(t):[];Object.keys(n).filter((e=>!r.includes(e))).forEach((t=>e.removeAttribute(t)))}(e,n,r),void(n&&function(e,t){Object.entries(t).forEach((t=>{let[n,r]=t;return H(e,{name:n},r)}))}(e,n));!G(i)&&(function(e){return I(e,"boolean")}(n)||R(n)||k(n))&&(e[i]=n),e[function(e){return L(e)||!1===e||""===e||R(e)||k(e)?Y:$}(n)](i,function(e,t){return!0===t?e:t}(i,n))}const X=/^on/,J={handleEvent(e){this[e.type](e)}},Z=new WeakMap;function W(e){return L(e)?"":e}const Q=(e,t)=>{const n=e.childNodes[t];if(n.nodeType===Node.COMMENT_NODE){const t=document.createTextNode("");return e.replaceChild(t,n),t}return n};var ee={0:H,1:function(e,t,n){let{name:r}=t;const i=r.replace(X,""),o=Z.get(e)||(e=>{const t=Object.create(J);return Z.set(e,t),t})(e),[s,a]=(e=>Array.isArray(e)?e:[e,!1])(n),u=o[i],l=s&&!u;u&&!s&&e.removeEventListener(i,o),l&&e.addEventListener(i,o,a),o[i]=s},2:function(e,t,n){e.data=W(n)},3:function(e,t,n){e.value=W(n)}};const te={mount(e){return this.value=this.evaluate(e),ne(this,this.value),this},update(e){const t=this.evaluate(e);return this.value!==t&&(ne(this,t),this.value=t),this},unmount(){return 1===this.type&&ne(this,null),this}};function ne(e,t){return ee[e.type](e.node,e,t,e.value)}function re(e,t){return Object.assign({},te,t,{node:2===t.type?Q(e,t.childNodeIndex):e})}const ie=(e,t)=>e[j]||t,oe={attributes:[],getTemplateScope(e,t){return function(e,t,n){if(!e||!e.length)return n;const r=e.map((e=>Object.assign({},e,{value:e.evaluate(t)})));return Object.assign(Object.create(n||null),K(r))}(this.attributes,e,t)},mount(e,t){const n=!!e.slots&&e.slots.find((e=>{let{id:t}=e;return t===this.name})),{parentNode:r}=this.node,i=ie(e,t);return this.template=n&&me(n.html,n.bindings).createDOM(r),this.template&&(this.template.mount(this.node,this.getTemplateScope(e,i),i),this.template.children=Array.from(this.node.childNodes),se(this.node)),s(this.node),this},update(e,t){if(this.template){const n=ie(e,t);this.template.update(this.getTemplateScope(e,n),n)}return this},unmount(e,t,n){return this.template&&this.template.unmount(this.getTemplateScope(e,t),null,n),this}};function se(e){const t=e&&e.firstChild;t&&(a(t,e),se(e))}function ae(e){return e.reduce(((e,t)=>{let{bindings:n}=t;return e.concat(n)}),[])}const ue={mount(e){return this.update(e)},update(e,t){const n=this.evaluate(e);return n===this.name?this.tag.update(e):(this.unmount(e,t,!0),this.name=n,this.tag=function(e,t,n){return void 0===t&&(t=[]),void 0===n&&(n=[]),e?e({slots:t,attributes:n}):me(function(e){return e.reduce(((e,t)=>e+t.html),"")}(t),[...ae(t),{expressions:n.map((e=>Object.assign({type:0},e)))}])}(this.getComponent(n),this.slots,this.attributes),this.tag.mount(this.node,e)),this},unmount(e,t,n){return this.tag&&this.tag.unmount(n),this}};var le={1:function(e,t){let{evaluate:n,template:r}=t;const i=document.createTextNode("");return a(i,e),s(e),Object.assign({},B,{node:e,evaluate:n,placeholder:i,template:r.createDOM(e)})},2:function(e,t){let{expressions:n}=t;return Object.assign({},(r=n.map((t=>re(e,t))),["mount","update","unmount"].reduce(((e,t)=>Object.assign({},e,{[t]:e=>r.map((n=>n[t](e)))&&i})),{})));var r,i},0:function(e,t){let{evaluate:n,condition:r,itemName:i,indexName:o,getKey:u,template:l}=t;const c=document.createTextNode(""),f=e.cloneNode();return a(c,e),s(e),Object.assign({},V,{childrenMap:new Map,node:e,root:f,condition:r,evaluate:n,isTemplateTag:C(f),template:l.createDOM(e),getKey:u,indexName:o,itemName:i,placeholder:c})},3:function(e,t){let{evaluate:n,getComponent:r,slots:i,attributes:o}=t;return Object.assign({},ue,{node:e,evaluate:n,slots:i,attributes:o,getComponent:r})},4:function(e,t){let{name:n,attributes:r}=t;return Object.assign({},oe,{attributes:r,node:e,name:n})}};function ce(e,t){return e.map((e=>2===e.type?Object.assign({},e,{childNodeIndex:e.childNodeIndex+t}):e))}function fe(e,t,n){const{selector:r,type:i,redundantAttribute:o,expressions:s}=t,a=r?e.querySelector(r):e;o&&a.removeAttribute(o);const u=s||[];return(le[i]||le[2])(a,Object.assign({},t,{expressions:n&&!r?ce(u,n):u}))}function pe(e,t){return U(e)?function(e,t){return t.ownerDocument.importNode((new window.DOMParser).parseFromString(`${e}`,"application/xml").documentElement,!0)}(t,e):function(e,t){const n=C(t)?t:document.createElement("template");return n.innerHTML=e,n.content}(t,e)}function de(e,t){switch(!0){case U(e):i(t,e);break;case C(e):e.parentNode.replaceChild(t,e);break;default:e.appendChild(t)}}const he=Object.freeze({createDOM(e){return this.dom=this.dom||function(e,t){return t&&("string"==typeof t?pe(e,t):t)}(e,this.html),this},mount(e,t,n,r){if(void 0===r&&(r={}),!e)throw new Error("Please provide DOM node to mount properly your template");this.el&&this.unmount(t);const{fragment:i,children:o,avoidDOMInjection:s}=r,{parentNode:a}=o?o[0]:e,u=C(e),l=u?Math.max(Array.from(a.childNodes).indexOf(e),0):null;return this.isTemplateTag=u,this.createDOM(e),this.dom&&(this.fragment=i||this.dom.cloneNode(!0)),this.el=this.isTemplateTag?a:e,this.children=this.isTemplateTag?o||Array.from(this.fragment.childNodes):null,!s&&this.fragment&&de(e,this.fragment),this.bindings=this.bindingsData.map((e=>fe(this.el,e,l))),this.bindings.forEach((e=>e.mount(t,n))),this},update(e,t){return this.bindings.forEach((n=>n.update(e,t))),this},unmount(e,t,n){if(this.el){switch(this.bindings.forEach((r=>r.unmount(e,t,n))),!0){case this.el[A]:break;case this.children&&null!==n:o(this.children);break;case!0===n:s(this.el);break;case null!==n:o(this.el.childNodes)}this.el=null}return this},clone(){return Object.assign({},this,{el:null})}});function me(e,t){return void 0===t&&(t=[]),Object.assign({},he,{html:e,bindingsData:t})}function ge(){return this}function be(e){return k(e)?e.prototype&&e.prototype.constructor?new e:e():e}function ve(e,t,n,r){return void 0===r&&(r={}),Object.defineProperty(e,t,Object.assign({value:n,enumerable:!1,writable:!1,configurable:!0},r)),e}function ye(e,t,n){return Object.entries(t).forEach((t=>{let[r,i]=t;ve(e,r,i,n)})),e}function Ee(e,t){return Object.entries(t).forEach((t=>{let[n,r]=t;e[n]||(e[n]=r)})),e}function xe(e){return Array.isArray(e)?e:/^\[object (HTMLCollection|NodeList|Object)\]$/.test(Object.prototype.toString.call(e))&&"number"==typeof e.length?Array.from(e):[e]}function Oe(e,t){return xe("string"==typeof e?(t||document).querySelectorAll(e):e)}const Ne=e=>1===e.length?e[0]:e;function Te(e,t,n){const r="object"==typeof t?t:{[t]:n},i=Object.keys(r);return xe(e).forEach((e=>{i.forEach((t=>e.setAttribute(t,r[t])))})),e}function we(e,t){return function(e,t,n){const r="string"==typeof t?[t]:t;return Ne(xe(e).map((e=>Ne(r.map((t=>e[n](t)))))))}(e,t,"getAttribute")}const Ae=new Map,je=()=>_e||(Te(_e=Oe("style[riot]")[0]||document.createElement("style"),"type","text/css"),_e.parentNode||document.head.appendChild(_e),_e);var _e,Se={CSS_BY_NAME:Ae,add(e,t){return Ae.has(e)||(Ae.set(e,t),this.inject()),this},inject(){return je().innerHTML=[...Ae.values()].join("\n"),this},remove(e){return Ae.has(e)&&(Ae.delete(e),this.inject()),this}};function Me(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r(e[r(t.name)]=t.value,e)),{})}(e),be(t))}const Re=(e,t)=>e[l]=t;function Le(e){return[p,d,h].reduce(((t,n)=>(t[n]=e(n),t)),{})}function ze(e){let{css:t,template:n,exports:r,name:i}=e;const o=n?function(e,t){return e(me,P,D,(e=>t[e]||u.get(e)))}(n,r?function(e){void 0===e&&(e={});return Object.entries(be(e)).reduce(((e,t)=>{let[n,r]=t; +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "./src/field-error.riot": +/*!******************************!*\ + !*** ./src/field-error.riot ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__ +/* harmony export */ }); +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ + 'css': null, + + 'exports': { + state: { + errors: [ + + ], + }, + + onMounted(props, state) { + + const parent = this.root.closest('.field') + const element = document.querySelector('[name="' + props.name + '"]') + const form = element.closest('form') + + // element and form set + if (element && form) { + element.addEventListener('keyup', function(event) { + + const fieldUpdateEvent = new CustomEvent('field-update', { + 'detail': { + 'name': props.name, + 'value': this.value + } + }) + + form.dispatchEvent(fieldUpdateEvent) + }) + } + + // add custom event to listen to form-validation + this.root.addEventListener('form-validation', (event) => { + + // if detail is set with element name, get errors + if (event.detail) { + this.state.errors = event.detail + parent.classList.add('field--error') + parent.classList.remove('field--valid') + } else { + this.state.errors = [] + parent.classList.remove('field--error') + parent.classList.add('field--valid') + } + + this.update() + }) + } + }, + + 'template': function( + template, + expressionTypes, + bindingTypes, + getComponent + ) { + return template( + '
', + [ + { + 'type': bindingTypes.IF, + + 'evaluate': function( + scope + ) { + return scope.state.errors.length > 0; + }, + + 'redundantAttribute': 'expr0', + 'selector': '[expr0]', + + 'template': template( + '
', + [ + { + 'type': bindingTypes.EACH, + 'getKey': null, + 'condition': null, + + 'template': template( + ' ', + [ + { + 'expressions': [ + { + 'type': expressionTypes.TEXT, + 'childNodeIndex': 0, + + 'evaluate': function( + scope + ) { + return [ + scope.error + ].join( + '' + ); + } + } + ] + } + ] + ), + + 'redundantAttribute': 'expr1', + 'selector': '[expr1]', + 'itemName': 'error', + 'indexName': null, + + 'evaluate': function( + scope + ) { + return scope.state.errors; + } + } + ] + ) + } + ] + ); + }, + + 'name': 'field-error' +}); + +/***/ }), + +/***/ "./src/FormValidator.js": +/*!******************************!*\ + !*** ./src/FormValidator.js ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__ +/* harmony export */ }); +/* harmony import */ var validate_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! validate.js */ "./node_modules/validate.js/validate.js"); +/* harmony import */ var validate_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(validate_js__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var form_serialize__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! form-serialize */ "./node_modules/form-serialize/index.js"); +/* harmony import */ var form_serialize__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(form_serialize__WEBPACK_IMPORTED_MODULE_1__); +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + + + +/** + * + * + * + */ + +var FormValidator = /*#__PURE__*/function () { + /** + * + * @param {[type]} formSelector [description] + * @param {[type]} constraits [description] + */ + function FormValidator(formSelector, constraits) { + var _this = this; + + _classCallCheck(this, FormValidator); + + this.errors = []; // getting selector to find form-element + + this.formSelector = formSelector; // constraits for validate.js + + this.constraits = constraits; // get form and elements + + this.form = document.querySelector(this.formSelector); + this.elements = this.form.querySelectorAll('field-error'); // adding submit event + + this.form.addEventListener('submit', function (event) { + _this.onSubmit(event); + }); // adding event if a element is updated + + this.form.addEventListener('field-update', function (event) { + _this.onFieldUpdate(event); + }); + } + /** + * + * @param {[type]} name [description] + * @return {[type]} [description] + */ + + + _createClass(FormValidator, [{ + key: "findElementByName", + value: function findElementByName(name) { + var result; + this.elements.forEach(function (element) { + if (element.attributes.name.nodeValue == name) { + result = element; + return false; + } + }); + return result; + } + /** + * + * @param {[type]} event [description] + * @return {[type]} [description] + */ + + }, { + key: "onSubmit", + value: function onSubmit(event) { + var _this2 = this; + + var errors = validate_js__WEBPACK_IMPORTED_MODULE_0___default()(form_serialize__WEBPACK_IMPORTED_MODULE_1___default()(event.target, { + hash: true + }), this.constraits); + + if (errors) { + event.preventDefault(); + this.elements.forEach(function (element) { + var elementErrors = false; + + if (errors[element.attributes.name.nodeValue]) { + elementErrors = errors[element.attributes.name.nodeValue]; + } + + _this2.dispatchCustomEvent(elementErrors, element); + }); + } + } + /** + * + * @param {[type]} event [description] + * @return {[type]} [description] + */ + + }, { + key: "onFieldUpdate", + value: function onFieldUpdate(event) { + var errors = validate_js__WEBPACK_IMPORTED_MODULE_0___default().single(event.detail.value, this.constraits[event.detail.name]); + var element = this.findElementByName(event.detail.name); + this.dispatchCustomEvent(errors, element); + } + /** + * + * @param {[type]} errors [description] + * @param {[type]} element [description] + * @return {[type]} [description] + */ + + }, { + key: "dispatchCustomEvent", + value: function dispatchCustomEvent(errors, element) { + var detail = false; + + if (errors) { + detail = errors; + } + + var formValidationEvent = new CustomEvent('form-validation', { + 'detail': detail + }); + element.dispatchEvent(formValidationEvent); + } + }]); + + return FormValidator; +}(); + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FormValidator); + +/***/ }), + +/***/ "./src/demo/demo.js": +/*!**************************!*\ + !*** ./src/demo/demo.js ***! + \**************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var riot__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! riot */ "./node_modules/riot/riot.esm.js"); +/* harmony import */ var _FormValidator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../FormValidator */ "./src/FormValidator.js"); +/* harmony import */ var _field_error_riot__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./../field-error.riot */ "./src/field-error.riot"); + + + +riot__WEBPACK_IMPORTED_MODULE_2__.register('field-error', _field_error_riot__WEBPACK_IMPORTED_MODULE_1__.default); +riot__WEBPACK_IMPORTED_MODULE_2__.mount('field-error'); +var formValidation = new _FormValidator__WEBPACK_IMPORTED_MODULE_0__.default('form', { + 'email': { + 'presence': true, + 'email': true + }, + 'password': { + 'presence': true + } +}); + +/***/ }), + +/***/ "./node_modules/form-serialize/index.js": +/*!**********************************************!*\ + !*** ./node_modules/form-serialize/index.js ***! + \**********************************************/ +/***/ ((module) => { + +// get successful control from form and assemble into object +// http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2 + +// types which indicate a submit action and are not successful controls +// these will be ignored +var k_r_submitter = /^(?:submit|button|image|reset|file)$/i; + +// node names which could be successful controls +var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i; + +// Matches bracket notation. +var brackets = /(\[[^\[\]]*\])/g; + +// serializes form fields +// @param form MUST be an HTMLForm element +// @param options is an optional argument to configure the serialization. Default output +// with no options specified is a url encoded string +// - hash: [true | false] Configure the output type. If true, the output will +// be a js object. +// - serializer: [function] Optional serializer function to override the default one. +// The function takes 3 arguments (result, key, value) and should return new result +// hash and url encoded str serializers are provided with this module +// - disabled: [true | false]. If true serialize disabled fields. +// - empty: [true | false]. If true serialize empty fields +function serialize(form, options) { + if (typeof options != 'object') { + options = { hash: !!options }; + } + else if (options.hash === undefined) { + options.hash = true; + } + + var result = (options.hash) ? {} : ''; + var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize); + + var elements = form && form.elements ? form.elements : []; + + //Object store each radio and set if it's empty or not + var radio_store = Object.create(null); + + for (var i=0 ; i
',[{redundantAttribute:"expr2",selector:"[expr2]",expressions:[{type:t.EVENT,name:"onsubmit",evaluate:function(e){return t=>{e.state.validator.handle(t)}}}]},{redundantAttribute:"expr3",selector:"[expr3]",expressions:[{type:t.EVENT,name:"onkeyup",evaluate:function(e){return t=>{e.state.validator.handle(t,"email")}}}]},{type:n.TAG,getComponent:r,evaluate:function(e){return"field-error"},slots:[],attributes:[{type:t.ATTRIBUTE,name:"errors",evaluate:function(e){return e.state.validator.errors("email")}}],redundantAttribute:"expr4",selector:"[expr4]"},{redundantAttribute:"expr5",selector:"[expr5]",expressions:[{type:t.EVENT,name:"onkeyup",evaluate:function(e){return t=>{e.state.validator.handle(t,"password")}}}]},{type:n.TAG,getComponent:r,evaluate:function(e){return"field-error"},slots:[],attributes:[{type:t.ATTRIBUTE,name:"errors",evaluate:function(e){return e.state.validator.errors("password")}}],redundantAttribute:"expr6",selector:"[expr6]"}])},name:"demo"};qe("field-error",{css:null,exports:{state:{errors:[]},onBeforeUpdate(e,t){e.errors&&e.errors.length>0?t.errors=e.errors:t.errors=[]}},template:function(e,t,n,r){return e('
',[{type:n.IF,evaluate:function(e){return e.state.errors.length>0},redundantAttribute:"expr0",selector:"[expr0]",template:e('
',[{type:n.EACH,getKey:null,condition:null,template:e(" ",[{expressions:[{type:t.TEXT,childNodeIndex:0,evaluate:function(e){return e.error}}]}]),redundantAttribute:"expr1",selector:"[expr1]",itemName:"error",indexName:null,evaluate:function(e){return e.state.errors}}])}])},name:"field-error"}),Ge("field-error"),qe("demo",et),Ge("demo")},422:e=>{var t=/^(?:submit|button|image|reset|file)$/i,n=/^(?:input|select|textarea|keygen)/i,r=/(\[[^\[\]]*\])/g;function i(e,t,n){if(0===t.length)return e=n;var r=t.shift(),o=r.match(/^\[(.+?)\]$/);if("[]"===r)return e=e||[],Array.isArray(e)?e.push(i(null,t,n)):(e._values=e._values||[],e._values.push(i(null,t,n))),e;if(o){var s=o[1],a=+s;isNaN(a)?(e=e||{})[s]=i(e[s],t,n):(e=e||[])[a]=i(e[a],t,n)}else e[r]=i(e[r],t,n);return e}function o(e,t,n){if(t.match(r)){i(e,function(e){var t=[],n=new RegExp(r),i=/^([^\[\]]*)/.exec(e);for(i[1]&&t.push(i[1]);null!==(i=n.exec(e));)t.push(i[1]);return t}(t),n)}else{var o=e[t];o?(Array.isArray(o)||(e[t]=[o]),e[t].push(n)):e[t]=n}return e}function s(e,t,n){return n=n.replace(/(\r)?\n/g,"\r\n"),n=(n=encodeURIComponent(n)).replace(/%20/g,"+"),e+(e?"&":"")+encodeURIComponent(t)+"="+n}e.exports=function(e,r){"object"!=typeof r?r={hash:!!r}:void 0===r.hash&&(r.hash=!0);for(var i=r.hash?{}:"",a=r.serializer||(r.hash?o:s),u=e&&e.elements?e.elements:[],l=Object.create(null),c=0;c{},765:function(e,t,n){e=n.nmd(e), +/** + * Convert a string from camel case to dash-case + * @param {string} string - probably a component tag name + * @returns {string} component name normalized + */ +function camelToDashCase(string) { + return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); +} +/** + * Convert a string containing dashes to camel case + * @param {string} string - input string + * @returns {string} my-string -> myString + */ + +function dashToCamelCase(string) { + return string.replace(/-(\w)/g, (_, c) => c.toUpperCase()); +} + +/** + * Get all the element attributes as object + * @param {HTMLElement} element - DOM node we want to parse + * @returns {Object} all the attributes found as a key value pairs + */ + +function DOMattributesToObject(element) { + return Array.from(element.attributes).reduce((acc, attribute) => { + acc[dashToCamelCase(attribute.name)] = attribute.value; + return acc; + }, {}); +} +/** + * Move all the child nodes from a source tag to another + * @param {HTMLElement} source - source node + * @param {HTMLElement} target - target node + * @returns {undefined} it's a void method ¯\_(ツ)_/¯ + */ +// Ignore this helper because it's needed only for svg tags + +function moveChildren(source, target) { + if (source.firstChild) { + target.appendChild(source.firstChild); + moveChildren(source, target); + } +} +/** + * Remove the child nodes from any DOM node + * @param {HTMLElement} node - target node + * @returns {undefined} + */ + +function cleanNode(node) { + clearChildren(node.childNodes); +} +/** + * Clear multiple children in a node + * @param {HTMLElement[]} children - direct children nodes + * @returns {undefined} + */ + +function clearChildren(children) { + Array.from(children).forEach(removeChild); +} +/** + * Remove a node + * @param {HTMLElement}node - node to remove + * @returns {undefined} + */ + +const removeChild = node => node && node.parentNode && node.parentNode.removeChild(node); +/** + * Insert before a node + * @param {HTMLElement} newNode - node to insert + * @param {HTMLElement} refNode - ref child + * @returns {undefined} + */ + +const insertBefore = (newNode, refNode) => refNode && refNode.parentNode && refNode.parentNode.insertBefore(newNode, refNode); +/** + * Replace a node + * @param {HTMLElement} newNode - new node to add to the DOM + * @param {HTMLElement} replaced - node to replace + * @returns {undefined} + */ + +const replaceChild = (newNode, replaced) => replaced && replaced.parentNode && replaced.parentNode.replaceChild(newNode, replaced); + +// Riot.js constants that can be used accross more modules +const COMPONENTS_IMPLEMENTATION_MAP = new Map(), + DOM_COMPONENT_INSTANCE_PROPERTY = Symbol('riot-component'), + PLUGINS_SET = new Set(), + IS_DIRECTIVE = 'is', + VALUE_ATTRIBUTE = 'value', + MOUNT_METHOD_KEY = 'mount', + UPDATE_METHOD_KEY = 'update', + UNMOUNT_METHOD_KEY = 'unmount', + SHOULD_UPDATE_KEY = 'shouldUpdate', + ON_BEFORE_MOUNT_KEY = 'onBeforeMount', + ON_MOUNTED_KEY = 'onMounted', + ON_BEFORE_UPDATE_KEY = 'onBeforeUpdate', + ON_UPDATED_KEY = 'onUpdated', + ON_BEFORE_UNMOUNT_KEY = 'onBeforeUnmount', + ON_UNMOUNTED_KEY = 'onUnmounted', + PROPS_KEY = 'props', + STATE_KEY = 'state', + SLOTS_KEY = 'slots', + ROOT_KEY = 'root', + IS_PURE_SYMBOL = Symbol.for('pure'), + PARENT_KEY_SYMBOL = Symbol('parent'), + ATTRIBUTES_KEY_SYMBOL = Symbol('attributes'), + TEMPLATE_KEY_SYMBOL = Symbol('template'); + +var globals = /*#__PURE__*/Object.freeze({ + __proto__: null, + COMPONENTS_IMPLEMENTATION_MAP: COMPONENTS_IMPLEMENTATION_MAP, + DOM_COMPONENT_INSTANCE_PROPERTY: DOM_COMPONENT_INSTANCE_PROPERTY, + PLUGINS_SET: PLUGINS_SET, + IS_DIRECTIVE: IS_DIRECTIVE, + VALUE_ATTRIBUTE: VALUE_ATTRIBUTE, + MOUNT_METHOD_KEY: MOUNT_METHOD_KEY, + UPDATE_METHOD_KEY: UPDATE_METHOD_KEY, + UNMOUNT_METHOD_KEY: UNMOUNT_METHOD_KEY, + SHOULD_UPDATE_KEY: SHOULD_UPDATE_KEY, + ON_BEFORE_MOUNT_KEY: ON_BEFORE_MOUNT_KEY, + ON_MOUNTED_KEY: ON_MOUNTED_KEY, + ON_BEFORE_UPDATE_KEY: ON_BEFORE_UPDATE_KEY, + ON_UPDATED_KEY: ON_UPDATED_KEY, + ON_BEFORE_UNMOUNT_KEY: ON_BEFORE_UNMOUNT_KEY, + ON_UNMOUNTED_KEY: ON_UNMOUNTED_KEY, + PROPS_KEY: PROPS_KEY, + STATE_KEY: STATE_KEY, + SLOTS_KEY: SLOTS_KEY, + ROOT_KEY: ROOT_KEY, + IS_PURE_SYMBOL: IS_PURE_SYMBOL, + PARENT_KEY_SYMBOL: PARENT_KEY_SYMBOL, + ATTRIBUTES_KEY_SYMBOL: ATTRIBUTES_KEY_SYMBOL, + TEMPLATE_KEY_SYMBOL: TEMPLATE_KEY_SYMBOL +}); + +const EACH = 0; +const IF = 1; +const SIMPLE = 2; +const TAG = 3; +const SLOT = 4; +var bindingTypes = { + EACH, + IF, + SIMPLE, + TAG, + SLOT +}; + +const ATTRIBUTE = 0; +const EVENT = 1; +const TEXT = 2; +const VALUE = 3; +var expressionTypes = { + ATTRIBUTE, + EVENT, + TEXT, + VALUE +}; + +/** + * Create the template meta object in case of