Skip to content

Commit a13117e

Browse files
refactorthisMcKendrick, Brent
authored andcommitted
Complete rewrite for v2.0.
* Inline, form summary & tooltip validation styles * Validation strategies (this replaces validation profiles from v1.0) * Added many unit tests and travis CI build * Automatically manages aria attributes for accessibility * Abstracted templates and fully classed for ease of styling * New docs on github.io
1 parent b808d26 commit a13117e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+4017
-411
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto

.gitignore

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,17 @@
1-
# Created by .gitignore support plugin (hsz.mobi)
1+
# Include your project-specific ignores in this file
2+
# Read about how to use .gitignore: https://help.github.com/articles/ignoring-files
23

3-
### JetBrains template
4-
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
5-
6-
## Directory-based project format
7-
.idea/
8-
9-
## File-based project format
10-
*.ipr
11-
*.iml
12-
*.iws
13-
14-
## Additional for IntelliJ
15-
out/
4+
logs/*
5+
!.gitkeep
6+
node_modules/
7+
bower_components/
8+
docs/dist/
9+
coverage/
10+
tmp
11+
test_out/
12+
.DS_Store
13+
.idea
1614

17-
# generated by mpeltonen/sbt-idea plugin
18-
.idea_modules/
1915

20-
# generated by JIRA plugin
21-
atlassian-ide-plugin.xml
2216

23-
# generated by Crashlytics plugin (for Android Studio and Intellij)
24-
com_crashlytics_export_strings.xml
2517

26-
bower_components/

.jshintrc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"globalstrict": true,
3+
"browser": true,
4+
"esnext": true,
5+
"bitwise": true,
6+
"camelcase": true,
7+
"curly": true,
8+
"eqeqeq": true,
9+
"immed": true,
10+
"indent": 2,
11+
"latedef": true,
12+
"newcap": true,
13+
"noarg": true,
14+
"quotmark": "single",
15+
"undef": true,
16+
"unused": true,
17+
"strict": true,
18+
"trailing": true,
19+
"smarttabs": true,
20+
"multistr": true,
21+
"node": true,
22+
"jquery": true,
23+
"globals": {
24+
"angular": false,
25+
"describe": false,
26+
"it": false,
27+
"expect": false,
28+
"beforeEach": false,
29+
"afterEach": false,
30+
"module": false,
31+
"inject": false,
32+
"xtForm": true
33+
}
34+
}

.travis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# See http://docs.travis-ci.com/user/languages/javascript-with-nodejs/
2+
# npm install && npm start are run by travis, everything is covered in the package.json file
3+
4+
language: node_js
5+
node_js:
6+
- "0.10"

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
### Change log
2+
3+
### 2.0.0
4+
5+
Completely re-imagined and rewritten from 1.0. Now includes multiple new features:
6+
* Inline, form summary & tooltip validation styles
7+
* Validation strategies (this replaces validation profiles from v1.0)
8+
* Added many unit tests and travis CI build
9+
* Automatically manages aria attributes for accessibility
10+
* Abstracted templates and fully classed for ease of styling
11+
* New docs on github.io
12+
13+
### 1.0.0
14+
15+
* Tooltip validation styles using bootstrap
16+
* Allows for adding validation messages as attributes on the input itself
17+
* Allows for built in generated messages

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2013 Brent McKendrick
3+
Copyright (c) 2012-2015 Brent McKendrick
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy of
66
this software and associated documentation files (the "Software"), to deal in

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ xtform
33

44
AngularJS form validation directive.
55

6-
76
![example](http://blog.brentmckendrick.com/assets/images/xtform.png)
87

98
For online examples [click here](http://www.brentmckendrick.com/code/xtform).

bower.json

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,35 @@
11
{
22
"name": "xtform",
3-
"version": "1.0.1",
3+
"version": "2.0.0-beta.1",
44
"homepage": "https://github.com/refactorthis/xtform",
55
"authors": [
6-
"refactorthis <www.brentmckendrick.com>"
6+
"Brent McKendrick <www.brentmckendrick.com>"
77
],
8-
"description": "AngularJS tooltip form validation",
9-
"main": "xtForm.js",
8+
"description": "AngularJS form validation extensions",
109
"keywords": [
1110
"angularjs",
1211
"form",
1312
"validation",
14-
"html5"
13+
"html5",
14+
"generated",
15+
"tooltip",
16+
"xtform",
17+
"validate"
1518
],
1619
"license": "MIT",
1720
"ignore": [
1821
"**/.*",
1922
"node_modules",
2023
"bower_components",
21-
"test",
22-
"tests"
24+
"coverage"
2325
],
26+
"devDependencies": {
27+
"bootstrap": "~3.0",
28+
"angular-mocks": "~1.3.8",
29+
"google-code-prettify": "~1.0.3"
30+
},
2431
"dependencies": {
25-
"angular": ">=1.2",
26-
"bootstrap": ">=2.0",
27-
"jquery": ">=1.0"
32+
"angular": "~1.3",
33+
"jquery": "~2.0"
2834
}
2935
}

build.conf.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* This file contains all of the user settings for the gulp build process
3+
*/
4+
module.exports = {
5+
6+
srcJs: ['component/**/*.module.js', 'component/**/*.js', '!component/**/*.test.js'],
7+
tests: 'component/**/*.test.js',
8+
views: 'component/**/*.html',
9+
docs: {
10+
views: 'docs/templates/*.html',
11+
items: 'docs/**/*',
12+
templateBanner: '/*!\n' +
13+
' * This has been generated from "gulp docs", please edit the templates instead templates/*.html\n' +
14+
' */\n',
15+
templateJsFilename: 'js/docs.tpl.js',
16+
build: 'docs/dist'
17+
},
18+
coverageFolder: 'coverage',
19+
buildFolder: 'dist',
20+
buildJsFilename: 'xtForm.js',
21+
templateJsFilename: 'xtForm.tpl.js',
22+
banner: '/*!\n' +
23+
' * See LICENSE in this repository for license information\n' +
24+
' */\n',
25+
closureStart: '(function(){\n\'use strict\';\n',
26+
closureEnd: '\n})();'
27+
};

component/core/ngModel.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
xtForm.directive('ngModel', function (xtFormConfig, $rootScope, $interpolate, $document) {
2+
'use strict';
3+
4+
var UNTOUCHED_CLASS = 'ng-untouched',
5+
TOUCHED_CLASS = 'ng-touched';
6+
7+
return {
8+
require: ['ngModel', '^?xtForm', '^?form'],
9+
link: function (scope, element, attrs, ctrls) {
10+
11+
var defaultErrors = xtFormConfig.getErrorMessages(),
12+
ngModel = ctrls[0],
13+
xtForm = ctrls[1],
14+
form = ctrls[2],
15+
setTouchedFn,
16+
validationStrategyFn;
17+
18+
/**
19+
* Active the directive
20+
*/
21+
function activate() {
22+
23+
setTouchedFn = ngModel.$setTouched || setTouchedPolyfill;
24+
validationStrategyFn = xtForm.getValidationStrategy();
25+
ngModel.$untouched = true;
26+
27+
// add extensions to ngModel
28+
var labelEl = $document[0].querySelectorAll('label[for="' + attrs.id + '"]');
29+
angular.extend(ngModel, {
30+
$focused: false,
31+
$label: labelEl.length > 0 ? labelEl[0].innerText : '',
32+
$xtErrors: []
33+
});
34+
35+
// set errors on the ngModel when $error changes
36+
scope.$watch(function () {
37+
return ngModel.$error;
38+
}, updateErrors, true);
39+
40+
scope.$on('XtForm.ForceErrorUpdate', updateErrors);
41+
42+
element
43+
.on('focus', function () {
44+
if (!ngModel.$touched) {
45+
setTouchedFn();
46+
}
47+
ngModel.$focused = true;
48+
updateErrors();
49+
scope.$apply();
50+
})
51+
.on('blur', function () {
52+
ngModel.$focused = false;
53+
updateErrors();
54+
scope.$apply();
55+
});
56+
}
57+
58+
function getErrorMessageForKey(key) {
59+
var attrKey = 'msg' + key[0].toUpperCase() + key.substring(1);
60+
61+
// use either the provided string as an interpolated attribute, or the default message
62+
return attrs[attrKey] ?
63+
attrs[attrKey] :
64+
$interpolate(defaultErrors[key])(attrs);
65+
}
66+
67+
/**
68+
* Sets the $xtErrors collection on validation change
69+
*/
70+
function updateErrors() {
71+
ngModel.$xtErrors = [];
72+
73+
angular.forEach(ngModel.$error, function (item, key) {
74+
var showErrors = validationStrategyFn(form, ngModel);
75+
if (showErrors) {
76+
var error = {
77+
key: key,
78+
message: getErrorMessageForKey(key)
79+
};
80+
81+
// Ensure required is the last message to be shown
82+
// TODO possibly introduce priority here.
83+
if (key === 'required') {
84+
ngModel.$xtErrors.push(error);
85+
} else {
86+
ngModel.$xtErrors.unshift(error);
87+
}
88+
}
89+
});
90+
91+
$rootScope.$broadcast('XtForm.ErrorsUpdated', ngModel);
92+
}
93+
94+
// Polyfill for $touched in AngularJS < 1.3
95+
function setTouchedPolyfill() {
96+
ngModel.$touched = true;
97+
ngModel.$untouched = false;
98+
element.addClass(TOUCHED_CLASS).removeClass(UNTOUCHED_CLASS);
99+
}
100+
101+
if (xtForm) {
102+
activate();
103+
}
104+
}
105+
};
106+
});

0 commit comments

Comments
 (0)