develop
HerrHase 3 years ago
parent 0602a35e5a
commit 73338c4e93

@ -1 +0,0 @@
/*! 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}

File diff suppressed because one or more lines are too long

@ -1,29 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo | Tiny Validator</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link href="styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<form class="form" novalidate>
<div class="field">
<label>
email
<input type="email" name="email" />
</label>
<field-error name="email"></field-error>
</div>
<div class="field">
<label>
password
<input type="password" name="password" />
</label>
<field-error name="password"></field-error>
</div>
<button type="submit">Send</button>
</form>
<script type="text/javascript" src="demo.js"></script>
</body>
</html>

15420
dist/demo.css vendored

File diff suppressed because it is too large Load Diff

4641
dist/demo.js vendored

File diff suppressed because it is too large Load Diff

66
dist/index.html vendored

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tiny Components | Validator</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link href="demo.css" rel="stylesheet" type="text/css">
</head>
<body>
<header class="header">
<div class="bar">
<div class="bar__start">
<h1 class="m-top-4 m-bottom-4 h4">
@tiny-components/validator
</h1>
</div>
<div class="bar__main justify-end">
<a class="button button--small m-left-sm-3 m-bottom-0" href="https://gitea.node001.net/tiny-components/validator" rel="noopener" target="_blank">
Gitea
<svg class="m-left-3 icon fill-text" aria-hidden="true">
<use xlink:href="symbol-defs.svg#icon-gitea"></use>
</svg>
</a>
</div>
</div>
</header>
<div class="container">
<div class="grid">
<div class="col-12">
<form class="form" novalidate method="post">
<div class="field-group">
<label class="field-label">
email
<input type="email" class="field-text" name="email" />
</label>
<field-error name="email"></field-error>
</div>
<div class="field-group">
<label class="field-label">
password
<input type="password" class="field-text" name="password" />
</label>
<field-error name="password"></field-error>
</div>
<button class="button" type="submit">
Send
</button>
</form>
<div id="result" class="panel color-text-contrast background-color-success hidden">
<div class="panel__body">
<div class="content m-bottom-last-child-0">
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="demo.js"></script>
</body>
</html>

@ -1,4 +1,4 @@
{ {
"/demo/demo.js": "/demo/demo.js", "/dist/demo.js": "/dist/demo.js",
"/demo/demo.css": "/demo/demo.css" "/dist/demo.css": "/dist/demo.css"
} }

@ -1,25 +1,25 @@
{ {
"name": "@tentakelfabrik/tiny-validator", "name": "@tiny-components/validator",
"version": "2.0.0", "version": "0.1.0",
"description": "Form Validator with validator.js for riotjs", "description": "Form Validation with Riotjs",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git@github.com:tentakelfabrik/tiny-validator.git" "url": "git@gitea.node001.net:tiny-components/validator.git"
}, },
"author": "Björn Hase", "author": "Björn Hase",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tentakelfabrik/plain-ui": "^0.3.0",
"form-serialize": "^0.7.2", "form-serialize": "^0.7.2",
"riot": "^5.1.2", "riot": "^6.1.2",
"validate.js": "^0.13.1" "validate.js": "^0.13.1"
}, },
"devDependencies": { "devDependencies": {
"@riotjs/compiler": "^5.1.3", "@riotjs/compiler": "^6.1.3",
"@riotjs/webpack-loader": "^5.0.0", "@riotjs/webpack-loader": "^6.0.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"laravel-mix": "^6.0.5", "laravel-mix": "^6.0.5",
"postcss": "^8.2.1",
"sass": "^1.32.0", "sass": "^1.32.0",
"sass-loader": "^8.0.2" "sass-loader": "^12.4.0"
} }
} }

@ -0,0 +1,25 @@
import * as riot from 'riot'
import FormValidator from './FormValidator'
import FieldError from './fieldError.riot'
// register & mount riot component
riot.register('field-error', FieldError)
riot.mount('field-error')
// creating formValidation
const formValidation = new FormValidator('form', {
'email': {
'presence': true,
'email': true
},
'password': {
'presence': true
}
}, (event, data) => {
event.preventDefault()
// show message and content of data from form
document.querySelector('#result .content').innerHTML = '<p>' + JSON.stringify(data) + '</p>'
document.querySelector('#result').classList.remove('hidden')
})

@ -0,0 +1,6 @@
@import
'../node_modules/@tentakelfabrik/plain-ui/src/scss/plain-ui';
.hidden {
display: none;
}

@ -1,17 +0,0 @@
import * as riot from 'riot'
import FormValidator from './../FormValidator'
import FieldError from './../field-error.riot'
riot.register('field-error', FieldError)
riot.mount('field-error')
const formValidation = new FormValidator('form', {
'email': {
'presence': true,
'email': true
},
'password': {
'presence': true
}
})

@ -1,6 +0,0 @@
/*! 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;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}template{display:none}[hidden]{display:none}
/*# sourceMappingURL=normalize.min.css.map */
body {
}

@ -1,5 +1,5 @@
<field-error> <field-error>
<div class="field__error" if={ state.errors.length > 0 }> <div class="field-error" if={ state.errors.length > 0 }>
<ul> <ul>
<li each={ error in state.errors }> <li each={ error in state.errors }>
{ error } { error }
@ -9,12 +9,13 @@
<script> <script>
/** /**
*
* Shows errors of Validation and raise a element to * Shows errors of Validation and raise a element to
* trigger single validation of field * trigger single validation of field
* *
* <field-error name="name" nofieldupdate></field-error> * <field-error name="name" closest="<optional>" nofieldupdate></field-error>
* *
* @author Björn Hase, Tentakelfabrik, me@tentakelfabrik.de * @author Björn Hase, me@herr-hase.wtf
* *
*/ */
@ -24,22 +25,39 @@
errors: [ errors: [
], ],
// css class for
closest: '.field-group',
},
/**
*
*
* @param {Object} props
* @param {Object} state
*
*/
onBeforeMounted(props, state)
{
if (props.closest) {
state.closest = props.closest
}
}, },
/** /**
* *
* *
* @param {Object} props [description] * @param {Object} props
* @param {Object} state [description] * @param {Object} state
* *
*/ */
onMounted(props, state) onMounted(props, state)
{ {
// getting parent element for entire field // getting parent element for entire field
const parent = this.root.closest('.field') const parent = this.root.closest(state.closest)
// getting current element by name // getting current element by name
const element = document.querySelector('[name="' + props.name + '"]') const element = parent.querySelector('[name="' + props.name + '"]')
// getting form // getting form
const form = element.closest('form') const form = element.closest('form')

@ -5,9 +5,11 @@ import serialize from 'form-serialize'
* Form Validator with RiotJS Components * Form Validator with RiotJS Components
* *
* *
* * @author HerrHase
* @
* *
*/ */
class FormValidator class FormValidator
{ {
/** /**
@ -15,7 +17,7 @@ class FormValidator
* @param {[type]} formSelector [description] * @param {[type]} formSelector [description]
* @param {[type]} constraits [description] * @param {[type]} constraits [description]
*/ */
constructor(formSelector, constraits) constructor(formSelector, constraits, onSuccess)
{ {
// getting selector to find form-element // getting selector to find form-element
this.formSelector = formSelector this.formSelector = formSelector
@ -23,58 +25,90 @@ class FormValidator
// constraits for validate.js // constraits for validate.js
this.constraits = constraits this.constraits = constraits
// adding onSuccess
this._onSuccess = onSuccess
// if form not found
if (!this._onSuccess) {
console.error('FormValidator: onSuccess not found!')
}
// get form and elements // get form and elements
this.form = document.querySelector(this.formSelector) this.form = document.querySelector(this.formSelector)
// if form not found
if (!this.form) {
console.error('FormValidator: form not found!')
}
this.elements = this.form.querySelectorAll('field-error') this.elements = this.form.querySelectorAll('field-error')
// adding submit event // adding submit event
this.form.addEventListener('submit', (event) => { this.form.addEventListener('submit', (event) => {
this.onSubmit(event) this._onSubmit(event)
}) })
// adding event if a element is updated // adding event if a element is updated
this.form.addEventListener('field-update', (event) => { this.form.addEventListener('field-update', (event) => {
this.onFieldUpdate(event) this._onFieldUpdate(event)
}) })
} }
/** /**
* handle submit
*
*
* @param {Event} event
* *
* @param {[type]} event [description]
* @return {[type]} [description]
*/ */
onSubmit(event) _onSubmit(event)
{ {
let errors = validate(serialize(event.target, { // getting data from target of submit event
const data = serialize(event.target, {
hash: true hash: true
}), this.constraits, {
fullMessages: false
}) })
if (errors) { // options for validate.js
event.preventDefault() const options = {
fullMessages: false
}
// send each element a event validate.async(data, this.constraits, options).then(
this.elements.forEach((element) => {
let elementErrors = false
// check for errors by name // handling success
if (errors[element.attributes.name.nodeValue]) { () => {
elementErrors = errors[element.attributes.name.nodeValue] this._onSuccess(event, data)
} },
this.dispatchCustomEvent(elementErrors, element) // handling error
}) (errors) => {
}
event.preventDefault()
// send each element a event
this.elements.forEach((element) => {
let elementErrors = false
// check for errors by name
if (errors[element.attributes.name.nodeValue]) {
elementErrors = errors[element.attributes.name.nodeValue]
}
this._dispatchCustomEvent(elementErrors, element)
})
}
)
} }
/** /**
* send update to fields
* *
* *
* @param {Event} event * @param {Event} event
* *
*/ */
onFieldUpdate(event) _onFieldUpdate(event)
{ {
// workaround, make sure that value for single is undefined if it is empty // workaround, make sure that value for single is undefined if it is empty
if (event.detail.value == '') { if (event.detail.value == '') {
@ -86,7 +120,7 @@ class FormValidator
// search for element by name and dispatch event // search for element by name and dispatch event
this.elements.forEach((element) => { this.elements.forEach((element) => {
if (element.attributes.name.nodeValue == event.detail.name) { if (element.attributes.name.nodeValue == event.detail.name) {
this.dispatchCustomEvent(errors, element) this._dispatchCustomEvent(errors, element)
} }
}) })
} }
@ -98,7 +132,7 @@ class FormValidator
* @param {Element} element * @param {Element} element
* *
*/ */
dispatchCustomEvent(errors, element) _dispatchCustomEvent(errors, element)
{ {
let detail = false let detail = false

@ -26,8 +26,8 @@ mix.webpackConfig({
} }
}) })
mix.js('src/demo/demo.js', 'demo') mix.js('src/demo.js', 'dist')
.sass('src/demo/demo.scss', 'demo') .sass('src/demo.scss', 'dist')
.options({ .options({
terser: { terser: {
extractComments: false, extractComments: false,

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save