weaver 0.8.9 → 0.8.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/exe/weaver +2 -1
  3. data/lib/weaver/element_types/code.rb +2 -2
  4. data/lib/weaver/element_types/credit_card_form.rb +23 -0
  5. data/lib/weaver/element_types/dynamic_table.rb +1 -1
  6. data/lib/weaver/element_types/form_elements.rb +6 -2
  7. data/lib/weaver/element_types/panel.rb +1 -1
  8. data/lib/weaver/elements.rb +8 -5
  9. data/lib/weaver/page_types/page.rb +3 -1
  10. data/lib/weaver/version.rb +1 -1
  11. data/weaver.gemspec +2 -2
  12. metadata +16 -82
  13. data/data/weaver/js/plugins/skeuocard/Gruntfile.coffee +0 -74
  14. data/data/weaver/js/plugins/skeuocard/LICENSE +0 -21
  15. data/data/weaver/js/plugins/skeuocard/README.md +0 -388
  16. data/data/weaver/js/plugins/skeuocard/bower.json +0 -40
  17. data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.eot +0 -0
  18. data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.svg +0 -138
  19. data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.ttf +0 -0
  20. data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.woff +0 -0
  21. data/data/weaver/js/plugins/skeuocard/images/card-flip-arrow.png +0 -0
  22. data/data/weaver/js/plugins/skeuocard/images/card-front-background.png +0 -0
  23. data/data/weaver/js/plugins/skeuocard/images/card-invalid-indicator.png +0 -0
  24. data/data/weaver/js/plugins/skeuocard/images/card-valid-anim.gif +0 -0
  25. data/data/weaver/js/plugins/skeuocard/images/card-valid-indicator.png +0 -0
  26. data/data/weaver/js/plugins/skeuocard/images/error-pointer.png +0 -0
  27. data/data/weaver/js/plugins/skeuocard/images/issuers/visa-chase-sapphire.png +0 -0
  28. data/data/weaver/js/plugins/skeuocard/images/issuers/visa-simple-front.png +0 -0
  29. data/data/weaver/js/plugins/skeuocard/images/products/amex-front.png +0 -0
  30. data/data/weaver/js/plugins/skeuocard/images/products/dinersclubintl-front.png +0 -0
  31. data/data/weaver/js/plugins/skeuocard/images/products/discover-front.png +0 -0
  32. data/data/weaver/js/plugins/skeuocard/images/products/generic-back.png +0 -0
  33. data/data/weaver/js/plugins/skeuocard/images/products/generic-front.png +0 -0
  34. data/data/weaver/js/plugins/skeuocard/images/products/jcb-front.png +0 -0
  35. data/data/weaver/js/plugins/skeuocard/images/products/maestro-front.png +0 -0
  36. data/data/weaver/js/plugins/skeuocard/images/products/mastercard-front.png +0 -0
  37. data/data/weaver/js/plugins/skeuocard/images/products/unionpay-front.png +0 -0
  38. data/data/weaver/js/plugins/skeuocard/images/products/visa-back.png +0 -0
  39. data/data/weaver/js/plugins/skeuocard/images/products/visa-front.png +0 -0
  40. data/data/weaver/js/plugins/skeuocard/images/src/card-front-background.fw.png +0 -0
  41. data/data/weaver/js/plugins/skeuocard/images/src/error-pointer.png +0 -0
  42. data/data/weaver/js/plugins/skeuocard/images/src/product-amex-front.fw.png +0 -0
  43. data/data/weaver/js/plugins/skeuocard/images/src/product-dinersclub-front.fw.png +0 -0
  44. data/data/weaver/js/plugins/skeuocard/images/src/product-discover-front.fw.png +0 -0
  45. data/data/weaver/js/plugins/skeuocard/images/src/product-generic-front.fw.png +0 -0
  46. data/data/weaver/js/plugins/skeuocard/images/src/product-jcb-front.fw.png +0 -0
  47. data/data/weaver/js/plugins/skeuocard/images/src/product-maestro-front.fw.png +0 -0
  48. data/data/weaver/js/plugins/skeuocard/images/src/product-mastercard-front.fw.png +0 -0
  49. data/data/weaver/js/plugins/skeuocard/images/src/product-unionpay-front.fw.png +0 -0
  50. data/data/weaver/js/plugins/skeuocard/images/src/product-visa-front.fw.png +0 -0
  51. data/data/weaver/js/plugins/skeuocard/index.html +0 -124
  52. data/data/weaver/js/plugins/skeuocard/javascripts/skeuocard.js +0 -1748
  53. data/data/weaver/js/plugins/skeuocard/javascripts/skeuocard.min.js +0 -2
  54. data/data/weaver/js/plugins/skeuocard/javascripts/src/CardProduct.coffee +0 -284
  55. data/data/weaver/js/plugins/skeuocard/javascripts/src/ExpirationInputView.coffee +0 -206
  56. data/data/weaver/js/plugins/skeuocard/javascripts/src/FlipTabView.coffee +0 -67
  57. data/data/weaver/js/plugins/skeuocard/javascripts/src/SegmentedCardNumberInputView.coffee +0 -284
  58. data/data/weaver/js/plugins/skeuocard/javascripts/src/Skeuocard.coffee +0 -439
  59. data/data/weaver/js/plugins/skeuocard/javascripts/src/TextInputView.coffee +0 -42
  60. data/data/weaver/js/plugins/skeuocard/javascripts/vendor/cssua.min.js +0 -7
  61. data/data/weaver/js/plugins/skeuocard/javascripts/vendor/demo.fix.js +0 -17
  62. data/data/weaver/js/plugins/skeuocard/javascripts/vendor/jquery-2.0.3.min.js +0 -5
  63. data/data/weaver/js/plugins/skeuocard/package-lock.json +0 -760
  64. data/data/weaver/js/plugins/skeuocard/package.json +0 -19
  65. data/data/weaver/js/plugins/skeuocard/screenshot.png +0 -0
  66. data/data/weaver/js/plugins/skeuocard/styles/demo.css +0 -2
  67. data/data/weaver/js/plugins/skeuocard/styles/demo.css.map +0 -7
  68. data/data/weaver/js/plugins/skeuocard/styles/skeuocard.css +0 -2
  69. data/data/weaver/js/plugins/skeuocard/styles/skeuocard.css.map +0 -7
  70. data/data/weaver/js/plugins/skeuocard/styles/skeuocard.reset.css +0 -2
  71. data/data/weaver/js/plugins/skeuocard/styles/skeuocard.reset.css.map +0 -7
  72. data/data/weaver/js/plugins/skeuocard/styles/src/_browser_hacks.scss +0 -52
  73. data/data/weaver/js/plugins/skeuocard/styles/src/_cards.scss +0 -512
  74. data/data/weaver/js/plugins/skeuocard/styles/src/_util.scss +0 -15
  75. data/data/weaver/js/plugins/skeuocard/styles/src/demo.scss +0 -265
  76. data/data/weaver/js/plugins/skeuocard/styles/src/skeuocard.reset.scss +0 -60
  77. data/data/weaver/js/plugins/skeuocard/styles/src/skeuocard.scss +0 -178
@@ -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
- }