weaver 0.8.10 → 0.8.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/weaver +2 -1
- data/lib/weaver/element_types/code.rb +2 -2
- data/lib/weaver/element_types/dynamic_table.rb +1 -1
- data/lib/weaver/element_types/form_elements.rb +6 -2
- data/lib/weaver/element_types/panel.rb +1 -1
- data/lib/weaver/elements.rb +8 -5
- data/lib/weaver/page_types/page.rb +3 -1
- data/lib/weaver/version.rb +1 -1
- data/weaver.gemspec +2 -2
- metadata +16 -82
- data/data/weaver/js/plugins/skeuocard/Gruntfile.coffee +0 -74
- data/data/weaver/js/plugins/skeuocard/LICENSE +0 -21
- data/data/weaver/js/plugins/skeuocard/README.md +0 -393
- data/data/weaver/js/plugins/skeuocard/bower.json +0 -40
- data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.eot +0 -0
- data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.svg +0 -138
- data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.ttf +0 -0
- data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.woff +0 -0
- data/data/weaver/js/plugins/skeuocard/images/card-flip-arrow.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/card-front-background.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/card-invalid-indicator.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/card-valid-anim.gif +0 -0
- data/data/weaver/js/plugins/skeuocard/images/card-valid-indicator.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/error-pointer.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/issuers/visa-chase-sapphire.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/issuers/visa-simple-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/amex-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/dinersclubintl-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/discover-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/generic-back.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/generic-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/jcb-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/maestro-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/mastercard-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/unionpay-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/visa-back.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/products/visa-front.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/card-front-background.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/error-pointer.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/product-amex-front.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/product-dinersclub-front.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/product-discover-front.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/product-generic-front.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/product-jcb-front.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/product-maestro-front.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/product-mastercard-front.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/product-unionpay-front.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/images/src/product-visa-front.fw.png +0 -0
- data/data/weaver/js/plugins/skeuocard/index.html +0 -124
- data/data/weaver/js/plugins/skeuocard/javascripts/skeuocard.js +0 -1748
- data/data/weaver/js/plugins/skeuocard/javascripts/skeuocard.min.js +0 -2
- data/data/weaver/js/plugins/skeuocard/javascripts/src/CardProduct.coffee +0 -284
- data/data/weaver/js/plugins/skeuocard/javascripts/src/ExpirationInputView.coffee +0 -206
- data/data/weaver/js/plugins/skeuocard/javascripts/src/FlipTabView.coffee +0 -67
- data/data/weaver/js/plugins/skeuocard/javascripts/src/SegmentedCardNumberInputView.coffee +0 -284
- data/data/weaver/js/plugins/skeuocard/javascripts/src/Skeuocard.coffee +0 -439
- data/data/weaver/js/plugins/skeuocard/javascripts/src/TextInputView.coffee +0 -42
- data/data/weaver/js/plugins/skeuocard/javascripts/vendor/cssua.min.js +0 -7
- data/data/weaver/js/plugins/skeuocard/javascripts/vendor/demo.fix.js +0 -17
- data/data/weaver/js/plugins/skeuocard/javascripts/vendor/jquery-2.0.3.min.js +0 -5
- data/data/weaver/js/plugins/skeuocard/package-lock.json +0 -760
- data/data/weaver/js/plugins/skeuocard/package.json +0 -19
- data/data/weaver/js/plugins/skeuocard/screenshot.png +0 -0
- data/data/weaver/js/plugins/skeuocard/styles/demo.css +0 -2
- data/data/weaver/js/plugins/skeuocard/styles/demo.css.map +0 -7
- data/data/weaver/js/plugins/skeuocard/styles/skeuocard.css +0 -2
- data/data/weaver/js/plugins/skeuocard/styles/skeuocard.css.map +0 -7
- data/data/weaver/js/plugins/skeuocard/styles/skeuocard.reset.css +0 -2
- data/data/weaver/js/plugins/skeuocard/styles/skeuocard.reset.css.map +0 -7
- data/data/weaver/js/plugins/skeuocard/styles/src/_browser_hacks.scss +0 -52
- data/data/weaver/js/plugins/skeuocard/styles/src/_cards.scss +0 -516
- data/data/weaver/js/plugins/skeuocard/styles/src/_util.scss +0 -15
- data/data/weaver/js/plugins/skeuocard/styles/src/demo.scss +0 -265
- data/data/weaver/js/plugins/skeuocard/styles/src/skeuocard.reset.scss +0 -60
- data/data/weaver/js/plugins/skeuocard/styles/src/skeuocard.scss +0 -190
@@ -1,439 +0,0 @@
|
|
1
|
-
###
|
2
|
-
"Skeuocard" -- A Skeuomorphic Credit-Card Input Enhancement
|
3
|
-
@description Skeuocard is a skeuomorphic credit card input plugin, supporting
|
4
|
-
progressive enhancement. It renders a credit-card input which
|
5
|
-
behaves similarly to a physical credit card.
|
6
|
-
@author Ken Keiter <ken@kenkeiter.com>
|
7
|
-
@updated 2013-07-25
|
8
|
-
@website http://kenkeiter.com/
|
9
|
-
@exports [window.Skeuocard]
|
10
|
-
###
|
11
|
-
|
12
|
-
$ = jQuery
|
13
|
-
|
14
|
-
class Skeuocard
|
15
|
-
|
16
|
-
@currentDate: new Date()
|
17
|
-
|
18
|
-
constructor: (el, opts = {})->
|
19
|
-
@el = container: $(el), underlyingFields: {}
|
20
|
-
@_inputViews = {}
|
21
|
-
@_inputViewsByFace = {front: [], back: []}
|
22
|
-
@_tabViews = {}
|
23
|
-
@_state = {}
|
24
|
-
@product = null
|
25
|
-
@visibleFace = 'front'
|
26
|
-
|
27
|
-
# configure default opts
|
28
|
-
optDefaults =
|
29
|
-
debug: false
|
30
|
-
dontFocus: false
|
31
|
-
acceptedCardProducts: null
|
32
|
-
cardNumberPlaceholderChar: 'X'
|
33
|
-
genericPlaceholder: "XXXX XXXX XXXX XXXX"
|
34
|
-
typeInputSelector: '[name="cc_type"]'
|
35
|
-
numberInputSelector: '[name="cc_number"]'
|
36
|
-
expMonthInputSelector: '[name="cc_exp_month"]'
|
37
|
-
expYearInputSelector: '[name="cc_exp_year"]'
|
38
|
-
nameInputSelector: '[name="cc_name"]'
|
39
|
-
cvcInputSelector: '[name="cc_cvc"]'
|
40
|
-
initialValues: {}
|
41
|
-
validationState: {}
|
42
|
-
strings:
|
43
|
-
hiddenFaceFillPrompt: "<strong>Click here</strong> to <br>fill in the other side."
|
44
|
-
hiddenFaceErrorWarning: "There's a problem on the other side."
|
45
|
-
hiddenFaceSwitchPrompt: "Forget something?<br> Flip the card over."
|
46
|
-
@options = $.extend(optDefaults, opts)
|
47
|
-
|
48
|
-
# initialize the card
|
49
|
-
@_conformDOM() # conform the DOM, add our elements
|
50
|
-
@_bindInputEvents() # bind input and interaction events
|
51
|
-
@_importImplicitOptions() # import init options from DOM element attrs
|
52
|
-
@render() # perform initial render
|
53
|
-
|
54
|
-
# Debugging helper; if debug is set to true at instantiation, messages will
|
55
|
-
# be printed to the console.
|
56
|
-
_log: (msg...)->
|
57
|
-
if console?.log and !!@options.debug
|
58
|
-
console.log("[skeuocard]", msg...) if @options.debug?
|
59
|
-
|
60
|
-
# Trigger an event on a Skeuocard instance (jQuery's #trigger signature).
|
61
|
-
trigger: (args...)->
|
62
|
-
@el.container.trigger(args...)
|
63
|
-
|
64
|
-
# Bind an event handler on a Skeuocard instance (jQuery's #trigger signature).
|
65
|
-
bind: (args...)->
|
66
|
-
@el.container.bind(args...)
|
67
|
-
|
68
|
-
###
|
69
|
-
Transform the elements within the container, conforming the DOM so that it
|
70
|
-
becomes styleable, and that the underlying inputs are hidden.
|
71
|
-
###
|
72
|
-
_conformDOM: ->
|
73
|
-
@el.container.removeClass('no-js')
|
74
|
-
@el.container.addClass("skeuocard js")
|
75
|
-
|
76
|
-
# Attach underlying form fields.
|
77
|
-
@el.underlyingFields =
|
78
|
-
type: @el.container.find(@options.typeInputSelector)
|
79
|
-
number: @el.container.find(@options.numberInputSelector)
|
80
|
-
expMonth: @el.container.find(@options.expMonthInputSelector)
|
81
|
-
expYear: @el.container.find(@options.expYearInputSelector)
|
82
|
-
name: @el.container.find(@options.nameInputSelector)
|
83
|
-
cvc: @el.container.find(@options.cvcInputSelector)
|
84
|
-
# remove anything that's not an underlying form field
|
85
|
-
$(elem).detach() for own name, elem of @el.underlyingFields
|
86
|
-
@el.container.find("> :not(input,select,textarea)").remove()
|
87
|
-
$(elem).appendTo(@el.container) for own name, elem of @el.underlyingFields
|
88
|
-
@el.container.find("> input,select,textarea").hide()
|
89
|
-
# construct the necessary card elements
|
90
|
-
@el.front = $("<div>").attr(class: "face front")
|
91
|
-
@el.back = $("<div>").attr(class: "face back")
|
92
|
-
@el.cardBody = $("<div>").attr(class: "card-body")
|
93
|
-
# add elements to the DOM
|
94
|
-
@el.front.appendTo(@el.cardBody)
|
95
|
-
@el.back.appendTo(@el.cardBody)
|
96
|
-
@el.cardBody.appendTo(@el.container)
|
97
|
-
# create the validation indicator (flip tab), and attach them.
|
98
|
-
@_tabViews.front = new Skeuocard::FlipTabView(@, 'front', strings: @options.strings)
|
99
|
-
@_tabViews.back = new Skeuocard::FlipTabView(@, 'back', strings: @options.strings)
|
100
|
-
@el.front.prepend(@_tabViews.front.el)
|
101
|
-
@el.back.prepend(@_tabViews.back.el)
|
102
|
-
@_tabViews.front.hide()
|
103
|
-
@_tabViews.back.hide()
|
104
|
-
# Create new input views, attach them to the appropriate surfaces
|
105
|
-
@_inputViews =
|
106
|
-
number: new @SegmentedCardNumberInputView()
|
107
|
-
exp: new @ExpirationInputView(currentDate: @options.currentDate)
|
108
|
-
name: new @TextInputView(class: "cc-name", placeholder: "YOUR NAME")
|
109
|
-
cvc: new @TextInputView(class: "cc-cvc", placeholder: "XXX", requireMaxLength: true)
|
110
|
-
# style and attach the number view to the DOM
|
111
|
-
@_inputViews.number.el.addClass('cc-number')
|
112
|
-
@_inputViews.number.el.appendTo(@el.front)
|
113
|
-
# attach name input
|
114
|
-
@_inputViews.name.el.appendTo(@el.front)
|
115
|
-
# style and attach the exp view to the DOM
|
116
|
-
@_inputViews.exp.el.addClass('cc-exp')
|
117
|
-
@_inputViews.exp.el.appendTo(@el.front)
|
118
|
-
# attach cvc field to the DOM
|
119
|
-
@_inputViews.cvc.el.appendTo(@el.back)
|
120
|
-
|
121
|
-
return @el.container
|
122
|
-
|
123
|
-
###
|
124
|
-
Import implicit initialization options from the DOM. Brings in things like
|
125
|
-
the accepted card type, initial validation state, existing values, etc.
|
126
|
-
###
|
127
|
-
_importImplicitOptions: ->
|
128
|
-
|
129
|
-
for fieldName, fieldEl of @el.underlyingFields
|
130
|
-
# import initial values, with constructor options taking precedence
|
131
|
-
unless @options.initialValues[fieldName]?
|
132
|
-
@options.initialValues[fieldName] = fieldEl.val()
|
133
|
-
else # update underlying field value so that it is canonical.
|
134
|
-
@options.initialValues[fieldName] = @options.initialValues[fieldName].toString()
|
135
|
-
@_setUnderlyingValue(fieldName, @options.initialValues[fieldName])
|
136
|
-
# set a flag if any fields were initially filled
|
137
|
-
if @options.initialValues[fieldName]?.length > 0
|
138
|
-
@_state['initiallyFilled'] = true
|
139
|
-
# import initial validation state
|
140
|
-
unless @options.validationState[fieldName]?
|
141
|
-
@options.validationState[fieldName] = not fieldEl.hasClass('invalid')
|
142
|
-
|
143
|
-
# If no explicit acceptedCardProducts were specified, determine accepted
|
144
|
-
# card products using the underlying type select field.
|
145
|
-
unless @options.acceptedCardProducts?
|
146
|
-
@options.acceptedCardProducts = []
|
147
|
-
@el.underlyingFields.type.find('option').each (i, _el)=>
|
148
|
-
el = $(_el)
|
149
|
-
shortname = el.attr('data-sc-type') || el.attr('value')
|
150
|
-
@options.acceptedCardProducts.push shortname
|
151
|
-
|
152
|
-
# setup default values; when render is called, these will be picked up
|
153
|
-
if @options.initialValues.number?.length > 0
|
154
|
-
@set 'number', @options.initialValues.number
|
155
|
-
|
156
|
-
if @options.initialValues.name?.length > 0
|
157
|
-
@set 'name', @options.initialValues.name
|
158
|
-
|
159
|
-
if @options.initialValues.cvc?.length > 0
|
160
|
-
@set 'cvc', @options.initialValues.cvc
|
161
|
-
|
162
|
-
if @options.initialValues.expYear?.length > 0 and
|
163
|
-
@options.initialValues.expMonth?.length > 0
|
164
|
-
_initialExp = new Date parseInt(@options.initialValues.expYear),
|
165
|
-
parseInt(@options.initialValues.expMonth) - 1, 1
|
166
|
-
@set 'exp', _initialExp
|
167
|
-
|
168
|
-
@_updateValidationForFace('front')
|
169
|
-
@_updateValidationForFace('back')
|
170
|
-
|
171
|
-
set: (field, newValue)->
|
172
|
-
@_inputViews[field].setValue(newValue)
|
173
|
-
@_inputViews[field].trigger('valueChanged', @_inputViews[field])
|
174
|
-
|
175
|
-
###
|
176
|
-
Bind interaction events to their appropriate handlers.
|
177
|
-
###
|
178
|
-
_bindInputEvents: ->
|
179
|
-
# bind change handlers to render
|
180
|
-
@el.underlyingFields.number.bind "change", (e)=>
|
181
|
-
@_inputViews.number.setValue @_getUnderlyingValue('number')
|
182
|
-
@render()
|
183
|
-
|
184
|
-
_expirationChange = (e)=>
|
185
|
-
month = parseInt @_getUnderlyingValue('expMonth')
|
186
|
-
year = parseInt @_getUnderlyingValue('expYear')
|
187
|
-
@_inputViews.exp.setValue new Date(year, month - 1)
|
188
|
-
@render()
|
189
|
-
|
190
|
-
@el.underlyingFields.expMonth.bind "change", _expirationChange
|
191
|
-
@el.underlyingFields.expYear.bind "change", _expirationChange
|
192
|
-
|
193
|
-
@el.underlyingFields.name.bind "change", (e)=>
|
194
|
-
@_inputViews.exp.setValue @_getUnderlyingValue('name')
|
195
|
-
@render()
|
196
|
-
|
197
|
-
@el.underlyingFields.cvc.bind "change", (e)=>
|
198
|
-
@_inputViews.exp.setValue @_getUnderlyingValue('cvc')
|
199
|
-
@render()
|
200
|
-
|
201
|
-
# bind change events to their underlying form elements
|
202
|
-
@_inputViews.number.bind "change valueChanged", (e, input)=>
|
203
|
-
cardNumber = input.getValue()
|
204
|
-
@_setUnderlyingValue 'number', cardNumber
|
205
|
-
@_updateValidation 'number', cardNumber
|
206
|
-
# update the product if needed.
|
207
|
-
number = @_getUnderlyingValue('number')
|
208
|
-
matchedProduct = Skeuocard::CardProduct.firstMatchingNumber(number)
|
209
|
-
# check if the product is accepted
|
210
|
-
if not @product?.eql(matchedProduct)
|
211
|
-
@_log("Product will change:", @product, "=>", matchedProduct)
|
212
|
-
if matchedProduct?.attrs.companyShortname in @options.acceptedCardProducts
|
213
|
-
@trigger 'productWillChange.skeuocard', [@, @product, matchedProduct]
|
214
|
-
previousProduct = @product
|
215
|
-
@el.container.removeClass('unaccepted')
|
216
|
-
@_renderProduct(matchedProduct)
|
217
|
-
@product = matchedProduct
|
218
|
-
else if matchedProduct?
|
219
|
-
@trigger 'productWillChange.skeuocard', [@, @product, null]
|
220
|
-
@el.container.addClass('unaccepted')
|
221
|
-
@_renderProduct(null)
|
222
|
-
@product = null
|
223
|
-
else
|
224
|
-
@trigger 'productWillChange.skeuocard', [@, @product, null]
|
225
|
-
@el.container.removeClass('unaccepted')
|
226
|
-
@_renderProduct(null)
|
227
|
-
@product = null
|
228
|
-
@trigger 'productDidChange.skeuocard', [@, previousProduct, @product]
|
229
|
-
|
230
|
-
@_inputViews.exp.bind "keyup valueChanged", (e, input)=>
|
231
|
-
newDate = input.getValue()
|
232
|
-
@_updateValidation('exp', newDate)
|
233
|
-
if newDate?
|
234
|
-
@_setUnderlyingValue('expMonth', newDate.getMonth() + 1)
|
235
|
-
@_setUnderlyingValue('expYear', newDate.getFullYear())
|
236
|
-
|
237
|
-
@_inputViews.name.bind "keyup valueChanged", (e, input)=>
|
238
|
-
value = input.getValue()
|
239
|
-
@_setUnderlyingValue('name', value)
|
240
|
-
@_updateValidation('name', value)
|
241
|
-
|
242
|
-
@_inputViews.cvc.bind "keyup valueChanged", (e, input)=>
|
243
|
-
value = input.getValue()
|
244
|
-
@_setUnderlyingValue('cvc', value)
|
245
|
-
@_updateValidation('cvc', value)
|
246
|
-
|
247
|
-
@el.container.delegate "input", "keyup keydown", @_handleFieldTab.bind(@)
|
248
|
-
|
249
|
-
@_tabViews.front.el.click => @flip()
|
250
|
-
@_tabViews.back.el.click => @flip()
|
251
|
-
|
252
|
-
_handleFieldTab: (e)->
|
253
|
-
if e.which is 9 # tab
|
254
|
-
currentFieldEl = $(e.currentTarget)
|
255
|
-
_oppositeFace = if @visibleFace is 'front' then 'back' else 'front'
|
256
|
-
_currentFace = if @visibleFace is 'front' then 'front' else 'back'
|
257
|
-
backFieldEls = @el[_oppositeFace].find('input')
|
258
|
-
frontFieldEls = @el[_currentFace].find('input')
|
259
|
-
|
260
|
-
if @visibleFace is 'front' and
|
261
|
-
@el.front.hasClass('filled') and
|
262
|
-
backFieldEls.length > 0 and
|
263
|
-
frontFieldEls.index(currentFieldEl) is frontFieldEls.length-1 and
|
264
|
-
not e.shiftKey
|
265
|
-
@flip()
|
266
|
-
backFieldEls.first().focus()
|
267
|
-
e.preventDefault()
|
268
|
-
if @visibleFace is 'back' and e.shiftKey
|
269
|
-
@flip()
|
270
|
-
backFieldEls.last().focus() # other side, now...
|
271
|
-
e.preventDefault()
|
272
|
-
return true
|
273
|
-
|
274
|
-
_updateValidation: (fieldName, newValue)->
|
275
|
-
return false unless @product?
|
276
|
-
|
277
|
-
# Check against the current product to determine if the field is filled
|
278
|
-
isFilled = @product[fieldName].isFilled(newValue)
|
279
|
-
# If an initial value was supplied and marked as invalid, ensure that it
|
280
|
-
# has been changed to a new value.
|
281
|
-
needsFix = @options.validationState[fieldName]? is false
|
282
|
-
isFixed = @options.initialValues[fieldName]? and
|
283
|
-
newValue isnt @options.initialValues[fieldName]
|
284
|
-
# Check validity of value, asserting fixes have occurred if necessary.
|
285
|
-
isValid = @product[fieldName].isValid(newValue) and ((needsFix and isFixed) or true)
|
286
|
-
|
287
|
-
# Determine if state changed
|
288
|
-
fillStateChanged = @_state["#{fieldName}Filled"] isnt isFilled
|
289
|
-
validationStateChanged = @_state["#{fieldName}Valid"] isnt isValid
|
290
|
-
|
291
|
-
# If the fill state has changed, trigger events, and make styling changes.
|
292
|
-
if fillStateChanged
|
293
|
-
@trigger "fieldFillStateWillChange.skeuocard", [@, fieldName, isFilled]
|
294
|
-
@_inputViews[fieldName].el.toggleClass 'filled', isFilled
|
295
|
-
@_state["#{fieldName}Filled"] = isFilled
|
296
|
-
@trigger "fieldFillStateDidChange.skeuocard", [@, fieldName, isFilled]
|
297
|
-
|
298
|
-
# If the valid state has changed, trigger events, and make styling changes.
|
299
|
-
if validationStateChanged
|
300
|
-
@trigger "fieldValidationStateWillChange.skeuocard", [@, fieldName, isValid]
|
301
|
-
@_inputViews[fieldName].el.toggleClass 'valid', isValid
|
302
|
-
@_inputViews[fieldName].el.toggleClass 'invalid', not isValid
|
303
|
-
@_state["#{fieldName}Valid"] = isValid
|
304
|
-
@trigger "fieldValidationStateDidChange.skeuocard", [@, fieldName, isValid]
|
305
|
-
|
306
|
-
@_updateValidationForFace('front')
|
307
|
-
@_updateValidationForFace('back')
|
308
|
-
|
309
|
-
_updateValidationForFace: (face)->
|
310
|
-
fieldsFilled = (iv.el.hasClass('filled') for iv in @_inputViewsByFace[face]).every(Boolean)
|
311
|
-
fieldsValid = (iv.el.hasClass('valid') for iv in @_inputViewsByFace[face]).every(Boolean)
|
312
|
-
|
313
|
-
isFilled = (fieldsFilled and @product?) or (@_state['initiallyFilled'] or false)
|
314
|
-
isValid = fieldsValid and @product?
|
315
|
-
|
316
|
-
fillStateChanged = @_state["#{face}Filled"] isnt isFilled
|
317
|
-
validationStateChanged = @_state["#{face}Valid"] isnt isValid
|
318
|
-
|
319
|
-
if fillStateChanged
|
320
|
-
@trigger "faceFillStateWillChange.skeuocard", [@, face, isFilled]
|
321
|
-
@el[face].toggleClass 'filled', isFilled
|
322
|
-
@_state["#{face}Filled"] = isFilled
|
323
|
-
@trigger "faceFillStateDidChange.skeuocard", [@, face, isFilled]
|
324
|
-
|
325
|
-
if validationStateChanged
|
326
|
-
@trigger "faceValidationStateWillChange.skeuocard", [@, face, isValid]
|
327
|
-
@el[face].toggleClass 'valid', isValid
|
328
|
-
@el[face].toggleClass 'invalid', not isValid
|
329
|
-
@_state["#{face}Valid"] = isValid
|
330
|
-
@trigger "faceValidationStateDidChange.skeuocard", [@, face, isValid]
|
331
|
-
|
332
|
-
###
|
333
|
-
Assert rendering changes necessary for the current product. Passing a null
|
334
|
-
value instead of a product will revert the card to a generic state.
|
335
|
-
###
|
336
|
-
_renderProduct: (product)->
|
337
|
-
@_log("[_renderProduct]", "Rendering product:", product)
|
338
|
-
|
339
|
-
# remove existing product and issuer classes (destyling product)
|
340
|
-
@el.container.removeClass (index, css)=>
|
341
|
-
(css.match(/\b(product|issuer)-\S+/g) || []).join(' ')
|
342
|
-
# add classes necessary to identify new product
|
343
|
-
if product?.attrs.companyShortname?
|
344
|
-
@el.container.addClass("product-#{product.attrs.companyShortname}")
|
345
|
-
if product?.attrs.issuerShortname?
|
346
|
-
@el.container.addClass("issuer-#{product.attrs.issuerShortname}")
|
347
|
-
# update the underlying card type field
|
348
|
-
@_setUnderlyingValue('type', product?.attrs.companyShortname || null)
|
349
|
-
# reconfigure the number input groupings
|
350
|
-
@_inputViews.number.setGroupings(product?.attrs.cardNumberGrouping ||
|
351
|
-
[@options.genericPlaceholder.length], @options.dontFocus)
|
352
|
-
delete @options.dontFocus
|
353
|
-
if product?
|
354
|
-
# reconfigure the expiration input groupings
|
355
|
-
@_inputViews.exp.reconfigure
|
356
|
-
pattern: product?.attrs.expirationFormat || "MM/YY"
|
357
|
-
# reconfigure the CVC
|
358
|
-
@_inputViews.cvc.attr
|
359
|
-
maxlength: product.attrs.cvcLength
|
360
|
-
placeholder: new Array(product.attrs.cvcLength + 1).join(@options.cardNumberPlaceholderChar)
|
361
|
-
|
362
|
-
# set visibility and re-layout fields
|
363
|
-
@_inputViewsByFace = {front: [], back: []}
|
364
|
-
focused = $('input:focus') # allow restoration of focus upon re-attachment
|
365
|
-
for fieldName, destFace of product.attrs.layout
|
366
|
-
@_log("Moving", fieldName, "to", destFace)
|
367
|
-
viewEl = @_inputViews[fieldName].el.detach()
|
368
|
-
viewEl.appendTo(@el[destFace])
|
369
|
-
@_inputViewsByFace[destFace].push @_inputViews[fieldName]
|
370
|
-
@_inputViews[fieldName].show()
|
371
|
-
# Restore focus. Use setTimeout to resolve IE10 issue.
|
372
|
-
setTimeout =>
|
373
|
-
fieldEl = focused.first()
|
374
|
-
if fieldEl.length
|
375
|
-
fieldLength = fieldEl[0].maxLength
|
376
|
-
fieldEl.focus()
|
377
|
-
fieldEl[0].setSelectionRange(fieldLength, fieldLength)
|
378
|
-
, 10
|
379
|
-
else
|
380
|
-
for fieldName, view of @_inputViews
|
381
|
-
view.hide() if fieldName isnt 'number'
|
382
|
-
|
383
|
-
return product
|
384
|
-
|
385
|
-
_renderValidation: ->
|
386
|
-
# update the validation state of all fields
|
387
|
-
for fieldName, fieldView of @_inputViews
|
388
|
-
@_updateValidation(fieldName, fieldView.getValue())
|
389
|
-
|
390
|
-
# Update the card's visual representation to reflect internal state.
|
391
|
-
render: ->
|
392
|
-
@_renderProduct(@product)
|
393
|
-
@_renderValidation()
|
394
|
-
# @_flipToInvalidSide()
|
395
|
-
|
396
|
-
# Flip the card over.
|
397
|
-
flip: ->
|
398
|
-
targetFace = if @visibleFace is 'front' then 'back' else 'front'
|
399
|
-
@trigger('faceWillBecomeVisible.skeuocard', [@, targetFace])
|
400
|
-
@visibleFace = targetFace
|
401
|
-
@el.cardBody.toggleClass('flip')
|
402
|
-
surfaceName = if @visibleFace is 'front' then 'front' else 'back'
|
403
|
-
@el[surfaceName].find('.cc-field').not('.filled').find('input').first().focus()
|
404
|
-
@trigger('faceDidBecomeVisible.skeuocard', [@, targetFace])
|
405
|
-
|
406
|
-
# Set a value in the underlying form.
|
407
|
-
_setUnderlyingValue: (field, newValue)->
|
408
|
-
fieldEl = @el.underlyingFields[field]
|
409
|
-
_newValue = (newValue || "").toString()
|
410
|
-
throw "Set underlying value of unknown field: #{field}." unless fieldEl?
|
411
|
-
|
412
|
-
@trigger('change.skeuocard', [@])
|
413
|
-
unless fieldEl.is('select')
|
414
|
-
@el.underlyingFields[field].val(_newValue)
|
415
|
-
else
|
416
|
-
remapAttrKey = "data-sc-" + field.toLowerCase()
|
417
|
-
fieldEl.find('option').each (i, _el)=>
|
418
|
-
optionEl = $(_el)
|
419
|
-
if _newValue is (optionEl.attr(remapAttrKey) || optionEl.attr('value'))
|
420
|
-
@el.underlyingFields[field].val optionEl.attr('value')
|
421
|
-
|
422
|
-
# Get a value from the underlying form.
|
423
|
-
_getUnderlyingValue: (field)->
|
424
|
-
@el.underlyingFields[field]?.val()
|
425
|
-
|
426
|
-
isValid: ->
|
427
|
-
if @product
|
428
|
-
if @product.faces is 'both'
|
429
|
-
not @el.front.hasClass('invalid') and not @el.back.hasClass('invalid')
|
430
|
-
else if @product.faces is 'front'
|
431
|
-
not @el.front.hasClass('invalid')
|
432
|
-
else
|
433
|
-
not @el.back.hasClass('invalid')
|
434
|
-
else
|
435
|
-
false
|
436
|
-
|
437
|
-
|
438
|
-
# Export the object.
|
439
|
-
window.Skeuocard = Skeuocard
|
@@ -1,42 +0,0 @@
|
|
1
|
-
###
|
2
|
-
Skeuocard::TextInputView
|
3
|
-
###
|
4
|
-
class Skeuocard::TextInputView
|
5
|
-
constructor: (opts)->
|
6
|
-
@el = $('<div>')
|
7
|
-
@inputEl = $("<input>").attr
|
8
|
-
type: 'text'
|
9
|
-
placeholder: opts.placeholder
|
10
|
-
class: opts.class
|
11
|
-
@el.append @inputEl
|
12
|
-
@el.addClass 'cc-field'
|
13
|
-
@options = opts
|
14
|
-
@el.delegate "input", "focus", (e)=> @el.addClass('focus')
|
15
|
-
@el.delegate "input", "blur", (e)=> @el.removeClass('focus')
|
16
|
-
@el.delegate "input", "keyup", (e)=>
|
17
|
-
e.stopPropagation()
|
18
|
-
@trigger('keyup', [@])
|
19
|
-
|
20
|
-
clear: ->
|
21
|
-
@inputEl.val("")
|
22
|
-
|
23
|
-
attr: (args...)->
|
24
|
-
@inputEl.attr(args...)
|
25
|
-
|
26
|
-
setValue: (newValue)->
|
27
|
-
@inputEl.val(newValue)
|
28
|
-
|
29
|
-
getValue: ->
|
30
|
-
@inputEl.val()
|
31
|
-
|
32
|
-
bind: (args...)->
|
33
|
-
@el.bind(args...)
|
34
|
-
|
35
|
-
trigger: (args...)->
|
36
|
-
@el.trigger(args...)
|
37
|
-
|
38
|
-
show: ->
|
39
|
-
@el.show()
|
40
|
-
|
41
|
-
hide: ->
|
42
|
-
@el.hide()
|
@@ -1,7 +0,0 @@
|
|
1
|
-
var cssua=function(k,n){var p=/\s*([\-\w ]+)[\s\/\:]([\d_]+\b(?:[\-\._\/]\w+)*)/,q=/([\w\-\.]+[\s\/][v]?[\d_]+\b(?:[\-\._\/]\w+)*)/g,r=/\b(?:(blackberry\w*|bb10)|(rim tablet os))(?:\/(\d+\.\d+(?:\.\w+)*))?/,s=/\bsilk-accelerated=true\b/,t=/\bfluidapp\b/,u=/(\bwindows\b|\bmacintosh\b|\blinux\b|\bunix\b)/,v=/(\bandroid\b|\bipad\b|\bipod\b|\bwindows phone\b|\bwpdesktop\b|\bxblwp7\b|\bzunewp7\b|\bwindows ce\b|\bblackberry\w*|\bbb10\b|\brim tablet os\b|\bmeego|\bwebos\b|\bpalm|\bsymbian|\bj2me\b|\bdocomo\b|\bpda\b|\bchtml\b|\bmidp\b|\bcldc\b|\w*?mobile\w*?|\w*?phone\w*?)/,
|
2
|
-
w=/(\bxbox\b|\bplaystation\b|\bnintendo\s+\w+)/,d={parse:function(c){var a={};c=(""+c).toLowerCase();if(!c)return a;for(var b,g,e=c.split(/[()]/),f=0,d=e.length;f<d;f++)if(f%2){var l=e[f].split(";");b=0;for(g=l.length;b<g;b++)if(p.exec(l[b])){var h=RegExp.$1.split(" ").join("_"),k=RegExp.$2;if(!a[h]||parseFloat(a[h])<parseFloat(k))a[h]=k}}else if(l=e[f].match(q))for(b=0,g=l.length;b<g;b++)h=l[b].split(/[\/\s]+/),h.length&&"mozilla"!==h[0]&&(a[h[0].split(" ").join("_")]=h.slice(1).join("-"));v.exec(c)?
|
3
|
-
(a.mobile=RegExp.$1,r.exec(c)&&(delete a[a.mobile],a.blackberry=a.version||RegExp.$3||RegExp.$2||RegExp.$1,RegExp.$1?a.mobile="blackberry":"0.0.1"===a.version&&(a.blackberry="7.1.0.0"))):u.exec(c)?a.desktop=RegExp.$1:w.exec(c)&&(a.game=RegExp.$1,b=a.game.split(" ").join("_"),a.version&&!a[b]&&(a[b]=a.version));a.intel_mac_os_x?(a.mac_os_x=a.intel_mac_os_x.split("_").join("."),delete a.intel_mac_os_x):a.cpu_iphone_os?(a.ios=a.cpu_iphone_os.split("_").join("."),delete a.cpu_iphone_os):a.cpu_os?(a.ios=
|
4
|
-
a.cpu_os.split("_").join("."),delete a.cpu_os):"iphone"!==a.mobile||a.ios||(a.ios="1");a.opera&&a.version?(a.opera=a.version,delete a.blackberry):s.exec(c)?a.silk_accelerated=!0:t.exec(c)&&(a.fluidapp=a.version);if(a.applewebkit)a.webkit=a.applewebkit,delete a.applewebkit,a.opr&&(a.opera=a.opr,delete a.opr,delete a.chrome),a.safari&&(a.chrome||a.crios||a.opera||a.silk||a.fluidapp||a.phantomjs||a.mobile&&!a.ios?delete a.safari:a.safari=a.version&&!a.rim_tablet_os?a.version:{419:"2.0.4",417:"2.0.3",
|
5
|
-
416:"2.0.2",412:"2.0",312:"1.3",125:"1.2",85:"1.0"}[parseInt(a.safari,10)]||a.safari);else if(a.msie||a.trident)if(a.opera||(a.ie=a.msie||a.rv),delete a.msie,a.windows_phone_os)a.windows_phone=a.windows_phone_os,delete a.windows_phone_os;else{if("wpdesktop"===a.mobile||"xblwp7"===a.mobile||"zunewp7"===a.mobile)a.mobile="windows desktop",a.windows_phone=9>+a.ie?"7.0":10>+a.ie?"7.5":"8.0",delete a.windows_nt}else if(a.gecko||a.firefox)a.gecko=a.rv;a.rv&&delete a.rv;a.version&&delete a.version;return a},
|
6
|
-
format:function(c){var a="",b;for(b in c)if(b&&c.hasOwnProperty(b)){var g=b,e=c[b],g=g.split(".").join("-"),f=" ua-"+g;if("string"===typeof e){for(var e=e.split(" ").join("_").split(".").join("-"),d=e.indexOf("-");0<d;)f+=" ua-"+g+"-"+e.substring(0,d),d=e.indexOf("-",d+1);f+=" ua-"+g+"-"+e}a+=f}return a},encode:function(c){var a="",b;for(b in c)b&&c.hasOwnProperty(b)&&(a&&(a+="\x26"),a+=encodeURIComponent(b)+"\x3d"+encodeURIComponent(c[b]));return a}};d.userAgent=d.ua=d.parse(n);var m=d.format(d.ua)+
|
7
|
-
" js";k.className=k.className?k.className.replace(/\bno-js\b/g,"")+m:m.substr(1);return d}(document.documentElement,navigator.userAgent);
|
@@ -1,17 +0,0 @@
|
|
1
|
-
var metas = document.getElementsByTagName('meta');
|
2
|
-
var i;
|
3
|
-
if (navigator.userAgent.match(/iPhone/i)) {
|
4
|
-
for (i=0; i<metas.length; i++) {
|
5
|
-
if (metas[i].name == "viewport") {
|
6
|
-
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
7
|
-
}
|
8
|
-
}
|
9
|
-
document.addEventListener("gesturestart", gestureStart, false);
|
10
|
-
}
|
11
|
-
function gestureStart() {
|
12
|
-
for (i=0; i<metas.length; i++) {
|
13
|
-
if (metas[i].name == "viewport") {
|
14
|
-
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
15
|
-
}
|
16
|
-
}
|
17
|
-
}
|