Skip to content

Commit 196d76c

Browse files
authored
Merge pull request #10 from horprogs/add-tooltips
Add tooltips
2 parents 4397e70 + 523760c commit 196d76c

18 files changed

+725
-4111
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ node_modules
22
.idea
33
.tmp
44
app.yaml
5+
package-lock.json
6+
yarn.lock

README.md

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# Just-validate
22
Lightweight form validation in Javascript Vanilla, without dependencies, with customizable rules (including remote validation), customizable messages and customizable submit form with ajax helper.
33

4-
Demo: https://horprogs.github.io/Just-validate/
4+
Demo: <br>
5+
Classic validation https://horprogs.github.io/Just-validate/ <br>
6+
Classic validation with tooltips https://horprogs.github.io/Just-validate/tooltip.html
57

68
## How to use
79
### npm
@@ -204,6 +206,54 @@ ajax({
204206
});
205207
```
206208
209+
### Tooltip
210+
211+
You can show errors in the form of tooltips. <br>
212+
213+
To do this, connect the file styles ``dist/css/justValidateTooltip.css`` or
214+
``dist/css/justValidateTooltip.min.css`` on page. <br>
215+
```
216+
<link rel="stylesheet" href="./path/to/justValidateTooltip.min.css">
217+
```
218+
219+
For a container inside of which input, add a class ``just-validate-tooltip-container`` or add our class
220+
221+
```
222+
<div class="form-group col-md-6">
223+
<label for="name">Enter your name</label>
224+
<div class="just-validate-tooltip-container">
225+
<input type="text" class="form__input form-control" placeholder="Enter your name" data-validate-field="name">
226+
</div>
227+
</div>
228+
```
229+
230+
You can customize time show of error, using property ``fadeOutTime``, for example: <br>
231+
```js
232+
new window.JustValidate('.js-form', {
233+
tooltip: {
234+
fadeOutTime: 4000 // default value - 5000
235+
}
236+
});
237+
```
238+
239+
You can customize class hide of tooltip, using property ``fadeOutClass``, for example: <br>
240+
```js
241+
new window.JustValidate('.js-form', {
242+
tooltip: {
243+
fadeOutClass: '.hide' // default value - just-validate-tooltip-hide
244+
}
245+
});
246+
```
247+
248+
You can customize class inside of which input, using property ``selectorWrap``, for example: <br>
249+
```js
250+
new window.JustValidate('.js-form', {
251+
tooltip: {
252+
selectorWrap: '.tooltip-wrapper' // default value - just-validate-tooltip-container
253+
}
254+
});
255+
```
256+
207257
### Styling
208258
209259
You can customize style color of error, using property ``colorWrong``, for example: <br>
@@ -285,11 +335,13 @@ new window.JustValidate('.js-form', {
285335
```
286336
287337
## Current version stable
288-
**V1.1.0**
338+
**V1.2.0**
289339
290340
## Changelog
291341
### 1.1.0
292342
Added rule for check strength of password (default and custom)
343+
### 1.2.0
344+
Added tooltip style error
293345
294346
## Contributing
295347
- Check the open issues or open a new issue to start a discussion around your feature idea or the bug you found.

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "just-validate",
33
"description": "Lightweight form validation in Javascript Vanilla, without dependencies, with customizable rules (including remote validation), customizable messages and customizable submit form with ajax helper.",
4-
"version": "1.1.0",
4+
"version": "1.2.0",
55
"authors": [
66
"Perepecho Georgy (Horprogs) <horprogs@gmail.com>"
77
],

dist/css/justValidateTooltip.css

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
@-webkit-keyframes fadeOut {
2+
from {
3+
opacity: 1; }
4+
to {
5+
opacity: 0; } }
6+
7+
@keyframes fadeOut {
8+
from {
9+
opacity: 1; }
10+
to {
11+
opacity: 0; } }
12+
13+
.just-validate-tooltip-container {
14+
position: relative; }
15+
16+
.just-validate-tooltip-hide {
17+
-webkit-animation: fadeOut .4s linear;
18+
animation: fadeOut .4s linear;
19+
opacity: 0; }
20+
21+
.js-validate-error-label {
22+
position: absolute;
23+
top: -20px;
24+
left: 10px;
25+
z-index: 10;
26+
background: rgba(0, 0, 0, 0.55);
27+
border-radius: 4px;
28+
color: #fff !important;
29+
padding: 4px 8px;
30+
font-size: 10px;
31+
pointer-events: none;
32+
-webkit-transition: all .4s linear;
33+
transition: all .4s linear; }

dist/css/justValidateTooltip.min.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.html

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Title</title>
6+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
7+
<style>
8+
.no-float {
9+
float: none;
10+
}
11+
12+
.mt30 {
13+
margin-top: 30px;
14+
}
15+
16+
.js-validate-error-label {
17+
margin-top: 5px;
18+
}
19+
</style>
20+
</head>
21+
<body class="container">
22+
<div class="col-md-6 center-block no-float mt30">
23+
<form action="#" class="js-form form">
24+
<div class="row">
25+
<div class="form-group col-md-6">
26+
<input type="text" class="form__input form-control" placeholder="Enter your name" autocomplete="off" data-validate-field="name" name="name" value="dkdf">
27+
</div>
28+
<div class="form-group col-md-6">
29+
<input type="text" class="form__input form-control" placeholder="Enter your login" autocomplete="off" data-validate-field="login" name="login" value="zzz">
30+
</div>
31+
<div class="form-group col-md-6">
32+
<input type="email" class="form__input form-control" placeholder="Enter your email" autocomplete="off" data-validate-field="email" name="email" value="ok@test.co">
33+
</div>
34+
</div>
35+
<div class="form-group">
36+
<input type="password" class="form__input form-control" placeholder="Enter your password" autocomplete="off" data-validate-field="password" name="password" value="123fd">
37+
</div>
38+
<div class="form-group">
39+
<div>
40+
<div>
41+
<textarea name="msg" cols="30" rows="10" class="form__textarea form-control" data-validate-field="text">sdfsfsdfsdf</textarea>
42+
</div>
43+
</div>
44+
</div>
45+
<div class="form-group">
46+
<input type="checkbox" name="check1" id="checkbox" class="form__checkbox" checked><label for="checkbox">I agree</label>
47+
</div>
48+
<div class="form-group">
49+
<label><input type="checkbox" name="check2" class="form__checkbox" data-validate-field="checkbox2" checked>I agree</label>
50+
</div>
51+
52+
<button class="form__btn btn btn-primary">SUBMIT</button>
53+
</form>
54+
</div>
55+
56+
<script src="js/just-validate.min.js"></script>
57+
58+
<script>
59+
new window.JustValidate('.js-form', {
60+
rules: {
61+
checkbox2: {
62+
required: true
63+
},
64+
email: {
65+
required: true,
66+
email: true,
67+
remote: {
68+
url: 'https://just-validate-api.herokuapp.com/check-correct',
69+
sendParam: 'email',
70+
successAnswer: 'OK',
71+
method: 'GET',
72+
}
73+
},
74+
login: {
75+
required: true,
76+
remote: {
77+
url: 'https://just-validate-api.herokuapp.com/check-correct',
78+
sendParam: 'login',
79+
successAnswer: 'OK',
80+
method: 'GET'
81+
}
82+
},
83+
password: {
84+
strength: {
85+
custom: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]',
86+
},
87+
},
88+
},
89+
messages: {
90+
login: {
91+
remote: 'Login already exists'
92+
}
93+
},
94+
submitHandler: function (form, values, ajax) {
95+
console.log(values)
96+
ajax({
97+
url: 'https://just-validate-api.herokuapp.com/submit',
98+
method: 'POST',
99+
data: values,
100+
async: true,
101+
callback: (response) => {
102+
console.log(response);
103+
}
104+
});
105+
},
106+
});
107+
</script>
108+
109+
</body>
110+
</html>

dist/js/just-validate.js

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
274274
RULE_PASSWORD = 'password',
275275
RULE_ZIP = 'zip',
276276
RULE_PHONE = 'phone',
277-
RULE_REMOTE = 'remote';
277+
RULE_REMOTE = 'remote',
278+
RULE_STRENGTH = 'strength';
278279

279280
var formatParams = function formatParams(params, method) {
280281
if (typeof params === 'string') {
@@ -336,6 +337,10 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
336337
this.colorWrong = this.options.colorWrong || '#B81111';
337338
this.result = {};
338339
this.elements = [];
340+
this.tooltip = this.options.tooltip || {};
341+
this.tooltipFadeOutTime = this.tooltip.fadeOutTime || 5000;
342+
this.tooltipFadeOutClass = this.tooltip.fadeOutClass || 'just-validate-tooltip-hide';
343+
this.tooltipSelectorWrap = document.querySelectorAll(this.tooltip.selectorWrap).length ? document.querySelectorAll(this.tooltip.selectorWrap) : document.querySelectorAll('.just-validate-tooltip-container');
339344
this.bindHandlerKeyup = this.handlerKeyup.bind(this);
340345
this.submitHandler = this.options.submitHandler || undefined;
341346
this.promisesRemote = [];
@@ -345,9 +350,13 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
345350
email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
346351
zip: /^\d{5}(-\d{4})?$/,
347352
phone: /^([0-9]( |-)?)?(\(?[0-9]{3}\)?|[0-9]{3})( |-)?([0-9]{3}( |-)?[0-9]{4}|[a-zA-Z0-9]{7})$/,
348-
password: /[^\w\d]*(([0-9]+.*[A-Za-z]+.*)|[A-Za-z]+.*([0-9]+.*))/
353+
password: /[^\w\d]*(([0-9]+.*[A-Za-z]+.*)|[A-Za-z]+.*([0-9]+.*))/,
354+
strengthPass: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]/
349355
};
350356
this.DEFAULT_REMOTE_ERROR = 'Error';
357+
this.state = {
358+
tooltipsTimer: null
359+
};
351360

352361
this.setForm(document.querySelector(selector));
353362
};
@@ -389,7 +398,8 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
389398
maxLength: 'The field must contain a maximum of :value characters',
390399
minLength: 'The field must contain a minimum of :value characters',
391400
password: 'Password is not valid',
392-
remote: 'Email already exists'
401+
remote: 'Email already exists',
402+
strength: 'Password must contents at least one uppercase letter, one lowercase letter and one number'
393403
},
394404
/**
395405
* Keyup handler
@@ -518,6 +528,10 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
518528
return text.length >= min;
519529
},
520530

531+
checkStrengthPass: function checkStrengthPass(password) {
532+
return this.REGEXP.strengthPass.test(password);
533+
},
534+
521535
getElements: function getElements() {
522536
var _this2 = this;
523537

@@ -605,6 +619,15 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
605619
return this.checkLengthMax(value, max);
606620
},
607621

622+
/**
623+
* Validate field for strength password
624+
* @param {string} password Value for validate
625+
* @returns {boolean} True if validate is OK
626+
*/
627+
validateStrengthPass: function validateStrengthPass(password) {
628+
return this.checkStrengthPass(password);
629+
},
630+
608631
/**
609632
* Validate Password field
610633
* @param {string} value Value for validate
@@ -798,6 +821,36 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
798821
return;
799822
}
800823

824+
case RULE_STRENGTH:
825+
{
826+
if (!ruleValue || (typeof ruleValue === 'undefined' ? 'undefined' : _typeof(ruleValue)) !== 'object') {
827+
break;
828+
}
829+
830+
if (ruleValue.default && this.validateStrengthPass(value)) {
831+
break;
832+
}
833+
834+
if (ruleValue.custom) {
835+
var regexp = void 0;
836+
837+
try {
838+
regexp = new RegExp(ruleValue.custom);
839+
} catch (e) {
840+
regexp = this.REGEXP.strengthPass;
841+
842+
// eslint-disable-next-line no-console
843+
console.error('Custom regexp for strength rule is not valid. Default regexp was used.');
844+
}
845+
846+
if (regexp.test(value)) {
847+
break;
848+
}
849+
}
850+
this.generateMessage(RULE_STRENGTH, name);
851+
return;
852+
}
853+
801854
case RULE_ZIP:
802855
{
803856
if (!ruleValue) {
@@ -857,6 +910,8 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
857910
},
858911

859912
renderErrors: function renderErrors() {
913+
var _this4 = this;
914+
860915
this.clearErrors();
861916
this.unlockForm();
862917

@@ -897,6 +952,26 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
897952
_item.parentNode.insertBefore(div, _item.nextSibling);
898953
}
899954
}
955+
956+
if (!this.tooltipSelectorWrap.length) {
957+
return;
958+
}
959+
960+
this.state.tooltipsTimer = setTimeout(function () {
961+
_this4.hideTooltips();
962+
}, this.tooltipFadeOutTime);
963+
},
964+
965+
hideTooltips: function hideTooltips() {
966+
var _this5 = this;
967+
968+
var $elemsErrorLabel = document.querySelectorAll('.js-validate-error-label');
969+
970+
$elemsErrorLabel.forEach(function (item) {
971+
item.classList.add(_this5.tooltipFadeOutClass);
972+
});
973+
974+
this.state.tooltipsTimer = null;
900975
},
901976

902977
lockForm: function lockForm() {

0 commit comments

Comments
 (0)