fustrate-rails 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fustrate/rails/version.rb +1 -1
- data/vendor/assets/javascripts/fustrate/_module.coffee +14 -8
- data/vendor/assets/javascripts/fustrate/components/autocomplete.coffee +4 -4
- data/vendor/assets/javascripts/fustrate/components/file_picker.coffee +1 -0
- data/vendor/assets/javascripts/fustrate/components/flash.coffee +4 -4
- data/vendor/assets/javascripts/fustrate/components/modal.coffee +79 -19
- data/vendor/assets/javascripts/fustrate/components/pagination.coffee +5 -5
- data/vendor/assets/javascripts/fustrate/generic_form.coffee +4 -5
- data/vendor/assets/javascripts/fustrate/generic_page.coffee +6 -6
- data/vendor/assets/javascripts/fustrate/generic_table.coffee +2 -2
- data/vendor/assets/javascripts/fustrate/listenable.coffee +1 -1
- data/vendor/assets/stylesheets/_fustrate.sass +6 -6
- data/vendor/assets/stylesheets/awesomplete.sass +2 -1
- data/vendor/assets/stylesheets/fustrate/_colors.sass +3 -0
- data/vendor/assets/stylesheets/fustrate/_settings.sass +7 -7
- data/vendor/assets/stylesheets/fustrate/components/_components.sass +17 -17
- data/vendor/assets/stylesheets/fustrate/components/_functions.sass +9 -8
- data/vendor/assets/stylesheets/fustrate/components/alerts.sass +26 -18
- data/vendor/assets/stylesheets/fustrate/components/buttons.sass +17 -21
- data/vendor/assets/stylesheets/fustrate/components/disclosures.sass +5 -5
- data/vendor/assets/stylesheets/fustrate/components/dropdowns.sass +24 -19
- data/vendor/assets/stylesheets/fustrate/components/flash.sass +21 -16
- data/vendor/assets/stylesheets/fustrate/components/forms.sass +99 -92
- data/vendor/assets/stylesheets/fustrate/components/grid.sass +15 -23
- data/vendor/assets/stylesheets/fustrate/components/labels.sass +13 -12
- data/vendor/assets/stylesheets/fustrate/components/modals.sass +97 -49
- data/vendor/assets/stylesheets/fustrate/components/pagination.sass +41 -29
- data/vendor/assets/stylesheets/fustrate/components/panels.sass +30 -12
- data/vendor/assets/stylesheets/fustrate/components/popovers.sass +10 -6
- data/vendor/assets/stylesheets/fustrate/components/tables.sass +13 -9
- data/vendor/assets/stylesheets/fustrate/components/tabs.sass +6 -6
- data/vendor/assets/stylesheets/fustrate/components/tooltips.sass +12 -12
- data/vendor/assets/stylesheets/fustrate/components/typography.sass +140 -104
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df054189ffa1878cc1b2315846a917e969a48c5b
|
4
|
+
data.tar.gz: 2f958a0fa3e5e527a30e4550ca5263b7ba19c722
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2277809e67752f86598ae25edf26f0fc57158cc9a05d9d8fb12f65d1d2f1fab32b8e0476fd23840eae8396a9e986231228550437b4ac7d109f4e9872535fa3e9
|
7
|
+
data.tar.gz: 5262aaf6879f964a5f508105680921f4f273cf3838685225a5331509901c923136de021b35d3ea550cdbf23be82abb3d3f05bf1c3e3743b134ae9d4514202778
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#= require_tree .
|
4
4
|
|
5
5
|
class window.Fustrate
|
6
|
-
@VERSION: '0.
|
6
|
+
@VERSION: '0.4.0'
|
7
7
|
@libs: {}
|
8
8
|
|
9
9
|
constructor: ->
|
@@ -15,6 +15,9 @@ class window.Fustrate
|
|
15
15
|
@initialize()
|
16
16
|
|
17
17
|
initialize: ->
|
18
|
+
# Loop through every element on the page with a data-js-class attribute
|
19
|
+
# and convert the data attribute's value to a real object. Then instantiate
|
20
|
+
# a new object of that class.
|
18
21
|
$('[data-js-class]').each (index, elem) ->
|
19
22
|
element = $(elem)
|
20
23
|
klass = Fustrate._stringToClass element.data('js-class')
|
@@ -30,24 +33,26 @@ class window.Fustrate
|
|
30
33
|
$('.number').each (index, elem) ->
|
31
34
|
elem = $ @
|
32
35
|
|
33
|
-
number = if elem.data('number')
|
36
|
+
number = if elem.data('number') isnt undefined
|
34
37
|
elem.data('number')
|
35
38
|
else
|
36
39
|
elem.html()
|
37
40
|
|
38
41
|
elem.addClass 'negative' if parseInt(number, 10) < 0
|
39
42
|
|
43
|
+
# Take a string like 'Asgard.Whiteboard.Entry' and retrieve the real class
|
44
|
+
# with that name. Start at `window` and work down from there.
|
40
45
|
@_stringToClass: (string) ->
|
41
46
|
pieces = string.split('.')
|
42
47
|
|
43
48
|
Fustrate._arrayToClass(pieces, window)
|
44
49
|
|
45
50
|
@_arrayToClass: (pieces, root) ->
|
46
|
-
if pieces.length
|
47
|
-
|
48
|
-
|
49
|
-
Fustrate._arrayToClass pieces.slice(1), root[pieces[0]]
|
51
|
+
return root[pieces[0]] if pieces.length is 1
|
52
|
+
|
53
|
+
Fustrate._arrayToClass pieces.slice(1), root[pieces[0]]
|
50
54
|
|
55
|
+
# Very similar to the Rails helper `link_to`. Returns an HTML string.
|
51
56
|
@linkTo: (text, path, options = {}) ->
|
52
57
|
$('<a>').prop('href', path).html(text).prop(options).outerHTML()
|
53
58
|
|
@@ -67,13 +72,13 @@ class window.Fustrate
|
|
67
72
|
$.rails.CSRFProtection xhr
|
68
73
|
|
69
74
|
@humanDate: (date, time = false) ->
|
70
|
-
if date.year()
|
75
|
+
if date.year() is moment().year()
|
71
76
|
date.format("M/D#{if time then ' h:mm A' else ''}")
|
72
77
|
else
|
73
78
|
date.format("M/D/YY#{if time then ' h:mm A' else ''}")
|
74
79
|
|
75
80
|
@label: (text, type) ->
|
76
|
-
type = if type then "#{type} " else
|
81
|
+
type = if type then "#{type} " else ''
|
77
82
|
|
78
83
|
$('<span>')
|
79
84
|
.text(text)
|
@@ -84,6 +89,7 @@ class window.Fustrate
|
|
84
89
|
|
85
90
|
"<i class=\"fa #{classes}\"></i>"
|
86
91
|
|
92
|
+
# Replicate a few common prototype methods on String and Array
|
87
93
|
String::titleize = ->
|
88
94
|
@replace(/_/g, ' ').replace /\b[a-z]/g, (char) -> char.toUpperCase()
|
89
95
|
|
@@ -43,7 +43,7 @@ class Fustrate.Components.Autocomplete extends Fustrate.Components.Base
|
|
43
43
|
.on 'focus', @onFocus
|
44
44
|
|
45
45
|
blanked: =>
|
46
|
-
return unless @input.val().trim()
|
46
|
+
return unless @input.val().trim() is ''
|
47
47
|
|
48
48
|
@awesomplete.close()
|
49
49
|
|
@@ -90,17 +90,17 @@ class Fustrate.Components.Autocomplete extends Fustrate.Components.Base
|
|
90
90
|
false
|
91
91
|
|
92
92
|
onKeyup: (e) =>
|
93
|
-
keyCode = e.which
|
93
|
+
keyCode = e.which or e.keyCode
|
94
94
|
|
95
95
|
value = @input.val().trim()
|
96
96
|
|
97
|
-
return @blanked() if value
|
97
|
+
return @blanked() if value is ''
|
98
98
|
|
99
99
|
# Ignore: Tab, Enter, Esc, Left, Up, Right, Down
|
100
100
|
return if keyCode in [9, 13, 27, 37, 38, 39, 40]
|
101
101
|
|
102
102
|
# Don't perform the same search twice in a row
|
103
|
-
return unless value
|
103
|
+
return unless value isnt @value and value.length >= 2
|
104
104
|
|
105
105
|
@value = value
|
106
106
|
@items = []
|
@@ -3,7 +3,7 @@ class Fustrate.Components.Flash extends Fustrate.Components.Base
|
|
3
3
|
@fadeOutSpeed: 2000
|
4
4
|
@displayTime: 4000
|
5
5
|
|
6
|
-
constructor: (message, {type, icon} = {}) ->
|
6
|
+
constructor: (message, { type, icon } = {}) ->
|
7
7
|
message = "#{Fustrate.icon(icon)} #{message}" if icon
|
8
8
|
|
9
9
|
bar = $ "<div class=\"flash #{type ? 'info'}\"></div>"
|
@@ -19,13 +19,13 @@ class Fustrate.Components.Flash extends Fustrate.Components.Base
|
|
19
19
|
$('body').append '<div id="flashes">'
|
20
20
|
|
21
21
|
class @Error
|
22
|
-
constructor: (message, {icon} = {}) ->
|
22
|
+
constructor: (message, { icon } = {}) ->
|
23
23
|
new Fustrate.Components.Flash message, type: 'error', icon: icon
|
24
24
|
|
25
25
|
class @Info
|
26
|
-
constructor: (message, {icon} = {}) ->
|
26
|
+
constructor: (message, { icon } = {}) ->
|
27
27
|
new Fustrate.Components.Flash message, type: 'info', icon: icon
|
28
28
|
|
29
29
|
class @Success
|
30
|
-
constructor: (message, {icon} = {}) ->
|
30
|
+
constructor: (message, { icon } = {}) ->
|
31
31
|
new Fustrate.Components.Flash message, type: 'success', icon: icon
|
@@ -1,4 +1,10 @@
|
|
1
1
|
class Fustrate.Components.Modal extends Fustrate.Components.Base
|
2
|
+
@size: 'tiny'
|
3
|
+
@type: null
|
4
|
+
@icon: null
|
5
|
+
@title: null
|
6
|
+
@buttons: []
|
7
|
+
|
2
8
|
@fadeSpeed: 250
|
3
9
|
|
4
10
|
@settings:
|
@@ -16,13 +22,14 @@ class Fustrate.Components.Modal extends Fustrate.Components.Base
|
|
16
22
|
display: 'none'
|
17
23
|
_cachedHeight: undefined
|
18
24
|
|
19
|
-
constructor: ({
|
20
|
-
@modal = @constructor.createModal
|
25
|
+
constructor: ({ content, settings } = {}) ->
|
26
|
+
@modal = @constructor.createModal()
|
21
27
|
@settings = $.extend true, @constructor.settings, (settings ? {})
|
22
28
|
@settings.previousModal = $()
|
23
29
|
|
24
|
-
@setTitle title
|
25
|
-
@setContent content
|
30
|
+
@setTitle @constructor.title, icon: @constructor.icon
|
31
|
+
@setContent content, false
|
32
|
+
@setButtons @constructor.buttons, false
|
26
33
|
|
27
34
|
@_reloadUIElements()
|
28
35
|
@addEventListeners()
|
@@ -44,15 +51,64 @@ class Fustrate.Components.Modal extends Fustrate.Components.Base
|
|
44
51
|
button = $ element
|
45
52
|
@buttons[button.data('button')] = button
|
46
53
|
|
47
|
-
setTitle: (title) =>
|
48
|
-
|
54
|
+
setTitle: (title, { icon } = {}) =>
|
55
|
+
if icon
|
56
|
+
$('.modal-title span', @modal).html "#{Fustrate.icon icon} #{title}"
|
57
|
+
else if @constructor.icon and icon isnt false
|
58
|
+
$('.modal-title span', @modal)
|
59
|
+
.html "#{Fustrate.icon @constructor.icon} #{title}"
|
60
|
+
else
|
61
|
+
$('.modal-title span', @modal).html title
|
49
62
|
|
50
|
-
setContent: (content) =>
|
63
|
+
setContent: (content, reload = true) =>
|
51
64
|
$('.modal-content', @modal).html content
|
52
65
|
|
53
66
|
@settings._cachedHeight = undefined
|
54
67
|
|
55
|
-
@_reloadUIElements()
|
68
|
+
@_reloadUIElements() if reload
|
69
|
+
|
70
|
+
setButtons: (buttons, reload = true) =>
|
71
|
+
if buttons?.length < 1
|
72
|
+
$('.modal-buttons', @modal).empty()
|
73
|
+
|
74
|
+
return
|
75
|
+
|
76
|
+
list = []
|
77
|
+
|
78
|
+
for button in buttons
|
79
|
+
if typeof button is 'string'
|
80
|
+
list.push """
|
81
|
+
<button data-button="#{button}" class="#{button} expand">
|
82
|
+
#{button.titleize()}
|
83
|
+
</button>"""
|
84
|
+
else if typeof button is 'object'
|
85
|
+
for name, options of button
|
86
|
+
if typeof options is 'object'
|
87
|
+
text = options.text
|
88
|
+
else if typeof options is 'string'
|
89
|
+
text = options
|
90
|
+
|
91
|
+
text ?= name.titleize()
|
92
|
+
|
93
|
+
list.push(
|
94
|
+
$("<button data-button=\"#{name}\" class=\"expand\">")
|
95
|
+
.text(text)
|
96
|
+
.addClass(options.type ? name)
|
97
|
+
.outerHTML()
|
98
|
+
)
|
99
|
+
|
100
|
+
columns = list.map (button) -> "<div class=\"columns\">#{button}</div>"
|
101
|
+
|
102
|
+
$('.modal-buttons', @modal)
|
103
|
+
.empty()
|
104
|
+
.html "<div class=\"row\">#{columns.join('')}</div>"
|
105
|
+
|
106
|
+
$('.modal-buttons .row .columns', @modal)
|
107
|
+
.addClass("large-#{12 / columns.length}")
|
108
|
+
|
109
|
+
@settings._cachedHeight = undefined
|
110
|
+
|
111
|
+
@_reloadUIElements() if reload
|
56
112
|
|
57
113
|
addEventListeners: =>
|
58
114
|
@modal
|
@@ -73,13 +129,13 @@ class Fustrate.Components.Modal extends Fustrate.Components.Base
|
|
73
129
|
# Focus requires a slight physical scroll on iOS 8.4
|
74
130
|
return true if /iPad|iPhone|iPod/g.test navigator.userAgent
|
75
131
|
|
76
|
-
$('input, select', @modal)
|
132
|
+
$('input, select, textarea', @modal)
|
77
133
|
.filter(':visible:not(:disabled):not([readonly])')
|
78
134
|
.first()
|
79
135
|
.focus()
|
80
136
|
|
81
137
|
open: =>
|
82
|
-
return if @modal.hasClass('locked')
|
138
|
+
return if @modal.hasClass('locked') or @modal.hasClass('open')
|
83
139
|
|
84
140
|
@modal.addClass('locked')
|
85
141
|
|
@@ -91,13 +147,13 @@ class Fustrate.Components.Modal extends Fustrate.Components.Base
|
|
91
147
|
$('body')
|
92
148
|
.off 'keyup.modal'
|
93
149
|
.on 'keyup.modal', (e) =>
|
94
|
-
return if @modal.hasClass('locked')
|
150
|
+
return if @modal.hasClass('locked') or e.which isnt 27
|
95
151
|
|
96
152
|
@close()
|
97
153
|
|
98
154
|
@modal.trigger 'opening.modal'
|
99
155
|
|
100
|
-
@_cacheHeight() if typeof @settings._cachedHeight
|
156
|
+
@_cacheHeight() if typeof @settings._cachedHeight is 'undefined'
|
101
157
|
|
102
158
|
if @settings.previousModal.length
|
103
159
|
@settings.previousModal.trigger('hide.modal')
|
@@ -123,17 +179,17 @@ class Fustrate.Components.Modal extends Fustrate.Components.Base
|
|
123
179
|
), 125
|
124
180
|
|
125
181
|
close: (openPrevious = true) =>
|
126
|
-
return if @modal.hasClass('locked')
|
182
|
+
return if @modal.hasClass('locked') or not @modal.hasClass('open')
|
127
183
|
|
128
184
|
@modal.addClass 'locked'
|
129
185
|
|
130
186
|
$('body').off 'keyup.modal'
|
131
187
|
|
132
|
-
unless @settings.previousModal.length
|
188
|
+
unless @settings.previousModal.length and openPrevious
|
133
189
|
@constructor.toggleBackground(false)
|
134
190
|
|
135
191
|
end_css =
|
136
|
-
top:
|
192
|
+
top: -$(window).scrollTop() - @settings._cachedHeight + 'px',
|
137
193
|
opacity: 0
|
138
194
|
|
139
195
|
setTimeout (=>
|
@@ -166,16 +222,20 @@ class Fustrate.Components.Modal extends Fustrate.Components.Base
|
|
166
222
|
|
167
223
|
@modal.hide()
|
168
224
|
|
169
|
-
@createModal:
|
225
|
+
@createModal: ->
|
170
226
|
$("""
|
171
|
-
<div class="
|
227
|
+
<div class="#{@_defaultClasses().join(' ')}">
|
172
228
|
<div class="modal-title">
|
173
229
|
<span></span>
|
174
230
|
<a href="#" class="modal-close">×</a>
|
175
231
|
</div>
|
176
232
|
<div class="modal-content"></div>
|
233
|
+
<div class="modal-buttons"></div>
|
177
234
|
</div>""").appendTo(@settings.appendTo)
|
178
235
|
|
236
|
+
@_defaultClasses: ->
|
237
|
+
['modal', @size, @type].filter (klass) -> klass isnt null
|
238
|
+
|
179
239
|
@toggleBackground: (visible = true) =>
|
180
240
|
@overlay = $ '<div class="modal-overlay">' unless @overlay
|
181
241
|
|
@@ -194,7 +254,7 @@ class Fustrate.Components.Modal extends Fustrate.Components.Base
|
|
194
254
|
@backgroundClicked: ->
|
195
255
|
modal = $ '.modal.open'
|
196
256
|
|
197
|
-
return if
|
257
|
+
return if not modal or modal.hasClass('locked')
|
198
258
|
|
199
259
|
# Don't continue to close if we're not supposed to
|
200
260
|
return unless Fustrate.Components.Modal.settings.closeOnBackgroundClick
|
@@ -206,7 +266,7 @@ class Fustrate.Components.Modal extends Fustrate.Components.Base
|
|
206
266
|
@closeButtonClicked: ->
|
207
267
|
modal = $ '.modal.open'
|
208
268
|
|
209
|
-
return if
|
269
|
+
return if not modal or modal.hasClass('locked')
|
210
270
|
|
211
271
|
modal.trigger 'close.modal'
|
212
272
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Fustrate.Components.Pagination extends Fustrate.Components.Base
|
2
|
-
constructor: ({@current_page, @total_pages, @total_entries, @per_page}) ->
|
2
|
+
constructor: ({ @current_page, @total_pages, @total_entries, @per_page }) ->
|
3
3
|
@base = @constructor._getPreppedPaginationURL()
|
4
4
|
|
5
5
|
link: (text, page, options = {}) =>
|
@@ -28,9 +28,9 @@ class Fustrate.Components.Pagination extends Fustrate.Components.Base
|
|
28
28
|
|
29
29
|
if @total_pages > 1
|
30
30
|
pages = for i in @windowedPageNumbers()
|
31
|
-
if i
|
31
|
+
if i is @current_page
|
32
32
|
"<li class=\"current\">#{Fustrate.linkTo(i, '#')}</li>"
|
33
|
-
else if i
|
33
|
+
else if i is 'gap'
|
34
34
|
'<li class="unavailable"><span class="gap">…</span></li>'
|
35
35
|
else
|
36
36
|
"<li>#{@link i, i}</li>"
|
@@ -74,9 +74,9 @@ class Fustrate.Components.Pagination extends Fustrate.Components.Base
|
|
74
74
|
@_getPreppedPaginationURL: ->
|
75
75
|
search = window.location.search.replace(/[?&]page=\d+/, '')
|
76
76
|
|
77
|
-
search = if search[0]
|
77
|
+
search = if search[0] is '?'
|
78
78
|
"#{search}&"
|
79
|
-
else if search[0]
|
79
|
+
else if search[0] is '&'
|
80
80
|
"?#{search[1...search.length]}&"
|
81
81
|
else
|
82
82
|
'?'
|
@@ -21,11 +21,10 @@ class Fustrate.GenericForm extends Fustrate.GenericPage
|
|
21
21
|
validate: -> true
|
22
22
|
|
23
23
|
onSubmit: (e) =>
|
24
|
-
|
24
|
+
return true if @validate()
|
25
25
|
|
26
|
-
|
27
|
-
setTimeout (=> $.rails.enableFormElements(@root)), 100
|
26
|
+
e.preventDefault()
|
28
27
|
|
29
|
-
|
28
|
+
setTimeout (=> $.rails.enableFormElements(@root)), 100
|
30
29
|
|
31
|
-
|
30
|
+
false
|
@@ -14,21 +14,21 @@ class Fustrate.GenericPage
|
|
14
14
|
@fields = {}
|
15
15
|
@buttons = {}
|
16
16
|
|
17
|
-
$('[data-field]', @root).each (
|
17
|
+
$('[data-field]', @root).not('.modal [data-field]').each (i, element) =>
|
18
18
|
field = $ element
|
19
19
|
@fields[field.data('field')] = field
|
20
20
|
|
21
|
-
$('[data-button]', @root).each (
|
21
|
+
$('[data-button]', @root).not('.modal [data-button]').each (i, element) =>
|
22
22
|
button = $ element
|
23
23
|
@buttons[button.data('button')] = button
|
24
24
|
|
25
|
-
flashSuccess: (message, {icon} = {}) ->
|
25
|
+
flashSuccess: (message, { icon } = {}) ->
|
26
26
|
new Fustrate.Components.Flash.Success(message, icon: icon)
|
27
27
|
|
28
|
-
flashError: (message, {icon} = {}) ->
|
28
|
+
flashError: (message, { icon } = {}) ->
|
29
29
|
new Fustrate.Components.Flash.Error(message, icon: icon)
|
30
30
|
|
31
|
-
flashInfo: (message, {icon} = {}) ->
|
31
|
+
flashInfo: (message, { icon } = {}) ->
|
32
32
|
new Fustrate.Components.Flash.Info(message, icon: icon)
|
33
33
|
|
34
34
|
setHeader: (text) ->
|
@@ -37,4 +37,4 @@ class Fustrate.GenericPage
|
|
37
37
|
# Calls all methods matching /refresh.+/
|
38
38
|
refresh: =>
|
39
39
|
for own name, func of @
|
40
|
-
func() if name.indexOf('refresh')
|
40
|
+
func() if name.indexOf('refresh') is 0 and name isnt 'refresh'
|
@@ -12,7 +12,7 @@ class Fustrate.GenericTable extends Fustrate.GenericPage
|
|
12
12
|
sortRows: (rows, sortFunction = ->) ->
|
13
13
|
sorted = ([sortFunction(row), row] for row in rows)
|
14
14
|
sorted.sort (x, y) ->
|
15
|
-
if x[0]
|
15
|
+
if x[0] is y[0] then 0 else if x[0] > y[0] then 1 else -1
|
16
16
|
sorted.map (row) -> row[1]
|
17
17
|
|
18
18
|
createRow: (item) =>
|
@@ -21,7 +21,7 @@ class Fustrate.GenericTable extends Fustrate.GenericPage
|
|
21
21
|
updateRow: (row, item) ->
|
22
22
|
row
|
23
23
|
|
24
|
-
reloadRows: (rows, {sort} = { sort: null }) =>
|
24
|
+
reloadRows: (rows, { sort } = { sort: null }) =>
|
25
25
|
tbody = $ 'tbody', @table
|
26
26
|
|
27
27
|
$('tr.loading', tbody).hide()
|