|
1 /** |
|
2 * MyAMS modal dialogs management |
|
3 */ |
|
4 (function($, globals) { |
|
5 |
|
6 var MyAMS = globals.MyAMS, |
|
7 ams = MyAMS; |
|
8 |
|
9 MyAMS.dialog = { |
|
10 |
|
11 /** |
|
12 * List of registered 'shown' callbacks |
|
13 */ |
|
14 _shown_callbacks: [], |
|
15 |
|
16 /** |
|
17 * Register a callback which should be called when a dialog is shown |
|
18 */ |
|
19 registerShownCallback: function(callback, element) { |
|
20 var dialog; |
|
21 if (element) { |
|
22 dialog = element.objectOrParentWithClass('modal-dialog'); |
|
23 } |
|
24 |
|
25 var callbacks; |
|
26 if (dialog && dialog.exists()) { |
|
27 callbacks = dialog.data('shown-callbacks'); |
|
28 if (callbacks === undefined) { |
|
29 callbacks = []; |
|
30 dialog.data('shown-callbacks', callbacks); |
|
31 } |
|
32 } else { |
|
33 callbacks = ams.dialog._shown_callbacks; |
|
34 } |
|
35 if (callbacks.indexOf(callback) < 0) { |
|
36 callbacks.push(callback); |
|
37 } |
|
38 }, |
|
39 |
|
40 /** |
|
41 * List of registered 'hide' callbacks |
|
42 */ |
|
43 _hide_callbacks: [], |
|
44 |
|
45 /** |
|
46 * Register a callback which should be called when a dialog is closed |
|
47 */ |
|
48 registerHideCallback: function(callback, element) { |
|
49 var dialog; |
|
50 if (element) { |
|
51 dialog = element.objectOrParentWithClass('modal-dialog'); |
|
52 } |
|
53 |
|
54 var callbacks; |
|
55 if (dialog && dialog.exists()) { |
|
56 callbacks = dialog.data('hide-callbacks'); |
|
57 if (callbacks === undefined) { |
|
58 callbacks = []; |
|
59 dialog.data('hide-callbacks', callbacks); |
|
60 } |
|
61 } else { |
|
62 callbacks = ams.dialog._hide_callbacks; |
|
63 } |
|
64 if (callbacks.indexOf(callback) < 0) { |
|
65 callbacks.push(callback); |
|
66 } |
|
67 }, |
|
68 |
|
69 /** |
|
70 * Modal dialog opener |
|
71 */ |
|
72 open: function(source, options, callbacks) { |
|
73 ams.ajax.check($.fn.modalmanager, |
|
74 ams.baseURL + 'ext/bootstrap-modalmanager' + ams.devext + '.js', |
|
75 function() { |
|
76 ams.ajax.check($.fn.modal.defaults, |
|
77 ams.baseURL + 'ext/bootstrap-modal' + ams.devext + '.js', |
|
78 function(first_load) { |
|
79 if (first_load) { |
|
80 $(document).off('click.modal'); |
|
81 $.fn.modal.defaults.spinner = $.fn.modalmanager.defaults.spinner = |
|
82 '<div class="loading-spinner" style="width: 200px; margin-left: -100px;">' + |
|
83 '<div class="progress progress-striped active">' + |
|
84 '<div class="progress-bar" style="width: 100%;"></div>' + |
|
85 '</div>' + |
|
86 '</div>'; |
|
87 } |
|
88 |
|
89 var sourceData; |
|
90 var url; |
|
91 if (typeof(source) === 'string') { |
|
92 sourceData = {}; |
|
93 url = source; |
|
94 } else { |
|
95 sourceData = source.data(); |
|
96 url = source.attr('href') || sourceData.amsUrl; |
|
97 var url_getter = ams.getFunctionByName(url); |
|
98 if (typeof(url_getter) === 'function') { |
|
99 url = url_getter.call(source); |
|
100 } |
|
101 } |
|
102 if (!url) { |
|
103 return; |
|
104 } |
|
105 $('body').modalmanager('loading'); |
|
106 if (url.indexOf('#') === 0) { |
|
107 // Inner hidden modal dialog |
|
108 $(url).modal('show'); |
|
109 } else { |
|
110 // Remote URL modal dialog |
|
111 $.ajax({ |
|
112 url: url, |
|
113 type: 'get', |
|
114 cache: sourceData.amsAllowCache === undefined ? false : sourceData.amsAllowCache, |
|
115 data: options, |
|
116 success: function(data, status, request) { |
|
117 $('body').modalmanager('removeLoading'); |
|
118 var response = ams.ajax.getResponse(request); |
|
119 var dataType = response.contentType; |
|
120 var result = response.data; |
|
121 switch (dataType) { |
|
122 case 'json': |
|
123 ams.ajax.handleJSON(result, $($(source).data('ams-json-target') || '#content')); |
|
124 break; |
|
125 case 'script': |
|
126 break; |
|
127 case 'xml': |
|
128 break; |
|
129 case 'html': |
|
130 /* falls through */ |
|
131 case 'text': |
|
132 /* falls through */ |
|
133 default: |
|
134 var content = $(result); |
|
135 var dialog = $('.modal-dialog', content.wrap('<div></div>').parent()); |
|
136 var dialogData = dialog.data() || {}; |
|
137 var dataOptions = { |
|
138 backdrop: 'static', |
|
139 overflow: dialogData.amsModalOverflow || '.modal-viewport', |
|
140 maxHeight: dialogData.amsModalMaxHeight === undefined ? |
|
141 function() { |
|
142 return $(window).height() - |
|
143 $('.modal-header', content).outerHeight(true) - |
|
144 $('footer', content).outerHeight(true) - 85; |
|
145 } |
|
146 : ams.getFunctionByName(dialogData.amsModalMaxHeight) |
|
147 }; |
|
148 var settings = $.extend({}, dataOptions, dialogData.amsModalOptions); |
|
149 settings = ams.executeFunctionByName(dialogData.amsModalInitCallback, dialog, settings) || settings; |
|
150 if (callbacks) { |
|
151 if (callbacks.shown) { |
|
152 ams.dialog.registerShownCallback(callbacks.shown, content); |
|
153 } |
|
154 if (callbacks.hide) { |
|
155 ams.dialog.registerHideCallback(callbacks.hide, content); |
|
156 } |
|
157 } |
|
158 $('<div>').addClass('modal fade') |
|
159 .append(content) |
|
160 .modal(settings) |
|
161 .on('shown', ams.dialog.shown) |
|
162 .on('hidden', ams.dialog.hidden); |
|
163 ams.initContent(content); |
|
164 if (sourceData.amsLogEvent !== false) { |
|
165 ams.stats.logPageview(url); |
|
166 } |
|
167 } |
|
168 } |
|
169 }); |
|
170 } |
|
171 }); |
|
172 }); |
|
173 }, |
|
174 |
|
175 /** |
|
176 * Modals shown callback |
|
177 * This callback is used to initialize modal's viewport size |
|
178 */ |
|
179 shown: function(e) { |
|
180 |
|
181 function resetViewport(ev) { |
|
182 var top = $('.scrollmarker.top', viewport); |
|
183 var topPosition = viewport.scrollTop(); |
|
184 if (topPosition > 0) { |
|
185 top.show(); |
|
186 } else { |
|
187 top.hide(); |
|
188 } |
|
189 var bottom = $('.scrollmarker.bottom', viewport); |
|
190 if (maxHeight + topPosition >= viewport.get(0).scrollHeight) { |
|
191 bottom.hide(); |
|
192 } else { |
|
193 bottom.show(); |
|
194 } |
|
195 } |
|
196 |
|
197 var modal = e.target; |
|
198 var viewport = $('.modal-viewport', modal); |
|
199 if (viewport.exists()) { |
|
200 var maxHeight = parseInt(viewport.css('max-height')); |
|
201 var barWidth = $.scrollbarWidth(); |
|
202 if ((viewport.css('overflow') !== 'hidden') && |
|
203 (viewport.height() === maxHeight)) { |
|
204 $('<div></div>').addClass('scrollmarker') |
|
205 .addClass('top') |
|
206 .css('top', 0) |
|
207 .css('width', viewport.width() - barWidth) |
|
208 .hide() |
|
209 .appendTo(viewport); |
|
210 $('<div></div>').addClass('scrollmarker') |
|
211 .addClass('bottom') |
|
212 .css('top', maxHeight - 20) |
|
213 .css('width', viewport.width() - barWidth) |
|
214 .appendTo(viewport); |
|
215 viewport.scroll(resetViewport); |
|
216 viewport.off('resize') |
|
217 .on('resize', resetViewport); |
|
218 } else { |
|
219 $('.scrollmarker', viewport).remove(); |
|
220 } |
|
221 } |
|
222 |
|
223 // Check for shown callbacks defined via data API |
|
224 $('[data-ams-shown-callback]', modal).each(function() { |
|
225 var callback = ams.getFunctionByName($(this).data('ams-shown-callback')); |
|
226 if (callback) { |
|
227 callback.call(modal, this); |
|
228 } |
|
229 }); |
|
230 // Call shown callbacks registered for this dialog |
|
231 var index; |
|
232 var callbacks = $('.modal-dialog', modal).data('shown-callbacks'); |
|
233 if (callbacks) { |
|
234 for (index=0; index < callbacks.length; index++) { |
|
235 callbacks[index].call(modal); |
|
236 } |
|
237 } |
|
238 // Call globally registered shown callbacks |
|
239 callbacks = ams.dialog._shown_callbacks; |
|
240 if (callbacks) { |
|
241 for (index=0; index < callbacks.length; index++) { |
|
242 callbacks[index].call(modal); |
|
243 } |
|
244 } |
|
245 |
|
246 ams.form.setFocus(modal); |
|
247 }, |
|
248 |
|
249 /** |
|
250 * Close modal dialog associated with given context |
|
251 */ |
|
252 close: function(context) { |
|
253 if (typeof(context) === 'string') { |
|
254 context = $(context); |
|
255 } |
|
256 var modal = context.parents('.modal').data('modal'); |
|
257 if (modal) { |
|
258 var manager = $('body').data('modalmanager'); |
|
259 if (manager && (manager.getOpenModals().indexOf(modal) >= 0)) { |
|
260 modal.hide(); |
|
261 } |
|
262 } |
|
263 }, |
|
264 |
|
265 /** |
|
266 * Modals hidden callback |
|
267 * This callback can be used to clean contents added by plug-ins |
|
268 */ |
|
269 hidden: function(e) { |
|
270 var modal = e.target; |
|
271 // Call registered cleaning callbacks |
|
272 ams.skin.cleanContainer(modal); |
|
273 // Check for hidden callbacks defined via data API |
|
274 $('[data-ams-hidden-callback]', modal).each(function() { |
|
275 var callback = ams.getFunctionByName($(this).data('ams-hidden-callback')); |
|
276 if (callback) { |
|
277 callback.call(modal, this); |
|
278 } |
|
279 }); |
|
280 // Call hidden callbacks registered for this dialog |
|
281 var index; |
|
282 var callbacks = $('.modal-dialog', modal).data('hide-callbacks'); |
|
283 if (callbacks) { |
|
284 for (index=0; index < callbacks.length; index++) { |
|
285 callbacks[index].call(modal); |
|
286 } |
|
287 } |
|
288 // Call globally registered hidden callbacks |
|
289 callbacks = ams.dialog._hide_callbacks; |
|
290 if (callbacks) { |
|
291 for (index=0; index < callbacks.length; index++) { |
|
292 callbacks[index].call(modal); |
|
293 } |
|
294 } |
|
295 } |
|
296 }; |
|
297 |
|
298 })(jQuery, this); |