-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbsModalBuilder.coffee
278 lines (248 loc) · 8.97 KB
/
bsModalBuilder.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# --- Bootstrap 3.x Modal Builder ---------------------------------------------------------------
# --- constructor ---
ModalBuilder = (defaultParams = null) ->
@__version = '0.1.5'
@defaultParams =
title: null
hasTitle: true
hasFooter: true
content: null
isClosable: true,
doesFade: true,
size: false,
buttons: [
{
text: 'Close'
type: 'dismiss'
style: 'btn-default'
}
{
text: 'Ok'
type: 'submit'
style: 'btn-primary'
}
]
$.extend @defaultParams, defaultParams if defaultParams?
return
# --- generalized modal builder ---
ModalBuilder::buildModal = (title, content, callback, params = false) ->
modalParams = @defaultParams
if params isnt false
currentParamsMap = Object.getOwnPropertyNames(params)
currentParamsMap.forEach (item) ->
modalParams[item] = params[item]
return
modalId = @__getModalId()
modalTitle = title ? @defaultParams.title
modalContent = content ? @defaultParams.content
modalCallback = if typeof callback is 'function' then callback else null
modalCloseBtn = '<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>'
modalCloseBtn = '' if modalParams.noClose? and modalParams.noClose is true
modalDOMHeader = """
<div class="modal-header">
#{modalCloseBtn}
<h4 class="modal-title" id="ModalLabel_#{modalId}">#{modalTitle}</h4>
</div>
"""
modalDOMHeader = if modalParams.hasTitle? and modalParams.hasTitle is true then modalDOMHeader else ''
modalDOMContent = """
<div class="modal-body">
#{modalContent}
</div>
"""
modalDOMContent = if content? then modalDOMContent else ''
modalDOMFooter = '<div class="modal-footer">'
buttonHandlers = []
modalParams.buttons.forEach (button) ->
buttonDataType = ' data-'+button.type+'="modal"' if button.type?
buttonStyle = if button.style? then button.style else 'btn-default'
buttonBind = if button.bind? then ' data-bind="'+button.bind+'"' else ''
buttonType = if button.type is 'submit' then 'submit' else 'button'
modalDOMFooter += '<button type="'+buttonType+'" class="btn '+buttonStyle+'"'+buttonDataType+buttonBind+'>'+button.text+'</button>'
buttonHandlers.push button.type if button.type? and button.type isnt 'dismiss' and button.type isnt 'submit'
return
modalDOMFooter += '</div>'
modalDOMFooter += '</div>'
modalDOMFooter = if modalParams.hasFooter? and modalParams.hasFooter is true then modalDOMFooter else ''
modalKbClose = if modalParams.noClose? and modalParams.noClose is true then '' else ' keyboard'
modalDoesFade = if modalParams.doesFade? and modalParams.doesFade is false then '' else ' fade'
modalSize = ''
if modalParams.size?
modalSize = ' modal-lg' if modalParams.size is 'lg'
modalSize = ' modal-sm' if modalParams.size is 'sm'
modalDom = """
<div class="modal#{modalDoesFade}#{modalKbClose}" id="modal_#{modalId}" tabindex="-1" role="dialog" aria-labelledby="ModalLabel_#{modalId}" aria-hidden="true">
<div class="modal-dialog#{modalSize}">
<div class="modal-content">
#{modalDOMHeader}
#{modalDOMContent}
#{modalDOMFooter}
</div>
</div>
</div>
"""
modalContainer = @__getContainer()
modalContainer.append modalDom
$('#modal_'+modalId+' [data-submit="modal"]').click ->
$('#modal_'+modalId).attr 'data-interaction', 'submit'
$('#modal_'+modalId).modal 'toggle'
if callback isnt null and typeof callback isnt 'string' and typeof callback isnt 'number' and typeof callback isnt 'boolean'
if $('#modal_'+modalId+' .form-input').length is 1
output = $('#modal_'+modalId+' .form-input').val()
else
ci = 0
max = $('#modal_'+modalId+' .form-input').length
output = {}
while ci < max
element = $('#modal_'+modalId+' .form-input').eq(ci)
output[element.attr('name')] = element.val()
ci++
callback(output) if typeof callback is 'function'
callback.submit(output) if typeof callback is 'object' and callback.submit?
return
$('#modal_'+modalId+' [data-dismiss="modal"]').click ->
$('#modal_'+modalId).attr 'data-interaction', 'dismiss'
$('#modal_'+modalId).modal 'toggle'
if callback isnt null and typeof callback isnt 'string' and typeof callback isnt 'number' and typeof callback isnt 'boolean'
callback.dismiss() if typeof callback is 'object' and callback.dismiss?
return
buttonHandlers.forEach (handler) ->
$('#modal_'+modalId+' [data-'+handler+'="modal"]').click ->
$('#modal_'+modalId).attr 'data-interaction', handler
$('#modal_'+modalId).modal 'toggle'
if callback isnt null and typeof callback isnt 'string' and typeof callback isnt 'number' and typeof callback isnt 'boolean'
callback[handler]() if typeof callback is 'object' and callback[handler]?
return
$('#modal_'+modalId).keydown (e) ->
if e.key is 'Enter'
$('#modal_'+modalId+' [data-submit="modal"]').trigger 'click'
else if e.key is 'Escape'
$('#modal_'+modalId+' [data-dismiss="modal"]').trigger 'click'
return
'#modal_' + modalId
# --- modal displayer ---
ModalBuilder::show = (modalId, onloadCallback = false, oncloseCallback = false) ->
$(modalId).modal('show').on 'shown.bs.modal', ->
$(modalId).find('input').eq(0).focus()
if onloadCallback isnt false
onloadCallback modalId
return
$(modalId).on 'hide.bs.modal', (e) ->
$(modalId).find('input').eq(0).focus()
if oncloseCallback isnt false
oncloseCallback modalId, e
return
return
# --- modal hider ---
ModalBuilder::hide = (modalId) ->
$(modalId).modal 'hide'
return
# --- combined modal builder with displayer ---
ModalBuilder::modal = (title, content, callback, params = false) ->
modalId = @buildModal title, content, callback, params
if typeof params.onloadCallback is 'function' and typeof params.oncloseCallback is 'function'
@show modalId, params.onloadCallback, params.oncloseCallback
else if typeof params.onloadCallback is 'function'
@show modalId, params.onloadCallback
else
@show modalId
modalId
# --- modal-powered alert box ---
ModalBuilder::alert = (title, content) ->
modalId = @modal title, content, null,
hasTitle: title?
buttons: [
{
text: 'Ok'
type: 'submit'
style: 'btn-primary'
}
]
modalId
# --- modal-powered confirm box ---
ModalBuilder::confirm = (title, content, callback) ->
modalId = @modal title, content, callback,
hasTitle: title?
buttons: [
{
text: 'Cancel'
type: 'dismiss'
style: 'btn-standard'
}
{
text: 'Ok'
type: 'submit'
style: 'btn-primary'
}
]
modalId
# --- modal-powered prompt box ---
ModalBuilder::prompt = (title, content, callback, params = false) ->
placeholderText = if params.placeholder? then params.placeholder else 'Text input'
inputBind = if params.inputBind? then ' data-bind="'+params.inputBind+'"' else ''
promptContent = """
<div class="form-group">
<p>#{content}</p>
<input type="text" class="form-control form-input" placeholder="#{placeholderText}" autofocus="autofocus"#{inputBind}>
</div>
"""
modalId = @modal title, promptContent, callback,
hasTitle: title?
buttons: [
{
text: 'Cancel'
type: 'dismiss'
style: 'btn-standard'
bind: if params.cancelBind? then params.cancelBind else null
}
{
text: 'Ok'
type: 'submit'
style: 'btn-primary'
bind: if params.confirmBind? then params.confirmBind else null
}
]
modalId
# --- html-filled modal ---
ModalBuilder::html = (title, content, callback, params = false) ->
modalContent = content
modalButtons = if params.buttons? then params.buttons else [
{
text: 'Cancel'
type: 'dismiss'
style: 'btn-standard'
}
{
text: 'Ok'
type: 'submit'
style: 'btn-primary'
}
]
modalId = @modal title, modalContent, callback,
hasTitle: title?
buttons: modalButtons
onloadCallback: (if params.onloadCallback? then params.onloadCallback else null)
modalId
# --- internal stuff ---
# --- pseudo-random id generator ---
ModalBuilder::__getModalId = ->
Math.floor(Math.random() * 101) + Math.floor(Math.random() * 101)
# --- container fetcher ---
# this one could be tweaked a bit, though - e.g. could check for container visibility
ModalBuilder::__getContainer = ->
container = if $('.container:visible').length isnt 0 then $('.container:visible') else $('.container-fluid:visible')
if container.length is 0
container = $('body')
if container.length is 1
return container
else
heights = []
container.each (count) ->
item =
order: count
height: $(@).height()
heights.push item
return
sortedHeights = heights.sort (a, b) ->
a.height < b.height
return container.eq sortedHeights[0].order