fustrate-rails 0.3.3 → 0.4.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/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()
|