jquery-payment-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Vladimir Chistiakov
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # jQuery.Payment for Rails asset pipeline
2
+
3
+ This gem integrates [jQuery.payment](https://github.com/stripe/jquery.payment) plugin with Rails asset pipeline.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'jquery-payment-rails'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install jquery-payment-rails
18
+
19
+ ## Usage
20
+
21
+ Add the following to your `app/assets/javascripts/application.js`:
22
+
23
+ //= require jquery.payment
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
@@ -0,0 +1,9 @@
1
+ require "jquery-payment-rails/version"
2
+
3
+ module Jquery
4
+ module Payment
5
+ module Rails
6
+ require "jquery-payment-rails/engine"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module Jquery
2
+ module Payment
3
+ module Rails
4
+ class Engine < ::Rails::Engine
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Jquery
2
+ module Payment
3
+ module Rails
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,483 @@
1
+ // Generated by CoffeeScript 1.4.0
2
+ (function() {
3
+ var $, cardFromNumber, cardFromType, cards, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardNumber, formatExpiry, formatForwardExpiry, formatForwardSlash, hasTextSelected, luhnCheck, reFormatCardNumber, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric, setCardType,
4
+ __slice = [].slice,
5
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
6
+ _this = this;
7
+
8
+ $ = jQuery;
9
+
10
+ $.payment = {};
11
+
12
+ $.payment.fn = {};
13
+
14
+ $.fn.payment = function() {
15
+ var args, method;
16
+ method = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
17
+ return $.payment.fn[method].apply(this, args);
18
+ };
19
+
20
+ defaultFormat = /(\d{1,4})/g;
21
+
22
+ cards = [
23
+ {
24
+ type: 'maestro',
25
+ pattern: /^(5018|5020|5038|6304|6759|676[1-3])/,
26
+ format: defaultFormat,
27
+ length: [12, 13, 14, 15, 16, 17, 18, 19],
28
+ cvcLength: [3],
29
+ luhn: true
30
+ }, {
31
+ type: 'dinersclub',
32
+ pattern: /^(36|38|30[0-5])/,
33
+ format: defaultFormat,
34
+ length: [14],
35
+ cvcLength: [3],
36
+ luhn: true
37
+ }, {
38
+ type: 'laser',
39
+ pattern: /^(6706|6771|6709)/,
40
+ format: defaultFormat,
41
+ length: [16, 17, 18, 19],
42
+ cvcLength: [3],
43
+ luhn: true
44
+ }, {
45
+ type: 'jcb',
46
+ pattern: /^35/,
47
+ format: defaultFormat,
48
+ length: [16],
49
+ cvcLength: [3],
50
+ luhn: true
51
+ }, {
52
+ type: 'unionpay',
53
+ pattern: /^62/,
54
+ format: defaultFormat,
55
+ length: [16, 17, 18, 19],
56
+ cvcLength: [3],
57
+ luhn: false
58
+ }, {
59
+ type: 'discover',
60
+ pattern: /^(6011|65|64[4-9]|622)/,
61
+ format: defaultFormat,
62
+ length: [16],
63
+ cvcLength: [3],
64
+ luhn: true
65
+ }, {
66
+ type: 'mastercard',
67
+ pattern: /^5[1-5]/,
68
+ format: defaultFormat,
69
+ length: [16],
70
+ cvcLength: [3],
71
+ luhn: true
72
+ }, {
73
+ type: 'amex',
74
+ pattern: /^3[47]/,
75
+ format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/,
76
+ length: [15],
77
+ cvcLength: [3, 4],
78
+ luhn: true
79
+ }, {
80
+ type: 'visa',
81
+ pattern: /^4/,
82
+ format: defaultFormat,
83
+ length: [13, 14, 15, 16],
84
+ cvcLength: [3],
85
+ luhn: true
86
+ }
87
+ ];
88
+
89
+ cardFromNumber = function(num) {
90
+ var card, _i, _len;
91
+ num = (num + '').replace(/\D/g, '');
92
+ for (_i = 0, _len = cards.length; _i < _len; _i++) {
93
+ card = cards[_i];
94
+ if (card.pattern.test(num)) {
95
+ return card;
96
+ }
97
+ }
98
+ };
99
+
100
+ cardFromType = function(type) {
101
+ var card, _i, _len;
102
+ for (_i = 0, _len = cards.length; _i < _len; _i++) {
103
+ card = cards[_i];
104
+ if (card.type === type) {
105
+ return card;
106
+ }
107
+ }
108
+ };
109
+
110
+ luhnCheck = function(num) {
111
+ var digit, digits, odd, sum, _i, _len;
112
+ odd = true;
113
+ sum = 0;
114
+ digits = (num + '').split('').reverse();
115
+ for (_i = 0, _len = digits.length; _i < _len; _i++) {
116
+ digit = digits[_i];
117
+ digit = parseInt(digit, 10);
118
+ if ((odd = !odd)) {
119
+ digit *= 2;
120
+ }
121
+ if (digit > 9) {
122
+ digit -= 9;
123
+ }
124
+ sum += digit;
125
+ }
126
+ return sum % 10 === 0;
127
+ };
128
+
129
+ hasTextSelected = function($target) {
130
+ var _ref;
131
+ if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== $target.prop('selectionEnd')) {
132
+ return true;
133
+ }
134
+ if (typeof document !== "undefined" && document !== null ? (_ref = document.selection) != null ? typeof _ref.createRange === "function" ? _ref.createRange().text : void 0 : void 0 : void 0) {
135
+ return true;
136
+ }
137
+ return false;
138
+ };
139
+
140
+ reFormatCardNumber = function(e) {
141
+ var _this = this;
142
+ return setTimeout(function() {
143
+ var $target, value;
144
+ $target = $(e.currentTarget);
145
+ value = $target.val();
146
+ value = $.payment.formatCardNumber(value);
147
+ return $target.val(value);
148
+ });
149
+ };
150
+
151
+ formatCardNumber = function(e) {
152
+ var $target, card, digit, length, re, upperLength, value;
153
+ digit = String.fromCharCode(e.which);
154
+ if (!/^\d+$/.test(digit)) {
155
+ return;
156
+ }
157
+ $target = $(e.currentTarget);
158
+ value = $target.val();
159
+ card = cardFromNumber(value + digit);
160
+ length = (value.replace(/\D/g, '') + digit).length;
161
+ upperLength = 16;
162
+ if (card) {
163
+ upperLength = card.length[card.length.length - 1];
164
+ }
165
+ if (length >= upperLength) {
166
+ return;
167
+ }
168
+ if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== value.length) {
169
+ return;
170
+ }
171
+ if (card && card.type === 'amex') {
172
+ re = /^(\d{4}|\d{4}\s\d{6})$/;
173
+ } else {
174
+ re = /(?:^|\s)(\d{4})$/;
175
+ }
176
+ if (re.test(value)) {
177
+ e.preventDefault();
178
+ return $target.val(value + ' ' + digit);
179
+ } else if (re.test(value + digit)) {
180
+ e.preventDefault();
181
+ return $target.val(value + digit + ' ');
182
+ }
183
+ };
184
+
185
+ formatBackCardNumber = function(e) {
186
+ var $target, value;
187
+ $target = $(e.currentTarget);
188
+ value = $target.val();
189
+ if (e.meta) {
190
+ return;
191
+ }
192
+ if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== value.length) {
193
+ return;
194
+ }
195
+ if (e.which === 8 && /\s\d?$/.test(value)) {
196
+ e.preventDefault();
197
+ return $target.val(value.replace(/\s\d?$/, ''));
198
+ }
199
+ };
200
+
201
+ formatExpiry = function(e) {
202
+ var $target, digit, val;
203
+ digit = String.fromCharCode(e.which);
204
+ if (!/^\d+$/.test(digit)) {
205
+ return;
206
+ }
207
+ $target = $(e.currentTarget);
208
+ val = $target.val() + digit;
209
+ if (/^\d$/.test(val) && (val !== '0' && val !== '1')) {
210
+ e.preventDefault();
211
+ return $target.val("0" + val + " / ");
212
+ } else if (/^\d\d$/.test(val)) {
213
+ e.preventDefault();
214
+ return $target.val("" + val + " / ");
215
+ }
216
+ };
217
+
218
+ formatForwardExpiry = function(e) {
219
+ var $target, digit, val;
220
+ digit = String.fromCharCode(e.which);
221
+ if (!/^\d+$/.test(digit)) {
222
+ return;
223
+ }
224
+ $target = $(e.currentTarget);
225
+ val = $target.val();
226
+ if (/^\d\d$/.test(val)) {
227
+ return $target.val("" + val + " / ");
228
+ }
229
+ };
230
+
231
+ formatForwardSlash = function(e) {
232
+ var $target, slash, val;
233
+ slash = String.fromCharCode(e.which);
234
+ if (slash !== '/') {
235
+ return;
236
+ }
237
+ $target = $(e.currentTarget);
238
+ val = $target.val();
239
+ if (/^\d$/.test(val) && val !== '0') {
240
+ return $target.val("0" + val + " / ");
241
+ }
242
+ };
243
+
244
+ formatBackExpiry = function(e) {
245
+ var $target, value;
246
+ if (e.meta) {
247
+ return;
248
+ }
249
+ $target = $(e.currentTarget);
250
+ value = $target.val();
251
+ if (e.which !== 8) {
252
+ return;
253
+ }
254
+ if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== value.length) {
255
+ return;
256
+ }
257
+ if (/\s\/\s?\d?$/.test(value)) {
258
+ e.preventDefault();
259
+ return $target.val(value.replace(/\s\/\s?\d?$/, ''));
260
+ }
261
+ };
262
+
263
+ restrictNumeric = function(e) {
264
+ var input;
265
+ if (e.metaKey || e.ctrlKey) {
266
+ return true;
267
+ }
268
+ if (e.which === 32) {
269
+ return false;
270
+ }
271
+ if (e.which === 0) {
272
+ return true;
273
+ }
274
+ if (e.which < 33) {
275
+ return true;
276
+ }
277
+ input = String.fromCharCode(e.which);
278
+ return !!/[\d\s]/.test(input);
279
+ };
280
+
281
+ restrictCardNumber = function(e) {
282
+ var $target, card, digit, value;
283
+ $target = $(e.currentTarget);
284
+ digit = String.fromCharCode(e.which);
285
+ if (!/^\d+$/.test(digit)) {
286
+ return;
287
+ }
288
+ if (hasTextSelected($target)) {
289
+ return;
290
+ }
291
+ value = ($target.val() + digit).replace(/\D/g, '');
292
+ card = cardFromNumber(value);
293
+ if (card) {
294
+ return value.length <= card.length[card.length.length - 1];
295
+ } else {
296
+ return value.length <= 16;
297
+ }
298
+ };
299
+
300
+ restrictExpiry = function(e) {
301
+ var $target, digit, value;
302
+ $target = $(e.currentTarget);
303
+ digit = String.fromCharCode(e.which);
304
+ if (!/^\d+$/.test(digit)) {
305
+ return;
306
+ }
307
+ if (hasTextSelected($target)) {
308
+ return;
309
+ }
310
+ value = $target.val() + digit;
311
+ value = value.replace(/\D/g, '');
312
+ if (value.length > 6) {
313
+ return false;
314
+ }
315
+ };
316
+
317
+ restrictCVC = function(e) {
318
+ var $target, digit, val;
319
+ $target = $(e.currentTarget);
320
+ digit = String.fromCharCode(e.which);
321
+ if (!/^\d+$/.test(digit)) {
322
+ return;
323
+ }
324
+ val = $target.val() + digit;
325
+ return val.length <= 4;
326
+ };
327
+
328
+ setCardType = function(e) {
329
+ var $target, allTypes, card, cardType, val;
330
+ $target = $(e.currentTarget);
331
+ val = $target.val();
332
+ cardType = $.payment.cardType(val) || 'unknown';
333
+ if (!$target.hasClass(cardType)) {
334
+ allTypes = (function() {
335
+ var _i, _len, _results;
336
+ _results = [];
337
+ for (_i = 0, _len = cards.length; _i < _len; _i++) {
338
+ card = cards[_i];
339
+ _results.push(card.type);
340
+ }
341
+ return _results;
342
+ })();
343
+ $target.removeClass('unknown');
344
+ $target.removeClass(allTypes.join(' '));
345
+ $target.addClass(cardType);
346
+ $target.toggleClass('identified', cardType !== 'unknown');
347
+ return $target.trigger('payment.cardType', cardType);
348
+ }
349
+ };
350
+
351
+ $.payment.fn.formatCardCVC = function() {
352
+ this.payment('restrictNumeric');
353
+ this.on('keypress', restrictCVC);
354
+ return this;
355
+ };
356
+
357
+ $.payment.fn.formatCardExpiry = function() {
358
+ this.payment('restrictNumeric');
359
+ this.on('keypress', restrictExpiry);
360
+ this.on('keypress', formatExpiry);
361
+ this.on('keypress', formatForwardSlash);
362
+ this.on('keypress', formatForwardExpiry);
363
+ this.on('keydown', formatBackExpiry);
364
+ return this;
365
+ };
366
+
367
+ $.payment.fn.formatCardNumber = function() {
368
+ this.payment('restrictNumeric');
369
+ this.on('keypress', restrictCardNumber);
370
+ this.on('keypress', formatCardNumber);
371
+ this.on('keydown', formatBackCardNumber);
372
+ this.on('keyup', setCardType);
373
+ this.on('paste', reFormatCardNumber);
374
+ return this;
375
+ };
376
+
377
+ $.payment.fn.restrictNumeric = function() {
378
+ this.on('keypress', restrictNumeric);
379
+ return this;
380
+ };
381
+
382
+ $.payment.fn.cardExpiryVal = function() {
383
+ return $.payment.cardExpiryVal($(this).val());
384
+ };
385
+
386
+ $.payment.cardExpiryVal = function(value) {
387
+ var month, prefix, year, _ref;
388
+ value = value.replace(/\s/g, '');
389
+ _ref = value.split('/', 2), month = _ref[0], year = _ref[1];
390
+ if ((year != null ? year.length : void 0) === 2 && /^\d+$/.test(year)) {
391
+ prefix = (new Date).getFullYear();
392
+ prefix = prefix.toString().slice(0, 2);
393
+ year = prefix + year;
394
+ }
395
+ month = parseInt(month, 10);
396
+ year = parseInt(year, 10);
397
+ return {
398
+ month: month,
399
+ year: year
400
+ };
401
+ };
402
+
403
+ $.payment.validateCardNumber = function(num) {
404
+ var card, _ref;
405
+ num = (num + '').replace(/\s+|-/g, '');
406
+ if (!/^\d+$/.test(num)) {
407
+ return false;
408
+ }
409
+ card = cardFromNumber(num);
410
+ if (!card) {
411
+ return false;
412
+ }
413
+ return (_ref = num.length, __indexOf.call(card.length, _ref) >= 0) && (card.luhn === false || luhnCheck(num));
414
+ };
415
+
416
+ $.payment.validateCardExpiry = function(month, year) {
417
+ var currentTime, expiry, _ref;
418
+ if (typeof month === 'object' && 'month' in month) {
419
+ _ref = month, month = _ref.month, year = _ref.year;
420
+ }
421
+ if (!(month && year)) {
422
+ return false;
423
+ }
424
+ month = $.trim(month);
425
+ year = $.trim(year);
426
+ if (!/^\d+$/.test(month)) {
427
+ return false;
428
+ }
429
+ if (!/^\d+$/.test(year)) {
430
+ return false;
431
+ }
432
+ if (!(parseInt(month, 10) <= 12)) {
433
+ return false;
434
+ }
435
+ expiry = new Date(year, month);
436
+ currentTime = new Date;
437
+ expiry.setMonth(expiry.getMonth() - 1);
438
+ expiry.setMonth(expiry.getMonth() + 1, 1);
439
+ return expiry > currentTime;
440
+ };
441
+
442
+ $.payment.validateCardCVC = function(cvc, type) {
443
+ var _ref, _ref1;
444
+ cvc = $.trim(cvc);
445
+ if (!/^\d+$/.test(cvc)) {
446
+ return false;
447
+ }
448
+ if (type) {
449
+ return _ref = cvc.length, __indexOf.call((_ref1 = cardFromType(type)) != null ? _ref1.cvcLength : void 0, _ref) >= 0;
450
+ } else {
451
+ return cvc.length >= 3 && cvc.length <= 4;
452
+ }
453
+ };
454
+
455
+ $.payment.cardType = function(num) {
456
+ var _ref;
457
+ if (!num) {
458
+ return null;
459
+ }
460
+ return ((_ref = cardFromNumber(num)) != null ? _ref.type : void 0) || null;
461
+ };
462
+
463
+ $.payment.formatCardNumber = function(num) {
464
+ var card, groups, upperLength, _ref;
465
+ card = cardFromNumber(num);
466
+ if (!card) {
467
+ return num;
468
+ }
469
+ upperLength = card.length[card.length.length - 1];
470
+ num = num.replace(/\D/g, '');
471
+ num = num.slice(0, +upperLength + 1 || 9e9);
472
+ if (card.format.global) {
473
+ return (_ref = num.match(card.format)) != null ? _ref.join(' ') : void 0;
474
+ } else {
475
+ groups = card.format.exec(num);
476
+ if (groups != null) {
477
+ groups.shift();
478
+ }
479
+ return groups != null ? groups.join(' ') : void 0;
480
+ }
481
+ };
482
+
483
+ }).call(this);
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jquery-payment-rails
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Vladimir Chistiakov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ none: false
21
+ prerelease: false
22
+ name: railties
23
+ requirement: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '3.1'
28
+ none: false
29
+ type: :runtime
30
+ description: jQuery.payment is a general purpose library for building credit card
31
+ forms, validating inputs and formatting numbers.
32
+ email:
33
+ - vlad.chistyakov@gmail.com
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - lib/jquery-payment-rails/engine.rb
39
+ - lib/jquery-payment-rails/version.rb
40
+ - lib/jquery-payment-rails.rb
41
+ - vendor/assets/javascripts/jquery.payment.js
42
+ - LICENSE.txt
43
+ - README.md
44
+ homepage: ''
45
+ licenses: []
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ segments:
56
+ - 0
57
+ hash: 3264000385598535175
58
+ none: false
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ segments:
65
+ - 0
66
+ hash: 3264000385598535175
67
+ none: false
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 1.8.24
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: jQuery.payment plugin for rails asset pipeline
74
+ test_files: []