├── .gitignore
├── LICENSE
├── README.md
├── example
├── example.html
└── example.js
├── package-lock.json
├── package.json
└── src
└── card.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
27 | node_modules
28 |
29 | bower_components
30 |
31 | tags
32 | .idea
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Sergey Gavruk
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | angular-card
2 | ============
3 |
4 | Angular directive for card https://github.com/jessepollak/card
5 |
6 | 
7 |
8 | ## Demo
9 |
10 | http://jessepollak.github.io/card/
11 |
12 | ## Installation
13 |
14 | ### npm
15 | `npm install angular-card`
16 |
17 | ## Usage
18 |
19 | ### `name` is required for form and inputs (you can use any unique name)
20 | ### `width` is optional, it can be set on the element or the options object (defaults to 350)
21 |
22 | ```html
23 |
47 | ```
48 |
49 | ```js
50 | angular.module('app', ['gavruk.card'])
51 | .controller('ExampleCtrl', ['$scope', function($scope) {
52 |
53 | $scope.card = {
54 | name: 'Mike Brown',
55 | number: '5555 4444 3333 1111',
56 | expiry: '11 / 2020',
57 | cvc: '123'
58 | };
59 |
60 | $scope.cardPlaceholders = {
61 | name: 'Your Full Name',
62 | number: 'xxxx xxxx xxxx xxxx',
63 | expiry: 'MM/YY',
64 | cvc: 'xxx'
65 | };
66 |
67 | $scope.cardMessages = {
68 | validDate: 'valid\nthru',
69 | monthYear: 'MM/YYYY',
70 | };
71 |
72 | $scope.cardOptions = {
73 | debug: false,
74 | formatting: true,
75 | width: 500 //optional
76 | };
77 |
78 | }]);
79 | ```
80 |
81 | #### Using multiple fields for card expiry
82 |
83 | Simply use 2 input fields for the expiry, and pass either `month`, or `year` to the directive.
84 |
85 | ```js
86 |
87 |
88 | ```
89 |
--------------------------------------------------------------------------------
/example/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Angular-Card Example
7 |
8 |
9 |
10 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/example/example.js:
--------------------------------------------------------------------------------
1 | angular.module('app', ['gavruk.card'])
2 |
3 | .controller('ExampleCtrl', ['$scope', function($scope) {
4 |
5 | var card1 = {
6 | name: 'Mike Brown',
7 | number: '5555 4444 3333 1111',
8 | expiry: '11 / 2020',
9 | cvc: '123'
10 | };
11 | var card2 = {
12 | name: 'Bill Smith',
13 | number: '4321 4321 4321 4321',
14 | expiry: '02 / 2018',
15 | cvc: '591'
16 | };
17 |
18 | var selectedCard = 1;
19 | $scope.card = card1;
20 |
21 | $scope.changeCard = function() {
22 | if (selectedCard == 1) {
23 | $scope.card = card2;
24 | selectedCard = 2;
25 | } else {
26 | $scope.card = card1;
27 | selectedCard = 1;
28 | }
29 | };
30 |
31 | $scope.clear = function() {
32 | $scope.card = {};
33 | };
34 |
35 |
36 | $scope.cardPlaceholders = {
37 | name: 'Your Full Name',
38 | number: 'xxxx xxxx xxxx xxxx',
39 | expiry: 'MM/YY',
40 | cvc: 'xxx'
41 | };
42 |
43 | $scope.cardMessages = {
44 | validDate: 'valid\nthru',
45 | monthYear: 'MM/YYYY',
46 | };
47 |
48 | $scope.cardOptions = {
49 | debug: false,
50 | formatting: true
51 | };
52 |
53 | }]);
54 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-card",
3 | "version": "0.3.12",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "angular": {
8 | "version": "1.6.6",
9 | "resolved": "https://registry.npmjs.org/angular/-/angular-1.6.6.tgz",
10 | "integrity": "sha1-/Vo8+0N844LYVO4BEgeXl4Uny2Q=",
11 | "dev": true
12 | },
13 | "card": {
14 | "version": "2.4.0",
15 | "resolved": "https://registry.npmjs.org/card/-/card-2.4.0.tgz",
16 | "integrity": "sha1-fBATHFROZ9q/3oJgizDdClOLEvo=",
17 | "requires": {
18 | "node.extend": "1.1.6",
19 | "payment": "2.3.0",
20 | "qj": "2.0.0"
21 | }
22 | },
23 | "is": {
24 | "version": "3.2.1",
25 | "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz",
26 | "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU="
27 | },
28 | "node.extend": {
29 | "version": "1.1.6",
30 | "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz",
31 | "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=",
32 | "requires": {
33 | "is": "3.2.1"
34 | }
35 | },
36 | "payment": {
37 | "version": "2.3.0",
38 | "resolved": "https://registry.npmjs.org/payment/-/payment-2.3.0.tgz",
39 | "integrity": "sha1-sqlenDBSRZZH2jkmuLZsVT2TCY8=",
40 | "requires": {
41 | "qj": "2.0.0"
42 | }
43 | },
44 | "qj": {
45 | "version": "2.0.0",
46 | "resolved": "https://registry.npmjs.org/qj/-/qj-2.0.0.tgz",
47 | "integrity": "sha1-BU3Tt1zgGHKNI6BgXwMN/aC9FYo="
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-card",
3 | "version": "0.3.13",
4 | "description": "Angular directive for card https://github.com/jessepollak/card",
5 | "main": "src/card.js",
6 | "directories": {
7 | "example": "example"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://gavruk@github.com/gavruk/angular-card.git"
15 | },
16 | "keywords": [
17 | "angular",
18 | "credit",
19 | "card"
20 | ],
21 | "author": "Sergey Gavruk ",
22 | "license": "MIT",
23 | "bugs": {
24 | "url": "https://github.com/gavruk/angular-card/issues"
25 | },
26 | "homepage": "https://github.com/gavruk/angular-card#readme",
27 | "dependencies": {
28 | "card": "^2.4.0"
29 | },
30 | "peerDependencies": {
31 | "angular": "^1.4.8"
32 | },
33 | "devDependencies": {
34 | "angular": "^1.4.8"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/card.js:
--------------------------------------------------------------------------------
1 | var hasRequire = window && window.angular ? false : typeof require === 'function';
2 |
3 | (function (window, document, Card, angular, undefined) {
4 | 'use strict';
5 | angular
6 | .module('gavruk.card', [])
7 |
8 | .controller('CardCtrl', ['$scope', function ($scope) {
9 | }])
10 |
11 | .directive('card', ['$timeout', function ($timeout) {
12 | return {
13 | restrict: 'A',
14 | scope: {
15 | cardContainer: '@', // required
16 | width: '@',
17 | placeholders: '=',
18 | options: '=',
19 | messages: '=',
20 | },
21 | controller: 'CardCtrl',
22 | link: function (scope, element, attributes, cardCtrl) {
23 | var defaultPlaceholders = {
24 | number: '•••• •••• •••• ••••',
25 | name: 'Full Name',
26 | expiry: '••/••',
27 | cvc: '•••'
28 | };
29 | var defaultMessages = {
30 | validDate: 'valid\nthru',
31 | monthYear: 'month/year',
32 | };
33 | var defaultOptions = {
34 | debug: false,
35 | formatting: true
36 | };
37 |
38 | var placeholders = angular.extend(defaultPlaceholders, scope.placeholders);
39 | var messages = angular.extend(defaultMessages, scope.messages);
40 | var options = angular.extend(defaultOptions, scope.options);
41 |
42 | var opts = {
43 | form: '[name="' + attributes.name + '"]',
44 |
45 | // a selector or jQuery object for the container
46 | // where you want the card to appear
47 | container: scope.cardContainer, // *required*
48 |
49 | formSelectors: {},
50 |
51 | width: options.width,
52 |
53 | // Strings for translation - optional
54 | messages: {
55 | validDate: messages.validDate,
56 | monthYear: messages.monthYear
57 | },
58 |
59 | // Default placeholders for rendered fields - options
60 | placeholders: {
61 | number: placeholders.number,
62 | name: placeholders.name,
63 | expiry: placeholders.expiry,
64 | cvc: placeholders.cvc
65 | },
66 |
67 | formatting: options.formatting, // optional - default true
68 | debug: options.debug // if true, will log helpful messages for setting up Card
69 | };
70 |
71 | opts.width = opts.width || scope.width || 350;
72 |
73 | if (cardCtrl.numberInput && cardCtrl.numberInput.length > 0) {
74 | opts.formSelectors.numberInput = 'input[name="' + cardCtrl.numberInput[0].name + '"]';
75 | }
76 | if (angular.isDefined(cardCtrl.expiryInput.combined)) {
77 | opts.formSelectors.expiryInput = 'input[name="' + cardCtrl.expiryInput.combined[0].name + '"]';
78 | } else if (angular.isDefined(cardCtrl.expiryInput.month) && angular.isDefined(cardCtrl.expiryInput.year)) {
79 | opts.formSelectors.expiryInput = 'input[name="' + cardCtrl.expiryInput.month[0].name + '"], input[name="' + cardCtrl.expiryInput.year[0].name + '"]';
80 | }
81 | if (cardCtrl.cvcInput && cardCtrl.cvcInput.length > 0) {
82 | opts.formSelectors.cvcInput = 'input[name="' + cardCtrl.cvcInput[0].name + '"]';
83 | }
84 | if (cardCtrl.nameInput && cardCtrl.nameInput.length > 0) {
85 | opts.formSelectors.nameInput = 'input[name="' + cardCtrl.nameInput[0].name + '"]';
86 | }
87 |
88 | //Don't initialize card until angular has had a chance to update the DOM with any interpolated bindings
89 | $timeout(angular.noop)
90 | .then(function () {
91 | new Card(opts);
92 | });
93 | }
94 | };
95 | }])
96 |
97 | .directive('cardNumber', ['$compile', function ($compile) {
98 | return {
99 | restrict: 'A',
100 | scope: {
101 | ngModel: '='
102 | },
103 | require: [
104 | '^card',
105 | 'ngModel'
106 | ],
107 | link: function (scope, element, attributes, ctrls) {
108 | var cardCtrl = ctrls[0];
109 | cardCtrl.numberInput = element;
110 | scope.$watch('ngModel', function (newVal, oldVal) {
111 | if (!oldVal && !newVal) {
112 | return;
113 | }
114 | if (oldVal === newVal && !newVal) {
115 | return;
116 | }
117 |
118 | var evt = document.createEvent('HTMLEvents');
119 | evt.initEvent('keyup', false, true);
120 | element[0].dispatchEvent(evt);
121 | });
122 | }
123 | };
124 | }])
125 |
126 | .directive('cardName', ['$compile', function ($compile) {
127 | return {
128 | restrict: 'A',
129 | scope: {
130 | ngModel: '='
131 | },
132 | require: [
133 | '^card',
134 | 'ngModel'
135 | ],
136 | link: function (scope, element, attributes, ctrls) {
137 | var cardCtrl = ctrls[0];
138 | cardCtrl.nameInput = element;
139 | scope.$watch('ngModel', function (newVal, oldVal) {
140 | if (!oldVal && !newVal) {
141 | return;
142 | }
143 | if (oldVal === newVal && !newVal) {
144 | return;
145 | }
146 |
147 | var evt = document.createEvent('HTMLEvents');
148 | evt.initEvent('keyup', false, true);
149 | element[0].dispatchEvent(evt);
150 | });
151 | }
152 | };
153 | }])
154 |
155 | .directive('cardExpiry', ['$compile', function ($compile) {
156 | return {
157 | restrict: 'A',
158 | scope: {
159 | ngModel: '=',
160 | type: '@cardExpiry'
161 | },
162 | require: [
163 | '^card',
164 | 'ngModel'
165 | ],
166 | link: function (scope, element, attributes, ctrls) {
167 | var cardCtrl = ctrls[0];
168 | var expiryType = scope.type || 'combined';
169 | if (angular.isUndefined(cardCtrl.expiryInput)) {
170 | cardCtrl.expiryInput = {};
171 | }
172 | cardCtrl.expiryInput[expiryType] = element;
173 | scope.$watch('ngModel', function (newVal, oldVal) {
174 | if (!oldVal && !newVal) {
175 | return;
176 | }
177 | if (oldVal === newVal && !newVal) {
178 | return;
179 | }
180 |
181 | var evt = document.createEvent('HTMLEvents');
182 | evt.initEvent('keyup', false, true);
183 | element[0].dispatchEvent(evt);
184 | });
185 | }
186 | };
187 | }])
188 |
189 | .directive('cardCvc', ['$compile', function ($compile) {
190 | return {
191 | restrict: 'A',
192 | scope: {
193 | ngModel: '='
194 | },
195 | require: [
196 | '^card',
197 | 'ngModel'
198 | ],
199 | link: function (scope, element, attributes, ctrls) {
200 | var cardCtrl = ctrls[0];
201 | cardCtrl.cvcInput = element;
202 | scope.$watch('ngModel', function (newVal, oldVal) {
203 | if (!oldVal && !newVal) {
204 | return;
205 | }
206 | if (oldVal === newVal && !newVal) {
207 | return;
208 | }
209 |
210 | var evt = document.createEvent('HTMLEvents');
211 | evt.initEvent('keyup', false, true);
212 | element[0].dispatchEvent(evt);
213 | });
214 | }
215 | };
216 | }]);
217 |
218 | })(window, window.document, hasRequire ? require('card') : window.Card, hasRequire ? require('angular') : window.angular);
219 |
220 | if(typeof module !== 'undefined') {
221 | module.exports = 'gavruk.card';
222 | }
223 |
--------------------------------------------------------------------------------