weaver 0.8.13 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/data/weaver/css/plugins/codemirror/codemirror.css +97 -96
- data/data/weaver/css/style-dark.css +8628 -0
- data/data/weaver/css/style.css +37 -0
- data/data/weaver/js/plugins/codemirror/codemirror.js +8817 -6763
- data/data/weaver/js/plugins/skeuocard/Gruntfile.coffee +74 -0
- data/data/weaver/js/plugins/skeuocard/LICENSE +21 -0
- data/data/weaver/js/plugins/skeuocard/README.md +393 -0
- data/data/weaver/js/plugins/skeuocard/bower.json +40 -0
- data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.eot +0 -0
- data/data/weaver/js/plugins/skeuocard/fonts/ocra-webfont.svg +138 -0
- 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 +124 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/skeuocard.js +1748 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/skeuocard.min.js +2 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/src/CardProduct.coffee +284 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/src/ExpirationInputView.coffee +206 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/src/FlipTabView.coffee +67 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/src/SegmentedCardNumberInputView.coffee +284 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/src/Skeuocard.coffee +439 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/src/TextInputView.coffee +42 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/vendor/cssua.min.js +7 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/vendor/demo.fix.js +17 -0
- data/data/weaver/js/plugins/skeuocard/javascripts/vendor/jquery-2.0.3.min.js +5 -0
- data/data/weaver/js/plugins/skeuocard/package-lock.json +760 -0
- data/data/weaver/js/plugins/skeuocard/package.json +19 -0
- data/data/weaver/js/plugins/skeuocard/screenshot.png +0 -0
- data/data/weaver/js/plugins/skeuocard/styles/demo.css +2 -0
- data/data/weaver/js/plugins/skeuocard/styles/skeuocard.css +2 -0
- data/data/weaver/js/plugins/skeuocard/styles/skeuocard.reset.css +2 -0
- data/data/weaver/js/plugins/skeuocard/styles/src/_browser_hacks.scss +52 -0
- data/data/weaver/js/plugins/skeuocard/styles/src/_cards.scss +516 -0
- data/data/weaver/js/plugins/skeuocard/styles/src/_util.scss +15 -0
- data/data/weaver/js/plugins/skeuocard/styles/src/demo.scss +265 -0
- data/data/weaver/js/plugins/skeuocard/styles/src/skeuocard.reset.scss +60 -0
- data/data/weaver/js/plugins/skeuocard/styles/src/skeuocard.scss +190 -0
- data/lib/weaver/element_types/accordion.rb +2 -0
- data/lib/weaver/page_types/page.rb +5 -0
- data/lib/weaver/page_types/structured_page.rb +1 -1
- data/lib/weaver/version.rb +1 -1
- metadata +69 -6
@@ -0,0 +1,284 @@
|
|
1
|
+
###
|
2
|
+
# Skeuocard::SegmentedCardNumberInputView
|
3
|
+
# Provides a reconfigurable segmented input view for credit card numbers.
|
4
|
+
###
|
5
|
+
class Skeuocard::SegmentedCardNumberInputView
|
6
|
+
|
7
|
+
_digits: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
8
|
+
|
9
|
+
_keys:
|
10
|
+
backspace: 8
|
11
|
+
tab: 9
|
12
|
+
enter: 13
|
13
|
+
del: 46
|
14
|
+
arrowLeft: 37
|
15
|
+
arrowUp: 38
|
16
|
+
arrowRight: 39
|
17
|
+
arrowDown: 40
|
18
|
+
arrows: [37..40]
|
19
|
+
command: 16
|
20
|
+
alt: 17
|
21
|
+
|
22
|
+
_specialKeys: [8, 9, 13, 46, 37, 38, 39, 40, 16, 17]
|
23
|
+
|
24
|
+
constructor: (opts = {})->
|
25
|
+
@optDefaults =
|
26
|
+
value: ""
|
27
|
+
groupings: [19]
|
28
|
+
placeholderChar: "X"
|
29
|
+
@options = $.extend({}, @optDefaults, opts)
|
30
|
+
@_state =
|
31
|
+
selectingAll: false # indicates whether the field is in "select all"
|
32
|
+
@_buildDOM()
|
33
|
+
@setGroupings(@options.groupings)
|
34
|
+
|
35
|
+
_buildDOM: ->
|
36
|
+
@el = $('<fieldset>')
|
37
|
+
@el.addClass('cc-field')
|
38
|
+
@el.delegate "input", "keypress", @_handleGroupKeyPress.bind(@)
|
39
|
+
@el.delegate "input", "keydown", @_handleGroupKeyDown.bind(@)
|
40
|
+
@el.delegate "input", "keyup", @_handleGroupKeyUp.bind(@)
|
41
|
+
@el.delegate "input", "paste", @_handleGroupPaste.bind(@)
|
42
|
+
@el.delegate "input", "change", @_handleGroupChange.bind(@)
|
43
|
+
@el.delegate "input", "focus", (e)=>
|
44
|
+
@el.addClass('focus')
|
45
|
+
@el.delegate "input", "blur", (e)=>
|
46
|
+
@el.removeClass('focus')
|
47
|
+
|
48
|
+
_handleGroupKeyDown: (e)->
|
49
|
+
# If this is called with the control or meta key, defer to another handler
|
50
|
+
return @_handleModifiedKeyDown(e) if e.ctrlKey or e.metaKey
|
51
|
+
|
52
|
+
inputGroupEl = $(e.currentTarget)
|
53
|
+
currentTarget = e.currentTarget # get rid of that e.
|
54
|
+
cursorStart = currentTarget.selectionStart
|
55
|
+
cursorEnd = currentTarget.selectionEnd
|
56
|
+
inputMaxLength = currentTarget.maxLength
|
57
|
+
|
58
|
+
prevInputEl = inputGroupEl.prevAll('input')
|
59
|
+
nextInputEl = inputGroupEl.nextAll('input')
|
60
|
+
|
61
|
+
switch e.which
|
62
|
+
# handle backspace
|
63
|
+
when @_keys.backspace
|
64
|
+
if prevInputEl.length > 0 and cursorEnd is 0
|
65
|
+
@_focusField(prevInputEl.first(), 'end')
|
66
|
+
# handle up arrow
|
67
|
+
when @_keys.arrowUp
|
68
|
+
if cursorEnd is inputMaxLength
|
69
|
+
@_focusField(inputGroupEl, 'start')
|
70
|
+
else
|
71
|
+
@_focusField(inputGroupEl.prev(), 'end')
|
72
|
+
e.preventDefault()
|
73
|
+
# handle down arrow
|
74
|
+
when @_keys.arrowDown
|
75
|
+
if cursorEnd is inputMaxLength
|
76
|
+
@_focusField(inputGroupEl.next(), 'start')
|
77
|
+
else
|
78
|
+
@_focusField(inputGroupEl, 'end')
|
79
|
+
e.preventDefault()
|
80
|
+
# handle left arrow
|
81
|
+
when @_keys.arrowLeft
|
82
|
+
if cursorEnd is 0
|
83
|
+
@_focusField(inputGroupEl.prev(), 'end')
|
84
|
+
e.preventDefault()
|
85
|
+
# handle right arrow
|
86
|
+
when @_keys.arrowRight
|
87
|
+
if cursorEnd is inputMaxLength
|
88
|
+
@_focusField(inputGroupEl.next(), 'start')
|
89
|
+
e.preventDefault()
|
90
|
+
else
|
91
|
+
if not (e.which in @_specialKeys) and
|
92
|
+
(cursorStart is inputMaxLength and cursorEnd is inputMaxLength) and
|
93
|
+
nextInputEl.length isnt 0
|
94
|
+
@_focusField(nextInputEl.first(), 'start')
|
95
|
+
|
96
|
+
# Allow the event to propagate, and otherwise be happy
|
97
|
+
return true
|
98
|
+
|
99
|
+
_handleGroupKeyPress: (e)->
|
100
|
+
inputGroupEl = $(e.currentTarget)
|
101
|
+
isDigit = (String.fromCharCode(e.which) in @_digits)
|
102
|
+
|
103
|
+
return true if e.ctrlKey or e.metaKey
|
104
|
+
return true if e.which is 0
|
105
|
+
|
106
|
+
if (not e.shiftKey and (e.which in @_specialKeys)) or isDigit
|
107
|
+
return true
|
108
|
+
|
109
|
+
e.preventDefault()
|
110
|
+
return false
|
111
|
+
|
112
|
+
_handleGroupKeyUp: (e)->
|
113
|
+
inputGroupEl = $(e.currentTarget)
|
114
|
+
currentTarget = e.currentTarget # get rid of that e.
|
115
|
+
inputMaxLength = currentTarget.maxLength
|
116
|
+
|
117
|
+
cursorStart = currentTarget.selectionStart
|
118
|
+
cursorEnd = currentTarget.selectionEnd
|
119
|
+
|
120
|
+
nextInputEl = inputGroupEl.nextAll('input')
|
121
|
+
|
122
|
+
return true if e.ctrlKey or e.metaKey # ignore control keys
|
123
|
+
|
124
|
+
|
125
|
+
if @_state.selectingAll and
|
126
|
+
(e.which in @_specialKeys) and
|
127
|
+
e.which isnt @_keys.command and
|
128
|
+
e.which isnt @_keys.alt
|
129
|
+
@_endSelectAll()
|
130
|
+
|
131
|
+
if not (e.which in @_specialKeys) and
|
132
|
+
not (e.shiftKey and e.which is @_keys.tab) and
|
133
|
+
(cursorStart is inputMaxLength and cursorEnd is inputMaxLength) and
|
134
|
+
nextInputEl.length isnt 0
|
135
|
+
@_focusField(nextInputEl.first(), 'start')
|
136
|
+
|
137
|
+
unless e.shiftKey and (e.which in @_specialKeys)
|
138
|
+
@trigger('change', [@])
|
139
|
+
|
140
|
+
return true
|
141
|
+
|
142
|
+
_handleModifiedKeyDown: (e)->
|
143
|
+
char = String.fromCharCode(e.which)
|
144
|
+
switch char
|
145
|
+
when 'a', 'A'
|
146
|
+
@_beginSelectAll()
|
147
|
+
e.preventDefault()
|
148
|
+
|
149
|
+
_handleGroupPaste: (e)->
|
150
|
+
# clean and re-split the value
|
151
|
+
setTimeout =>
|
152
|
+
newValue = @getValue().replace(/[^0-9]+/g, '')
|
153
|
+
@_endSelectAll() if @_state.selectingAll
|
154
|
+
@setValue(newValue)
|
155
|
+
@trigger('change', [@])
|
156
|
+
, 50
|
157
|
+
|
158
|
+
_handleGroupChange: (e)->
|
159
|
+
e.stopPropagation()
|
160
|
+
|
161
|
+
_getFocusedField: ->
|
162
|
+
@el.find("input:focus")
|
163
|
+
|
164
|
+
_beginSelectAll: ->
|
165
|
+
unless @el.hasClass('selecting-all')
|
166
|
+
@_state.lastGrouping = @options.groupings
|
167
|
+
@_state.lastLength = @getValue().length
|
168
|
+
@setGroupings(@optDefaults.groupings)
|
169
|
+
@el.addClass('selecting-all')
|
170
|
+
fieldEl = @el.find("input")
|
171
|
+
fieldEl[0].setSelectionRange(0, fieldEl.val().length)
|
172
|
+
@_state.selectingAll = true
|
173
|
+
else
|
174
|
+
fieldEl = @el.find("input")
|
175
|
+
fieldEl[0].setSelectionRange(0, fieldEl.val().length)
|
176
|
+
|
177
|
+
_endSelectAll: ->
|
178
|
+
if @el.hasClass('selecting-all')
|
179
|
+
# if the value hasn't been changed while selecting all, restore grouping
|
180
|
+
@_state.selectingAll = false
|
181
|
+
# restore groupings if length is the same
|
182
|
+
if @_state.lastLength is @getValue().length
|
183
|
+
@setGroupings(@_state.lastGrouping)
|
184
|
+
@el.removeClass('selecting-all')
|
185
|
+
|
186
|
+
# figure out what position in the overall value we're at given a selection
|
187
|
+
_indexInValueAtFieldSelection: (field)->
|
188
|
+
groupingIndex = @el.find('input').index(field)
|
189
|
+
offset = 0
|
190
|
+
offset += len for len, i in @options.groupings when i < groupingIndex
|
191
|
+
return offset + field[0].selectionEnd
|
192
|
+
|
193
|
+
setGroupings: (groupings, dontFocus)->
|
194
|
+
# store the value and current caret position so we can reapply it
|
195
|
+
_currentField = @_getFocusedField()
|
196
|
+
_value = @getValue()
|
197
|
+
_caretPosition = 0
|
198
|
+
if _currentField.length > 0
|
199
|
+
_caretPosition = @_indexInValueAtFieldSelection(_currentField)
|
200
|
+
# remove any existing input elements
|
201
|
+
@el.empty() # remove all existing inputs
|
202
|
+
for groupLength in groupings
|
203
|
+
groupEl = $("<input>").attr
|
204
|
+
type: 'text'
|
205
|
+
pattern: '[0-9]*'
|
206
|
+
size: groupLength
|
207
|
+
maxlength: groupLength
|
208
|
+
class: "group#{groupLength}"
|
209
|
+
placeholder: new Array(groupLength+1).join(@options.placeholderChar)
|
210
|
+
@el.append(groupEl)
|
211
|
+
@options.groupings = groupings
|
212
|
+
@setValue(_value)
|
213
|
+
_currentField = @_focusFieldForValue([_caretPosition, _caretPosition], dontFocus)
|
214
|
+
if _currentField? and _currentField[0].selectionEnd is _currentField[0].maxLength
|
215
|
+
@_focusField(_currentField.next(), 'start')
|
216
|
+
|
217
|
+
_focusFieldForValue: (place, dontFocus)->
|
218
|
+
value = @getValue()
|
219
|
+
if place is 'start'
|
220
|
+
field = @el.find('input').first()
|
221
|
+
@_focusField(field, place) unless dontFocus
|
222
|
+
else if place is 'end'
|
223
|
+
field = @el.find('input').last()
|
224
|
+
@_focusField(field, place) unless dontFocus
|
225
|
+
else
|
226
|
+
field = null
|
227
|
+
fieldOffset = null
|
228
|
+
_lastStartPos = 0
|
229
|
+
for groupLength, groupIndex in @options.groupings
|
230
|
+
if place[1] > _lastStartPos and place[1] <= _lastStartPos + groupLength
|
231
|
+
field = $(@el.find('input')[groupIndex])
|
232
|
+
fieldPosition = place[1] - _lastStartPos
|
233
|
+
_lastStartPos += groupLength
|
234
|
+
if field? and fieldPosition?
|
235
|
+
@_focusField(field, [fieldPosition, fieldPosition]) unless dontFocus
|
236
|
+
else
|
237
|
+
@_focusField(@el.find('input'), 'end') unless dontFocus
|
238
|
+
return field
|
239
|
+
|
240
|
+
_focusField: (field, place)->
|
241
|
+
if field.length isnt 0
|
242
|
+
field[0].focus()
|
243
|
+
if $(field[0]).is(':visible') and field[0] is document.activeElement
|
244
|
+
if place is 'start'
|
245
|
+
field[0].setSelectionRange(0, 0)
|
246
|
+
else if place is 'end'
|
247
|
+
fieldLen = field[0].maxLength
|
248
|
+
field[0].setSelectionRange(fieldLen, fieldLen)
|
249
|
+
else # array of start, end
|
250
|
+
field[0].setSelectionRange(place[0], place[1])
|
251
|
+
|
252
|
+
setValue: (newValue)->
|
253
|
+
_lastStartPos = 0
|
254
|
+
for groupLength, groupIndex in @options.groupings
|
255
|
+
el = $(@el.find('input').get(groupIndex))
|
256
|
+
groupVal = newValue.substr(_lastStartPos, groupLength)
|
257
|
+
el.val(groupVal)
|
258
|
+
_lastStartPos += groupLength
|
259
|
+
|
260
|
+
getValue: ->
|
261
|
+
buffer = ""
|
262
|
+
buffer += $(el).val() for el in @el.find('input')
|
263
|
+
return buffer
|
264
|
+
|
265
|
+
maxLength: ->
|
266
|
+
@options.groupings.reduce((a,b)->(a+b))
|
267
|
+
|
268
|
+
bind: (args...)->
|
269
|
+
@el.bind(args...)
|
270
|
+
|
271
|
+
trigger: (args...)->
|
272
|
+
@el.trigger(args...)
|
273
|
+
|
274
|
+
show: ->
|
275
|
+
@el.show()
|
276
|
+
|
277
|
+
hide: ->
|
278
|
+
@el.hide()
|
279
|
+
|
280
|
+
addClass: (args...)->
|
281
|
+
@el.addClass(args...)
|
282
|
+
|
283
|
+
removeClass: (args...)->
|
284
|
+
@el.removeClass(args...)
|