fustrate-rails 0.4.1 → 0.10.1
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 +5 -5
- data/config/initializers/jbuilder.rb +13 -0
- data/config/initializers/renderers.rb +40 -0
- data/config/initializers/sanitize.rb +112 -0
- data/config/rubocop/default.yml +96 -0
- data/config/rubocop/rails.yml +22 -0
- data/lib/fustrate/rails/concerns/clean_attributes.rb +49 -0
- data/lib/fustrate/rails/concerns/model.rb +48 -0
- data/lib/fustrate/rails/concerns/sanitize_html.rb +34 -0
- data/lib/fustrate/rails/engine.rb +14 -7
- data/lib/fustrate/rails/services/base.rb +46 -0
- data/lib/fustrate/rails/services/generate_csv.rb +35 -0
- data/lib/fustrate/rails/services/generate_excel.rb +32 -0
- data/lib/fustrate/rails/services/log_edit.rb +132 -0
- data/lib/fustrate/rails/spec_helper.rb +62 -0
- data/lib/fustrate/rails/version.rb +5 -1
- data/lib/fustrate-rails.rb +5 -2
- metadata +44 -140
- data/vendor/assets/javascripts/awesomplete.js +0 -402
- data/vendor/assets/javascripts/fustrate/_module.coffee +0 -140
- data/vendor/assets/javascripts/fustrate/components/_module.coffee +0 -3
- data/vendor/assets/javascripts/fustrate/components/alert_box.coffee +0 -10
- data/vendor/assets/javascripts/fustrate/components/autocomplete.coffee +0 -161
- data/vendor/assets/javascripts/fustrate/components/disclosure.coffee +0 -12
- data/vendor/assets/javascripts/fustrate/components/drop_zone.coffee +0 -9
- data/vendor/assets/javascripts/fustrate/components/dropdown.coffee +0 -48
- data/vendor/assets/javascripts/fustrate/components/file_picker.coffee +0 -11
- data/vendor/assets/javascripts/fustrate/components/flash.coffee +0 -31
- data/vendor/assets/javascripts/fustrate/components/modal.coffee +0 -273
- data/vendor/assets/javascripts/fustrate/components/pagination.coffee +0 -84
- data/vendor/assets/javascripts/fustrate/components/tabs.coffee +0 -28
- data/vendor/assets/javascripts/fustrate/components/tooltip.coffee +0 -72
- data/vendor/assets/javascripts/fustrate/generic_form.coffee +0 -30
- data/vendor/assets/javascripts/fustrate/generic_page.coffee +0 -40
- data/vendor/assets/javascripts/fustrate/generic_table.coffee +0 -57
- data/vendor/assets/javascripts/fustrate/listenable.coffee +0 -25
- data/vendor/assets/javascripts/fustrate/object.coffee +0 -21
- data/vendor/assets/javascripts/fustrate/record.coffee +0 -23
- data/vendor/assets/javascripts/fustrate.coffee +0 -6
- data/vendor/assets/stylesheets/_fustrate.sass +0 -7
- data/vendor/assets/stylesheets/awesomplete.sass +0 -76
- data/vendor/assets/stylesheets/fustrate/_colors.sass +0 -12
- data/vendor/assets/stylesheets/fustrate/_settings.sass +0 -20
- data/vendor/assets/stylesheets/fustrate/components/_components.sass +0 -36
- data/vendor/assets/stylesheets/fustrate/components/_functions.sass +0 -41
- data/vendor/assets/stylesheets/fustrate/components/alerts.sass +0 -86
- data/vendor/assets/stylesheets/fustrate/components/buttons.sass +0 -99
- data/vendor/assets/stylesheets/fustrate/components/disclosures.sass +0 -23
- data/vendor/assets/stylesheets/fustrate/components/dropdowns.sass +0 -36
- data/vendor/assets/stylesheets/fustrate/components/flash.sass +0 -38
- data/vendor/assets/stylesheets/fustrate/components/forms.sass +0 -195
- data/vendor/assets/stylesheets/fustrate/components/grid.sass +0 -196
- data/vendor/assets/stylesheets/fustrate/components/labels.sass +0 -64
- data/vendor/assets/stylesheets/fustrate/components/modals.sass +0 -167
- data/vendor/assets/stylesheets/fustrate/components/pagination.sass +0 -69
- data/vendor/assets/stylesheets/fustrate/components/panels.sass +0 -67
- data/vendor/assets/stylesheets/fustrate/components/popovers.sass +0 -19
- data/vendor/assets/stylesheets/fustrate/components/tables.sass +0 -62
- data/vendor/assets/stylesheets/fustrate/components/tabs.sass +0 -44
- data/vendor/assets/stylesheets/fustrate/components/tooltips.sass +0 -28
- data/vendor/assets/stylesheets/fustrate/components/typography.sass +0 -391
@@ -1,12 +0,0 @@
|
|
1
|
-
class Fustrate.Components.Disclosure extends Fustrate.Components.Base
|
2
|
-
@initialize: ->
|
3
|
-
$('body').on 'click', '.disclosure-title', (event) ->
|
4
|
-
disclosure = $(event.currentTarget).closest('.disclosure')
|
5
|
-
|
6
|
-
isOpen = disclosure.hasClass 'open'
|
7
|
-
|
8
|
-
disclosure
|
9
|
-
.toggleClass 'open'
|
10
|
-
.trigger "#{if isOpen then 'closed' else 'opened'}.disclosure"
|
11
|
-
|
12
|
-
false
|
@@ -1,9 +0,0 @@
|
|
1
|
-
class Fustrate.Components.DropZone extends Fustrate.Components.Base
|
2
|
-
constructor: (target, callback) ->
|
3
|
-
$(target)
|
4
|
-
.off '.drop_zone'
|
5
|
-
.on 'dragover.drop_zone dragenter.drop_zone', false
|
6
|
-
.on 'drop.drop_zone', (event) ->
|
7
|
-
callback event.originalEvent.dataTransfer.files
|
8
|
-
|
9
|
-
false
|
@@ -1,48 +0,0 @@
|
|
1
|
-
class Fustrate.Components.Dropdown extends Fustrate.Components.Base
|
2
|
-
@locked: false
|
3
|
-
|
4
|
-
@initialize: ->
|
5
|
-
@body = $ 'body'
|
6
|
-
|
7
|
-
@body.on 'click.dropdowns', '.has-dropdown', @open
|
8
|
-
|
9
|
-
@open: (event) =>
|
10
|
-
@hide()
|
11
|
-
|
12
|
-
button = $ event.currentTarget
|
13
|
-
dropdown = $ '+ .dropdown', button
|
14
|
-
|
15
|
-
@locked = true
|
16
|
-
|
17
|
-
if button.position().top > (@body.height() / 2)
|
18
|
-
top = button.position().top - dropdown.outerHeight() - 2
|
19
|
-
else
|
20
|
-
top = button.position().top + button.outerHeight() + 2
|
21
|
-
|
22
|
-
if button.position().left > (@body.width() / 2)
|
23
|
-
left = 'inherit'
|
24
|
-
right = @body.width() - button.position().left - button.outerWidth()
|
25
|
-
else
|
26
|
-
right = 'inherit'
|
27
|
-
left = button.position().left
|
28
|
-
|
29
|
-
@showDropdown dropdown, left: left, top: top, right: right
|
30
|
-
|
31
|
-
false
|
32
|
-
|
33
|
-
@showDropdown: (dropdown, css) ->
|
34
|
-
dropdown
|
35
|
-
.addClass 'visible'
|
36
|
-
.hide()
|
37
|
-
.css css
|
38
|
-
.fadeIn 200, =>
|
39
|
-
@locked = false
|
40
|
-
|
41
|
-
@body.one 'click', @hide
|
42
|
-
|
43
|
-
@hide: =>
|
44
|
-
return if @locked
|
45
|
-
|
46
|
-
$('.dropdown.visible')
|
47
|
-
.removeClass 'visible'
|
48
|
-
.fadeOut 200
|
@@ -1,31 +0,0 @@
|
|
1
|
-
class Fustrate.Components.Flash extends Fustrate.Components.Base
|
2
|
-
@fadeInSpeed: 500
|
3
|
-
@fadeOutSpeed: 2000
|
4
|
-
@displayTime: 4000
|
5
|
-
|
6
|
-
constructor: (message, { type, icon } = {}) ->
|
7
|
-
message = "#{Fustrate.icon(icon)} #{message}" if icon
|
8
|
-
|
9
|
-
bar = $ "<div class=\"flash #{type ? 'info'}\"></div>"
|
10
|
-
.html message
|
11
|
-
.hide()
|
12
|
-
.prependTo $('#flashes')
|
13
|
-
.fadeIn @constructor.fadeInSpeed
|
14
|
-
.delay @constructor.displayTime
|
15
|
-
.fadeOut @constructor.fadeOutSpeed, ->
|
16
|
-
bar.remove()
|
17
|
-
|
18
|
-
@initialize: ->
|
19
|
-
$('body').append '<div id="flashes">'
|
20
|
-
|
21
|
-
class @Error
|
22
|
-
constructor: (message, { icon } = {}) ->
|
23
|
-
new Fustrate.Components.Flash message, type: 'error', icon: icon
|
24
|
-
|
25
|
-
class @Info
|
26
|
-
constructor: (message, { icon } = {}) ->
|
27
|
-
new Fustrate.Components.Flash message, type: 'info', icon: icon
|
28
|
-
|
29
|
-
class @Success
|
30
|
-
constructor: (message, { icon } = {}) ->
|
31
|
-
new Fustrate.Components.Flash message, type: 'success', icon: icon
|
@@ -1,273 +0,0 @@
|
|
1
|
-
class Fustrate.Components.Modal extends Fustrate.Components.Base
|
2
|
-
@size: 'tiny'
|
3
|
-
@type: null
|
4
|
-
@icon: null
|
5
|
-
@title: null
|
6
|
-
@buttons: []
|
7
|
-
|
8
|
-
@fadeSpeed: 250
|
9
|
-
|
10
|
-
@settings:
|
11
|
-
closeOnBackgroundClick: true
|
12
|
-
distanceFromTop: 25
|
13
|
-
appendTo: 'body'
|
14
|
-
css:
|
15
|
-
open:
|
16
|
-
opacity: 0
|
17
|
-
visibility: 'visible'
|
18
|
-
display: 'block'
|
19
|
-
close:
|
20
|
-
opacity: 1
|
21
|
-
visibility: 'hidden'
|
22
|
-
display: 'none'
|
23
|
-
_cachedHeight: undefined
|
24
|
-
|
25
|
-
constructor: ({ content, settings } = {}) ->
|
26
|
-
@modal = @constructor.createModal()
|
27
|
-
@settings = $.extend true, @constructor.settings, (settings ? {})
|
28
|
-
@settings.previousModal = $()
|
29
|
-
|
30
|
-
@setTitle @constructor.title, icon: @constructor.icon
|
31
|
-
@setContent content, false
|
32
|
-
@setButtons @constructor.buttons, false
|
33
|
-
|
34
|
-
@_reloadUIElements()
|
35
|
-
@addEventListeners()
|
36
|
-
@initialize()
|
37
|
-
|
38
|
-
super
|
39
|
-
|
40
|
-
initialize: ->
|
41
|
-
|
42
|
-
_reloadUIElements: =>
|
43
|
-
@fields = {}
|
44
|
-
@buttons = {}
|
45
|
-
|
46
|
-
$('[data-field]', @modal).each (index, element) =>
|
47
|
-
field = $ element
|
48
|
-
@fields[field.data('field')] = field
|
49
|
-
|
50
|
-
$('[data-button]', @modal).each (index, element) =>
|
51
|
-
button = $ element
|
52
|
-
@buttons[button.data('button')] = button
|
53
|
-
|
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
|
62
|
-
|
63
|
-
setContent: (content, reload = true) =>
|
64
|
-
$('.modal-content', @modal).html content
|
65
|
-
|
66
|
-
@settings._cachedHeight = undefined
|
67
|
-
|
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
|
112
|
-
|
113
|
-
addEventListeners: =>
|
114
|
-
@modal
|
115
|
-
.off '.modal'
|
116
|
-
.on 'close.modal', @close
|
117
|
-
.on 'open.modal', @open
|
118
|
-
.on 'hide.modal', @hide
|
119
|
-
.on 'opened.modal', @focusFirstInput
|
120
|
-
.on 'click.modal', '.modal-close', @constructor.closeButtonClicked
|
121
|
-
|
122
|
-
# TODO: Re-enable when modals are fully converted
|
123
|
-
# .off '.modal'
|
124
|
-
$(document).on 'click.modal touchstart.modal',
|
125
|
-
'.modal-overlay',
|
126
|
-
@constructor.backgroundClicked
|
127
|
-
|
128
|
-
focusFirstInput: =>
|
129
|
-
# Focus requires a slight physical scroll on iOS 8.4
|
130
|
-
return true if /iPad|iPhone|iPod/g.test navigator.userAgent
|
131
|
-
|
132
|
-
$('input, select, textarea', @modal)
|
133
|
-
.filter(':visible:not(:disabled):not([readonly])')
|
134
|
-
.first()
|
135
|
-
.focus()
|
136
|
-
|
137
|
-
open: =>
|
138
|
-
return if @modal.hasClass('locked') or @modal.hasClass('open')
|
139
|
-
|
140
|
-
@modal.addClass('locked')
|
141
|
-
|
142
|
-
# If there is currently a modal being shown, store it and re-open it when
|
143
|
-
# this modal closes.
|
144
|
-
@settings.previousModal = $('.modal.open')
|
145
|
-
|
146
|
-
# These events only matter when the modal is visible
|
147
|
-
$('body')
|
148
|
-
.off 'keyup.modal'
|
149
|
-
.on 'keyup.modal', (e) =>
|
150
|
-
return if @modal.hasClass('locked') or e.which isnt 27
|
151
|
-
|
152
|
-
@close()
|
153
|
-
|
154
|
-
@modal.trigger 'opening.modal'
|
155
|
-
|
156
|
-
@_cacheHeight() if typeof @settings._cachedHeight is 'undefined'
|
157
|
-
|
158
|
-
if @settings.previousModal.length
|
159
|
-
@settings.previousModal.trigger('hide.modal')
|
160
|
-
else
|
161
|
-
# There are no open modals - show the background overlay
|
162
|
-
@constructor.toggleBackground true
|
163
|
-
|
164
|
-
css = @settings.css.open
|
165
|
-
# css.top = parseInt @modal.css('top'), 10
|
166
|
-
|
167
|
-
css.top = $(window).scrollTop() - @settings._cachedHeight + 'px'
|
168
|
-
|
169
|
-
end_css =
|
170
|
-
top: $(window).scrollTop() + @settings.distanceFromTop + 'px',
|
171
|
-
opacity: 1
|
172
|
-
|
173
|
-
setTimeout (=>
|
174
|
-
@modal
|
175
|
-
.css css
|
176
|
-
.addClass('open')
|
177
|
-
.animate end_css, 250, 'linear', =>
|
178
|
-
@modal.removeClass('locked').trigger('opened.modal')
|
179
|
-
), 125
|
180
|
-
|
181
|
-
close: (openPrevious = true) =>
|
182
|
-
return if @modal.hasClass('locked') or not @modal.hasClass('open')
|
183
|
-
|
184
|
-
@modal.addClass 'locked'
|
185
|
-
|
186
|
-
$('body').off 'keyup.modal'
|
187
|
-
|
188
|
-
unless @settings.previousModal.length and openPrevious
|
189
|
-
@constructor.toggleBackground(false)
|
190
|
-
|
191
|
-
end_css =
|
192
|
-
top: -$(window).scrollTop() - @settings._cachedHeight + 'px',
|
193
|
-
opacity: 0
|
194
|
-
|
195
|
-
setTimeout (=>
|
196
|
-
@modal
|
197
|
-
.animate end_css, 250, 'linear', =>
|
198
|
-
@modal
|
199
|
-
.css @settings.css.close
|
200
|
-
.removeClass 'locked'
|
201
|
-
.trigger 'closed.modal'
|
202
|
-
|
203
|
-
if openPrevious
|
204
|
-
@openPreviousModal()
|
205
|
-
else
|
206
|
-
@settings.previousModal = $()
|
207
|
-
|
208
|
-
.removeClass('open')
|
209
|
-
), 125
|
210
|
-
|
211
|
-
# Just hide the modal immediately and don't bother with an overlay
|
212
|
-
hide: =>
|
213
|
-
@modal.removeClass('open locked').css @settings.css.close
|
214
|
-
|
215
|
-
openPreviousModal: =>
|
216
|
-
@settings.previousModal.trigger 'open.modal'
|
217
|
-
|
218
|
-
@settings.previousModal = $()
|
219
|
-
|
220
|
-
_cacheHeight: =>
|
221
|
-
@settings._cachedHeight = @modal.show().height()
|
222
|
-
|
223
|
-
@modal.hide()
|
224
|
-
|
225
|
-
@createModal: ->
|
226
|
-
$("""
|
227
|
-
<div class="#{@_defaultClasses().join(' ')}">
|
228
|
-
<div class="modal-title">
|
229
|
-
<span></span>
|
230
|
-
<a href="#" class="modal-close">×</a>
|
231
|
-
</div>
|
232
|
-
<div class="modal-content"></div>
|
233
|
-
<div class="modal-buttons"></div>
|
234
|
-
</div>""").appendTo(@settings.appendTo)
|
235
|
-
|
236
|
-
@_defaultClasses: ->
|
237
|
-
['modal', @size, @type].filter (klass) -> klass isnt null
|
238
|
-
|
239
|
-
@toggleBackground: (visible = true) =>
|
240
|
-
@overlay = $ '<div class="modal-overlay">' unless @overlay
|
241
|
-
|
242
|
-
if visible
|
243
|
-
return if @overlay.is(':visible')
|
244
|
-
|
245
|
-
@overlay
|
246
|
-
.hide()
|
247
|
-
.appendTo('body')
|
248
|
-
.fadeIn @fadeSpeed
|
249
|
-
else
|
250
|
-
@overlay
|
251
|
-
.fadeOut @fadeSpeed, ->
|
252
|
-
$(@).detach()
|
253
|
-
|
254
|
-
@backgroundClicked: ->
|
255
|
-
modal = $ '.modal.open'
|
256
|
-
|
257
|
-
return if not modal or modal.hasClass('locked')
|
258
|
-
|
259
|
-
# Don't continue to close if we're not supposed to
|
260
|
-
return unless Fustrate.Components.Modal.settings.closeOnBackgroundClick
|
261
|
-
|
262
|
-
modal.trigger 'close.modal'
|
263
|
-
|
264
|
-
false
|
265
|
-
|
266
|
-
@closeButtonClicked: ->
|
267
|
-
modal = $ '.modal.open'
|
268
|
-
|
269
|
-
return if not modal or modal.hasClass('locked')
|
270
|
-
|
271
|
-
modal.trigger 'close.modal'
|
272
|
-
|
273
|
-
false
|
@@ -1,84 +0,0 @@
|
|
1
|
-
class Fustrate.Components.Pagination extends Fustrate.Components.Base
|
2
|
-
constructor: ({ @current_page, @total_pages, @total_entries, @per_page }) ->
|
3
|
-
@base = @constructor._getPreppedPaginationURL()
|
4
|
-
|
5
|
-
link: (text, page, options = {}) =>
|
6
|
-
Fustrate.linkTo(text, "#{@base}page=#{page}", options)
|
7
|
-
|
8
|
-
previousLink: =>
|
9
|
-
if @current_page > 1
|
10
|
-
return "
|
11
|
-
<li class=\"previous_page\">
|
12
|
-
#{@link('← Previous', @current_page - 1, rel: 'prev')}
|
13
|
-
</li>"
|
14
|
-
|
15
|
-
'<li class="previous_page unavailable"><a href="#">← Previous</a></li>'
|
16
|
-
|
17
|
-
nextLink: =>
|
18
|
-
if @current_page < @total_pages
|
19
|
-
return "
|
20
|
-
<li class=\"next_page\">
|
21
|
-
#{@link('Next →', @current_page + 1, rel: 'next')}
|
22
|
-
</li>"
|
23
|
-
|
24
|
-
'<li class="next_page unavailable"><a href="#">Next →</a></li>'
|
25
|
-
|
26
|
-
generate: =>
|
27
|
-
pages = []
|
28
|
-
|
29
|
-
if @total_pages > 1
|
30
|
-
pages = for i in @windowedPageNumbers()
|
31
|
-
if i is @current_page
|
32
|
-
"<li class=\"current\">#{Fustrate.linkTo(i, '#')}</li>"
|
33
|
-
else if i is 'gap'
|
34
|
-
'<li class="unavailable"><span class="gap">…</span></li>'
|
35
|
-
else
|
36
|
-
"<li>#{@link i, i}</li>"
|
37
|
-
|
38
|
-
pages.unshift @previousLink()
|
39
|
-
pages.push @nextLink()
|
40
|
-
|
41
|
-
$('<ul class="pagination">').html pages.join(' ')
|
42
|
-
|
43
|
-
windowedPageNumbers: =>
|
44
|
-
window_from = @current_page - 4
|
45
|
-
window_to = @current_page + 4
|
46
|
-
|
47
|
-
if window_to > @total_pages
|
48
|
-
window_from -= window_to - @total_pages
|
49
|
-
window_to = @total_pages
|
50
|
-
|
51
|
-
if window_from < 1
|
52
|
-
window_to += 1 - window_from
|
53
|
-
window_from = 1
|
54
|
-
window_to = @total_pages if window_to > @total_pages
|
55
|
-
|
56
|
-
middle = [window_from..window_to]
|
57
|
-
|
58
|
-
left = if 4 < middle[0] then [1, 2, 'gap'] else [1...middle[0]]
|
59
|
-
|
60
|
-
if @total_pages - 3 > middle.last()
|
61
|
-
right = [(@total_pages - 1)..@total_pages]
|
62
|
-
right.unshift 'gap'
|
63
|
-
else if middle.last() + 1 <= @total_pages
|
64
|
-
right = [(middle.last() + 1)..@total_pages]
|
65
|
-
else
|
66
|
-
right = []
|
67
|
-
|
68
|
-
left.concat middle, right
|
69
|
-
|
70
|
-
@getCurrentPage: ->
|
71
|
-
window.location.search.match(/[?&]page=(\d+)/)?[1] ? 1
|
72
|
-
|
73
|
-
# Just add 'page='
|
74
|
-
@_getPreppedPaginationURL: ->
|
75
|
-
search = window.location.search.replace(/[?&]page=\d+/, '')
|
76
|
-
|
77
|
-
search = if search[0] is '?'
|
78
|
-
"#{search}&"
|
79
|
-
else if search[0] is '&'
|
80
|
-
"?#{search[1...search.length]}&"
|
81
|
-
else
|
82
|
-
'?'
|
83
|
-
|
84
|
-
"#{window.location.pathname}#{search}"
|
@@ -1,28 +0,0 @@
|
|
1
|
-
class Fustrate.Components.Tabs extends Fustrate.Components.Base
|
2
|
-
constructor: (@tabs) ->
|
3
|
-
@tabs.on 'click', 'li > a', (e) =>
|
4
|
-
@activateTab $(e.currentTarget)
|
5
|
-
|
6
|
-
false
|
7
|
-
|
8
|
-
if window.location.hash
|
9
|
-
@activateTab $("li > a[href='#{window.location.hash}']", @tabs).first()
|
10
|
-
else if $('li > a.active', @tabs).length > 0
|
11
|
-
@activateTab $('li > a.active', @tabs).first()
|
12
|
-
else
|
13
|
-
@activateTab $('li > a', @tabs).first()
|
14
|
-
|
15
|
-
activateTab: (tab) =>
|
16
|
-
return unless tab
|
17
|
-
|
18
|
-
$('.active', @tabs).removeClass 'active'
|
19
|
-
tab.addClass 'active'
|
20
|
-
|
21
|
-
$("##{tab.attr('href').split('#')[1]}")
|
22
|
-
.addClass 'active'
|
23
|
-
.siblings()
|
24
|
-
.removeClass 'active'
|
25
|
-
|
26
|
-
@initialize: =>
|
27
|
-
$('ul.tabs').each (index, elem) =>
|
28
|
-
new @($ elem)
|
@@ -1,72 +0,0 @@
|
|
1
|
-
class Fustrate.Components.Tooltip extends Fustrate.Components.Base
|
2
|
-
@fadeSpeed: 100
|
3
|
-
|
4
|
-
constructor: (element, title) ->
|
5
|
-
@element = $ element
|
6
|
-
@active = false
|
7
|
-
|
8
|
-
@addEventListeners()
|
9
|
-
|
10
|
-
@element.attr('title', title) if title
|
11
|
-
|
12
|
-
addEventListeners: =>
|
13
|
-
@element
|
14
|
-
.off '.tooltip'
|
15
|
-
.on 'mouseenter.tooltip', @_show
|
16
|
-
.on 'mousemove.tooltip', @_move
|
17
|
-
.on 'mouseleave.tooltip', @_hide
|
18
|
-
|
19
|
-
setTitle: (title) ->
|
20
|
-
if @active
|
21
|
-
@tooltip.text title
|
22
|
-
else
|
23
|
-
@element.prop('title', title)
|
24
|
-
|
25
|
-
_move: (e) =>
|
26
|
-
@tooltip.css @_tooltipPosition(e) if @active
|
27
|
-
|
28
|
-
false
|
29
|
-
|
30
|
-
_show: (e) =>
|
31
|
-
return false if @active
|
32
|
-
|
33
|
-
title = @element.prop('title') ? ''
|
34
|
-
|
35
|
-
return false unless title.length > 0
|
36
|
-
|
37
|
-
@tooltip ?= $('<span class="tooltip">').hide()
|
38
|
-
|
39
|
-
@element.attr('title', '').removeAttr('title')
|
40
|
-
|
41
|
-
@active = true
|
42
|
-
|
43
|
-
@tooltip
|
44
|
-
.text title
|
45
|
-
.appendTo $('body')
|
46
|
-
.css @_tooltipPosition(e)
|
47
|
-
.fadeIn @constructor.fadeSpeed
|
48
|
-
|
49
|
-
false
|
50
|
-
|
51
|
-
_hide: (e) =>
|
52
|
-
# No use hiding something that doesn't exist.
|
53
|
-
if @tooltip
|
54
|
-
@element.attr 'title', @tooltip.text()
|
55
|
-
@active = false
|
56
|
-
|
57
|
-
@tooltip.fadeOut @constructor.fadeSpeed, @tooltip.detach
|
58
|
-
|
59
|
-
false
|
60
|
-
|
61
|
-
_tooltipPosition: (e) ->
|
62
|
-
top: "#{e.pageY + 15}px"
|
63
|
-
left: "#{e.pageX - 10}px"
|
64
|
-
|
65
|
-
@initialize: ->
|
66
|
-
$('[data-tooltip]').each (index, elem) ->
|
67
|
-
new Fustrate.Components.Tooltip elem
|
68
|
-
|
69
|
-
$.fn.extend
|
70
|
-
tooltip: (options) ->
|
71
|
-
@each (index, element) ->
|
72
|
-
new Fustrate.Components.Tooltip element
|
@@ -1,30 +0,0 @@
|
|
1
|
-
#= require './generic_page'
|
2
|
-
|
3
|
-
class Fustrate.GenericForm extends Fustrate.GenericPage
|
4
|
-
addEventListeners: =>
|
5
|
-
super
|
6
|
-
|
7
|
-
@root.on 'submit', @onSubmit
|
8
|
-
|
9
|
-
_reloadUIElements: =>
|
10
|
-
super
|
11
|
-
|
12
|
-
for domObject in $('[name][id]', @root)
|
13
|
-
element = $ domObject
|
14
|
-
name = element.prop 'name'
|
15
|
-
|
16
|
-
if captures = name.match /\[([a-z_]+)\]$/
|
17
|
-
@fields[captures[1]] = element
|
18
|
-
else
|
19
|
-
@fields[name] = element
|
20
|
-
|
21
|
-
validate: -> true
|
22
|
-
|
23
|
-
onSubmit: (e) =>
|
24
|
-
return true if @validate()
|
25
|
-
|
26
|
-
e.preventDefault()
|
27
|
-
|
28
|
-
setTimeout (=> $.rails.enableFormElements(@root)), 100
|
29
|
-
|
30
|
-
false
|
@@ -1,40 +0,0 @@
|
|
1
|
-
class Fustrate.GenericPage
|
2
|
-
constructor: (@root) ->
|
3
|
-
@_reloadUIElements()
|
4
|
-
@addEventListeners()
|
5
|
-
@initialize()
|
6
|
-
|
7
|
-
addEventListeners: ->
|
8
|
-
|
9
|
-
# Once the interface is loaded and the event listeners are active, run any
|
10
|
-
# other tasks.
|
11
|
-
initialize: ->
|
12
|
-
|
13
|
-
_reloadUIElements: =>
|
14
|
-
@fields = {}
|
15
|
-
@buttons = {}
|
16
|
-
|
17
|
-
$('[data-field]', @root).not('.modal [data-field]').each (i, element) =>
|
18
|
-
field = $ element
|
19
|
-
@fields[field.data('field')] = field
|
20
|
-
|
21
|
-
$('[data-button]', @root).not('.modal [data-button]').each (i, element) =>
|
22
|
-
button = $ element
|
23
|
-
@buttons[button.data('button')] = button
|
24
|
-
|
25
|
-
flashSuccess: (message, { icon } = {}) ->
|
26
|
-
new Fustrate.Components.Flash.Success(message, icon: icon)
|
27
|
-
|
28
|
-
flashError: (message, { icon } = {}) ->
|
29
|
-
new Fustrate.Components.Flash.Error(message, icon: icon)
|
30
|
-
|
31
|
-
flashInfo: (message, { icon } = {}) ->
|
32
|
-
new Fustrate.Components.Flash.Info(message, icon: icon)
|
33
|
-
|
34
|
-
setHeader: (text) ->
|
35
|
-
$('.header > span', @root).text text
|
36
|
-
|
37
|
-
# Calls all methods matching /refresh.+/
|
38
|
-
refresh: =>
|
39
|
-
for own name, func of @
|
40
|
-
func() if name.indexOf('refresh') is 0 and name isnt 'refresh'
|