jquery_payment 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bbe943b4869a023e4fba27d4668edec3330d5e98
4
+ data.tar.gz: 6f73bb991dd38e166dbe948840549d71459216eb
5
+ SHA512:
6
+ metadata.gz: ce56e8553f93bb46ae0028af09b8707a1cd9d9018fed95abefaae3bf733059ae8ba22024d3b5b0cb6e7da2186cdc3234da75312d1c99dfc12327b89486b4992f
7
+ data.tar.gz: b2ae9ae6513af5ed06f5a9e914e32bab9959ae558d423baceb11e85b584ca501acf47a2628e153f72aec40e5f8fa83b1e1d8ab7bfa899ab304d491a915aac6d5
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in jquery_payment.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Victor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ 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, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # JqueryPayment
2
+
3
+ This is a gem wrapper for [jquery.payment](https://github.com/stripe/jquery.payment)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'jquery_payment'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install jquery_payment
18
+
19
+ ## Usage
20
+
21
+
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'jquery_payment/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "jquery_payment"
8
+ spec.version = JqueryPayment::VERSION
9
+ spec.authors = ["ampvchen"]
10
+ spec.email = ["self@vchen.me"]
11
+ spec.description = %q{jquery.payments gem wrapper}
12
+ spec.summary = %q{jquery.payments gem wrapper}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+
24
+ # coffee-script
25
+ spec.add_dependency "coffee-script"
26
+ end
@@ -0,0 +1,3 @@
1
+ module JqueryPayment
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,8 @@
1
+ require "jquery_payment/version"
2
+
3
+ module JqueryPayment
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,439 @@
1
+ $ = jQuery
2
+ $.payment = {}
3
+ $.payment.fn = {}
4
+ $.fn.payment = (method, args...) ->
5
+ $.payment.fn[method].apply(this, args)
6
+
7
+ # Utils
8
+
9
+ defaultFormat = /(\d{1,4})/g
10
+
11
+ cards = [
12
+ {
13
+ type: 'maestro'
14
+ pattern: /^(5018|5020|5038|6304|6759|676[1-3])/
15
+ format: defaultFormat
16
+ length: [12..19]
17
+ cvcLength: [3]
18
+ luhn: true
19
+ }
20
+ {
21
+ type: 'dinersclub'
22
+ pattern: /^(36|38|30[0-5])/
23
+ format: defaultFormat
24
+ length: [14]
25
+ cvcLength: [3]
26
+ luhn: true
27
+ }
28
+ {
29
+ type: 'laser'
30
+ pattern: /^(6706|6771|6709)/
31
+ format: defaultFormat
32
+ length: [16..19]
33
+ cvcLength: [3]
34
+ luhn: true
35
+ }
36
+ {
37
+ type: 'jcb'
38
+ pattern: /^35/
39
+ format: defaultFormat
40
+ length: [16]
41
+ cvcLength: [3]
42
+ luhn: true
43
+ }
44
+ {
45
+ type: 'unionpay'
46
+ pattern: /^62/
47
+ format: defaultFormat
48
+ length: [16..19]
49
+ cvcLength: [3]
50
+ luhn: false
51
+ }
52
+ {
53
+ type: 'discover'
54
+ pattern: /^(6011|65|64[4-9]|622)/
55
+ format: defaultFormat
56
+ length: [16]
57
+ cvcLength: [3]
58
+ luhn: true
59
+ }
60
+ {
61
+ type: 'mastercard'
62
+ pattern: /^5[1-5]/
63
+ format: defaultFormat
64
+ length: [16]
65
+ cvcLength: [3]
66
+ luhn: true
67
+ }
68
+ {
69
+ type: 'amex'
70
+ pattern: /^3[47]/
71
+ format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/
72
+ length: [15]
73
+ cvcLength: [3..4]
74
+ luhn: true
75
+ }
76
+ {
77
+ type: 'visa'
78
+ pattern: /^4/
79
+ format: defaultFormat
80
+ length: [13..16]
81
+ cvcLength: [3]
82
+ luhn: true
83
+ }
84
+ ]
85
+
86
+ cardFromNumber = (num) ->
87
+ num = (num + '').replace(/\D/g, '')
88
+ return card for card in cards when card.pattern.test(num)
89
+
90
+ cardFromType = (type) ->
91
+ return card for card in cards when card.type is type
92
+
93
+ luhnCheck = (num) ->
94
+ odd = true
95
+ sum = 0
96
+
97
+ digits = (num + '').split('').reverse()
98
+
99
+ for digit in digits
100
+ digit = parseInt(digit, 10)
101
+ digit *= 2 if (odd = !odd)
102
+ digit -= 9 if digit > 9
103
+ sum += digit
104
+
105
+ sum % 10 == 0
106
+
107
+ hasTextSelected = ($target) ->
108
+ # If some text is selected
109
+ return true if $target.prop('selectionStart')? and
110
+ $target.prop('selectionStart') isnt $target.prop('selectionEnd')
111
+
112
+ # If some text is selected in IE
113
+ return true if document?.selection?.createRange?().text
114
+
115
+ false
116
+
117
+ # Private
118
+
119
+ # Format Card Number
120
+
121
+ reFormatCardNumber = (e) ->
122
+ setTimeout =>
123
+ $target = $(e.currentTarget)
124
+ value = $target.val()
125
+ value = $.payment.formatCardNumber(value)
126
+ $target.val(value)
127
+
128
+ formatCardNumber = (e) ->
129
+ # Only format if input is a number
130
+ digit = String.fromCharCode(e.which)
131
+ return unless /^\d+$/.test(digit)
132
+
133
+ $target = $(e.currentTarget)
134
+ value = $target.val()
135
+ card = cardFromNumber(value + digit)
136
+ length = (value.replace(/\D/g, '') + digit).length
137
+
138
+ upperLength = 16
139
+ upperLength = card.length[card.length.length - 1] if card
140
+ return if length >= upperLength
141
+
142
+ # Return if focus isn't at the end of the text
143
+ return if $target.prop('selectionStart')? and
144
+ $target.prop('selectionStart') isnt value.length
145
+
146
+ if card && card.type is 'amex'
147
+ # Amex cards are formatted differently
148
+ re = /^(\d{4}|\d{4}\s\d{6})$/
149
+ else
150
+ re = /(?:^|\s)(\d{4})$/
151
+
152
+ # If '4242' + 4
153
+ if re.test(value)
154
+ e.preventDefault()
155
+ $target.val(value + ' ' + digit)
156
+
157
+ # If '424' + 2
158
+ else if re.test(value + digit)
159
+ e.preventDefault()
160
+ $target.val(value + digit + ' ')
161
+
162
+ formatBackCardNumber = (e) ->
163
+ $target = $(e.currentTarget)
164
+ value = $target.val()
165
+
166
+ return if e.meta
167
+
168
+ # Return unless backspacing
169
+ return unless e.which is 8
170
+
171
+ # Return if focus isn't at the end of the text
172
+ return if $target.prop('selectionStart')? and
173
+ $target.prop('selectionStart') isnt value.length
174
+
175
+ # Remove the trailing space
176
+ if /\d\s$/.test(value)
177
+ e.preventDefault()
178
+ $target.val(value.replace(/\d\s$/, ''))
179
+ else if /\s\d?$/.test(value)
180
+ e.preventDefault()
181
+ $target.val(value.replace(/\s\d?$/, ''))
182
+
183
+ # Format Expiry
184
+
185
+ formatExpiry = (e) ->
186
+ # Only format if input is a number
187
+ digit = String.fromCharCode(e.which)
188
+ return unless /^\d+$/.test(digit)
189
+
190
+ $target = $(e.currentTarget)
191
+ val = $target.val() + digit
192
+
193
+ if /^\d$/.test(val) and val not in ['0', '1']
194
+ e.preventDefault()
195
+ $target.val("0#{val} / ")
196
+
197
+ else if /^\d\d$/.test(val)
198
+ e.preventDefault()
199
+ $target.val("#{val} / ")
200
+
201
+ formatForwardExpiry = (e) ->
202
+ digit = String.fromCharCode(e.which)
203
+ return unless /^\d+$/.test(digit)
204
+
205
+ $target = $(e.currentTarget)
206
+ val = $target.val()
207
+
208
+ if /^\d\d$/.test(val)
209
+ $target.val("#{val} / ")
210
+
211
+ formatForwardSlash = (e) ->
212
+ slash = String.fromCharCode(e.which)
213
+ return unless slash is '/'
214
+
215
+ $target = $(e.currentTarget)
216
+ val = $target.val()
217
+
218
+ if /^\d$/.test(val) and val isnt '0'
219
+ $target.val("0#{val} / ")
220
+
221
+ formatBackExpiry = (e) ->
222
+ # If shift+backspace is pressed
223
+ return if e.meta
224
+
225
+ $target = $(e.currentTarget)
226
+ value = $target.val()
227
+
228
+ # Return unless backspacing
229
+ return unless e.which is 8
230
+
231
+ # Return if focus isn't at the end of the text
232
+ return if $target.prop('selectionStart')? and
233
+ $target.prop('selectionStart') isnt value.length
234
+
235
+ # Remove the trailing space
236
+ if /\d(\s|\/)+$/.test(value)
237
+ e.preventDefault()
238
+ $target.val(value.replace(/\d(\s|\/)*$/, ''))
239
+ else if /\s\/\s?\d?$/.test(value)
240
+ e.preventDefault()
241
+ $target.val(value.replace(/\s\/\s?\d?$/, ''))
242
+
243
+ # Restrictions
244
+
245
+ restrictNumeric = (e) ->
246
+ # Key event is for a browser shortcut
247
+ return true if e.metaKey or e.ctrlKey
248
+
249
+ # If keycode is a space
250
+ return false if e.which is 32
251
+
252
+ # If keycode is a special char (WebKit)
253
+ return true if e.which is 0
254
+
255
+ # If char is a special char (Firefox)
256
+ return true if e.which < 33
257
+
258
+ input = String.fromCharCode(e.which)
259
+
260
+ # Char is a number or a space
261
+ !!/[\d\s]/.test(input)
262
+
263
+ restrictCardNumber = (e) ->
264
+ $target = $(e.currentTarget)
265
+ digit = String.fromCharCode(e.which)
266
+ return unless /^\d+$/.test(digit)
267
+
268
+ return if hasTextSelected($target)
269
+
270
+ # Restrict number of digits
271
+ value = ($target.val() + digit).replace(/\D/g, '')
272
+ card = cardFromNumber(value)
273
+
274
+ if card
275
+ value.length <= card.length[card.length.length - 1]
276
+ else
277
+ # All other cards are 16 digits long
278
+ value.length <= 16
279
+
280
+ restrictExpiry = (e) ->
281
+ $target = $(e.currentTarget)
282
+ digit = String.fromCharCode(e.which)
283
+ return unless /^\d+$/.test(digit)
284
+
285
+ return if hasTextSelected($target)
286
+
287
+ value = $target.val() + digit
288
+ value = value.replace(/\D/g, '')
289
+
290
+ return false if value.length > 6
291
+
292
+ restrictCVC = (e) ->
293
+ $target = $(e.currentTarget)
294
+ digit = String.fromCharCode(e.which)
295
+ return unless /^\d+$/.test(digit)
296
+
297
+ val = $target.val() + digit
298
+ val.length <= 4
299
+
300
+ setCardType = (e) ->
301
+ $target = $(e.currentTarget)
302
+ val = $target.val()
303
+ cardType = $.payment.cardType(val) or 'unknown'
304
+
305
+ unless $target.hasClass(cardType)
306
+ allTypes = (card.type for card in cards)
307
+
308
+ $target.removeClass('unknown')
309
+ $target.removeClass(allTypes.join(' '))
310
+
311
+ $target.addClass(cardType)
312
+ $target.toggleClass('identified', cardType isnt 'unknown')
313
+ $target.trigger('payment.cardType', cardType)
314
+
315
+ # Public
316
+
317
+ # Formatting
318
+
319
+ $.payment.fn.formatCardCVC = ->
320
+ @payment('restrictNumeric')
321
+ @on('keypress', restrictCVC)
322
+ this
323
+
324
+ $.payment.fn.formatCardExpiry = ->
325
+ @payment('restrictNumeric')
326
+ @on('keypress', restrictExpiry)
327
+ @on('keypress', formatExpiry)
328
+ @on('keypress', formatForwardSlash)
329
+ @on('keypress', formatForwardExpiry)
330
+ @on('keydown', formatBackExpiry)
331
+ this
332
+
333
+ $.payment.fn.formatCardNumber = ->
334
+ @payment('restrictNumeric')
335
+ @on('keypress', restrictCardNumber)
336
+ @on('keypress', formatCardNumber)
337
+ @on('keydown', formatBackCardNumber)
338
+ @on('keyup', setCardType)
339
+ @on('paste', reFormatCardNumber)
340
+ this
341
+
342
+ # Restrictions
343
+
344
+ $.payment.fn.restrictNumeric = ->
345
+ @on('keypress', restrictNumeric)
346
+ this
347
+
348
+ # Validations
349
+
350
+ $.payment.fn.cardExpiryVal = ->
351
+ $.payment.cardExpiryVal($(this).val())
352
+
353
+ $.payment.cardExpiryVal = (value) ->
354
+ value = value.replace(/\s/g, '')
355
+ [month, year] = value.split('/', 2)
356
+
357
+ # Allow for year shortcut
358
+ if year?.length is 2 and /^\d+$/.test(year)
359
+ prefix = (new Date).getFullYear()
360
+ prefix = prefix.toString()[0..1]
361
+ year = prefix + year
362
+
363
+ month = parseInt(month, 10)
364
+ year = parseInt(year, 10)
365
+
366
+ month: month, year: year
367
+
368
+ $.payment.validateCardNumber = (num) ->
369
+ num = (num + '').replace(/\s+|-/g, '')
370
+ return false unless /^\d+$/.test(num)
371
+
372
+ card = cardFromNumber(num)
373
+ return false unless card
374
+
375
+ num.length in card.length and
376
+ (card.luhn is false or luhnCheck(num))
377
+
378
+ $.payment.validateCardExpiry = (month, year) =>
379
+ # Allow passing an object
380
+ if typeof month is 'object' and 'month' of month
381
+ {month, year} = month
382
+
383
+ return false unless month and year
384
+
385
+ month = $.trim(month)
386
+ year = $.trim(year)
387
+
388
+ return false unless /^\d+$/.test(month)
389
+ return false unless /^\d+$/.test(year)
390
+ return false unless parseInt(month, 10) <= 12
391
+
392
+ if year.length is 2
393
+ prefix = (new Date).getFullYear()
394
+ prefix = prefix.toString()[0..1]
395
+ year = prefix + year
396
+
397
+ expiry = new Date(year, month)
398
+ currentTime = new Date
399
+
400
+ # Months start from 0 in JavaScript
401
+ expiry.setMonth(expiry.getMonth() - 1)
402
+
403
+ # The cc expires at the end of the month,
404
+ # so we need to make the expiry the first day
405
+ # of the month after
406
+ expiry.setMonth(expiry.getMonth() + 1, 1)
407
+
408
+ expiry > currentTime
409
+
410
+ $.payment.validateCardCVC = (cvc, type) ->
411
+ cvc = $.trim(cvc)
412
+ return false unless /^\d+$/.test(cvc)
413
+
414
+ if type
415
+ # Check against a explicit card type
416
+ cvc.length in cardFromType(type)?.cvcLength
417
+ else
418
+ # Check against all types
419
+ cvc.length >= 3 and cvc.length <= 4
420
+
421
+ $.payment.cardType = (num) ->
422
+ return null unless num
423
+ cardFromNumber(num)?.type or null
424
+
425
+ $.payment.formatCardNumber = (num) ->
426
+ card = cardFromNumber(num)
427
+ return num unless card
428
+
429
+ upperLength = card.length[card.length.length - 1]
430
+
431
+ num = num.replace(/\D/g, '')
432
+ num = num[0..upperLength]
433
+
434
+ if card.format.global
435
+ num.match(card.format)?.join(' ')
436
+ else
437
+ groups = card.format.exec(num)
438
+ groups?.shift()
439
+ groups?.join(' ')
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jquery_payment
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - ampvchen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: coffee-script
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: jquery.payments gem wrapper
56
+ email:
57
+ - self@vchen.me
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - LICENSE
65
+ - README.md
66
+ - Rakefile
67
+ - jquery_payment.gemspec
68
+ - lib/jquery_payment.rb
69
+ - lib/jquery_payment/version.rb
70
+ - vendor/assets/javascript/jquery.payment.coffee
71
+ homepage: ''
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.0.6
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: jquery.payments gem wrapper
95
+ test_files: []