1 /* |
|
2 * MyAMS |
|
3 * « My Application Management Skin » |
|
4 * |
|
5 * $Tag$ (rev. 1) |
|
6 * A bootstrap based application/administration skin |
|
7 * |
|
8 * Custom administration and application skin tools |
|
9 * Released under Zope Public License ZPL 1.1 |
|
10 * ©2014-2020 Thierry Florac <tflorac@ulthar.net> |
|
11 */ |
|
12 |
|
13 "use strict"; |
|
14 |
|
15 (function ($, globals) { |
|
16 |
|
17 var console = globals.console; |
|
18 |
|
19 /** |
|
20 * String prototype extensions |
|
21 */ |
|
22 String.prototype.startsWith = function (str) { |
|
23 var slen = this.length, |
|
24 dlen = str.length; |
|
25 if (slen < dlen) { |
|
26 return false; |
|
27 } |
|
28 return (this.substr(0, dlen) === str); |
|
29 }; |
|
30 |
|
31 String.prototype.endsWith = function (str) { |
|
32 var slen = this.length, |
|
33 dlen = str.length; |
|
34 if (slen < dlen) { |
|
35 return false; |
|
36 } |
|
37 return (this.substr(slen - dlen) === str); |
|
38 }; |
|
39 |
|
40 String.prototype.unserialize = function (str) { |
|
41 var str = decodeURIComponent(this); |
|
42 var chunks = str.split('&'), |
|
43 obj = {}; |
|
44 for (var c = 0; c < chunks.length; c++) { |
|
45 var split = chunks[c].split('=', 2); |
|
46 obj[split[0]] = split[1]; |
|
47 } |
|
48 return obj; |
|
49 }; |
|
50 |
|
51 /** |
|
52 * Array prototype extensions |
|
53 */ |
|
54 if (!Array.prototype.indexOf) { |
|
55 Array.prototype.indexOf = function (elt, from) { |
|
56 var len = this.length; |
|
57 |
|
58 from = Number(from) || 0; |
|
59 from = (from < 0) ? Math.ceil(from) : Math.floor(from); |
|
60 if (from < 0) { |
|
61 from += len; |
|
62 } |
|
63 |
|
64 for (; from < len; from++) { |
|
65 if (from in this && this[from] === elt) { |
|
66 return from; |
|
67 } |
|
68 } |
|
69 return -1; |
|
70 }; |
|
71 } |
|
72 |
|
73 |
|
74 /** |
|
75 * JQuery 'hasvalue' expression |
|
76 * Filter inputs containing value |
|
77 */ |
|
78 $.expr[":"].hasvalue = function (obj, index, meta /*, stack*/) { |
|
79 return $(obj).val() !== ""; |
|
80 }; |
|
81 |
|
82 |
|
83 /** |
|
84 * JQuery 'econtains' expression |
|
85 * Case insensitive contains expression |
|
86 */ |
|
87 $.expr[":"].econtains = function (obj, index, meta /*, stack*/) { |
|
88 return (obj.textContent || obj.innerText || $(obj).text() || "").toLowerCase() === meta[3].toLowerCase(); |
|
89 }; |
|
90 |
|
91 |
|
92 /** |
|
93 * JQuery 'withtext' expression |
|
94 * Case sensitive exact search expression |
|
95 */ |
|
96 $.expr[":"].withtext = function (obj, index, meta /*, stack*/) { |
|
97 return (obj.textContent || obj.innerText || $(obj).text() || "") === meta[3]; |
|
98 }; |
|
99 |
|
100 |
|
101 /** |
|
102 * JQuery filter on parents class |
|
103 * This filter is often combined with ":not()" to select DOM objects which don't have |
|
104 * parents of a given class. |
|
105 * For example: |
|
106 * |
|
107 * $('.hint:not(:parents(.nohints))', element); |
|
108 * |
|
109 * will select all elements with ".hint" class which don't have a parent with '.nohints' class. |
|
110 */ |
|
111 $.expr[':'].parents = function (obj, index, meta /*, stack*/) { |
|
112 return $(obj).parents(meta[3]).length > 0; |
|
113 }; |
|
114 |
|
115 |
|
116 /** |
|
117 * JQuery 'scrollbarWidth' function |
|
118 * Get width of default vertical scrollbar |
|
119 */ |
|
120 if ($.scrollbarWidth === undefined) { |
|
121 $.scrollbarWidth = function () { |
|
122 var parent = $('<div style="width: 50px; height: 50px; overflow: auto"><div/></div>').appendTo('body'); |
|
123 var child = parent.children(); |
|
124 var width = child.innerWidth() - child.height(99).innerWidth(); |
|
125 parent.remove(); |
|
126 return width; |
|
127 }; |
|
128 } |
|
129 |
|
130 |
|
131 /** |
|
132 * MyAMS JQuery extensions |
|
133 */ |
|
134 $.fn.extend({ |
|
135 |
|
136 /** |
|
137 * Check if current object is empty or not |
|
138 */ |
|
139 exists: function () { |
|
140 return $(this).length > 0; |
|
141 }, |
|
142 |
|
143 /** |
|
144 * Get object if it supports given CSS class, |
|
145 * otherwise look for parents |
|
146 */ |
|
147 objectOrParentWithClass: function (klass) { |
|
148 if (this.hasClass(klass)) { |
|
149 return this; |
|
150 } else { |
|
151 return this.parents('.' + klass); |
|
152 } |
|
153 }, |
|
154 |
|
155 /** |
|
156 * Build an array of attributes of the given selection |
|
157 */ |
|
158 listattr: function (attr) { |
|
159 var result = []; |
|
160 this.each(function () { |
|
161 result.push($(this).attr(attr)); |
|
162 }); |
|
163 return result; |
|
164 }, |
|
165 |
|
166 /** |
|
167 * CSS style function |
|
168 * Code from Aram Kocharyan on stackoverflow.com |
|
169 */ |
|
170 style: function (styleName, value, priority) { |
|
171 // DOM node |
|
172 var node = this.get(0); |
|
173 // Ensure we have a DOM node |
|
174 if (typeof(node) === 'undefined') { |
|
175 return; |
|
176 } |
|
177 // CSSStyleDeclaration |
|
178 var style = this.get(0).style; |
|
179 // Getter/Setter |
|
180 if (typeof(styleName) !== 'undefined') { |
|
181 if (typeof(value) !== 'undefined') { |
|
182 // Set style property |
|
183 priority = typeof(priority) !== 'undefined' ? priority : ''; |
|
184 style.setProperty(styleName, value, priority); |
|
185 return this; |
|
186 } else { |
|
187 // Get style property |
|
188 return style.getPropertyValue(styleName); |
|
189 } |
|
190 } else { |
|
191 // Get CSSStyleDeclaration |
|
192 return style; |
|
193 } |
|
194 }, |
|
195 |
|
196 /** |
|
197 * Remove CSS classes starting with a given prefix |
|
198 */ |
|
199 removeClassPrefix: function (prefix) { |
|
200 this.each(function (i, it) { |
|
201 var classes = it.className.split(" ").map(function (item) { |
|
202 return item.startsWith(prefix) ? "" : item; |
|
203 }); |
|
204 it.className = $.trim(classes.join(" ")); |
|
205 }); |
|
206 return this; |
|
207 } |
|
208 }); |
|
209 |
|
210 |
|
211 /** |
|
212 * MyAMS extensions to JQuery |
|
213 */ |
|
214 if (globals.MyAMS === undefined) { |
|
215 globals.MyAMS = { |
|
216 devmode: true, |
|
217 devext: '', |
|
218 lang: 'en', |
|
219 throttleDelay: 350, |
|
220 menuSpeed: 235, |
|
221 navbarHeight: 49, |
|
222 ajaxNav: true, |
|
223 safeMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'], |
|
224 csrfCookieName: 'csrf_token', |
|
225 csrfHeaderName: 'X-CSRF-Token', |
|
226 enableWidgets: true, |
|
227 enableMobile: false, |
|
228 enableFastclick: false, |
|
229 warnOnFormChange: false, |
|
230 formChangedCallback: null, |
|
231 ismobile: (/iphone|ipad|ipod|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase())) |
|
232 }; |
|
233 } |
|
234 var MyAMS = globals.MyAMS; |
|
235 var ams = MyAMS; |
|
236 |
|
237 /** |
|
238 * Get MyAMS base URL |
|
239 * Copyright Andrew Davy: https://forrst.com/posts/Get_the_URL_of_the_current_javascript_file-Dst |
|
240 */ |
|
241 MyAMS.baseURL = (function () { |
|
242 var script = $('script[src*="/myams.js"], script[src*="/myams.min.js"], ' + |
|
243 'script[src*="/myams-core.js"], script[src*="/myams-core.min.js"], ' + |
|
244 'script[src*="/myams-require.js"], script[src*="/myams-require.min.js"]'); |
|
245 var src = script.attr("src"); |
|
246 ams.devmode = src.indexOf('.min.js') < 0; |
|
247 ams.devext = ams.devmode ? '' : '.min'; |
|
248 return src.substring(0, src.lastIndexOf('/') + 1); |
|
249 })(); |
|
250 |
|
251 |
|
252 /** |
|
253 * Basic logging function which log all arguments to console |
|
254 */ |
|
255 MyAMS.log = function () { |
|
256 if (console) { |
|
257 console.debug && console.debug(this, arguments); |
|
258 } |
|
259 }; |
|
260 |
|
261 |
|
262 /** |
|
263 * Extract parameter value from given query string |
|
264 */ |
|
265 MyAMS.getQueryVar = function (src, varName) { |
|
266 // Check src |
|
267 if (src.indexOf('?') < 0) { |
|
268 return false; |
|
269 } |
|
270 if (!src.endsWith('&')) { |
|
271 src += '&'; |
|
272 } |
|
273 // Dynamic replacement RegExp |
|
274 var regex = new RegExp('.*?[&\\?]' + varName + '=(.*?)&.*'); |
|
275 // Apply RegExp to the query string |
|
276 var val = src.replace(regex, "$1"); |
|
277 // If the string is the same, we didn't find a match - return false |
|
278 return val === src ? false : val; |
|
279 }; |
|
280 |
|
281 |
|
282 /** |
|
283 * Color conversion function |
|
284 */ |
|
285 MyAMS.rgb2hex = function (color) { |
|
286 return "#" + $.map(color.match(/\b(\d+)\b/g), function (digit) { |
|
287 return ('0' + parseInt(digit).toString(16)).slice(-2); |
|
288 }).join(''); |
|
289 }; |
|
290 |
|
291 |
|
292 /** |
|
293 * Generate a random ID |
|
294 */ |
|
295 MyAMS.generateId = function () { |
|
296 function s4() { |
|
297 return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); |
|
298 } |
|
299 |
|
300 return s4() + s4() + s4() + s4(); |
|
301 }; |
|
302 |
|
303 |
|
304 /** |
|
305 * Generate a random UUID |
|
306 */ |
|
307 MyAMS.generateUUID = function () { |
|
308 var d = new Date().getTime(); |
|
309 var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { |
|
310 var r = (d + Math.random() * 16) % 16 | 0; |
|
311 d = Math.floor(d / 16); |
|
312 return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); |
|
313 }); |
|
314 return uuid; |
|
315 }; |
|
316 |
|
317 |
|
318 /** |
|
319 * Get an object given by name |
|
320 */ |
|
321 MyAMS.getObject = function (objectName, context) { |
|
322 if (!objectName) { |
|
323 return undefined; |
|
324 } |
|
325 if (typeof(objectName) !== 'string') { |
|
326 return objectName; |
|
327 } |
|
328 var namespaces = objectName.split("."); |
|
329 context = (context === undefined || context === null) ? window : context; |
|
330 for (var i = 0; i < namespaces.length; i++) { |
|
331 try { |
|
332 context = context[namespaces[i]]; |
|
333 } catch (e) { |
|
334 return undefined; |
|
335 } |
|
336 } |
|
337 return context; |
|
338 }; |
|
339 |
|
340 /** |
|
341 * Get and execute a function given by name |
|
342 * Small piece of code by Jason Bunting |
|
343 */ |
|
344 MyAMS.getFunctionByName = function (functionName, context) { |
|
345 if (functionName === undefined) { |
|
346 return undefined; |
|
347 } else if (typeof(functionName) === 'function') { |
|
348 return functionName; |
|
349 } |
|
350 var namespaces = functionName.split("."); |
|
351 var func = namespaces.pop(); |
|
352 context = (context === undefined || context === null) ? window : context; |
|
353 for (var i = 0; i < namespaces.length; i++) { |
|
354 try { |
|
355 context = context[namespaces[i]]; |
|
356 } catch (e) { |
|
357 return undefined; |
|
358 } |
|
359 } |
|
360 try { |
|
361 return context[func]; |
|
362 } catch (e) { |
|
363 return undefined; |
|
364 } |
|
365 }; |
|
366 |
|
367 MyAMS.executeFunctionByName = function (functionName, context /*, args */) { |
|
368 var func = ams.getFunctionByName(functionName, window); |
|
369 if (typeof(func) === 'function') { |
|
370 var args = Array.prototype.slice.call(arguments, 2); |
|
371 return func.apply(context, args); |
|
372 } |
|
373 }; |
|
374 |
|
375 /** |
|
376 * Check to know if given element is still present in DOM |
|
377 */ |
|
378 MyAMS.isInDOM = function (element) { |
|
379 element = $(element); |
|
380 if (!element.exists()) { |
|
381 return false; |
|
382 } |
|
383 return globals.document.body.contains(element[0]); |
|
384 }; |
|
385 |
|
386 /** |
|
387 * Get target URL matching given source |
|
388 * |
|
389 * Given URL can include variable names (with their namespace), given between braces, as in {MyAMS.baseURL} |
|
390 */ |
|
391 MyAMS.getSource = function (url) { |
|
392 return url.replace(/{[^{}]*}/g, function (match) { |
|
393 return ams.getFunctionByName(match.substr(1, match.length - 2)); |
|
394 }); |
|
395 }; |
|
396 |
|
397 /** |
|
398 * Script loader function |
|
399 * |
|
400 * @param url: script URL |
|
401 * @param callback: a callback to be called after script loading |
|
402 * @param options: a set of options to be added to AJAX call |
|
403 * @param onerror: an error callback to be called instead of generic callback |
|
404 */ |
|
405 MyAMS.getScript = function (url, callback, options, onerror) { |
|
406 if (typeof(callback) === 'object') { |
|
407 onerror = options; |
|
408 options = callback; |
|
409 callback = null; |
|
410 } |
|
411 if (options === undefined) { |
|
412 options = {}; |
|
413 } |
|
414 var defaults = { |
|
415 dataType: 'script', |
|
416 url: ams.getSource(url), |
|
417 success: callback, |
|
418 error: onerror || ams.error.show, |
|
419 cache: !ams.devmode, |
|
420 async: options.async === undefined ? typeof(callback) === 'function' : options.async |
|
421 }; |
|
422 var settings = $.extend({}, defaults, options); |
|
423 return $.ajax(settings); |
|
424 }; |
|
425 |
|
426 /** |
|
427 * CSS file loader function |
|
428 * Cross-browser code copied from Stoyan Stefanov blog to be able to |
|
429 * call a callback when CSS is realy loaded. |
|
430 * See: https://www.phpied.com/when-is-a-stylesheet-really-loaded |
|
431 * |
|
432 * @param url: CSS file URL |
|
433 * @param id: a unique ID given to CSS file |
|
434 * @param callback: optional callback function to be called when CSS file is loaded. If set, callback is called |
|
435 * with a 'first_load' boolean argument to indicate is CSS was already loaded (*false* value) or not (*true* |
|
436 * value). |
|
437 * @param options: callback options |
|
438 */ |
|
439 MyAMS.getCSS = function (url, id, callback, options) { |
|
440 if (callback) { |
|
441 callback = ams.getFunctionByName(callback); |
|
442 } |
|
443 var head = $('HEAD'); |
|
444 var style = $('style[data-ams-id="' + id + '"]', head); |
|
445 if (style.length === 0) { |
|
446 style = $('<style>').attr('data-ams-id', id) |
|
447 .text('@import "' + ams.getSource(url) + '";'); |
|
448 if (callback) { |
|
449 var styleInterval = setInterval(function () { |
|
450 try { |
|
451 var _check = style[0].sheet.cssRules; // Is only populated when file is loaded |
|
452 callback.call(window, true, options); |
|
453 clearInterval(styleInterval); |
|
454 } catch (e) { |
|
455 // CSS is not loaded yet... |
|
456 } |
|
457 }, 10); |
|
458 } |
|
459 style.appendTo(head); |
|
460 } else { |
|
461 if (callback) { |
|
462 callback.call(window, false, options); |
|
463 } |
|
464 } |
|
465 }; |
|
466 |
|
467 /** |
|
468 * Initialize main events handlers |
|
469 */ |
|
470 MyAMS.initHandlers = function(element) { |
|
471 |
|
472 // Initialize custom click handlers |
|
473 $(element).on('click', '[data-ams-click-handler]', function(event) { |
|
474 var source = $(this); |
|
475 var handlers = source.data('ams-disabled-handlers'); |
|
476 if ((handlers === true) || (handlers === 'click') || (handlers === 'all')) { |
|
477 return; |
|
478 } |
|
479 var data = source.data(); |
|
480 if (data.amsClickHandler) { |
|
481 if ((data.amsStopPropagation === true) || (data.amsClickStopPropagation === true)) { |
|
482 event.stopPropagation(); |
|
483 } |
|
484 if (data.amsClickKeepDefault !== true) { |
|
485 event.preventDefault(); |
|
486 } |
|
487 var clickHandlers = data.amsClickHandler.split(/\s+/); |
|
488 for (var index=0; index < clickHandlers.length; index++) { |
|
489 var callback = ams.getFunctionByName(clickHandlers[index]); |
|
490 if (callback !== undefined) { |
|
491 callback.call(source, event, data.amsClickHandlerOptions); |
|
492 } |
|
493 } |
|
494 } |
|
495 }); |
|
496 |
|
497 // Initialize custom change handlers |
|
498 $(element).on('change', '[data-ams-change-handler]', function(event) { |
|
499 var source = $(this); |
|
500 // Disable change handlers for readonly inputs |
|
501 // These change handlers are activated by IE!!! |
|
502 if (source.prop('readonly')) { |
|
503 return; |
|
504 } |
|
505 var handlers = source.data('ams-disabled-handlers'); |
|
506 if ((handlers === true) || (handlers === 'change') || (handlers === 'all')) { |
|
507 return; |
|
508 } |
|
509 var data = source.data(); |
|
510 if (data.amsChangeHandler) { |
|
511 if ((data.amsStopPropagation === true) || (data.amsChangeStopPropagation === true)) { |
|
512 event.stopPropagation(); |
|
513 } |
|
514 if (data.amsChangeKeepDefault !== true) { |
|
515 event.preventDefault(); |
|
516 } |
|
517 var changeHandlers = data.amsChangeHandler.split(/\s+/); |
|
518 for (var index=0; index < changeHandlers.length; index++) { |
|
519 var callback = ams.getFunctionByName(changeHandlers[index]); |
|
520 if (callback !== undefined) { |
|
521 callback.call(source, event, data.amsChangeHandlerOptions); |
|
522 } |
|
523 } |
|
524 } |
|
525 }); |
|
526 |
|
527 // Notify reset to update Select2 widgets |
|
528 $(element).on('reset', 'form', function(e) { |
|
529 var form = $(this); |
|
530 setTimeout(function() { |
|
531 $('.alert-danger, SPAN.state-error', form).not('.persistent').remove(); |
|
532 $('LABEL.state-error', form).removeClass('state-error'); |
|
533 $('INPUT.select2[type="hidden"]', form).each(function() { |
|
534 var input = $(this); |
|
535 var select = input.data('select2'); |
|
536 var value = input.data('ams-select2-input-value'); |
|
537 if (value) { |
|
538 input.select2('val', value.split(select.opts.separator)); |
|
539 } |
|
540 }); |
|
541 form.find('.select2').trigger('change'); |
|
542 $('[data-ams-reset-callback]', form).each(function() { |
|
543 var element = $(this); |
|
544 var data = element.data(); |
|
545 var callback = ams.getFunctionByName(data.amsResetCallback); |
|
546 if (callback !== undefined) { |
|
547 callback.call(form, element, data.amsResetCallbackOptions); |
|
548 } |
|
549 }); |
|
550 }, 10); |
|
551 ams.form && ams.form.setFocus(form); |
|
552 }); |
|
553 |
|
554 // Initialize custom reset handlers |
|
555 $(element).on('reset', '[data-ams-reset-handler]', function(e) { |
|
556 var form = $(this); |
|
557 var data = form.data(); |
|
558 if (data.amsResetHandler) { |
|
559 if (data.amsResetKeepDefault !== true) { |
|
560 e.preventDefault(); |
|
561 } |
|
562 var callback = ams.getFunctionByName(data.amsResetHandler); |
|
563 if (callback !== undefined) { |
|
564 callback.call(form, data.amsResetHandlerOptions); |
|
565 } |
|
566 } |
|
567 }); |
|
568 |
|
569 // Initialize custom event on click |
|
570 $(element).on('click', '[data-ams-click-event]', function(e) { |
|
571 var source = $(this); |
|
572 $(e.target).trigger(source.data('ams-click-event'), |
|
573 source.data('ams-click-event-options')); |
|
574 }); |
|
575 |
|
576 // Cancel clicks on readonly checkbox |
|
577 $(element).on('click', 'input[type="checkbox"][readonly]', function() { |
|
578 return false; |
|
579 }); |
|
580 }; |
|
581 |
|
582 })(jQuery, this); |
|
583 |
|
584 (function($, globals) { |
|
585 |
|
586 var ams = globals.MyAMS; |
|
587 |
|
588 /** |
|
589 * MyAMS locale strings |
|
590 */ |
|
591 ams.i18n = { |
|
592 |
|
593 INFO: "Information", |
|
594 WARNING: "!! WARNING !!", |
|
595 ERROR: "ERROR: ", |
|
596 |
|
597 LOADING: "Loading...", |
|
598 PROGRESS: "Processing", |
|
599 |
|
600 WAIT: "Please wait!", |
|
601 FORM_SUBMITTED: "This form was already submitted...", |
|
602 NO_SERVER_RESPONSE: "No response from server!", |
|
603 |
|
604 ERROR_OCCURED: "An error occured!", |
|
605 ERRORS_OCCURED: "Some errors occured!", |
|
606 |
|
607 BAD_LOGIN_TITLE: "Bad login!", |
|
608 BAD_LOGIN_MESSAGE: "Your anthentication credentials didn't allow you to open a session; " + |
|
609 "please check your credentials or contact administrator.", |
|
610 |
|
611 CONFIRM: "Confirm", |
|
612 CONFIRM_REMOVE: "Removing this content can't be undone. Do you confirm?", |
|
613 |
|
614 CLEAR_STORAGE_TITLE: "Clear Local Storage", |
|
615 CLEAR_STORAGE_CONTENT: "Would you like to RESET all your saved widgets and clear LocalStorage?", |
|
616 |
|
617 BTN_OK: "OK", |
|
618 BTN_CANCEL: "Cancel", |
|
619 BTN_OK_CANCEL: "[OK][Cancel]", |
|
620 BTN_YES: "Yes", |
|
621 BTN_NO: "No", |
|
622 BTN_YES_NO: "[Yes][No]", |
|
623 |
|
624 CLIPBOARD_COPY: "Copy to clipboard with Ctrl+C, and Enter", |
|
625 CLIPBOARD_CHARACTER_COPY_OK: "Character copied to clipboard", |
|
626 CLIPBOARD_TEXT_COPY_OK: "Text copied to clipboard", |
|
627 |
|
628 FORM_CHANGED_WARNING: "Some changes were not saved. These updates will be lost if you leave this page.", |
|
629 DELETE_WARNING: "This change can't be undone. Are you sure that you want to delete this element?", |
|
630 NO_UPDATE: "No changes were applied.", |
|
631 DATA_UPDATED: "Data successfully updated.", |
|
632 |
|
633 HOME: "Home", |
|
634 LOGOUT: "Logout?", |
|
635 LOGOUT_COMMENT: "You can improve your security further after logging out by closing this opened browser", |
|
636 |
|
637 SELECT2_PLURAL: 's', |
|
638 SELECT2_MATCH: "One result is available, press enter to select it.", |
|
639 SELECT2_MATCHES: " results are available, use up and down arrow keys to navigate.", |
|
640 SELECT2_NOMATCHES: "No matches found", |
|
641 SELECT2_SEARCHING: "Searching...", |
|
642 SELECT2_LOADMORE: "Loading more results...", |
|
643 SELECT2_INPUT_TOOSHORT: "Please enter {0} more character{1}", |
|
644 SELECT2_INPUT_TOOLONG: "Please delete {0} character{1}", |
|
645 SELECT2_SELECTION_TOOBIG: "You can only select {0} item{1}", |
|
646 SELECT2_FREETAG_PREFIX: "Free text: ", |
|
647 |
|
648 DT_COLUMNS: "Columns" |
|
649 }; |
|
650 |
|
651 })(jQuery, this); |
|
652 |
|
653 /** |
|
654 * MyAMS UTF-8 features |
|
655 */ |
|
656 (function($, globals) { |
|
657 |
|
658 $.UTF8 = { |
|
659 |
|
660 // public method for url encoding |
|
661 encode : function (string) { |
|
662 string = string.replace(/\r\n/g,"\n"); |
|
663 var utftext = ""; |
|
664 |
|
665 for (var n = 0; n < string.length; n++) { |
|
666 |
|
667 var c = string.charCodeAt(n); |
|
668 |
|
669 if (c < 128) { |
|
670 utftext += String.fromCharCode(c); |
|
671 } |
|
672 else if((c > 127) && (c < 2048)) { |
|
673 utftext += String.fromCharCode((c >> 6) | 192); |
|
674 utftext += String.fromCharCode((c & 63) | 128); |
|
675 } |
|
676 else { |
|
677 utftext += String.fromCharCode((c >> 12) | 224); |
|
678 utftext += String.fromCharCode(((c >> 6) & 63) | 128); |
|
679 utftext += String.fromCharCode((c & 63) | 128); |
|
680 } |
|
681 } |
|
682 return utftext; |
|
683 }, |
|
684 |
|
685 // public method for url decoding |
|
686 decode : function (utftext) { |
|
687 var string = ""; |
|
688 var i = 0, |
|
689 c = 0, |
|
690 c2 = 0, |
|
691 c3 = 0; |
|
692 |
|
693 while ( i < utftext.length ) { |
|
694 |
|
695 c = utftext.charCodeAt(i); |
|
696 |
|
697 if (c < 128) { |
|
698 string += String.fromCharCode(c); |
|
699 i++; |
|
700 } |
|
701 else if((c > 191) && (c < 224)) { |
|
702 c2 = utftext.charCodeAt(i+1); |
|
703 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); |
|
704 i += 2; |
|
705 } |
|
706 else { |
|
707 c2 = utftext.charCodeAt(i+1); |
|
708 c3 = utftext.charCodeAt(i+2); |
|
709 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); |
|
710 i += 3; |
|
711 } |
|
712 } |
|
713 return string; |
|
714 } |
|
715 }; /** $.UTF8 */ |
|
716 |
|
717 })(jQuery, this); |
|
718 |
|
719 /** |
|
720 * MyAMS menus management |
|
721 */ |
|
722 (function($, globals) { |
|
723 |
|
724 var ams = globals.MyAMS; |
|
725 |
|
726 $.fn.extend({ |
|
727 |
|
728 /** |
|
729 * Context menu handler |
|
730 */ |
|
731 contextMenu: function(settings) { |
|
732 |
|
733 function getMenuPosition(mouse, direction, scrollDir) { |
|
734 var win = $(window)[direction](), |
|
735 menu = $(settings.menuSelector)[direction](), |
|
736 position = mouse; |
|
737 // opening menu would pass the side of the page |
|
738 if (mouse + menu > win && menu < mouse) { |
|
739 position -= menu; |
|
740 } |
|
741 return position; |
|
742 } |
|
743 |
|
744 return this.each(function () { |
|
745 |
|
746 // Open context menu |
|
747 $('a', $(settings.menuSelector)).each(function() { |
|
748 $(this).data('ams-context-menu', true); |
|
749 }); |
|
750 $(this).on("contextmenu", function (e) { |
|
751 // return native menu if pressing control |
|
752 if (e.ctrlKey) { |
|
753 return; |
|
754 } |
|
755 // open menu |
|
756 $(settings.menuSelector).data("invokedOn", $(e.target)) |
|
757 .show() |
|
758 .css({ |
|
759 position: 'fixed', |
|
760 left: getMenuPosition(e.clientX, 'width', 'scrollLeft') - 10, |
|
761 top: getMenuPosition(e.clientY, 'height', 'scrollTop') - 10 |
|
762 }) |
|
763 .off('click') |
|
764 .on('click', function (e) { |
|
765 $(this).hide(); |
|
766 var invokedOn = $(this).data("invokedOn"); |
|
767 var selectedMenu = $(e.target); |
|
768 settings.menuSelected.call(this, invokedOn, selectedMenu); |
|
769 ams.event && ams.event.stop(e); |
|
770 }); |
|
771 return false; |
|
772 }); |
|
773 |
|
774 // make sure menu closes on any click |
|
775 $(document).click(function () { |
|
776 $(settings.menuSelector).hide(); |
|
777 }); |
|
778 }); |
|
779 }, |
|
780 |
|
781 /* |
|
782 * Main menus manager |
|
783 */ |
|
784 myams_menu: function(options) { |
|
785 // Extend our default options with those provided |
|
786 var defaults = { |
|
787 accordion : true, |
|
788 speed : 200, |
|
789 closedSign : '<em class="fa fa-angle-down"></em>', |
|
790 openedSign : '<em class="fa fa-angle-up"></em>' |
|
791 }; |
|
792 var settings = $.extend({}, defaults, options); |
|
793 |
|
794 // Assign current element to variable, in this case is UL element |
|
795 var menu = $(this); |
|
796 |
|
797 // Add a mark [+] to a multilevel menu |
|
798 menu.find("LI").each(function() { |
|
799 var menuItem = $(this); |
|
800 if (menuItem.find("UL").size() > 0) { |
|
801 |
|
802 // add the multilevel sign next to the link |
|
803 menuItem.find("A:first") |
|
804 .append("<b class='collapse-sign'>" + settings.closedSign + "</b>"); |
|
805 |
|
806 // avoid jumping to the top of the page when the href is an # |
|
807 var firstLink = menuItem.find("A:first"); |
|
808 if (firstLink.attr('href') === "#") { |
|
809 firstLink.click(function() { |
|
810 return false; |
|
811 }); |
|
812 } |
|
813 } |
|
814 }); |
|
815 |
|
816 // Open active level |
|
817 menu.find("LI.active").each(function() { |
|
818 var activeParent = $(this).parents('UL'); |
|
819 var activeItem = activeParent.parent('LI'); |
|
820 activeParent.slideDown(settings.speed); |
|
821 activeItem.find("b:first").html(settings.openedSign); |
|
822 activeItem.addClass("open"); |
|
823 }); |
|
824 |
|
825 menu.find("LI A").on('click', function() { |
|
826 var link = $(this); |
|
827 if (link.hasClass('active')) { |
|
828 return; |
|
829 } |
|
830 var href = link.attr('href').replace(/^#/,''); |
|
831 var parentUL = link.parent().find("UL"); |
|
832 if (settings.accordion) { |
|
833 var parents = link.parent().parents("UL"); |
|
834 var visible = menu.find("UL:visible"); |
|
835 visible.each(function(visibleIndex) { |
|
836 var close = true; |
|
837 parents.each(function(parentIndex) { |
|
838 if (parents[parentIndex] === visible[visibleIndex]) { |
|
839 close = false; |
|
840 return false; |
|
841 } |
|
842 }); |
|
843 if (close) { |
|
844 if (parentUL !== visible[visibleIndex]) { |
|
845 var visibleItem = $(visible[visibleIndex]); |
|
846 if (href || !visibleItem.hasClass('active')) { |
|
847 visibleItem.slideUp(settings.speed, function () { |
|
848 $(this).parent("LI") |
|
849 .removeClass('open') |
|
850 .find("B:first") |
|
851 .delay(settings.speed) |
|
852 .html(settings.closedSign); |
|
853 }); |
|
854 } |
|
855 } |
|
856 } |
|
857 }); |
|
858 } |
|
859 var firstUL = link.parent().find("UL:first"); |
|
860 if (!href && firstUL.is(":visible") && !firstUL.hasClass("active")) { |
|
861 firstUL.slideUp(settings.speed, function() { |
|
862 link.parent("LI") |
|
863 .removeClass("open") |
|
864 .find("B:first") |
|
865 .delay(settings.speed) |
|
866 .html(settings.closedSign); |
|
867 }); |
|
868 } else /*if (link.attr('href') !== location.hash)*/ { |
|
869 firstUL.slideDown(settings.speed, function() { |
|
870 link.parent("LI") |
|
871 .addClass("open") |
|
872 .find("B:first") |
|
873 .delay(settings.speed) |
|
874 .html(settings.openedSign); |
|
875 }); |
|
876 } |
|
877 }); |
|
878 } |
|
879 }); |
|
880 |
|
881 })(jQuery, this); |
|
882 |
|
883 /** |
|
884 * MyAMS events management |
|
885 */ |
|
886 (function($, globals) { |
|
887 |
|
888 var ams = globals.MyAMS; |
|
889 |
|
890 ams.event = { |
|
891 |
|
892 /** |
|
893 * Stop current event propagation |
|
894 */ |
|
895 stop: function(event) { |
|
896 if (!event) { |
|
897 event = window.event; |
|
898 } |
|
899 if (event && (typeof(event) !== 'string')) { |
|
900 if (event.stopPropagation) { |
|
901 event.stopPropagation(); |
|
902 event.preventDefault(); |
|
903 } else { |
|
904 event.cancelBubble = true; |
|
905 event.returnValue = false; |
|
906 } |
|
907 } |
|
908 } |
|
909 }; |
|
910 |
|
911 })(jQuery, this); |
|
912 |
|
913 /** |
|
914 * MyAMS browser related features |
|
915 */ |
|
916 (function($, globals) { |
|
917 |
|
918 var ams = globals.MyAMS; |
|
919 |
|
920 ams.browser = { |
|
921 |
|
922 /** |
|
923 * Get IE version |
|
924 */ |
|
925 getInternetExplorerVersion: function() { |
|
926 var rv = -1; |
|
927 if (navigator.appName === "Microsoft Internet Explorer") { |
|
928 var ua = navigator.userAgent; |
|
929 var re = new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})"); |
|
930 if (re.exec(ua) !== null) { |
|
931 rv = parseFloat(RegExp.$1); |
|
932 } |
|
933 } |
|
934 return rv; |
|
935 }, |
|
936 |
|
937 /** |
|
938 * Display alert for old IE version |
|
939 */ |
|
940 checkVersion: function() { |
|
941 var msg = "You're not using Windows Internet Explorer."; |
|
942 var ver = this.getInternetExplorerVersion(); |
|
943 if (ver > -1) { |
|
944 if (ver >= 8) { |
|
945 msg = "You're using a recent copy of Windows Internet Explorer."; |
|
946 } else { |
|
947 msg = "You should upgrade your copy of Windows Internet Explorer."; |
|
948 } |
|
949 } |
|
950 if (globals.alert) { |
|
951 globals.alert(msg); |
|
952 } |
|
953 }, |
|
954 |
|
955 /** |
|
956 * Check if IE is in version 8 or lower |
|
957 */ |
|
958 isIE8orlower: function() { |
|
959 var msg = "0"; |
|
960 var ver = this.getInternetExplorerVersion(); |
|
961 if (ver > -1) { |
|
962 if (ver >= 9) { |
|
963 msg = 0; |
|
964 } else { |
|
965 msg = 1; |
|
966 } |
|
967 } |
|
968 return msg; |
|
969 }, |
|
970 |
|
971 |
|
972 /** |
|
973 * Copy selection to clipboard |
|
974 * |
|
975 * If 'text' argument is provided, given text is copied to clipboard. |
|
976 * Otherwise, text ou event's source is copied. |
|
977 * Several methods are tested to do clipboard copy (based on browser features); il copy can't be done, |
|
978 * a prompt is displayed to allow user to make a manual copy. |
|
979 */ |
|
980 copyToClipboard: function(text) { |
|
981 |
|
982 function doCopy(text) { |
|
983 var copied = false; |
|
984 if (window.clipboardData && window.clipboardData.setData) { |
|
985 // IE specific code |
|
986 copied = clipboardData.setData("Text", text); |
|
987 } else if (document.queryCommandSupported && document.queryCommandSupported("copy")) { |
|
988 var textarea = $("<textarea>"); |
|
989 textarea.val(text); |
|
990 textarea.css('position', 'fixed'); // Prevent scrolling to bottom of page in MS Edge. |
|
991 textarea.appendTo($('body')); |
|
992 textarea.get(0).select(); |
|
993 try { |
|
994 document.execCommand("copy"); // Security exception may be thrown by some browsers. |
|
995 copied = true; |
|
996 } catch (ex) { |
|
997 if (console) { |
|
998 console.warn && console.warn("Copy to clipboard failed.", ex); |
|
999 } |
|
1000 } finally { |
|
1001 textarea.remove(); |
|
1002 } |
|
1003 } |
|
1004 if (copied) { |
|
1005 ams.skin && ams.skin.smallBox('success', { |
|
1006 title: text.length > 1 |
|
1007 ? ams.i18n.CLIPBOARD_TEXT_COPY_OK |
|
1008 : ams.i18n.CLIPBOARD_CHARACTER_COPY_OK, |
|
1009 icon: 'fa fa-fw fa-info-circle font-xs align-top margin-top-10', |
|
1010 timeout: 3000 |
|
1011 }); |
|
1012 } else if (globals.prompt) { |
|
1013 globals.prompt(ams.i18n.CLIPBOARD_COPY, text); |
|
1014 } |
|
1015 } |
|
1016 |
|
1017 if (text === undefined) { |
|
1018 return function() { |
|
1019 var source = $(this); |
|
1020 var text = source.text(); |
|
1021 source.parents('.btn-group').removeClass('open'); |
|
1022 doCopy(text); |
|
1023 }; |
|
1024 } else { |
|
1025 doCopy(text); |
|
1026 } |
|
1027 } |
|
1028 }; |
|
1029 |
|
1030 })(jQuery, this); |
|
1031 |
|
1032 /** |
|
1033 * MyAMS errors management |
|
1034 */ |
|
1035 (function($, globals) { |
|
1036 |
|
1037 var ams = globals.MyAMS; |
|
1038 |
|
1039 ams.error = { |
|
1040 |
|
1041 /** |
|
1042 * Default JQuery AJAX error handler |
|
1043 */ |
|
1044 ajax: function(event, response, request, error) { |
|
1045 /* user shouldn't be notified of aborted requests */ |
|
1046 if (error === 'abort') { |
|
1047 return; |
|
1048 } |
|
1049 if (response && response.statusText && response.statusText.toUpperCase() === 'OK') { |
|
1050 return; |
|
1051 } |
|
1052 response = ams.ajax && ams.ajax.getResponse(response); |
|
1053 if (response) { |
|
1054 if (response.contentType === 'json') { |
|
1055 ams.ajax.handleJSON(response.data); |
|
1056 } else { |
|
1057 var title = error || event.statusText || event.type; |
|
1058 var message = response.responseText; |
|
1059 ams.skin && ams.skin.messageBox('error', { |
|
1060 title: ams.i18n.ERROR_OCCURED, |
|
1061 content: '<h4>' + title + '</h4><p>' + (message || '') + '</p>', |
|
1062 icon: 'fa fa-warning animated shake', |
|
1063 timeout: 10000 |
|
1064 }); |
|
1065 } |
|
1066 if (console) { |
|
1067 console.error && console.error(event); |
|
1068 console.debug && console.debug(response); |
|
1069 } |
|
1070 } else { |
|
1071 console.error && console.error("Missing MyAMS AJAX module!") |
|
1072 } |
|
1073 }, |
|
1074 |
|
1075 /** |
|
1076 * Show AJAX error |
|
1077 */ |
|
1078 show: function(request, status, error) { |
|
1079 if (!error) { |
|
1080 return; |
|
1081 } |
|
1082 var response = ams.ajax && ams.ajax.getResponse(request); |
|
1083 if (response) { |
|
1084 if (response.contentType === 'json') { |
|
1085 ams.ajax.handleJSON(response.data); |
|
1086 } else { |
|
1087 ams.skin.messageBox('error', { |
|
1088 title: ams.i18n.ERRORS_OCCURED, |
|
1089 content: '<h4>' + status + '</h4><p>' + error + '</p>', |
|
1090 icon: "fa fa-warning animated shake", |
|
1091 timeout: 10000 |
|
1092 }); |
|
1093 } |
|
1094 if (console) { |
|
1095 console.error && console.error(error); |
|
1096 console.debug && console.debug(request); |
|
1097 } |
|
1098 } else { |
|
1099 console.error && console.error("Missing MyAMS AJAX module!") |
|
1100 } |
|
1101 } |
|
1102 }; |
|
1103 |
|
1104 })(jQuery, this); |
|
1105 |
|
1106 /** |
|
1107 * MyAMS AJAX features |
|
1108 */ |
|
1109 (function($, globals) { |
|
1110 |
|
1111 var ams = globals.MyAMS; |
|
1112 |
|
1113 ams.ajax = { |
|
1114 |
|
1115 /** |
|
1116 * Check for given feature and download script if necessary |
|
1117 * |
|
1118 * @param checker: pointer to a javascript object which will be downloaded in undefined |
|
1119 * @param source: URL of a javascript file containing requested feature |
|
1120 * @param callback: pointer to a function which will be called after the script is downloaded. The first |
|
1121 * argument of this callback is a boolean value indicating if the script was just downloaded (true) |
|
1122 * or if the requested object was already loaded (false) |
|
1123 * @param options: callback options |
|
1124 */ |
|
1125 check: function(checker, source, callback, options) { |
|
1126 |
|
1127 function callCallbacks(firstLoad, options) { |
|
1128 if (callback === undefined) { |
|
1129 return; |
|
1130 } |
|
1131 if (!(callback instanceof Array)) { |
|
1132 callback = [callback]; |
|
1133 } |
|
1134 for (var index=0; index < callback.length; index++) { |
|
1135 var cb = ams.getFunctionByName(callback[index]); |
|
1136 if (typeof(cb) === 'function') { |
|
1137 cb(firstLoad, options); |
|
1138 } |
|
1139 } |
|
1140 } |
|
1141 |
|
1142 if (!(callback instanceof Array)) { |
|
1143 if (typeof(callback) === 'object') { |
|
1144 options = callback; |
|
1145 callback = undefined; |
|
1146 } |
|
1147 } |
|
1148 var defaults = { |
|
1149 async: typeof(callback) === 'function' |
|
1150 }; |
|
1151 var settings = $.extend({}, defaults, options), |
|
1152 deferred = [], |
|
1153 index; |
|
1154 if (checker instanceof Array) { |
|
1155 for (index = 0; index < checker.length; index++) { |
|
1156 if (checker[index] === undefined) { |
|
1157 deferred.push(ams.getScript(source[index], {async: true})); |
|
1158 } |
|
1159 } |
|
1160 if (deferred.length > 0) { |
|
1161 $.when.apply($, deferred).then(function () { |
|
1162 callCallbacks(true, options); |
|
1163 }); |
|
1164 } else { |
|
1165 callCallbacks(false, options); |
|
1166 } |
|
1167 } else if (checker === undefined) { |
|
1168 if (source instanceof Array) { |
|
1169 for (index = 0; index < source.length; index++) { |
|
1170 deferred.push(ams.getScript(source[index], {async: true})); |
|
1171 } |
|
1172 if (deferred.length > 0) { |
|
1173 $.when.apply($, deferred).then(function () { |
|
1174 callCallbacks(true, options); |
|
1175 }); |
|
1176 } else { |
|
1177 callCallbacks(false, options); |
|
1178 } |
|
1179 } else if (typeof(source) === 'string') { |
|
1180 ams.getScript(source, function () { |
|
1181 callCallbacks(true, options); |
|
1182 }, settings); |
|
1183 } |
|
1184 } else { |
|
1185 callCallbacks(false, options); |
|
1186 } |
|
1187 }, |
|
1188 |
|
1189 /** |
|
1190 * Get address relative to current page |
|
1191 */ |
|
1192 getAddr: function(addr) { |
|
1193 var href = addr || $('HTML HEAD BASE').attr('href') || window.location.href; |
|
1194 return href.substr(0, href.lastIndexOf("/") + 1); |
|
1195 }, |
|
1196 |
|
1197 /** |
|
1198 * AJAX start callback |
|
1199 */ |
|
1200 start: function() { |
|
1201 $('#ajax-gear').show(); |
|
1202 }, |
|
1203 |
|
1204 /** |
|
1205 * AJAX stop callback |
|
1206 */ |
|
1207 stop: function() { |
|
1208 $('#ajax-gear').hide(); |
|
1209 }, |
|
1210 |
|
1211 /** |
|
1212 * Handle AJAX upload and download progress |
|
1213 * |
|
1214 * @param event: the source event |
|
1215 */ |
|
1216 progress: function(event) { |
|
1217 if (!event.lengthComputable) { |
|
1218 return; |
|
1219 } |
|
1220 if (event.loaded >= event.total) { |
|
1221 return; |
|
1222 } |
|
1223 if (console) { |
|
1224 console.log && console.log(parseInt((event.loaded / event.total * 100), 10) + "%"); |
|
1225 } |
|
1226 }, |
|
1227 |
|
1228 /** |
|
1229 * Post data to given URL and handle result as JSON |
|
1230 */ |
|
1231 getJSON: function() { |
|
1232 return function(options) { |
|
1233 var url = options.url; |
|
1234 delete options.url; |
|
1235 ams.ajax.post(url, options, function(result, status, request) { |
|
1236 ams.ajax.handleJSON(result); |
|
1237 }); |
|
1238 } |
|
1239 }, |
|
1240 |
|
1241 /** |
|
1242 * Post data to given URL |
|
1243 */ |
|
1244 post: function(url, data, options, callback) { |
|
1245 var addr; |
|
1246 if (url.startsWith(window.location.protocol)) { |
|
1247 addr = url; |
|
1248 } else { |
|
1249 addr = this.getAddr() + url; |
|
1250 } |
|
1251 if (typeof(options) === 'function') { |
|
1252 callback = options; |
|
1253 options = {}; |
|
1254 } else if (!options) { |
|
1255 options = {}; |
|
1256 } |
|
1257 if (typeof(callback) === 'undefined') { |
|
1258 callback = options.callback; |
|
1259 } |
|
1260 if (typeof(callback) === 'string') { |
|
1261 callback = ams.getFunctionByName(callback); |
|
1262 } |
|
1263 delete options.callback; |
|
1264 |
|
1265 var result; |
|
1266 var defaults = { |
|
1267 url: addr, |
|
1268 type: 'post', |
|
1269 cache: false, |
|
1270 async: typeof(callback) === 'function', |
|
1271 data: $.param(data), |
|
1272 dataType: 'json', |
|
1273 beforeSend: function(request, options) { |
|
1274 if (globals.Cookies !== undefined) { |
|
1275 var token = Cookies.get(ams.csrfCookieName); |
|
1276 if (token) { |
|
1277 request.setRequestHeader(ams.csrfHeaderName, token); |
|
1278 } |
|
1279 } |
|
1280 }, |
|
1281 success: callback || function(data /*, status*/) { |
|
1282 result = data.result; |
|
1283 } |
|
1284 }; |
|
1285 var settings = $.extend({}, defaults, options); |
|
1286 $.ajax(settings); |
|
1287 return result; |
|
1288 }, |
|
1289 |
|
1290 /** |
|
1291 * Extract data type and result from response |
|
1292 */ |
|
1293 getResponse: function(request) { |
|
1294 var contentType = request.getResponseHeader('content-type'), |
|
1295 dataType, |
|
1296 result; |
|
1297 if (contentType) { |
|
1298 // Got server response |
|
1299 if (contentType.startsWith('application/javascript')) { |
|
1300 dataType = 'script'; |
|
1301 result = request.responseText; |
|
1302 } else if (contentType.startsWith('text/html')) { |
|
1303 dataType = 'html'; |
|
1304 result = request.responseText; |
|
1305 } else if (contentType.startsWith('text/xml')) { |
|
1306 dataType = 'xml'; |
|
1307 result = request.responseText; |
|
1308 } else { |
|
1309 result = request.responseJSON; |
|
1310 if (result) { |
|
1311 dataType = 'json'; |
|
1312 } else { |
|
1313 try { |
|
1314 result = JSON.parse(request.responseText); |
|
1315 dataType = 'json'; |
|
1316 } catch (e) { |
|
1317 result = request.responseText; |
|
1318 dataType = 'text'; |
|
1319 } |
|
1320 } |
|
1321 } |
|
1322 } else { |
|
1323 // Probably no response from server... |
|
1324 dataType = 'json'; |
|
1325 result = { |
|
1326 status: 'alert', |
|
1327 alert: { |
|
1328 title: ams.i18n.ERROR_OCCURED, |
|
1329 content: ams.i18n.NO_SERVER_RESPONSE |
|
1330 } |
|
1331 }; |
|
1332 } |
|
1333 return {contentType: dataType, |
|
1334 data: result}; |
|
1335 }, |
|
1336 |
|
1337 /** |
|
1338 * Handle server response in JSON format |
|
1339 * |
|
1340 * Result is made of several JSON attributes: |
|
1341 * - status: error, success, callback, callbacks, reload or redirect |
|
1342 * - close_form: boolean indicating if current modal should be closed |
|
1343 * - location: target URL for reload or redirect status |
|
1344 * - target: target container's selector for loaded content ('#content' by default) |
|
1345 * - content: available for any status producing output content: |
|
1346 * {target: target container's selector (source form by default) |
|
1347 * html: HTML result} |
|
1348 * - message: available for any status producing output message: |
|
1349 * {target: target message container's selector |
|
1350 * status: message status |
|
1351 * header: message header |
|
1352 * subtitle: message subtitle, |
|
1353 * body: message body} |
|
1354 * |
|
1355 * For errors data structure, please see MyAMS.form.showErrors function |
|
1356 */ |
|
1357 handleJSON: function(result, form, target) { |
|
1358 var status = result.status; |
|
1359 var url; |
|
1360 switch (status) { |
|
1361 case 'alert': |
|
1362 if (globals.alert) { |
|
1363 globals.alert(result.alert.title + '\n\n' + result.alert.content); |
|
1364 } |
|
1365 break; |
|
1366 case 'error': |
|
1367 ams.form && ams.form.showErrors(form, result); |
|
1368 break; |
|
1369 case 'info': |
|
1370 case 'success': |
|
1371 if (form !== undefined) { |
|
1372 ams.form && ams.form.resetChanged(form); |
|
1373 if (result.close_form !== false) { |
|
1374 ams.dialog && ams.dialog.close(form); |
|
1375 } |
|
1376 } |
|
1377 break; |
|
1378 case 'message': |
|
1379 case 'messagebox': |
|
1380 break; |
|
1381 case 'notify': |
|
1382 case 'callback': |
|
1383 case 'callbacks': |
|
1384 if (form !== undefined) { |
|
1385 ams.form && ams.form.resetChanged(form); |
|
1386 if (result.close_form !== false) { |
|
1387 ams.dialog && ams.dialog.close(form); |
|
1388 } |
|
1389 } |
|
1390 break; |
|
1391 case 'modal': |
|
1392 ams.dialog && ams.dialog.open(result.location); |
|
1393 break; |
|
1394 case 'reload': |
|
1395 if (form !== undefined) { |
|
1396 ams.form && ams.form.resetChanged(form); |
|
1397 if (result.close_form !== false) { |
|
1398 ams.dialog && ams.dialog.close(form); |
|
1399 } |
|
1400 } |
|
1401 url = result.location || window.location.hash; |
|
1402 if (url.startsWith('#')) { |
|
1403 url = url.substr(1); |
|
1404 } |
|
1405 var loadTarget = $(result.target || target || '#content'); |
|
1406 ams.skin && ams.skin.loadURL(url, loadTarget, { |
|
1407 preLoadCallback: ams.getFunctionByName(result.pre_reload) || function() { |
|
1408 $('[data-ams-pre-reload]', loadTarget).each(function() { |
|
1409 ams.executeFunctionByName($(this).data('ams-pre-reload')); |
|
1410 }); |
|
1411 }, |
|
1412 preLoadCallbackOptions: result.pre_reload_options, |
|
1413 afterLoadCallback: ams.getFunctionByName(result.post_reload) || function () { |
|
1414 $('[data-ams-post-reload]', loadTarget).each(function () { |
|
1415 ams.executeFunctionByName($(this).data('ams-post-reload')); |
|
1416 }); |
|
1417 }, |
|
1418 afterLoadCallbackOptions: result.post_reload_options |
|
1419 }); |
|
1420 break; |
|
1421 case 'redirect': |
|
1422 if (form !== undefined) { |
|
1423 ams.form && ams.form.resetChanged(form); |
|
1424 if (result.close_form === true) { |
|
1425 ams.dialog && ams.dialog.close(form); |
|
1426 } |
|
1427 } |
|
1428 url = result.location || window.location.href; |
|
1429 if (url.endsWith('##')) { |
|
1430 url = url.replace(/##/, window.location.hash); |
|
1431 } |
|
1432 if (result.window) { |
|
1433 window.open(url, result.window, result.options); |
|
1434 } else { |
|
1435 if (window.location.href === url) { |
|
1436 window.location.reload(true); |
|
1437 } else { |
|
1438 window.location.href = url; |
|
1439 } |
|
1440 } |
|
1441 break; |
|
1442 default: |
|
1443 if (console) { |
|
1444 console.log && console.log("Unhandled status: " + status); |
|
1445 } |
|
1446 } |
|
1447 |
|
1448 var index; |
|
1449 var content; |
|
1450 var container; |
|
1451 if (result.content) { |
|
1452 content = result.content; |
|
1453 container = $(content.target || target || form || '#content'); |
|
1454 if (content.raw === true) { |
|
1455 container.text(content.text); |
|
1456 } else { |
|
1457 container.html(content.html); |
|
1458 ams.initContent && ams.initContent(container); |
|
1459 } |
|
1460 if (!content.keep_hidden) { |
|
1461 container.removeClass('hidden'); |
|
1462 } |
|
1463 } |
|
1464 if (result.contents) { |
|
1465 var contents = result.contents; |
|
1466 for (index=0; index < contents.length; index++) { |
|
1467 content = contents[index]; |
|
1468 container = $(content.target); |
|
1469 if (content.raw === true) { |
|
1470 container.text(content.text); |
|
1471 } else { |
|
1472 container.html(content.html); |
|
1473 ams.initContent && ams.initContent(container); |
|
1474 } |
|
1475 if (!content.keep_hidden) { |
|
1476 container.removeClass('hidden'); |
|
1477 } |
|
1478 } |
|
1479 } |
|
1480 |
|
1481 var message; |
|
1482 if (result.message) { |
|
1483 message = result.message; |
|
1484 if (typeof(message) === 'string') { |
|
1485 if ((status === 'info') || (status === 'success')) { |
|
1486 ams.skin && ams.skin.smallBox(status, { |
|
1487 title: message, |
|
1488 icon: 'fa fa-fw fa-info-circle font-xs align-top margin-top-10', |
|
1489 timeout: 3000 |
|
1490 }); |
|
1491 } else { |
|
1492 ams.skin && ams.skin.alert($(form || '#content'), status, message); |
|
1493 } |
|
1494 } else { |
|
1495 ams.skin && ams.skin.alert($(message.target || target || form || '#content'), |
|
1496 message.status || 'success', |
|
1497 message.header, |
|
1498 message.body, |
|
1499 message.subtitle); |
|
1500 } |
|
1501 } |
|
1502 if (result.smallbox) { |
|
1503 message = result.smallbox; |
|
1504 if (typeof(message) === 'string') { |
|
1505 ams.skin && ams.skin.smallBox(result.smallbox_status || status, { |
|
1506 title: result.smallbox, |
|
1507 icon: result.smallbox_icon || 'fa fa-fw fa-info-circle font-xs align-top margin-top-10', |
|
1508 timeout: result.smallbox_timeout || 3000 |
|
1509 }); |
|
1510 } else { |
|
1511 ams.skin && ams.skin.smallBox(message.status || status, { |
|
1512 title: message.message, |
|
1513 icon: message.icon || 'fa fa-fw fa-info-circle font-xs align-top margin-top-10', |
|
1514 timeout: message.timeout || 3000 |
|
1515 }); |
|
1516 } |
|
1517 } |
|
1518 if (result.messagebox) { |
|
1519 message = result.messagebox; |
|
1520 if (typeof(message) === 'string') { |
|
1521 ams.skin && ams.skin.messageBox('info', { |
|
1522 title: ams.i18n.ERROR_OCCURED, |
|
1523 content: message, |
|
1524 timeout: 10000 |
|
1525 }); |
|
1526 } else { |
|
1527 var messageStatus = message.status || 'info'; |
|
1528 if (messageStatus === 'error' && form && target) { |
|
1529 ams.executeFunctionByName(form.data('ams-form-submit-error') || 'MyAMS.form.finalizeSubmitOnError', form, target); |
|
1530 } |
|
1531 ams.skin && ams.skin.messageBox(messageStatus, { |
|
1532 title: message.title || ams.i18n.ERROR_OCCURED, |
|
1533 content: message.content, |
|
1534 icon: message.icon, |
|
1535 number: message.number, |
|
1536 timeout: message.timeout === null ? undefined : (message.timeout || 10000) |
|
1537 }); |
|
1538 } |
|
1539 } |
|
1540 if (result.event) { |
|
1541 form.trigger(result.event, result.event_options); |
|
1542 } |
|
1543 if (result.events) { |
|
1544 var event; |
|
1545 if (form === undefined) { |
|
1546 form = $(document); |
|
1547 } |
|
1548 for (index =0; index < result.events.length; index++) { |
|
1549 event = result.events[index]; |
|
1550 if (event === null) { |
|
1551 continue; |
|
1552 } |
|
1553 if (typeof(event) === 'string') { |
|
1554 form.trigger(event, result.events_options); |
|
1555 } else { |
|
1556 form.trigger(event.event, event.options); |
|
1557 } |
|
1558 } |
|
1559 } |
|
1560 if (result.callback) { |
|
1561 ams.executeFunctionByName(result.callback, form, result.options); |
|
1562 } |
|
1563 if (result.callbacks) { |
|
1564 var callback; |
|
1565 for (index=0; index < result.callbacks.length; index++) { |
|
1566 callback = result.callbacks[index]; |
|
1567 if (typeof(callback) === 'function') { |
|
1568 ams.executeFunctionByName(callback, form, callback.options); |
|
1569 } else { |
|
1570 ams.executeFunctionByName(callback.callback, form, callback.options); |
|
1571 } |
|
1572 } |
|
1573 } |
|
1574 } |
|
1575 }; |
|
1576 |
|
1577 })(jQuery, this); |
|
1578 |
|
1579 /** |
|
1580 * MyAMS JSON-RPC features |
|
1581 */ |
|
1582 (function($, globals) { |
|
1583 |
|
1584 var ams = globals.MyAMS; |
|
1585 |
|
1586 ams.jsonrpc = { |
|
1587 |
|
1588 /** |
|
1589 * Get address relative to current page |
|
1590 */ |
|
1591 getAddr: function(addr) { |
|
1592 var href = addr || $('HTML HEAD BASE').attr('href') || window.location.href; |
|
1593 var target = href.replace(/\+\+skin\+\+\w+\//, ''); |
|
1594 return target.substr(0, target.lastIndexOf("/") + 1); |
|
1595 }, |
|
1596 |
|
1597 /** |
|
1598 * Execute JSON-RPC request on given method |
|
1599 * |
|
1600 * Query can be given as a simple "query" string or as an object containing all query parameters. |
|
1601 * Parameters: |
|
1602 * - @query: query string (posted as "query" parameter) or object containing all parameters |
|
1603 * - @method: name of JSON-RPC procedure to call |
|
1604 * - @options: additional JSON-RPC procedure parameters |
|
1605 * - @callback: name of a callback which will be called on server response |
|
1606 */ |
|
1607 query: function(query, method, options, callback) { |
|
1608 ams.ajax && ams.ajax.check($.jsonRPC, |
|
1609 ams.baseURL + 'ext/jquery-jsonrpc' + ams.devext + '.js', |
|
1610 function() { |
|
1611 if (typeof (options) === 'function') { |
|
1612 callback = options; |
|
1613 options = {}; |
|
1614 } else if (!options) { |
|
1615 options = {}; |
|
1616 } |
|
1617 if (callback === 'undefined') { |
|
1618 callback = options.callback; |
|
1619 } |
|
1620 if (typeof (callback) === 'string') { |
|
1621 callback = ams.getFunctionByName(callback); |
|
1622 } |
|
1623 delete options.callback; |
|
1624 |
|
1625 var params = {}; |
|
1626 if (typeof (query) === 'string') { |
|
1627 params.query = query; |
|
1628 } else if (typeof (query) === 'object') { |
|
1629 $.extend(params, query); |
|
1630 } |
|
1631 $.extend(params, options); |
|
1632 |
|
1633 var result; |
|
1634 var defaults = { |
|
1635 id: new Date().getTime(), |
|
1636 params: params, |
|
1637 success: callback || function(data) { |
|
1638 result = data; |
|
1639 }, |
|
1640 error: ams.error && ams.error.show |
|
1641 }; |
|
1642 var settings = $.extend({}, defaults, options); |
|
1643 $.jsonRPC.withOptions({ |
|
1644 endPoint: ams.jsonrpc.getAddr(options.url), |
|
1645 namespace: options.namespace, |
|
1646 cache: false |
|
1647 }, function() { |
|
1648 $.jsonRPC.request(method, settings); |
|
1649 }); |
|
1650 return result; |
|
1651 }); |
|
1652 }, |
|
1653 |
|
1654 /** |
|
1655 * Execute given JSON-RPC post on given method |
|
1656 * |
|
1657 * Parameters: |
|
1658 * - @method: name of JSON-RPC procedure to call |
|
1659 * - @options: additional JSON-RPC method call parameters |
|
1660 * - @callback: name of a callback which will be called on server response |
|
1661 */ |
|
1662 post: function(method, data, options, callback) { |
|
1663 ams.ajax && ams.ajax.check($.jsonRPC, |
|
1664 ams.baseURL + 'ext/jquery-jsonrpc' + ams.devext + '.js', |
|
1665 function() { |
|
1666 if (typeof (options) === 'function') { |
|
1667 callback = options; |
|
1668 options = {}; |
|
1669 } else if (!options) { |
|
1670 options = {}; |
|
1671 } |
|
1672 if (typeof (callback) === 'undefined') { |
|
1673 callback = options.callback; |
|
1674 } |
|
1675 if (typeof (callback) === 'string') { |
|
1676 callback = ams.getFunctionByName(callback); |
|
1677 } |
|
1678 delete options.callback; |
|
1679 |
|
1680 var result; |
|
1681 var defaults = { |
|
1682 id: new Date().getTime(), |
|
1683 params: data, |
|
1684 success: callback || function(data) { |
|
1685 result = data; |
|
1686 }, |
|
1687 error: ams.error && ams.error.show |
|
1688 }; |
|
1689 var settings = $.extend({}, defaults, options); |
|
1690 $.jsonRPC.withOptions({ |
|
1691 endPoint: ams.jsonrpc.getAddr(options.url), |
|
1692 namespace: options.namespace, |
|
1693 cache: false |
|
1694 }, function() { |
|
1695 $.jsonRPC.request(method, settings); |
|
1696 }); |
|
1697 return result; |
|
1698 }); |
|
1699 } |
|
1700 }; |
|
1701 |
|
1702 })(jQuery, this); |
|
1703 |
|
1704 /** |
|
1705 * MyAMS XML-RPC features |
|
1706 */ |
|
1707 (function($, globals) { |
|
1708 |
|
1709 var ams = globals.MyAMS; |
|
1710 |
|
1711 ams.xmlrpc = { |
|
1712 |
|
1713 /** |
|
1714 * Get address relative to current page |
|
1715 */ |
|
1716 getAddr: function(addr) { |
|
1717 var href = addr || $('HTML HEAD BASE').attr('href') || window.location.href; |
|
1718 var target = href.replace(/\+\+skin\+\+\w+\//, ''); |
|
1719 return target.substr(0, target.lastIndexOf("/") + 1); |
|
1720 }, |
|
1721 |
|
1722 /** |
|
1723 * Execute given XML-RPC post on given method |
|
1724 * |
|
1725 * Parameters: |
|
1726 * - @url: base method URL |
|
1727 * - @method: name of JSON-RPC procedure to call |
|
1728 * - @options: additional JSON-RPC procedure parameters |
|
1729 * - @callback: name of a callback which will be called on server response |
|
1730 */ |
|
1731 post: function(url, method, data, options, callback) { |
|
1732 ams.ajax && ams.ajax.check($.xmlrpc, |
|
1733 ams.baseURL + 'ext/jquery-xmlrpc' + ams.devext + '.js', |
|
1734 function() { |
|
1735 if (typeof (options) === 'function') { |
|
1736 callback = options; |
|
1737 options = {}; |
|
1738 } else if (!options) { |
|
1739 options = {}; |
|
1740 } |
|
1741 if (typeof (callback) === 'undefined') { |
|
1742 callback = options.callback; |
|
1743 } |
|
1744 if (typeof (callback) === 'string') { |
|
1745 callback = ams.getFunctionByName(callback); |
|
1746 } |
|
1747 delete options.callback; |
|
1748 |
|
1749 var result; |
|
1750 var defaults = { |
|
1751 url: ams.xmlrpc.getAddr(url), |
|
1752 methodName: method, |
|
1753 params: data, |
|
1754 success: callback || function(response /*, status, xhr*/) { |
|
1755 result = response; |
|
1756 }, |
|
1757 error: ams.error && ams.error.show |
|
1758 }; |
|
1759 var settings = $.extend({}, defaults, options); |
|
1760 $.xmlrpc(settings); |
|
1761 return result; |
|
1762 }); |
|
1763 } |
|
1764 }; |
|
1765 |
|
1766 })(jQuery, this); |
|
1767 |
|
1768 /** |
|
1769 * MyAMS forms management |
|
1770 */ |
|
1771 (function($, globals) { |
|
1772 |
|
1773 var ams = globals.MyAMS; |
|
1774 |
|
1775 ams.form = { |
|
1776 |
|
1777 /** |
|
1778 * Init forms to activate form change listeners |
|
1779 * |
|
1780 * @param element: the parent element |
|
1781 */ |
|
1782 init: function(element) { |
|
1783 |
|
1784 $('FORM', element).each(function() { |
|
1785 var form = $(this); |
|
1786 // Store value of hidden inputs |
|
1787 $('INPUT.select2[type="hidden"]', form).each(function() { |
|
1788 var input = $(this); |
|
1789 input.data('ams-select2-input-value', input.val()); |
|
1790 }); |
|
1791 }); |
|
1792 |
|
1793 // Activate form changes if required |
|
1794 var forms; |
|
1795 if (ams.warnOnFormChange) { |
|
1796 forms = $('FORM[data-ams-warn-on-change!="false"]', element); |
|
1797 } else { |
|
1798 forms = $('FORM[data-ams-warn-on-change="true"]', element); |
|
1799 } |
|
1800 forms.each(function() { |
|
1801 var form = $(this), |
|
1802 formChangedCallback = form.data('ams-form-changed-callback') || |
|
1803 ams.formChangedCallback; |
|
1804 $('INPUT[type="text"], ' + |
|
1805 'INPUT[type="checkbox"], ' + |
|
1806 'INPUT[type="radio"], ' + |
|
1807 'SELECT, ' + |
|
1808 'TEXTAREA, ' + |
|
1809 '[data-ams-changed-event]', form).each(function() { |
|
1810 var source = $(this); |
|
1811 if (source.data('ams-ignore-change') !== true) { |
|
1812 var event = source.data('ams-changed-event') || 'change'; |
|
1813 source.on(event, function () { |
|
1814 ams.form.setChanged(form); |
|
1815 ams.executeFunctionByName(formChangedCallback, form, source); |
|
1816 }); |
|
1817 } |
|
1818 }); |
|
1819 form.on('reset', function() { |
|
1820 ams.form.resetChanged($(this)); |
|
1821 }); |
|
1822 }); |
|
1823 }, |
|
1824 |
|
1825 /** |
|
1826 * Set focus to first container input |
|
1827 */ |
|
1828 setFocus: function(container) { |
|
1829 var focused = $('[data-ams-focus-target]', container).first(); |
|
1830 if (!focused.exists()) { |
|
1831 focused = $('input, select', container).first(); |
|
1832 } |
|
1833 if (focused.exists()) { |
|
1834 if (focused.hasClass('select2-input')) { |
|
1835 focused = focused.parents('.select2'); |
|
1836 } |
|
1837 if (focused.hasClass('select2')) { |
|
1838 setTimeout(function() { |
|
1839 focused.select2('focus'); |
|
1840 if (focused.data('ams-focus-open') === true) { |
|
1841 focused.select2('open'); |
|
1842 } |
|
1843 }, 100); |
|
1844 } else { |
|
1845 focused.focus(); |
|
1846 } |
|
1847 } |
|
1848 }, |
|
1849 |
|
1850 /** |
|
1851 * Check for modified forms before exiting |
|
1852 */ |
|
1853 checkBeforeUnload: function() { |
|
1854 var forms = $('FORM[data-ams-form-changed="true"]'); |
|
1855 if (forms.exists()) { |
|
1856 return ams.i18n.FORM_CHANGED_WARNING; |
|
1857 } |
|
1858 }, |
|
1859 |
|
1860 /** |
|
1861 * Check for modified forms before loading new inner content |
|
1862 */ |
|
1863 confirmChangedForm: function(element, callback, cancelCallback) { |
|
1864 if (typeof(element) === 'function') { |
|
1865 callback = element; |
|
1866 element = undefined; |
|
1867 } |
|
1868 var forms = $('FORM[data-ams-form-changed="true"]', element); |
|
1869 if (forms.exists()) { |
|
1870 if (cancelCallback) { |
|
1871 if (globals.confirm(ams.i18n.FORM_CHANGED_WARNING, ams.i18n.WARNING)) { |
|
1872 callback.call(element); |
|
1873 } else { |
|
1874 cancelCallback.call(element); |
|
1875 } |
|
1876 } else { |
|
1877 ams.skin && ams.skin.bigBox({ |
|
1878 title: ams.i18n.WARNING, |
|
1879 content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i> ' + ams.i18n.FORM_CHANGED_WARNING, |
|
1880 buttons: ams.i18n.BTN_OK_CANCEL |
|
1881 }, function(button) { |
|
1882 if (button === ams.i18n.BTN_OK) { |
|
1883 callback.call(element); |
|
1884 } |
|
1885 }); |
|
1886 } |
|
1887 } else { |
|
1888 callback.call(element); |
|
1889 } |
|
1890 }, |
|
1891 |
|
1892 /** |
|
1893 * Update form "chenged" status flag |
|
1894 */ |
|
1895 setChanged: function(form) { |
|
1896 form.attr('data-ams-form-changed', true); |
|
1897 }, |
|
1898 |
|
1899 /** |
|
1900 * Reset form changed flag |
|
1901 */ |
|
1902 resetChanged: function(form) { |
|
1903 if (form !== undefined) { |
|
1904 $(form).removeAttr('data-ams-form-changed'); |
|
1905 } |
|
1906 }, |
|
1907 |
|
1908 /** |
|
1909 * Submit given form |
|
1910 */ |
|
1911 submit: function(form, handler, submitOptions) { |
|
1912 // Check params |
|
1913 form = $(form); |
|
1914 if (!form.exists()) { |
|
1915 return false; |
|
1916 } |
|
1917 if (typeof(handler) === 'object') { |
|
1918 submitOptions = handler; |
|
1919 handler = undefined; |
|
1920 } |
|
1921 // Prevent multiple submits of the same form |
|
1922 if (form.data('submitted')) { |
|
1923 if (!form.data('ams-form-hide-submitted')) { |
|
1924 ams.skin && ams.skin.messageBox('warning', { |
|
1925 title: ams.i18n.WAIT, |
|
1926 content: ams.i18n.FORM_SUBMITTED, |
|
1927 icon: 'fa fa-save shake animated', |
|
1928 timeout: form.data('ams-form-alert-timeout') || 5000 |
|
1929 }); |
|
1930 } |
|
1931 return false; |
|
1932 } |
|
1933 // Check submit validators |
|
1934 if (ams.form && !ams.form._checkSubmitValidators(form)) { |
|
1935 return false; |
|
1936 } |
|
1937 // Remove remaining status messages |
|
1938 $('.alert-danger, SPAN.state-error', form).not('.persistent').remove(); |
|
1939 $('.state-error', form).removeClassPrefix('state-'); |
|
1940 // Check submit button |
|
1941 var button = $(form.data('ams-submit-button')); |
|
1942 if (button && !button.data('ams-form-hide-loading')) { |
|
1943 button.data('ams-progress-content', button.html()); |
|
1944 button.button('loading'); |
|
1945 } |
|
1946 ams.ajax && ams.ajax.check($.fn.ajaxSubmit, |
|
1947 ams.baseURL + 'ext/jquery-form-3.49' + ams.devext + '.js', |
|
1948 function() { |
|
1949 |
|
1950 function _submitAjaxForm(form, options) { |
|
1951 |
|
1952 var button, |
|
1953 buttonData, |
|
1954 buttonTarget, |
|
1955 data = form.data(), |
|
1956 formOptions = data.amsFormOptions, |
|
1957 formData, |
|
1958 formDataCallback; |
|
1959 |
|
1960 var progressHandler, |
|
1961 progressInterval, |
|
1962 progressCallback, |
|
1963 progressEndCallback; |
|
1964 |
|
1965 // Inner progress status handler |
|
1966 function _getProgress(handler, progress_id) { |
|
1967 |
|
1968 var timeout; |
|
1969 |
|
1970 function _clearProgressStatus() { |
|
1971 clearTimeout(timeout); |
|
1972 ams.form.resetAfterSubmit(form, button); |
|
1973 button.html(button.data('ams-progress-content')); |
|
1974 ams.executeFunctionByName(progressEndCallback, form, button); |
|
1975 ams.form.resetChanged(form); |
|
1976 } |
|
1977 |
|
1978 function _getProgressStatus() { |
|
1979 ams.ajax && ams.ajax.post(handler, |
|
1980 {progress_id: progress_id}, |
|
1981 {error: _clearProgressStatus}, |
|
1982 ams.getFunctionByName(progressCallback) || function(result, status) { |
|
1983 if (status === 'success') { |
|
1984 if (result.status === 'running') { |
|
1985 if (result.message) { |
|
1986 button.text(result.message); |
|
1987 } else { |
|
1988 var text = button.data('ams-progress-text') || ams.i18n.PROGRESS; |
|
1989 if (result.current) { |
|
1990 text += ': ' + result.current + '/ ' + (result.length || 100); |
|
1991 } else { |
|
1992 text += '...'; |
|
1993 } |
|
1994 button.text(text); |
|
1995 } |
|
1996 timeout = setTimeout(_getProgressStatus, progressInterval); |
|
1997 } else if (result.status === 'finished') { |
|
1998 _clearProgressStatus(); |
|
1999 } |
|
2000 } else { |
|
2001 _clearProgressStatus(); |
|
2002 } |
|
2003 }); |
|
2004 } |
|
2005 |
|
2006 button.button('loading'); |
|
2007 timeout = setTimeout(_getProgressStatus, progressInterval); |
|
2008 } |
|
2009 |
|
2010 // Initialize form data |
|
2011 if (submitOptions) { |
|
2012 formDataCallback = submitOptions.formDataInitCallback; |
|
2013 } |
|
2014 if (formDataCallback) { |
|
2015 delete submitOptions.formDataInitCallback; |
|
2016 } else { |
|
2017 formDataCallback = data.amsFormDataInitCallback; |
|
2018 } |
|
2019 if (formDataCallback) { |
|
2020 var veto = {}; |
|
2021 formData = ams.executeFunctionByName(formDataCallback, form, veto); |
|
2022 if (veto.veto) { |
|
2023 button = form.data('ams-submit-button'); |
|
2024 if (button) { |
|
2025 button.button('reset'); |
|
2026 } |
|
2027 ams.form.finalizeSubmitFooter.call(form); |
|
2028 return false; |
|
2029 } |
|
2030 } else { |
|
2031 formData = data.amsFormData || {}; |
|
2032 } |
|
2033 |
|
2034 // Check submit button for custom action handler and target |
|
2035 button = $(form.data('ams-submit-button')); |
|
2036 if (button && button.exists()) { |
|
2037 buttonData = button.data(); |
|
2038 buttonTarget = buttonData.amsFormSubmitTarget; |
|
2039 } else { |
|
2040 buttonData = {}; |
|
2041 } |
|
2042 |
|
2043 // Check action URL |
|
2044 var url; |
|
2045 var formHandler = handler || buttonData.amsFormHandler || data.amsFormHandler || ''; |
|
2046 if (formHandler.startsWith(window.location.protocol)) { |
|
2047 url = formHandler; |
|
2048 } else { |
|
2049 var action = buttonData.amsFormAction || form.attr('action').replace(/#/, ''); |
|
2050 if (action.startsWith(window.location.protocol)) { |
|
2051 url = action; |
|
2052 } else { |
|
2053 url = ams.ajax && (ams.ajax.getAddr() + action); |
|
2054 } |
|
2055 url += formHandler; |
|
2056 } |
|
2057 progressHandler = buttonData.amsProgressHandler || data.amsProgressHandler || ''; |
|
2058 progressInterval = buttonData.amsProgressInterval || data.amsProgressInterval || 1000; |
|
2059 progressCallback = buttonData.amsProgressCallback || data.amsProgressCallback; |
|
2060 progressEndCallback = buttonData.amsProgressEndCallback || data.amsProgressEndCallback; |
|
2061 |
|
2062 // Initialize submit target with AJAX indicator |
|
2063 var target = null; |
|
2064 if (submitOptions && submitOptions.initSubmitTarget) { |
|
2065 ams.executeFunctionByName(submitOptions.initSubmitTarget, form); |
|
2066 } else { |
|
2067 if (data.amsFormInitSubmitTarget) { |
|
2068 target = $(buttonTarget || data.amsFormSubmitTarget || '#content'); |
|
2069 ams.executeFunctionByName(data.amsFormInitSubmit || 'MyAMS.form.initSubmit', form, target); |
|
2070 } else if (!data.amsFormHideSubmitFooter) { |
|
2071 ams.executeFunctionByName(data.amsFormInitSubmit || 'MyAMS.form.initSubmitFooter', form); |
|
2072 } |
|
2073 } |
|
2074 |
|
2075 // Complete form data |
|
2076 if (submitOptions) { |
|
2077 formData = $.extend({}, formData, submitOptions.form_data); |
|
2078 } |
|
2079 |
|
2080 // Check progress handler |
|
2081 var hasUpload; |
|
2082 if (progressHandler) { |
|
2083 formData.progress_id = ams.generateUUID(); |
|
2084 } else { |
|
2085 // Check progress meter via Apache progress module |
|
2086 hasUpload = typeof (options.uuid) !== 'undefined'; |
|
2087 if (hasUpload) { |
|
2088 if (url.indexOf('X-Progress-ID') < 0) { |
|
2089 url += "?X-Progress-ID=" + options.uuid; |
|
2090 } |
|
2091 delete options.uuid; |
|
2092 } |
|
2093 } |
|
2094 |
|
2095 // Initialize default AJAX settings |
|
2096 var defaults = { |
|
2097 url: url, |
|
2098 type: 'post', |
|
2099 cache: false, |
|
2100 data: formData, |
|
2101 dataType: data.amsFormDatatype, |
|
2102 beforeSerialize: function(/*form, options*/) { |
|
2103 form.trigger('myams.form.before-serialize'); |
|
2104 if (typeof (globals.tinyMCE) !== 'undefined') { |
|
2105 globals.tinyMCE.triggerSave(); |
|
2106 } |
|
2107 }, |
|
2108 beforeSubmit: function(data, form /*, options*/) { |
|
2109 form.trigger('myams.form.before-submit', [data]); |
|
2110 form.data('submitted', true); |
|
2111 if (form.data('ams-form-reset-before-submit')) { |
|
2112 setTimeout(function() { |
|
2113 ams.form.resetAfterSubmit(form); |
|
2114 }, 250); |
|
2115 } |
|
2116 }, |
|
2117 error: function(request, status, error, form) { |
|
2118 form.trigger('myams.form.submit-error', [request, status, error]); |
|
2119 if (target) { |
|
2120 ams.executeFunctionByName(data.amsFormSubmitError || 'MyAMS.form.finalizeSubmitOnError', form, target); |
|
2121 } |
|
2122 ams.form.resetAfterSubmit(form); |
|
2123 }, |
|
2124 iframe: hasUpload |
|
2125 }; |
|
2126 |
|
2127 // Initialize IFrame for custom download target |
|
2128 var downloadTarget = (submitOptions && submitOptions.downloadTarget) || data.amsFormDownloadTarget; |
|
2129 if (downloadTarget) { |
|
2130 var iframe = $('iframe[name="' + downloadTarget + '"]'); |
|
2131 if (!iframe.exists()) { |
|
2132 iframe = $('<iframe></iframe>').hide() |
|
2133 .attr('name', downloadTarget) |
|
2134 .appendTo($('body')); |
|
2135 } |
|
2136 defaults = $.extend({}, defaults, { |
|
2137 iframe: true, |
|
2138 iframeTarget: iframe, |
|
2139 success: function(result, status, request, form) { |
|
2140 form.trigger('myams.form.after-submit', [result, status, request]); |
|
2141 var modal = $(form).parents('.modal-dialog'); |
|
2142 if (modal.exists()) { |
|
2143 ams.dialog && ams.dialog.close(form); |
|
2144 } else { |
|
2145 var callback, |
|
2146 button = form.data('ams-submit-button'); |
|
2147 if (button) { |
|
2148 callback = button.data('ams-form-submit-callback'); |
|
2149 } |
|
2150 if (!callback) { |
|
2151 callback = ams.getFunctionByName(data.amsFormSubmitCallback) || ams.form._submitCallback; |
|
2152 } |
|
2153 try { |
|
2154 callback.call(form, result, status, request, form); |
|
2155 } finally { |
|
2156 ams.form.resetAfterSubmit(form); |
|
2157 ams.form.resetChanged(form); |
|
2158 } |
|
2159 } |
|
2160 } |
|
2161 }); |
|
2162 } else { |
|
2163 defaults = $.extend({}, defaults, { |
|
2164 error: function(request, status, error, form) { |
|
2165 if (target) { |
|
2166 ams.executeFunctionByName(data.amsFormSubmitError || 'MyAMS.form.finalizeSubmitOnError', form, target); |
|
2167 } |
|
2168 ams.form.resetAfterSubmit(form); |
|
2169 }, |
|
2170 success: function(result, status, request, form) { |
|
2171 form.trigger('myams.form.after-submit', [result, status, request]); |
|
2172 var callback, |
|
2173 button = form.data('ams-submit-button'); |
|
2174 if (button) { |
|
2175 callback = button.data('ams-form-submit-callback'); |
|
2176 } |
|
2177 if (!callback) { |
|
2178 callback = ams.getFunctionByName(data.amsFormSubmitCallback) || ams.form._submitCallback; |
|
2179 } |
|
2180 try { |
|
2181 callback.call(form, result, status, request, form); |
|
2182 } finally { |
|
2183 ams.form.resetAfterSubmit(form); |
|
2184 ams.form.resetChanged(form); |
|
2185 } |
|
2186 }, |
|
2187 iframe: hasUpload |
|
2188 }); |
|
2189 } |
|
2190 var settings = $.extend({}, defaults, options, formOptions, submitOptions); |
|
2191 |
|
2192 // Initialize progress handler |
|
2193 if (progressHandler) { |
|
2194 _getProgress(progressHandler, formData.progress_id); |
|
2195 } |
|
2196 |
|
2197 // Submit form |
|
2198 $(form).ajaxSubmit(settings); |
|
2199 |
|
2200 // If external download target is specified, reset form submit button and footer |
|
2201 if (downloadTarget) { |
|
2202 var modal = $(form).parents('.modal-dialog'); |
|
2203 var keepModal = modal.exists() && button.exists() && button.data('ams-keep-modal'); |
|
2204 if (modal.exists() && (keepModal !== true)) { |
|
2205 ams.dialog && ams.dialog.close(form); |
|
2206 } else { |
|
2207 if (!progressHandler) { |
|
2208 setTimeout(function() { |
|
2209 ams.form.resetAfterSubmit(form, button); |
|
2210 ams.form.resetChanged(form); |
|
2211 }, button.data('ams-form-reset-timeout') || 2000); |
|
2212 } |
|
2213 } |
|
2214 } |
|
2215 } |
|
2216 |
|
2217 var hasUpload = (form.data('ams-form-ignore-uploads') !== true) && |
|
2218 ($('INPUT[type="file"]', form).length > 0); |
|
2219 if (hasUpload) { |
|
2220 // JQuery-progressbar plug-in must be loaded synchronously!! |
|
2221 // Otherwise, hidden input fields created by jquery-validate plug-in |
|
2222 // and matching named buttons will be deleted (on first form submit) |
|
2223 // before JQuery-form plug-in can get them when submitting the form... |
|
2224 ams.ajax && ams.ajax.check($.progressBar, |
|
2225 ams.baseURL + 'ext/jquery-progressbar' + ams.devext + '.js'); |
|
2226 var settings = $.extend({}, { |
|
2227 uuid: $.progressBar.submit(form) |
|
2228 }); |
|
2229 _submitAjaxForm(form, settings); |
|
2230 } else { |
|
2231 _submitAjaxForm(form, {}); |
|
2232 } |
|
2233 }); |
|
2234 return false; |
|
2235 }, |
|
2236 |
|
2237 /** |
|
2238 * Initialize AJAX submit call |
|
2239 * |
|
2240 * @param this: the submitted form |
|
2241 * @param target: the form submit container target |
|
2242 * @param message: the optional message |
|
2243 */ |
|
2244 initSubmit: function(target, message) { |
|
2245 var form = $(this), |
|
2246 spin = '<i class="fa fa-3x fa-gear fa-spin"></i>'; |
|
2247 if (!message) { |
|
2248 message = form.data('ams-form-submit-message'); |
|
2249 } |
|
2250 if (message) { |
|
2251 spin += '<strong>' + message + '</strong>'; |
|
2252 } |
|
2253 $(target).html('<div class="row margin-20"><div class="text-center">' + spin + '</div></div>'); |
|
2254 $(target).parents('.hidden').removeClass('hidden'); |
|
2255 }, |
|
2256 |
|
2257 /** |
|
2258 * Reset form status after submit |
|
2259 * |
|
2260 * @param form: the submitted form |
|
2261 */ |
|
2262 resetAfterSubmit: function(form) { |
|
2263 if (form.data('submitted')) { |
|
2264 if (form.is(':visible')) { |
|
2265 var button = form.data('ams-submit-button'); |
|
2266 if (button) { |
|
2267 button.button('reset'); |
|
2268 } |
|
2269 ams.form.finalizeSubmitFooter.call(form); |
|
2270 } |
|
2271 form.data('submitted', false); |
|
2272 form.removeData('ams-submit-button'); |
|
2273 form.trigger('myams.form.after-reset'); |
|
2274 } |
|
2275 }, |
|
2276 |
|
2277 /** |
|
2278 * Finalize AJAX submit call |
|
2279 * |
|
2280 * @param target: the form submit container target |
|
2281 */ |
|
2282 finalizeSubmitOnError: function(target) { |
|
2283 $('i', target).removeClass('fa-spin') |
|
2284 .removeClass('fa-gear') |
|
2285 .addClass('fa-ambulance'); |
|
2286 }, |
|
2287 |
|
2288 /** |
|
2289 * Initialize AJAX submit call in form footer |
|
2290 * |
|
2291 * @param this: the submitted form |
|
2292 * @param message: the optional submit message |
|
2293 */ |
|
2294 initSubmitFooter: function(message) { |
|
2295 var form = $(this), |
|
2296 spin = '<i class="fa fa-3x fa-gear fa-spin"></i>'; |
|
2297 if (!message) { |
|
2298 message = $(this).data('ams-form-submit-message'); |
|
2299 } |
|
2300 if (message) { |
|
2301 spin += '<strong class="submit-message align-top padding-left-10 margin-top-10">' + message + '</strong>'; |
|
2302 } |
|
2303 var footer = $('footer', form); |
|
2304 $('button', footer).hide(); |
|
2305 footer.append('<div class="row"><div class="text-center">' + spin + '</div></div>'); |
|
2306 }, |
|
2307 |
|
2308 /** |
|
2309 * Finalize AJAX submit call |
|
2310 * |
|
2311 * @param this: the submitted form |
|
2312 * @param target: the form submit container target |
|
2313 */ |
|
2314 finalizeSubmitFooter: function(/*target*/) { |
|
2315 var form = $(this), |
|
2316 footer = $('footer', form); |
|
2317 if (footer) { |
|
2318 $('.row', footer).remove(); |
|
2319 $('button', footer).show(); |
|
2320 } |
|
2321 }, |
|
2322 |
|
2323 /** |
|
2324 * Handle AJAX submit results |
|
2325 * |
|
2326 * Submit results are auto-detected via response content type, except when this content type |
|
2327 * is specified into form's data attributes. |
|
2328 * Submit response can be of several content types: |
|
2329 * - html or text: the response is directly included into a "target" container (#content by default) |
|
2330 * - json: a "status" attribute indicates how the request was handled and how the response should be |
|
2331 * treated: |
|
2332 * - error: indicates that an error occured; other response attributes indicate error messages |
|
2333 * - success: basic success, no other action is requested |
|
2334 * - callback: only call given function to handle the result |
|
2335 * - callbacks: only call given set of functions to handle the result |
|
2336 * - reload: page's body should be reloaded from a given URL |
|
2337 * - redirect: redirect browser to given URL |
|
2338 * Each JSON response can also specify an HTML content, a message and a callback ( |
|
2339 */ |
|
2340 _submitCallback: function(result, status, request, form) { |
|
2341 |
|
2342 var button; |
|
2343 if (form.is(':visible')) { |
|
2344 ams.form.finalizeSubmitFooter.call(form); |
|
2345 button = form.data('ams-submit-button'); |
|
2346 if (button) { |
|
2347 button.button('reset'); |
|
2348 } |
|
2349 } |
|
2350 |
|
2351 var data = form.data(), |
|
2352 dataType; |
|
2353 if (data.amsFormDatatype) { |
|
2354 dataType = data.amsFormDatatype; |
|
2355 } else { |
|
2356 var response = ams.ajax && ams.ajax.getResponse(request); |
|
2357 if (response) { |
|
2358 dataType = response.contentType; |
|
2359 result = response.data; |
|
2360 } |
|
2361 } |
|
2362 |
|
2363 var target; |
|
2364 if (button) { |
|
2365 target = $(button.data('ams-form-submit-target') || data.amsFormSubmitTarget || '#content'); |
|
2366 } else { |
|
2367 target = $(data.amsFormSubmitTarget || '#content'); |
|
2368 } |
|
2369 |
|
2370 switch (dataType) { |
|
2371 case 'json': |
|
2372 ams.ajax && ams.ajax.handleJSON(result, form, target); |
|
2373 break; |
|
2374 case 'script': |
|
2375 break; |
|
2376 case 'xml': |
|
2377 break; |
|
2378 case 'html': |
|
2379 /* falls through */ |
|
2380 case 'text': |
|
2381 /* falls through */ |
|
2382 default: |
|
2383 ams.form.resetChanged(form); |
|
2384 if (button && (button.data('ams-keep-modal') !== true)) { |
|
2385 ams.dialog && ams.dialog.close(form); |
|
2386 } |
|
2387 if (!target.exists()) { |
|
2388 target = $('body'); |
|
2389 } |
|
2390 target.parents('.hidden').removeClass('hidden'); |
|
2391 $('.alert', target.parents('.alerts-container')).remove(); |
|
2392 target.css({opacity: '0.0'}) |
|
2393 .html(result) |
|
2394 .delay(50) |
|
2395 .animate({opacity: '1.0'}, 300); |
|
2396 ams.initContent && ams.initContent(target); |
|
2397 ams.form.setFocus(target); |
|
2398 } |
|
2399 var callback = request.getResponseHeader('X-AMS-Callback'); |
|
2400 if (callback) { |
|
2401 var options = request.getResponseHeader('X-AMS-Callback-Options'); |
|
2402 ams.executeFunctionByName(callback, form, options === undefined ? {} : JSON.parse(options), request); |
|
2403 } |
|
2404 }, |
|
2405 |
|
2406 /** |
|
2407 * Get list of custom validators called before submit |
|
2408 */ |
|
2409 _getSubmitValidators: function(form) { |
|
2410 var validators = []; |
|
2411 var formValidator = form.data('ams-form-validator'); |
|
2412 if (formValidator) { |
|
2413 validators.push([form, formValidator]); |
|
2414 } |
|
2415 $('[data-ams-form-validator]', form).each(function() { |
|
2416 var source = $(this); |
|
2417 validators.push([source, source.data('ams-form-validator')]); |
|
2418 }); |
|
2419 return validators; |
|
2420 }, |
|
2421 |
|
2422 /** |
|
2423 * Call list of custom validators before submit |
|
2424 * |
|
2425 * Each validator can return: |
|
2426 * - a boolean 'false' value to just specify that an error occured |
|
2427 * - a string value containing an error message |
|
2428 * - an array containing a list of string error messages |
|
2429 * Any other value (undefined, null, True...) will lead to a successful submit. |
|
2430 */ |
|
2431 _checkSubmitValidators: function(form) { |
|
2432 var validators = ams.form._getSubmitValidators(form); |
|
2433 if (!validators.length) { |
|
2434 return true; |
|
2435 } |
|
2436 var output = [], |
|
2437 result = true; |
|
2438 for (var index=0; index < validators.length; index++) { |
|
2439 var validator = validators[index], |
|
2440 source = validator[0], |
|
2441 handler = validator[1], |
|
2442 validatorResult = ams.executeFunctionByName(handler, form, source); |
|
2443 if (validatorResult === false) { |
|
2444 result = false; |
|
2445 } else if (typeof(validatorResult) === 'string') { |
|
2446 output.push(validatorResult); |
|
2447 } else if (result.length && (result.length > 0)) { |
|
2448 output = output.concat(result); |
|
2449 } |
|
2450 } |
|
2451 if (output.length > 0) { |
|
2452 var header = output.length === 1 ? ams.i18n.ERROR_OCCURED : ams.i18n.ERRORS_OCCURED; |
|
2453 ams.skin && ams.skin.alert(form, 'danger', header, output); |
|
2454 return false; |
|
2455 } else { |
|
2456 return result; |
|
2457 } |
|
2458 }, |
|
2459 |
|
2460 /** |
|
2461 * Display JSON errors |
|
2462 * JSON errors should be defined in an object as is: |
|
2463 * {status: 'error', |
|
2464 * error_message: "Main error message", |
|
2465 * messages: ["Message 1", "Message 2",...] |
|
2466 * widgets: [{label: "First widget name", |
|
2467 * name: "field-name-1", |
|
2468 * message: "Error message"}, |
|
2469 * {label: "Second widget name", |
|
2470 * name: "field-name-2", |
|
2471 * message: "Second error message"},...]} |
|
2472 */ |
|
2473 showErrors: function(form, errors) { |
|
2474 var header; |
|
2475 if (typeof(errors) === 'string') { |
|
2476 ams.skin && ams.skin.alert(form, 'error', ams.i18n.ERROR_OCCURED, errors); |
|
2477 } else if (errors instanceof Array) { |
|
2478 header = errors.length === 1 ? ams.i18n.ERROR_OCCURED : ams.i18n.ERRORS_OCCURED; |
|
2479 ams.skin && ams.skin.alert(form, 'error', header, errors); |
|
2480 } else { |
|
2481 $('.state-error', form).removeClass('state-error'); |
|
2482 header = errors.error_header || |
|
2483 (errors.widgets && (errors.widgets.length > 1) ? ams.i18n.ERRORS_OCCURED : ams.i18n.ERROR_OCCURED); |
|
2484 var message = []; |
|
2485 var index; |
|
2486 if (errors.messages) { |
|
2487 for (index = 0; index < errors.messages.length; index++) { |
|
2488 var msg = errors.messages[index]; |
|
2489 if (msg.header) { |
|
2490 message.push('<strong>' + msg.header + '</strong><br />' + msg.message); |
|
2491 } else { |
|
2492 message.push(msg.message || msg); |
|
2493 } |
|
2494 } |
|
2495 } |
|
2496 if (errors.widgets) { |
|
2497 for (index = 0; index < errors.widgets.length; index++) { |
|
2498 // set widget status message |
|
2499 var widgetData = errors.widgets[index]; |
|
2500 var widget = $('[name="' + widgetData.name + '"]', form); |
|
2501 if (!widget.exists()) { |
|
2502 widget = $('[name="' + widgetData.name + ':list"]', form); |
|
2503 } |
|
2504 if (widget.exists()) { |
|
2505 // Update widget state |
|
2506 widget.parents('label, .input') |
|
2507 .first() |
|
2508 .removeClassPrefix('state-') |
|
2509 .addClass('state-error') |
|
2510 .after('<span for="name" class="state-error">' + widgetData.message + '</span>'); |
|
2511 } else { |
|
2512 // complete form alert message |
|
2513 if (widgetData.label) { |
|
2514 message.push(widgetData.label + ' : ' + widgetData.message); |
|
2515 } |
|
2516 } |
|
2517 // mark parent tab (if any) with error status |
|
2518 var tabIndex = widget.parents('.tab-pane').index() + 1; |
|
2519 if (tabIndex > 0) { |
|
2520 var navTabs = $('.nav-tabs', $(widget).parents('.tabforms')); |
|
2521 $('li:nth-child(' + tabIndex + ')', navTabs).removeClassPrefix('state-') |
|
2522 .addClass('state-error'); |
|
2523 $('li.state-error:first a', form).click(); |
|
2524 } |
|
2525 } |
|
2526 } |
|
2527 ams.skin && ams.skin.alert($('.form-group:first', form), errors.error_level || 'error', header, message, errors.error_message); |
|
2528 } |
|
2529 } |
|
2530 }; |
|
2531 |
|
2532 })(jQuery, this); |
|
2533 |
|
2534 /** |
|
2535 * MyAMS modal dialogs management |
|
2536 */ |
|
2537 (function($, globals) { |
|
2538 |
|
2539 var ams = globals.MyAMS; |
|
2540 |
|
2541 ams.dialog = { |
|
2542 |
|
2543 /** |
|
2544 * List of registered 'shown' callbacks |
|
2545 */ |
|
2546 _shown_callbacks: [], |
|
2547 |
|
2548 /** |
|
2549 * Register a callback which should be called when a dialog is shown |
|
2550 */ |
|
2551 registerShownCallback: function(callback, element) { |
|
2552 var dialog; |
|
2553 if (element) { |
|
2554 dialog = element.objectOrParentWithClass('modal-dialog'); |
|
2555 } |
|
2556 |
|
2557 var callbacks; |
|
2558 if (dialog && dialog.exists()) { |
|
2559 callbacks = dialog.data('shown-callbacks'); |
|
2560 if (callbacks === undefined) { |
|
2561 callbacks = []; |
|
2562 dialog.data('shown-callbacks', callbacks); |
|
2563 } |
|
2564 } else { |
|
2565 callbacks = ams.dialog._shown_callbacks; |
|
2566 } |
|
2567 if (callbacks.indexOf(callback) < 0) { |
|
2568 callbacks.push(callback); |
|
2569 } |
|
2570 }, |
|
2571 |
|
2572 /** |
|
2573 * List of registered 'hide' callbacks |
|
2574 */ |
|
2575 _hide_callbacks: [], |
|
2576 |
|
2577 /** |
|
2578 * Register a callback which should be called when a dialog is closed |
|
2579 */ |
|
2580 registerHideCallback: function(callback, element) { |
|
2581 var dialog; |
|
2582 if (element) { |
|
2583 dialog = element.objectOrParentWithClass('modal-dialog'); |
|
2584 } |
|
2585 |
|
2586 var callbacks; |
|
2587 if (dialog && dialog.exists()) { |
|
2588 callbacks = dialog.data('hide-callbacks'); |
|
2589 if (callbacks === undefined) { |
|
2590 callbacks = []; |
|
2591 dialog.data('hide-callbacks', callbacks); |
|
2592 } |
|
2593 } else { |
|
2594 callbacks = ams.dialog._hide_callbacks; |
|
2595 } |
|
2596 if (callbacks.indexOf(callback) < 0) { |
|
2597 callbacks.push(callback); |
|
2598 } |
|
2599 }, |
|
2600 |
|
2601 /** |
|
2602 * Modal dialog opener |
|
2603 */ |
|
2604 open: function(source, options, callbacks) { |
|
2605 ams.ajax && ams.ajax.check($.fn.modalmanager, |
|
2606 ams.baseURL + 'ext/bootstrap-modalmanager' + ams.devext + '.js', |
|
2607 function() { |
|
2608 ams.ajax.check($.fn.modal.defaults, |
|
2609 ams.baseURL + 'ext/bootstrap-modal' + ams.devext + '.js', |
|
2610 function(first_load) { |
|
2611 if (first_load) { |
|
2612 $(document).off('click.modal'); |
|
2613 $.fn.modal.defaults.spinner = $.fn.modalmanager.defaults.spinner = |
|
2614 '<div class="loading-spinner" style="width: 200px; margin-left: -100px;">' + |
|
2615 '<div class="progress progress-striped active">' + |
|
2616 '<div class="progress-bar" style="width: 100%;"></div>' + |
|
2617 '</div>' + |
|
2618 '</div>'; |
|
2619 } |
|
2620 |
|
2621 var sourceData; |
|
2622 var url; |
|
2623 if (typeof (source) === 'string') { |
|
2624 sourceData = {}; |
|
2625 url = source; |
|
2626 } else { |
|
2627 sourceData = source.data(); |
|
2628 url = source.attr('href') || sourceData.amsUrl; |
|
2629 var url_getter = ams.getFunctionByName(url); |
|
2630 if (typeof (url_getter) === 'function') { |
|
2631 url = url_getter.call(source); |
|
2632 } |
|
2633 } |
|
2634 if (!url) { |
|
2635 return; |
|
2636 } |
|
2637 $('body').modalmanager('loading'); |
|
2638 if (url.indexOf('#') === 0) { |
|
2639 // Inner hidden modal dialog |
|
2640 $(url).modal('show'); |
|
2641 } else { |
|
2642 // Remote URL modal dialog |
|
2643 $.ajax({ |
|
2644 url: url, |
|
2645 type: 'get', |
|
2646 cache: sourceData.amsAllowCache === undefined ? false : sourceData.amsAllowCache, |
|
2647 data: options, |
|
2648 success: function(data, status, request) { |
|
2649 $('body').modalmanager('removeLoading'); |
|
2650 var response = ams.ajax.getResponse(request); |
|
2651 var dataType = response.contentType; |
|
2652 var result = response.data; |
|
2653 switch (dataType) { |
|
2654 case 'json': |
|
2655 ams.ajax.handleJSON(result, $($(source).data('ams-json-target') || '#content')); |
|
2656 break; |
|
2657 case 'script': |
|
2658 break; |
|
2659 case 'xml': |
|
2660 break; |
|
2661 case 'html': |
|
2662 /* falls through */ |
|
2663 case 'text': |
|
2664 /* falls through */ |
|
2665 default: |
|
2666 var content = $(result); |
|
2667 var dialog = $('.modal-dialog', content.wrap('<div></div>').parent()); |
|
2668 var dialogData = dialog.data() || {}; |
|
2669 var dataOptions = { |
|
2670 backdrop: 'static', |
|
2671 overflow: dialogData.amsModalOverflow || '.modal-viewport', |
|
2672 maxHeight: dialogData.amsModalMaxHeight === undefined ? |
|
2673 function() { |
|
2674 var win_height = $(window).height(), |
|
2675 top_margin = parseInt(dialog.css('margin-top')), |
|
2676 top_padding = Math.round(win_height / 10); |
|
2677 return win_height - |
|
2678 $('.modal-header', content).outerHeight(true) - |
|
2679 $('footer', content).outerHeight(true) - top_margin - top_padding; |
|
2680 } |
|
2681 : ams.getFunctionByName(dialogData.amsModalMaxHeight) |
|
2682 }; |
|
2683 var settings = $.extend({}, dataOptions, dialogData.amsModalOptions); |
|
2684 settings = ams.executeFunctionByName(dialogData.amsModalInitCallback, dialog, settings) || settings; |
|
2685 if (callbacks) { |
|
2686 if (callbacks.shown) { |
|
2687 ams.dialog.registerShownCallback(callbacks.shown, content); |
|
2688 } |
|
2689 if (callbacks.hide) { |
|
2690 ams.dialog.registerHideCallback(callbacks.hide, content); |
|
2691 } |
|
2692 } |
|
2693 $('<div>').addClass('modal fade') |
|
2694 .append(content) |
|
2695 .modal(settings) |
|
2696 .on('shown', ams.dialog.shown) |
|
2697 .on('hidden', ams.dialog.hidden); |
|
2698 ams.initContent && ams.initContent(content); |
|
2699 if (sourceData.amsLogEvent !== false) { |
|
2700 ams.stats && ams.stats.logPageview(url); |
|
2701 } |
|
2702 } |
|
2703 } |
|
2704 }); |
|
2705 } |
|
2706 }); |
|
2707 }); |
|
2708 }, |
|
2709 |
|
2710 /** |
|
2711 * Modals shown callback |
|
2712 * This callback is used to initialize modal's viewport size |
|
2713 */ |
|
2714 shown: function(e) { |
|
2715 |
|
2716 function resetViewport(ev) { |
|
2717 var top = $('.scrollmarker.top', viewport), |
|
2718 topPosition = viewport.scrollTop(); |
|
2719 if (topPosition > 0) { |
|
2720 top.show(); |
|
2721 } else { |
|
2722 top.hide(); |
|
2723 } |
|
2724 var bottom = $('.scrollmarker.bottom', viewport); |
|
2725 if (maxHeight + topPosition >= viewport.get(0).scrollHeight) { |
|
2726 bottom.hide(); |
|
2727 } else { |
|
2728 bottom.show(); |
|
2729 } |
|
2730 } |
|
2731 |
|
2732 var modal = e.target, |
|
2733 viewport = $('.modal-viewport', modal); |
|
2734 if (viewport.exists()) { |
|
2735 var maxHeight = parseInt(viewport.css('max-height')), |
|
2736 barWidth = $.scrollbarWidth(); |
|
2737 if ((viewport.css('overflow') !== 'hidden') && |
|
2738 (viewport.height() === maxHeight)) { |
|
2739 $('<div></div>').addClass('scrollmarker') |
|
2740 .addClass('top') |
|
2741 .css('top', 0) |
|
2742 .css('width', viewport.width() - barWidth) |
|
2743 .hide() |
|
2744 .appendTo(viewport); |
|
2745 $('<div></div>').addClass('scrollmarker') |
|
2746 .addClass('bottom') |
|
2747 .css('top', maxHeight - 20) |
|
2748 .css('width', viewport.width() - barWidth) |
|
2749 .appendTo(viewport); |
|
2750 viewport.scroll(resetViewport); |
|
2751 viewport.off('resize') |
|
2752 .on('resize', resetViewport); |
|
2753 } else { |
|
2754 $('.scrollmarker', viewport).remove(); |
|
2755 } |
|
2756 } |
|
2757 |
|
2758 // Check for shown callbacks defined via data API |
|
2759 $('[data-ams-shown-callback]', modal).each(function() { |
|
2760 var callback = ams.getFunctionByName($(this).data('ams-shown-callback')); |
|
2761 if (callback) { |
|
2762 callback.call(modal, this); |
|
2763 } |
|
2764 }); |
|
2765 // Call shown callbacks registered for this dialog |
|
2766 var index, |
|
2767 callbacks = $('.modal-dialog', modal).data('shown-callbacks'); |
|
2768 if (callbacks) { |
|
2769 for (index=0; index < callbacks.length; index++) { |
|
2770 callbacks[index].call(modal); |
|
2771 } |
|
2772 } |
|
2773 // Call globally registered shown callbacks |
|
2774 callbacks = ams.dialog._shown_callbacks; |
|
2775 if (callbacks) { |
|
2776 for (index=0; index < callbacks.length; index++) { |
|
2777 callbacks[index].call(modal); |
|
2778 } |
|
2779 } |
|
2780 |
|
2781 ams.form && ams.form.setFocus(modal); |
|
2782 }, |
|
2783 |
|
2784 /** |
|
2785 * Close modal dialog associated with given context |
|
2786 */ |
|
2787 close: function(context) { |
|
2788 if (typeof(context) === 'string') { |
|
2789 context = $(context); |
|
2790 } |
|
2791 var modal = context.parents('.modal').data('modal'); |
|
2792 if (modal) { |
|
2793 var manager = $('body').data('modalmanager'); |
|
2794 if (manager && (manager.getOpenModals().indexOf(modal) >= 0)) { |
|
2795 modal.hide(); |
|
2796 } |
|
2797 } |
|
2798 }, |
|
2799 |
|
2800 /** |
|
2801 * Modals hidden callback |
|
2802 * This callback can be used to clean contents added by plug-ins |
|
2803 */ |
|
2804 hidden: function(e) { |
|
2805 var modal = e.target; |
|
2806 // Call registered cleaning callbacks |
|
2807 ams.skin && ams.skin.cleanContainer(modal); |
|
2808 // Check for hidden callbacks defined via data API |
|
2809 $('[data-ams-hidden-callback]', modal).each(function() { |
|
2810 var callback = ams.getFunctionByName($(this).data('ams-hidden-callback')); |
|
2811 if (callback) { |
|
2812 callback.call(modal, this); |
|
2813 } |
|
2814 }); |
|
2815 // Call hidden callbacks registered for this dialog |
|
2816 var index; |
|
2817 var callbacks = $('.modal-dialog', modal).data('hide-callbacks'); |
|
2818 if (callbacks) { |
|
2819 for (index=0; index < callbacks.length; index++) { |
|
2820 callbacks[index].call(modal); |
|
2821 } |
|
2822 } |
|
2823 // Call globally registered hidden callbacks |
|
2824 callbacks = ams.dialog._hide_callbacks; |
|
2825 if (callbacks) { |
|
2826 for (index=0; index < callbacks.length; index++) { |
|
2827 callbacks[index].call(modal); |
|
2828 } |
|
2829 } |
|
2830 } |
|
2831 }; |
|
2832 |
|
2833 })(jQuery, this); |
|
2834 |
|
2835 /** |
|
2836 * MyAMS helpers |
|
2837 * |
|
2838 * These helpers functions are used by several JQuery plug-in extensions. |
|
2839 * They have been extracted from these extensions management code to reuse them more easily into |
|
2840 * application specific callbacks. |
|
2841 */ |
|
2842 (function($, globals) { |
|
2843 |
|
2844 var ams = globals.MyAMS; |
|
2845 |
|
2846 ams.helpers = { |
|
2847 |
|
2848 /** Sort DOM elements into selected container */ |
|
2849 sort: function(container, attribute) { |
|
2850 if (!attribute) { |
|
2851 attribute = 'weight'; |
|
2852 } |
|
2853 var childs = container.children(); |
|
2854 childs.sort(function(a, b) { |
|
2855 return +$(a).data(attribute) - +$(b).data(attribute); |
|
2856 }).each(function() { |
|
2857 container.append(this); |
|
2858 }); |
|
2859 }, |
|
2860 |
|
2861 /** Clear Select2 slection */ |
|
2862 select2ClearSelection: function() { |
|
2863 var source = $(this); |
|
2864 var label = source.parents('label').first(); |
|
2865 var target = source.data('ams-select2-target'); |
|
2866 $('[name="' + target + '"]', label).data('select2').val(''); |
|
2867 }, |
|
2868 |
|
2869 /** Select2 selection formatter */ |
|
2870 select2FormatSelection: function(object, container) { |
|
2871 if (!(object instanceof Array)) { |
|
2872 object = [object]; |
|
2873 } |
|
2874 $(object).each(function() { |
|
2875 if (typeof(this) === 'object') { |
|
2876 container.append(this.text); |
|
2877 } else { |
|
2878 container.append(this); |
|
2879 } |
|
2880 }); |
|
2881 }, |
|
2882 |
|
2883 /** Select2 'select-all' helper */ |
|
2884 select2SelectAllHelper: function() { |
|
2885 var source = $(this); |
|
2886 var label = source.parents('label').first(); |
|
2887 var target = source.data('ams-select2-target'); |
|
2888 var input = $('[name="' + target + '"]', label); |
|
2889 if (input.get(0).tagName === 'SELECT') { |
|
2890 input.select2('val', $('option', input).listattr('value')); |
|
2891 } else { |
|
2892 input.select2('data', input.data('ams-select2-data')); |
|
2893 } |
|
2894 }, |
|
2895 |
|
2896 /** Select2 query results callback */ |
|
2897 select2QueryUrlResultsCallback: function(data, page, context) { |
|
2898 switch (data.status) { |
|
2899 case 'error': |
|
2900 ams.skin && ams.skin.messageBox('error', { |
|
2901 title: ams.i18n.ERROR_OCCURED, |
|
2902 content: '<h4>' + data.error_message + '</h4>', |
|
2903 icon: "fa fa-warning animated shake", |
|
2904 timeout: 10000 |
|
2905 }); |
|
2906 break; |
|
2907 case 'modal': |
|
2908 $(this).data('select2').dropdown.hide(); |
|
2909 ams.dialog && ams.dialog.open(data.location); |
|
2910 break; |
|
2911 default: |
|
2912 return { |
|
2913 results: data.results || data, |
|
2914 more: data.has_more || false, |
|
2915 context: data.context |
|
2916 }; |
|
2917 } |
|
2918 }, |
|
2919 |
|
2920 /** Select2 JSON-RPC success callback */ |
|
2921 select2QueryMethodSuccessCallback: function(data, status, options) { |
|
2922 var result = data.result; |
|
2923 if (typeof(result) === 'string') { |
|
2924 try { |
|
2925 result = JSON.parse(result); |
|
2926 } catch (e) {} |
|
2927 } |
|
2928 switch (result.status) { |
|
2929 case 'error': |
|
2930 ams.skin && ams.skin.messageBox('error', { |
|
2931 title: ams.i18n.ERROR_OCCURED, |
|
2932 content: '<h4>' + result.error_message + '</h4>', |
|
2933 icon: "fa fa-warning animated shake", |
|
2934 timeout: 10000 |
|
2935 }); |
|
2936 break; |
|
2937 case 'modal': |
|
2938 $(this).data('select2').dropdown.hide(); |
|
2939 ams.dialog && ams.dialog.open(result.location); |
|
2940 break; |
|
2941 default: |
|
2942 options.callback({ |
|
2943 results: result.results || result, |
|
2944 more: result.has_more || false, |
|
2945 context: result.context |
|
2946 }); |
|
2947 } |
|
2948 }, |
|
2949 |
|
2950 /** Select2 helper to automate selection change */ |
|
2951 select2ChangeHelper: function() { |
|
2952 var source = $(this); |
|
2953 var data = source.data(); |
|
2954 var target = $(data.amsSelect2HelperTarget); |
|
2955 switch (data.amsSelect2HelperType) { |
|
2956 case 'html': |
|
2957 target.html('<div class="text-center"><i class="fa fa-2x fa-gear fa-spin"></i></div>'); |
|
2958 var params = {}; |
|
2959 params[data.amsSelect2HelperArgument || 'value'] = source.val(); |
|
2960 $.get(data.amsSelect2HelperUrl, params, |
|
2961 ams.getFunctionByName(data.amsSelect2HelperCallback) || function(result) { |
|
2962 if (result) { |
|
2963 target.html(result); |
|
2964 ams.initContent && ams.initContent(target); |
|
2965 } else { |
|
2966 target.empty(); |
|
2967 } |
|
2968 }) |
|
2969 .fail(function() { |
|
2970 target.empty(); |
|
2971 }); |
|
2972 break; |
|
2973 case 'json-rpc': |
|
2974 target.html('<div class="text-center"><i class="fa fa-2x fa-gear fa-spin"></i></div>'); |
|
2975 ams.jsonrpc && ams.jsonrpc.post(data.amsSelect2HelperMethod, |
|
2976 {value: source.val()}, |
|
2977 {url: data.amsSelect2HelperUrl}, |
|
2978 ams.getFunctionByName(data.amsSelect2HelperCallback) || function(result) { |
|
2979 if (result.result) { |
|
2980 target.html(result.result); |
|
2981 ams.initContent && ams.initContent(target); |
|
2982 } else { |
|
2983 target.empty(); |
|
2984 } |
|
2985 }); |
|
2986 break; |
|
2987 default: |
|
2988 var callback = data.amsSelect2HelperCallback; |
|
2989 if (callback) { |
|
2990 ams.executeFunctionByName(callback, source, data); |
|
2991 } |
|
2992 } |
|
2993 }, |
|
2994 |
|
2995 /** Context menu handler */ |
|
2996 contextMenuHandler: function(target, menu) { |
|
2997 if (menu.get(0).tagName !== 'A') { // Icon click? |
|
2998 menu = menu.parents('a').first(); |
|
2999 } |
|
3000 var menuData = menu.data(); |
|
3001 if (menuData.toggle === 'modal') { |
|
3002 ams.dialog && ams.dialog.open(menu); |
|
3003 } else { |
|
3004 var href = menu.attr('href') || menuData.amsUrl; |
|
3005 if (!href || href.startsWith('javascript') || menu.attr('target')) { |
|
3006 return; |
|
3007 } |
|
3008 ams.event && ams.event.stop(); |
|
3009 var hrefGetter = ams.getFunctionByName(href); |
|
3010 if (typeof(hrefGetter) === 'function') { |
|
3011 href = hrefGetter.call(menu, target); |
|
3012 } |
|
3013 if (typeof(href) === 'function') { |
|
3014 // Javascript function call |
|
3015 href.call(menu, target); |
|
3016 } else { |
|
3017 // Standard AJAX or browser URL call |
|
3018 // Convert %23 chars to # |
|
3019 href = href.replace(/\%23/, '#'); |
|
3020 target = menu.data('ams-target'); |
|
3021 if (target) { |
|
3022 ams.form && ams.form.confirmChangedForm(target, function () { |
|
3023 ams.skin && ams.skin.loadURL(href, target, menu.data('ams-link-options'), menu.data('ams-link-callback')); |
|
3024 }); |
|
3025 } else { |
|
3026 ams.form && ams.form.confirmChangedForm(function () { |
|
3027 if (href.startsWith('#')) { |
|
3028 if (href !== location.hash) { |
|
3029 if (ams.root.hasClass('mobile-view-activated')) { |
|
3030 ams.root.removeClass('hidden-menu'); |
|
3031 window.setTimeout(function () { |
|
3032 window.location.hash = href; |
|
3033 }, 150); |
|
3034 } else { |
|
3035 window.location.hash = href; |
|
3036 } |
|
3037 } |
|
3038 } else { |
|
3039 window.location = href; |
|
3040 } |
|
3041 }); |
|
3042 } |
|
3043 } |
|
3044 } |
|
3045 }, |
|
3046 |
|
3047 /** Datetimepicker dialog cleaner callback */ |
|
3048 datetimepickerDialogHiddenCallback: function() { |
|
3049 $('.datepicker, .timepicker, .datetimepicker', this).datetimepicker('destroy'); |
|
3050 }, |
|
3051 |
|
3052 /** Clear search form target when query is empty */ |
|
3053 clearSearchTarget: function() { |
|
3054 var input = $(this); |
|
3055 if (!input.val()) { |
|
3056 var form = $(input).parents('form').first(); |
|
3057 $(form.data('ams-form-submit-target')).empty(); |
|
3058 } |
|
3059 }, |
|
3060 |
|
3061 /** Set SEO status */ |
|
3062 setSEOStatus: function() { |
|
3063 var input = $(this); |
|
3064 var progress = input.siblings('.progress').children('.progress-bar'); |
|
3065 var length = Math.min(input.val().length, 100); |
|
3066 var status = 'success'; |
|
3067 if (length < 20 || length > 80) { |
|
3068 status = 'danger'; |
|
3069 } else if (length < 40 || length > 66) { |
|
3070 status = 'warning'; |
|
3071 } |
|
3072 progress.removeClassPrefix('progress-bar') |
|
3073 .addClass('progress-bar') |
|
3074 .addClass('progress-bar-' + status) |
|
3075 .css('width', length + '%'); |
|
3076 } |
|
3077 }; |
|
3078 |
|
3079 })(jQuery, this); |
|
3080 |
|
3081 /** |
|
3082 * MyAMS standard plug-ins loader |
|
3083 * |
|
3084 * Only basic JQuery, Bootstrap and MyAMS javascript extensions are typically loaded from main page. |
|
3085 * Other JQuery plug-ins may be loaded dynamically. |
|
3086 * Several JQuery extension plug-ins are already included and pre-configured by MyAMS. Other external |
|
3087 * plug-ins can be defined and loaded dynamically using simple "data" attributes. |
|
3088 * |
|
3089 * WARNING: any plug-in implicated into a form submit process (like JQuery-form or JQuery-progressbar) |
|
3090 * must be loaded in a synchronous way. Otherwise, if you use named buttons to submit your forms, |
|
3091 * dynamic hidden input fields created by JQuery-validate plug-in will be removed from the form |
|
3092 * before the form is submitted! |
|
3093 */ |
|
3094 (function($, globals) { |
|
3095 |
|
3096 "use strict"; |
|
3097 |
|
3098 var ams = globals.MyAMS; |
|
3099 |
|
3100 ams.plugins = { |
|
3101 |
|
3102 /** |
|
3103 * Container of enabled plug-ins |
|
3104 */ |
|
3105 enabled: {}, |
|
3106 |
|
3107 /** |
|
3108 * Initialize list of content plug-ins |
|
3109 */ |
|
3110 init: function(element) { |
|
3111 |
|
3112 // Initialize custom data attributes |
|
3113 ams.plugins.initData(element); |
|
3114 |
|
3115 // Check for disabled plug-ins |
|
3116 var disabled = []; |
|
3117 $('[data-ams-plugins-disabled]', element).each(function() { |
|
3118 var plugins = $(this).data('ams-plugins-disabled').split(/\s+/); |
|
3119 for (var index = 0; index < plugins.length; index++) { |
|
3120 disabled.push(plugins[index]); |
|
3121 } |
|
3122 }); |
|
3123 |
|
3124 // Scan new element for plug-ins |
|
3125 var plugins = {}; |
|
3126 var name; |
|
3127 |
|
3128 // Inner plug-in register function |
|
3129 function _registerPlugin(name, new_plugin) { |
|
3130 if (plugins.hasOwnProperty(name)) { |
|
3131 var plugin = plugins[name]; |
|
3132 plugin.css = plugin.css || new_plugin.css; |
|
3133 plugin.callbacks.push({ |
|
3134 callback: new_plugin.callback, |
|
3135 context: new_plugin.context |
|
3136 }); |
|
3137 if (new_plugin.register) { |
|
3138 plugin.register = true; |
|
3139 } |
|
3140 if (new_plugin.async === false) { |
|
3141 plugin.async = false; |
|
3142 } |
|
3143 } else { |
|
3144 plugins[name] = { |
|
3145 src: new_plugin.src, |
|
3146 css: new_plugin.css, |
|
3147 callbacks: [{ |
|
3148 callback: new_plugin.callback, |
|
3149 context: new_plugin.context |
|
3150 }], |
|
3151 register: new_plugin.register, |
|
3152 async: new_plugin.async |
|
3153 }; |
|
3154 } |
|
3155 if (new_plugin.css) { |
|
3156 ams.getCSS(new_plugin.css, name + '_css'); |
|
3157 } |
|
3158 } |
|
3159 |
|
3160 $('[data-ams-plugins]', element).each(function() { |
|
3161 |
|
3162 var source = $(this); |
|
3163 var amsPlugins = source.data('ams-plugins'); |
|
3164 if (typeof (amsPlugins) === 'string') { |
|
3165 var names = source.data('ams-plugins').split(/\s+/); |
|
3166 for (var index = 0; index < names.length; index++) { |
|
3167 name = names[index]; |
|
3168 var newPlugin = { |
|
3169 src: source.data('ams-plugin-' + name + '-src'), |
|
3170 css: source.data('ams-plugin-' + name + '-css'), |
|
3171 callback: source.data('ams-plugin-' + name + '-callback'), |
|
3172 context: source, |
|
3173 register: source.data('ams-plugin-' + name + '-register'), |
|
3174 async: source.data('ams-plugin-' + name + '-async') |
|
3175 }; |
|
3176 _registerPlugin(name, newPlugin); |
|
3177 } |
|
3178 } else { |
|
3179 for (name in amsPlugins) { |
|
3180 if (!amsPlugins.hasOwnProperty(name)) { |
|
3181 continue; |
|
3182 } |
|
3183 _registerPlugin(name, amsPlugins[name]); |
|
3184 } |
|
3185 } |
|
3186 }); |
|
3187 |
|
3188 // Inner plug-in loader function |
|
3189 var plugin; |
|
3190 |
|
3191 function _loadPlugin(reload) { |
|
3192 var index; |
|
3193 var callbacks = plugin.callbacks, |
|
3194 callback; |
|
3195 if (callbacks && callbacks.length) { |
|
3196 for (index = 0; index < callbacks.length; index++) { |
|
3197 callback = callbacks[index]; |
|
3198 callback.callback = ams.getFunctionByName(callback.callback); |
|
3199 if (plugin.register !== false) { |
|
3200 var enabled = ams.plugins.enabled; |
|
3201 if (enabled.hasOwnProperty(name)) { |
|
3202 enabled[name].push(callback); |
|
3203 } else { |
|
3204 enabled[name] = [callback]; |
|
3205 } |
|
3206 } |
|
3207 } |
|
3208 } else { |
|
3209 if (plugin.register !== false) { |
|
3210 ams.plugins.enabled[name] = null; |
|
3211 } |
|
3212 } |
|
3213 // If running in async mode, newly registered plug-ins are run |
|
3214 // before callback is called so we call plug-in manually |
|
3215 if ((reload !== true) && callbacks && callbacks.length && (plugin.async !== false)) { |
|
3216 for (index = 0; index < callbacks.length; index++) { |
|
3217 callback = callbacks[index]; |
|
3218 ams.executeFunctionByName(callback.callback, element, callback.context); |
|
3219 } |
|
3220 } |
|
3221 } |
|
3222 |
|
3223 function _checkPluginContext() { |
|
3224 // Update context for an already loaded plug-in |
|
3225 var enabled = ams.plugins.enabled[name]; |
|
3226 // Clean all plug-in contexts |
|
3227 for (index = 0; index < enabled.length; index++) { |
|
3228 var callback = enabled[index]; |
|
3229 if (callback && callback.context && !ams.isInDOM(callback.context)) { |
|
3230 enabled[index] = null; |
|
3231 } |
|
3232 } |
|
3233 } |
|
3234 |
|
3235 for (name in plugins) { |
|
3236 if (!plugins.hasOwnProperty(name)) { |
|
3237 continue; |
|
3238 } |
|
3239 plugin = plugins[name]; |
|
3240 if (ams.plugins.enabled[name] === undefined) { |
|
3241 ams.getScript(plugin.src, _loadPlugin, { |
|
3242 async: plugin.async === undefined ? true : plugin.async |
|
3243 }); |
|
3244 } else { |
|
3245 _checkPluginContext(); |
|
3246 _loadPlugin(true); |
|
3247 } |
|
3248 } |
|
3249 |
|
3250 // Run all enabled plug-ins |
|
3251 for (var index in ams.plugins.enabled) { |
|
3252 if (!ams.plugins.enabled.hasOwnProperty(index)) { |
|
3253 continue; |
|
3254 } |
|
3255 if (disabled.indexOf(index) >= 0) { |
|
3256 continue; |
|
3257 } |
|
3258 var callbacks = ams.plugins.enabled[index]; |
|
3259 if (callbacks) { |
|
3260 switch (typeof (callbacks)) { |
|
3261 case 'function': |
|
3262 callbacks(element); |
|
3263 break; |
|
3264 default: |
|
3265 for (var cbIndex = 0; cbIndex < callbacks.length; cbIndex++) { |
|
3266 var callback = callbacks[cbIndex]; |
|
3267 switch (typeof (callback)) { |
|
3268 case 'function': |
|
3269 callback(element); |
|
3270 break; |
|
3271 default: |
|
3272 if (callback && callback.callback) { |
|
3273 callback.callback(callback.context); |
|
3274 } |
|
3275 } |
|
3276 } |
|
3277 } |
|
3278 } |
|
3279 } |
|
3280 }, |
|
3281 |
|
3282 /** |
|
3283 * Data initializer |
|
3284 * This plug-in converts a single JSON "data-ams-data" attribute into a set of several equivalent "data-" attributes. |
|
3285 * This way of defining data attributes can be used with HTML templates engines which don't allow you |
|
3286 * to create dynamic attributes easily. |
|
3287 */ |
|
3288 initData: function(element) { |
|
3289 $('[data-ams-data]', element).each(function() { |
|
3290 var dataElement = $(this); |
|
3291 var data = dataElement.data('ams-data'); |
|
3292 if (data) { |
|
3293 for (var name in data) { |
|
3294 if (data.hasOwnProperty(name)) { |
|
3295 var elementData = data[name]; |
|
3296 if (typeof (elementData) !== 'string') { |
|
3297 elementData = JSON.stringify(elementData); |
|
3298 } |
|
3299 dataElement.attr('data-' + name, elementData); |
|
3300 } |
|
3301 } |
|
3302 } |
|
3303 }); |
|
3304 }, |
|
3305 |
|
3306 /** |
|
3307 * Register a new plug-in through Javascript instead of HTML data attributes |
|
3308 * |
|
3309 * @plugin: plugin function caller or object containing plug-in properties |
|
3310 * @name: if @plugin is a function, defines plug-in name |
|
3311 * @callback: a callback function which can be called after plug-in registry |
|
3312 */ |
|
3313 register: function(plugin, name, callback) { |
|
3314 if (typeof (name) === 'function') { |
|
3315 callback = name; |
|
3316 name = null; |
|
3317 } |
|
3318 name = name || plugin.name; |
|
3319 if (ams.plugins.enabled.indexOf(name) >= 0) { |
|
3320 if (console) { |
|
3321 console.warn && console.warn("Plugin " + name + " is already registered!"); |
|
3322 } |
|
3323 return; |
|
3324 } |
|
3325 if (typeof (plugin) === 'object') { |
|
3326 var src = plugin.src; |
|
3327 if (src) { |
|
3328 ams.ajax && ams.ajax.check(plugin.callback, src, function(first_load) { |
|
3329 if (first_load) { |
|
3330 ams.plugins.enabled[name] = ams.getFunctionByName(plugin.callback); |
|
3331 if (plugin.css) { |
|
3332 ams.getCSS(plugin.css, name + '_css'); |
|
3333 } |
|
3334 if (callback) { |
|
3335 ams.executeFunctionByName(callback); |
|
3336 } |
|
3337 } |
|
3338 }); |
|
3339 } else { |
|
3340 ams.plugins.enabled[name] = ams.getFunctionByName(plugin.callback); |
|
3341 if (plugin.css) { |
|
3342 ams.getCSS(plugin.css, name + '_css'); |
|
3343 } |
|
3344 if (callback) { |
|
3345 ams.executeFunctionByName(callback); |
|
3346 } |
|
3347 } |
|
3348 } else if (typeof (plugin) === 'function') { |
|
3349 ams.plugins.enabled[name] = plugin; |
|
3350 if (callback) { |
|
3351 ams.executeFunctionByName(callback); |
|
3352 } |
|
3353 } |
|
3354 } |
|
3355 }; |
|
3356 |
|
3357 ams.plugins.i18n = { |
|
3358 widgets: {}, |
|
3359 validate: {}, |
|
3360 datatables: {}, |
|
3361 fancybox: { |
|
3362 ERROR: "Can't load requested content.", |
|
3363 RETRY: "Please check URL or try again later.", |
|
3364 CLOSE: "Close", |
|
3365 NEXT: "Next", |
|
3366 PREVIOUS: "Previous" |
|
3367 }, |
|
3368 dndupload: { |
|
3369 FILES_SELECTED: '{count} files selected', |
|
3370 CHOOSE_FILE: 'Select file(s)', |
|
3371 ADD_INFO: 'to add them to current folder,', |
|
3372 DRAG_FILE: 'or drag and drop them here!', |
|
3373 UPLOAD: 'Upload', |
|
3374 UPLOADING: 'Uploading…', |
|
3375 DONE: 'Done!', |
|
3376 UPLOAD_MORE: 'Upload more?', |
|
3377 ERROR: 'Error!', |
|
3378 TRY_AGAIN: 'Try again?' |
|
3379 } |
|
3380 }; |
|
3381 |
|
3382 })(jQuery, this); |
|
3383 |
|
3384 /** |
|
3385 * MyAMS standard plug-ins |
|
3386 * |
|
3387 * Only basic JQuery, Bootstrap and MyAMS javascript extensions are typically loaded from main page. |
|
3388 * Other JQuery plug-ins may be loaded dynamically. |
|
3389 * Several JQuery extension plug-ins are already included and pre-configured by MyAMS. Other external |
|
3390 * plug-ins can be defined and loaded dynamically using simple "data" attributes. |
|
3391 * |
|
3392 * WARNING: any plug-in implicated into a form submit process (like JQuery-form or JQuery-progressbar) |
|
3393 * must be loaded in a synchronous way. Otherwise, if you use named buttons to submit your forms, |
|
3394 * dynamic hidden input fields created by JQuery-validate plug-in will be removed from the form |
|
3395 * before the form is submitted! |
|
3396 */ |
|
3397 (function($, globals) { |
|
3398 |
|
3399 var ams = globals.MyAMS; |
|
3400 |
|
3401 /** |
|
3402 * Map of enabled plug-ins |
|
3403 * This map can be extended by external plug-ins. |
|
3404 * |
|
3405 * Standard MyAMS plug-ins management method generally includes: |
|
3406 * - applying a class matching plug-in name on a set of HTML entities to apply the plug-in |
|
3407 * - defining a set of data-attributes on each of these entities to customize the plug-in |
|
3408 * For each standard plug-in, you can also provide an options object (to define plug-in options not handled |
|
3409 * by default MyAMS initialization engine) and an initialization callback (to define these options dynamically). |
|
3410 * Another callback can also be provided to be called after plug-in initialization. |
|
3411 * |
|
3412 * You can also register plug-ins using the 'register' function |
|
3413 */ |
|
3414 $.extend(ams.plugins.enabled, { |
|
3415 |
|
3416 /** |
|
3417 * SVG containers |
|
3418 */ |
|
3419 svg: function(element) { |
|
3420 var svgs = $('.svg-container', element); |
|
3421 if (svgs.length > 0) { |
|
3422 svgs.each(function() { |
|
3423 var container = $(this); |
|
3424 var svg = $('svg', container), |
|
3425 width = svg.attr('width'), |
|
3426 height = svg.attr('height'); |
|
3427 if (width && height) { |
|
3428 svg.get(0).setAttribute('viewBox', |
|
3429 '0 0 ' + Math.round(parseFloat(width)) + ' ' + |
|
3430 Math.round(parseFloat(height))); |
|
3431 } |
|
3432 svg.attr('width', '100%') |
|
3433 .attr('height', 'auto'); |
|
3434 }) |
|
3435 } |
|
3436 }, |
|
3437 |
|
3438 /** |
|
3439 * Label hints |
|
3440 */ |
|
3441 hint: function(element) { |
|
3442 var hints = $('.hint:not(:parents(.nohints))', element); |
|
3443 if (hints.length > 0) { |
|
3444 ams.ajax && ams.ajax.check($.fn.tipsy, |
|
3445 ams.baseURL + 'ext/jquery-tipsy' + ams.devext + '.js', |
|
3446 function() { |
|
3447 ams.getCSS(ams.baseURL + '../css/ext/jquery-tipsy' + ams.devext + '.css', |
|
3448 'jquery-tipsy', function() { |
|
3449 hints.each(function() { |
|
3450 var hint = $(this); |
|
3451 var data = hint.data(); |
|
3452 var dataOptions = { |
|
3453 html: data.amsHintHtml === undefined ? (hint.attr('title') || '').startsWith('<') : data.amsHintHtml, |
|
3454 title: ams.getFunctionByName(data.amsHintTitleGetter) || function() { |
|
3455 var hint = $(this); |
|
3456 var result = hint.attr('original-title') || |
|
3457 hint.attr(data.amsHintTitleAttr || 'title') || |
|
3458 (data.amsHintHtml ? hint.html() : hint.text()); |
|
3459 result = result.replace(/\?_="/, '?_=' + new Date().getTime() + '"'); |
|
3460 return result; |
|
3461 }, |
|
3462 opacity: data.amsHintOpacity || 0.95, |
|
3463 gravity: data.amsHintGravity || 'sw', |
|
3464 offset: data.amsHintOffset || 0 |
|
3465 }; |
|
3466 var settings = $.extend({}, dataOptions, data.amsHintOptions); |
|
3467 settings = ams.executeFunctionByName(data.amsHintInitCallback, hint, settings) || settings; |
|
3468 var plugin = hint.tipsy(settings); |
|
3469 ams.executeFunctionByName(data.amsHintAfterInitCallback, hint, plugin, settings); |
|
3470 }); |
|
3471 }); |
|
3472 }); |
|
3473 } |
|
3474 }, |
|
3475 |
|
3476 /** |
|
3477 * Context menu plug-in |
|
3478 */ |
|
3479 contextMenu: function(element) { |
|
3480 var menus = $('.context-menu', element); |
|
3481 if (menus.length > 0) { |
|
3482 menus.each(function() { |
|
3483 var menu = $(this); |
|
3484 var data = menu.data(); |
|
3485 var dataOptions = { |
|
3486 menuSelector: data.amsContextmenuSelector, |
|
3487 menuSelected: ams.helpers && ams.helpers.contextMenuHandler |
|
3488 }; |
|
3489 var settings = $.extend({}, dataOptions, data.amsContextmenuOptions); |
|
3490 settings = ams.executeFunctionByName(data.amsContextmenuInitCallback, menu, settings) || settings; |
|
3491 var plugin = menu.contextMenu(settings); |
|
3492 ams.executeFunctionByName(data.amsContextmenuAfterInitCallback, menu, plugin, settings); |
|
3493 }); |
|
3494 } |
|
3495 }, |
|
3496 |
|
3497 /** |
|
3498 * Fieldset legend switcher |
|
3499 */ |
|
3500 switcher: function(element) { |
|
3501 $('LEGEND.switcher', element).each(function() { |
|
3502 var legend = $(this); |
|
3503 var fieldset = legend.parent('fieldset'); |
|
3504 var data = legend.data(); |
|
3505 if (!data.amsSwitcher) { |
|
3506 $('<i class="fa fa-fw"></i>') |
|
3507 .prependTo($(this)) |
|
3508 .addClass(data.amsSwitcherState === 'open' ? |
|
3509 (data.amsSwitcherMinusClass || 'fa-minus') : |
|
3510 (data.amsSwitcherPlusClass || 'fa-plus')); |
|
3511 legend.on('click', function(e) { |
|
3512 e.preventDefault(); |
|
3513 var veto = {}; |
|
3514 legend.trigger('ams.switcher.before-switch', [legend, veto]); |
|
3515 if (veto.veto) { |
|
3516 return; |
|
3517 } |
|
3518 if (fieldset.hasClass('switched')) { |
|
3519 fieldset.removeClass('switched'); |
|
3520 $('.fa', legend).removeClass(data.amsSwitcherPlusClass || 'fa-plus') |
|
3521 .addClass(data.amsSwitcherMinusClass || 'fa-minus'); |
|
3522 legend.trigger('ams.switcher.opened', [legend]); |
|
3523 var id = legend.attr('id'); |
|
3524 if (id) { |
|
3525 $('legend.switcher[data-ams-switcher-sync="' + id + '"]', fieldset).each(function() { |
|
3526 var switcher = $(this); |
|
3527 if (switcher.parents('fieldset').hasClass('switched')) { |
|
3528 switcher.click(); |
|
3529 } |
|
3530 }); |
|
3531 } |
|
3532 } else { |
|
3533 fieldset.addClass('switched'); |
|
3534 $('.fa', legend).removeClass(data.amsSwitcherMinusClass || 'fa-minus') |
|
3535 .addClass(data.amsSwitcherPlusClass || 'fa-plus'); |
|
3536 legend.trigger('ams.switcher.closed', [legend]); |
|
3537 } |
|
3538 }); |
|
3539 if (data.amsSwitcherState !== 'open') { |
|
3540 fieldset.addClass('switched'); |
|
3541 } |
|
3542 legend.data('ams-switcher', 'on'); |
|
3543 } |
|
3544 }); |
|
3545 }, |
|
3546 |
|
3547 /** |
|
3548 * Fieldset legend checker |
|
3549 */ |
|
3550 checker: function(element) { |
|
3551 $('LEGEND.checker', element).each(function() { |
|
3552 var legend = $(this); |
|
3553 var fieldset = legend.parent('fieldset'); |
|
3554 var data = legend.data(); |
|
3555 if (!data.amsChecker) { |
|
3556 var checker = $('<label class="checkbox"></label>'); |
|
3557 var fieldname = data.amsCheckerFieldname || ('checker_' + ams.generateId()); |
|
3558 var checkboxId = fieldname.replace(/\./, '_'); |
|
3559 var prefix = data.amsCheckerHiddenPrefix; |
|
3560 var hidden = null; |
|
3561 var checkedValue = data.amsCheckerHiddenValueOn || 'true'; |
|
3562 var uncheckedValue = data.amsCheckerHiddenValueOff || 'false'; |
|
3563 var marker = data.amsCheckerMarker || false; |
|
3564 if (prefix) { |
|
3565 hidden = $('<input type="hidden">').attr('name', prefix + fieldname) |
|
3566 .val(data.amsCheckerState === 'on' ? checkedValue : uncheckedValue) |
|
3567 .prependTo(legend); |
|
3568 } else if (marker) { |
|
3569 $('<input type="hidden">').attr('name', marker) |
|
3570 .attr('value', 1) |
|
3571 .prependTo(legend); |
|
3572 } |
|
3573 var input = $('<input type="checkbox">').attr('name', fieldname) |
|
3574 .attr('id', checkboxId) |
|
3575 .data('ams-checker-hidden-input', hidden) |
|
3576 .data('ams-checker-init', true) |
|
3577 .val(data.amsCheckerValue || true) |
|
3578 .attr('checked', data.amsCheckerState === 'on' ? 'checked' : null); |
|
3579 if (data.amsCheckerReadonly) { |
|
3580 input.attr('disabled', 'disabled'); |
|
3581 } else { |
|
3582 input.on('change', function(e) { |
|
3583 e.preventDefault(); |
|
3584 var veto = {}; |
|
3585 var isChecked = $(this).is(':checked'); |
|
3586 legend.trigger('ams.checker.before-switch', [legend, veto]); |
|
3587 if (veto.veto) { |
|
3588 // reset checked status because event is fired after change... |
|
3589 $(this).prop('checked', !isChecked); |
|
3590 return; |
|
3591 } |
|
3592 ams.executeFunctionByName(data.amsCheckerChangeHandler, legend, isChecked); |
|
3593 if (!data.amsCheckerCancelDefault) { |
|
3594 var hidden = input.data('ams-checker-hidden-input'); |
|
3595 if (isChecked) { |
|
3596 if (data.amsCheckerMode === 'disable') { |
|
3597 fieldset.removeAttr('disabled'); |
|
3598 $('.select2', fieldset).removeAttr('disabled'); |
|
3599 } else { |
|
3600 fieldset.removeClass('switched'); |
|
3601 } |
|
3602 if (hidden) { |
|
3603 hidden.val(checkedValue); |
|
3604 } |
|
3605 $('[data-required]', fieldset).attr('required', 'required'); |
|
3606 legend.trigger('ams.checker.opened', [legend]); |
|
3607 } else { |
|
3608 if (data.amsCheckerMode === 'disable') { |
|
3609 fieldset.prop('disabled', 'disabled'); |
|
3610 $('.select2', fieldset).attr('disabled', 'disabled'); |
|
3611 } else { |
|
3612 fieldset.addClass('switched'); |
|
3613 } |
|
3614 if (hidden) { |
|
3615 hidden.val(uncheckedValue); |
|
3616 } |
|
3617 $('[data-required]', fieldset).removeAttr('required'); |
|
3618 legend.trigger('ams.checker.closed', [legend]); |
|
3619 } |
|
3620 } |
|
3621 }); |
|
3622 } |
|
3623 input.appendTo(checker); |
|
3624 $('>label', legend).attr('for', input.attr('id')); |
|
3625 checker.append('<i></i>') |
|
3626 .prependTo(legend); |
|
3627 var required = $('[required]', fieldset); |
|
3628 required.attr('data-required', true); |
|
3629 if (data.amsCheckerState === 'on') { |
|
3630 input.attr('checked', true); |
|
3631 } else { |
|
3632 if (data.amsCheckerMode === 'disable') { |
|
3633 fieldset.attr('disabled', 'disabled'); |
|
3634 $('.select2', fieldset).attr('disabled', 'disabled'); |
|
3635 } else { |
|
3636 fieldset.addClass('switched'); |
|
3637 } |
|
3638 required.removeAttr('required'); |
|
3639 } |
|
3640 legend.data('ams-checker', 'on'); |
|
3641 } |
|
3642 }); |
|
3643 }, |
|
3644 |
|
3645 /** |
|
3646 * Sliders |
|
3647 */ |
|
3648 slider: function(element) { |
|
3649 var sliders = $('.slider', element); |
|
3650 if (sliders.length > 0) { |
|
3651 ams.ajax && ams.ajax.check($.fn.slider, |
|
3652 ams.baseURL + 'ext/bootstrap-slider-2.0.0' + ams.devext + '.js', |
|
3653 function() { |
|
3654 sliders.each(function() { |
|
3655 var slider = $(this); |
|
3656 var data = slider.data(); |
|
3657 var dataOptions = {}; |
|
3658 var settings = $.extend({}, dataOptions, slider.data.amsSliderOptions); |
|
3659 settings = ams.executeFunctionByName(data.amsSliderInitCallback, slider, settings) || settings; |
|
3660 var plugin = slider.slider(settings); |
|
3661 ams.executeFunctionByName(data.amsSliderAfterInitCallback, slider, plugin, settings); |
|
3662 }); |
|
3663 }); |
|
3664 } |
|
3665 }, |
|
3666 |
|
3667 /** |
|
3668 * Draggable plug-in |
|
3669 */ |
|
3670 draggable: function(element) { |
|
3671 var draggables = $('.draggable', element); |
|
3672 if (draggables.length > 0) { |
|
3673 draggables.each(function() { |
|
3674 var draggable = $(this); |
|
3675 var data = draggable.data(); |
|
3676 var dataOptions = { |
|
3677 cursor: data.amsDraggableCursor || 'move', |
|
3678 containment: data.amsDraggableContainment, |
|
3679 handle: data.amsDraggableHandle, |
|
3680 connectToSortable: data.amsDraggableConnectSortable, |
|
3681 helper: ams.getFunctionByName(data.amsDraggableHelper) || data.amsDraggableHelper, |
|
3682 start: ams.getFunctionByName(data.amsDraggableStart), |
|
3683 stop: ams.getFunctionByName(data.amsDraggableStop) |
|
3684 }; |
|
3685 var settings = $.extend({}, dataOptions, data.amsDraggableOptions); |
|
3686 settings = ams.executeFunctionByName(data.amsDraggableInitCallback, draggable, settings) || settings; |
|
3687 var plugin = draggable.draggable(settings); |
|
3688 draggable.disableSelection(); |
|
3689 ams.executeFunctionByName(data.amsDraggableAfterInitCallback, draggable, plugin, settings); |
|
3690 }); |
|
3691 } |
|
3692 }, |
|
3693 |
|
3694 /** |
|
3695 * Droppable plug-in |
|
3696 */ |
|
3697 droppable: function(element) { |
|
3698 var droppables = $('.droppable', element); |
|
3699 if (droppables.length > 0) { |
|
3700 droppables.each(function() { |
|
3701 var droppable = $(this); |
|
3702 var data = droppable.data(); |
|
3703 var dataOptions = { |
|
3704 accept: data.amsdroppableAccept, |
|
3705 drop: ams.getFunctionByName(data.amsDroppableDrop) |
|
3706 }; |
|
3707 var settings = $.extend({}, dataOptions, data.amsDroppableOptions); |
|
3708 settings = ams.executeFunctionByName(data.amsDroppableInitCallback, droppable, settings) || settings; |
|
3709 var plugin = droppable.droppable(settings); |
|
3710 ams.executeFunctionByName(data.amsDroppableAfterInitCallback, droppable, plugin, settings); |
|
3711 }); |
|
3712 } |
|
3713 }, |
|
3714 |
|
3715 /** |
|
3716 * Sortable plug-in |
|
3717 */ |
|
3718 sortable: function(element) { |
|
3719 var sortables = $('.sortable', element); |
|
3720 if (sortables.length > 0) { |
|
3721 sortables.each(function() { |
|
3722 var sortable = $(this); |
|
3723 var data = sortable.data(); |
|
3724 var dataOptions = { |
|
3725 items: data.amsSortableItems, |
|
3726 handle: data.amsSortableHandle, |
|
3727 helper: data.amsSortableHelper, |
|
3728 connectWith: data.amsSortableConnectwith, |
|
3729 start: ams.getFunctionByName(data.amsSortableStart), |
|
3730 over: ams.getFunctionByName(data.amsSortableOver), |
|
3731 containment: data.amsSortableContainment, |
|
3732 placeholder: data.amsSortablePlaceholder, |
|
3733 stop: ams.getFunctionByName(data.amsSortableStop) |
|
3734 }; |
|
3735 var settings = $.extend({}, dataOptions, data.amsSortableOptions); |
|
3736 settings = ams.executeFunctionByName(data.amsSortableInitCallback, sortable, settings) || settings; |
|
3737 var plugin = sortable.sortable(settings); |
|
3738 sortable.disableSelection(); |
|
3739 ams.executeFunctionByName(data.amsSortableAfterInitCallback, sortable, plugin, settings); |
|
3740 }); |
|
3741 } |
|
3742 }, |
|
3743 |
|
3744 /** |
|
3745 * Resizable plug-in |
|
3746 */ |
|
3747 resizable: function(element) { |
|
3748 var resizables = $('.resizable', element); |
|
3749 if (resizables.length > 0) { |
|
3750 resizables.each(function() { |
|
3751 var resizable = $(this); |
|
3752 var data = resizable.data(); |
|
3753 var dataOptions = { |
|
3754 autoHide: data.amsResizableAutohide === false ? true : data.amsResizableAutohide, |
|
3755 containment: data.amsResizableContainment, |
|
3756 grid: data.amsResizableGrid, |
|
3757 handles: data.amsResizableHandles, |
|
3758 start: ams.getFunctionByName(data.amsResizableStart), |
|
3759 stop: ams.getFunctionByName(data.amsResizableStop) |
|
3760 }; |
|
3761 var settings = $.extend({}, dataOptions, data.amsResizableOptions); |
|
3762 settings = ams.executeFunctionByName(data.amsResizableInitCallback, resizable, settings) || settings; |
|
3763 var plugin = resizable.resizable(settings); |
|
3764 resizable.disableSelection(); |
|
3765 ams.executeFunctionByName(data.amsResizableAfterInitCallback, resizable, plugin, settings); |
|
3766 }); |
|
3767 } |
|
3768 }, |
|
3769 |
|
3770 /** |
|
3771 * JQuery typeahead plug-in |
|
3772 */ |
|
3773 typeahead: function(element) { |
|
3774 var typeaheads = $('.typeahead', element); |
|
3775 if (typeaheads.length > 0) { |
|
3776 ams.ajax && ams.ajax.check($.fn.typeahead, |
|
3777 ams.baseURL + 'ext/jquery-typeahead' + ams.devext + '.js', |
|
3778 function() { |
|
3779 typeaheads.each(function() { |
|
3780 var input = $(this); |
|
3781 var data = input.data(); |
|
3782 var dataOptions = {}; |
|
3783 var settings = $.extend({}, dataOptions, data.amsTypeaheadOptions); |
|
3784 settings = ams.executeFunctionByName(data.amsTypeaheadInitCallback, input, settings) || settings; |
|
3785 var plugin = input.typeahead(settings); |
|
3786 ams.executeFunctionByName(data.amsTypeaheadAfterInitCallback, input, plugin, settings); |
|
3787 }); |
|
3788 }); |
|
3789 } |
|
3790 }, |
|
3791 |
|
3792 /** |
|
3793 * Treeview plug-in |
|
3794 */ |
|
3795 treeview: function(element) { |
|
3796 var treeviews = $('.treeview', element); |
|
3797 if (treeviews.length > 0) { |
|
3798 ams.ajax && ams.ajax.check($.fn.treview, |
|
3799 ams.baseURL + 'ext/bootstrap-treeview' + ams.devext + '.js', |
|
3800 function() { |
|
3801 ams.getCSS(ams.baseURL + '../css/ext/bootstrap-treeview' + ams.devext + '.css', |
|
3802 'bootstrap-treeview', |
|
3803 function() { |
|
3804 treeviews.each(function() { |
|
3805 var treeview = $(this); |
|
3806 var data = treeview.data(); |
|
3807 var dataOptions = { |
|
3808 data: data.amsTreeviewData, |
|
3809 levels: data.amsTreeviewLevels, |
|
3810 injectStyle: data.amsTreeviewInjectStyle, |
|
3811 expandIcon: data.amsTreeviewExpandIcon || 'fa fa-fw fa-plus-square-o', |
|
3812 collapseIcon: data.amsTreeviewCollaspeIcon || 'fa fa-fw fa-minus-square-o', |
|
3813 emptyIcon: data.amsTreeviewEmptyIcon || 'fa fa-fw', |
|
3814 nodeIcon: data.amsTreeviewNodeIcon, |
|
3815 selectedIcon: data.amsTreeviewSelectedIcon, |
|
3816 checkedIcon: data.amsTreeviewCheckedIcon || 'fa fa-fw fa-check-square-o', |
|
3817 uncheckedIcon: data.amsTreeviewUncheckedIcon || 'fa fa-fw fa-square-o', |
|
3818 color: data.amsTreeviewColor, |
|
3819 backColor: data.amsTreeviewBackColor, |
|
3820 borderColor: data.amsTreeviewBorderColor, |
|
3821 onHoverColor: data.amsTreeviewHoverColor, |
|
3822 selectedColor: data.amsTreeviewSelectedColor, |
|
3823 selectedBackColor: data.amsTreeviewSelectedBackColor, |
|
3824 unselectableColor: data.amsTreeviewUnselectableColor || 'rgba(1,1,1,0.25)', |
|
3825 unselectableBackColor: data.amsTreeviewUnselectableBackColor || 'rgba(1,1,1,0.25)', |
|
3826 enableLinks: data.amsTreeviewEnableLinks, |
|
3827 highlightSelected: data.amsTreeviewHighlightSelected, |
|
3828 highlightSearchResults: data.amsTreeviewhighlightSearchResults, |
|
3829 showBorder: data.amsTreeviewShowBorder, |
|
3830 showIcon: data.amsTreeviewShowIcon, |
|
3831 showCheckbox: data.amsTreeviewShowCheckbox, |
|
3832 showTags: data.amsTreeviewShowTags, |
|
3833 toggleUnselectable: data.amsTreeviewToggleUnselectable, |
|
3834 multiSelect: data.amsTreeviewMultiSelect, |
|
3835 onNodeChecked: ams.getFunctionByName(data.amsTreeviewNodeChecked), |
|
3836 onNodeCollapsed: ams.getFunctionByName(data.amsTreeviewNodeCollapsed), |
|
3837 onNodeDisabled: ams.getFunctionByName(data.amsTreeviewNodeDisabled), |
|
3838 onNodeEnabled: ams.getFunctionByName(data.amsTreeviewNodeEnabled), |
|
3839 onNodeExpanded: ams.getFunctionByName(data.amsTreeviewNodeExpanded), |
|
3840 onNodeSelected: ams.getFunctionByName(data.amsTreeviewNodeSelected), |
|
3841 onNodeUnchecked: ams.getFunctionByName(data.amsTreeviewNodeUnchecked), |
|
3842 onNodeUnselected: ams.getFunctionByName(data.amsTreeviewNodeUnselected), |
|
3843 onSearchComplete: ams.getFunctionByName(data.amsTreeviewSearchComplete), |
|
3844 onSearchCleared: ams.getFunctionByName(data.amsTreeviewSearchCleared) |
|
3845 }; |
|
3846 var settings = $.extend({}, dataOptions, data.amsTreeviewOptions); |
|
3847 settings = ams.executeFunctionByName(data.amsTreeviewInitcallback, treeview, settings) || settings; |
|
3848 var plugin = treeview.treeview(settings); |
|
3849 ams.executeFunctionByName(data.amsTreeviewAfterInitCallback, treeview, plugin, settings); |
|
3850 }); |
|
3851 }); |
|
3852 }); |
|
3853 } |
|
3854 }, |
|
3855 |
|
3856 /** |
|
3857 * Select2 plug-in |
|
3858 */ |
|
3859 select2: function(element) { |
|
3860 var selects = $('.select2', element); |
|
3861 if (selects.length > 0) { |
|
3862 ams.ajax && ams.ajax.check($.fn.select2, |
|
3863 ams.baseURL + 'ext/jquery-select2-3.5.4' + ams.devext + '.js', |
|
3864 function() { |
|
3865 selects.each(function() { |
|
3866 var select = $(this); |
|
3867 var data = select.data(); |
|
3868 if (data.select2) { |
|
3869 // Already initialized |
|
3870 return; |
|
3871 } |
|
3872 var dataOptions = { |
|
3873 placeholder: data.amsSelect2Placeholder, |
|
3874 multiple: data.amsSelect2Multiple, |
|
3875 minimumInputLength: data.amsSelect2MinimumInputLength || 0, |
|
3876 maximumSelectionSize: data.amsSelect2MaximumSelectionSize, |
|
3877 openOnEnter: data.amsSelect2EnterOpen === undefined ? true : data.amsSelect2EnterOpen, |
|
3878 allowClear: data.amsSelect2AllowClear === undefined ? true : data.amsSelect2AllowClear, |
|
3879 width: data.amsSelect2Width || '100%', |
|
3880 initSelection: ams.getFunctionByName(data.amsSelect2InitSelection), |
|
3881 formatSelection: data.amsSelect2FormatSelection === undefined |
|
3882 ? ams.helpers && ams.helpers.select2FormatSelection |
|
3883 : ams.getFunctionByName(data.amsSelect2FormatSelection), |
|
3884 formatResult: ams.getFunctionByName(data.amsSelect2FormatResult), |
|
3885 formatMatches: data.amsSelect2FormatMatches === undefined ? |
|
3886 function(matches) { |
|
3887 if (matches === 1) { |
|
3888 return ams.i18n.SELECT2_MATCH; |
|
3889 } else { |
|
3890 return matches + ams.i18n.SELECT2_MATCHES; |
|
3891 } |
|
3892 } |
|
3893 : ams.getFunctionByName(data.amsSelect2FormatMatches), |
|
3894 formatNoMatches: data.amsSelect2FormatResult === undefined ? |
|
3895 function(term) { |
|
3896 return ams.i18n.SELECT2_NOMATCHES; |
|
3897 } |
|
3898 : ams.getFunctionByName(data.amsSelect2FormatResult), |
|
3899 formatInputTooShort: data.amsSelect2FormatInputTooShort === undefined ? |
|
3900 function(input, min) { |
|
3901 var n = min - input.length; |
|
3902 return ams.i18n.SELECT2_INPUT_TOOSHORT |
|
3903 .replace(/\{0\}/, n) |
|
3904 .replace(/\{1\}/, n === 1 ? "" : ams.i18n.SELECT2_PLURAL); |
|
3905 } |
|
3906 : ams.getFunctionByName(data.amsSelect2FormatInputTooShort), |
|
3907 formatInputTooLong: data.amsSelect2FormatInputTooLong === undefined ? |
|
3908 function(input, max) { |
|
3909 var n = input.length - max; |
|
3910 return ams.i18n.SELECT2_INPUT_TOOLONG |
|
3911 .replace(/\{0\}/, n) |
|
3912 .replace(/\{1\}/, n === 1 ? "" : ams.i18n.SELECT2_PLURAL); |
|
3913 } |
|
3914 : ams.getFunctionByName(data.amsSelect2FormatInputTooLong), |
|
3915 formatSelectionTooBig: data.amsSelect2FormatSelectionTooBig === undefined ? |
|
3916 function(limit) { |
|
3917 return ams.i18n.SELECT2_SELECTION_TOOBIG |
|
3918 .replace(/\{0\}/, limit) |
|
3919 .replace(/\{1\}/, limit === 1 ? "" : ams.i18n.SELECT2_PLURAL); |
|
3920 } |
|
3921 : ams.getFunctionByName(data.amsSelect2FormatSelectionTooBig), |
|
3922 formatLoadMore: data.amsSelect2FormatLoadMore === undefined ? |
|
3923 function(pageNumber) { |
|
3924 return ams.i18n.SELECT2_LOADMORE; |
|
3925 } |
|
3926 : ams.getFunctionByName(data.amsSelect2FormatLoadMore), |
|
3927 formatSearching: data.amsSelect2FormatSearching === undefined ? |
|
3928 function() { |
|
3929 return ams.i18n.SELECT2_SEARCHING; |
|
3930 } |
|
3931 : ams.getFunctionByName(data.amsSelect2FormatSearching), |
|
3932 separator: data.amsSelect2Separator || ',', |
|
3933 tokenSeparators: data.amsSelect2TokensSeparators || [','], |
|
3934 tokenizer: ams.getFunctionByName(data.amsSelect2Tokenizer) |
|
3935 }; |
|
3936 |
|
3937 switch (select.context.type) { |
|
3938 case 'text': |
|
3939 case 'hidden': |
|
3940 if (!dataOptions.initSelection) { |
|
3941 var valuesData = select.data('ams-select2-values'); |
|
3942 if (valuesData) { |
|
3943 dataOptions.initSelection = function(element, callback) { |
|
3944 var data = []; |
|
3945 $(element.val().split(dataOptions.separator)).each(function() { |
|
3946 data.push({ |
|
3947 id: this, |
|
3948 text: valuesData[this] || this |
|
3949 }); |
|
3950 }); |
|
3951 callback(data); |
|
3952 }; |
|
3953 } |
|
3954 } |
|
3955 break; |
|
3956 default: |
|
3957 break; |
|
3958 } |
|
3959 |
|
3960 if (select.attr('readonly')) { |
|
3961 if (select.attr('type') === 'hidden') { |
|
3962 dataOptions.query = function() { |
|
3963 return []; |
|
3964 }; |
|
3965 } |
|
3966 } else if (data.amsSelect2Query) { |
|
3967 // Custom query method |
|
3968 dataOptions.query = ams.getFunctionByName(data.amsSelect2Query); |
|
3969 dataOptions.minimumInputLength = data.amsSelect2MinimumInputLength || 1; |
|
3970 } else if (data.amsSelect2QueryUrl) { |
|
3971 // AJAX query |
|
3972 dataOptions.ajax = { |
|
3973 url: data.amsSelect2QueryUrl, |
|
3974 quietMillis: data.amsSelect2QuietMillis || 200, |
|
3975 type: data.amsSelect2QueryType || 'POST', |
|
3976 dataType: data.amsSelect2QueryDatatype || 'json', |
|
3977 data: function(term, page, context) { |
|
3978 var options = {}; |
|
3979 options[data.amsSelect2QueryParamName || 'query'] = term; |
|
3980 options[data.amsSelect2PageParamName || 'page'] = page; |
|
3981 options[data.amsSelect2ContextParamName || 'context'] = context; |
|
3982 return $.extend({}, options, data.amsSelect2QueryOptions); |
|
3983 }, |
|
3984 results: ams.helpers && ams.helpers.select2QueryUrlResultsCallback |
|
3985 }; |
|
3986 dataOptions.minimumInputLength = data.amsSelect2MinimumInputLength || 1; |
|
3987 } else if (data.amsSelect2QueryMethod) { |
|
3988 // JSON-RPC query |
|
3989 dataOptions.query = function(options) { |
|
3990 var settings = { |
|
3991 id: new Date().getTime(), |
|
3992 params: data.amsSelect2QueryParams || {}, |
|
3993 success: function(result) { |
|
3994 return ams.helpers && ams.helpers.select2QueryMethodSuccessCallback.call(select, result, 'success', options); |
|
3995 }, |
|
3996 error: ams.error && ams.error.show |
|
3997 }; |
|
3998 settings.params[data.amsSelect2QueryParamName || 'query'] = options.term; |
|
3999 settings.params[data.amsSelect2PageParamName || 'page'] = options.page; |
|
4000 settings.params[data.amsSelect2ContextParamName || 'context'] = options.context; |
|
4001 settings = $.extend({}, settings, data.amsSelect2QueryOptions); |
|
4002 settings = ams.executeFunctionByName(data.amsSelect2QueryInitCallback, select, settings) || settings; |
|
4003 ams.ajax && ams.ajax.check($.jsonRPC, |
|
4004 ams.baseURL + 'ext/jquery-jsonrpc' + ams.devext + '.js', |
|
4005 function() { |
|
4006 $.jsonRPC.withOptions({ |
|
4007 endPoint: data.amsSelect2MethodTarget || (ams.jsonrpc && ams.jsonrpc.getAddr()), |
|
4008 namespace: data.amsSelect2MethodNamespace, |
|
4009 cache: false |
|
4010 }, function() { |
|
4011 $.jsonRPC.request(data.amsSelect2QueryMethod, settings); |
|
4012 }); |
|
4013 }); |
|
4014 }; |
|
4015 dataOptions.minimumInputLength = data.amsSelect2MinimumInputLength || 1; |
|
4016 } else if (data.amsSelect2Tags) { |
|
4017 // Tags mode |
|
4018 dataOptions.tags = data.amsSelect2Tags; |
|
4019 } else if (data.amsSelect2Data) { |
|
4020 // Provided data mode |
|
4021 dataOptions.data = data.amsSelect2Data; |
|
4022 } |
|
4023 |
|
4024 if (data.amsSelect2EnableFreeTags) { |
|
4025 dataOptions.createSearchChoice = function(term) { |
|
4026 return { |
|
4027 id: term, |
|
4028 text: (data.amsSelect2FreeTagsPrefix || ams.i18n.SELECT2_FREETAG_PREFIX) + term |
|
4029 }; |
|
4030 }; |
|
4031 } |
|
4032 |
|
4033 var settings = $.extend({}, dataOptions, data.amsSelect2Options); |
|
4034 settings = ams.executeFunctionByName(data.amsSelect2InitCallback, select, settings) || settings; |
|
4035 var plugin = select.select2(settings); |
|
4036 ams.executeFunctionByName(data.amsSelect2AfterInitCallback, select, plugin, settings); |
|
4037 if (select.hasClass('ordered') && !select.prop('disabled')) { |
|
4038 ams.ajax && ams.ajax.check($.fn.select2Sortable, |
|
4039 ams.baseURL + 'ext/jquery-select2-sortable' + ams.devext + '.js', |
|
4040 function() { |
|
4041 select.select2Sortable({ |
|
4042 bindOrder: 'sortableStop' |
|
4043 }); |
|
4044 }); |
|
4045 } |
|
4046 |
|
4047 select.on('change', function() { |
|
4048 var validator = $(select.get(0).form).data('validator'); |
|
4049 if (validator !== undefined) { |
|
4050 $(select).valid(); |
|
4051 } |
|
4052 }); |
|
4053 }); |
|
4054 }); |
|
4055 } |
|
4056 }, |
|
4057 |
|
4058 /** |
|
4059 * Edit mask plug-in |
|
4060 */ |
|
4061 maskedit: function(element) { |
|
4062 var masks = $('[data-mask]', element); |
|
4063 if (masks.length > 0) { |
|
4064 ams.ajax && ams.ajax.check($.fn.mask, |
|
4065 ams.baseURL + 'ext/jquery-maskedinput-1.4.1' + ams.devext + '.js', |
|
4066 function() { |
|
4067 masks.each(function() { |
|
4068 var mask = $(this); |
|
4069 var data = mask.data(); |
|
4070 var dataOptions = { |
|
4071 placeholder: data.amsMaskeditPlaceholder === undefined ? 'X' : data.amsMaskeditPlaceholder, |
|
4072 complete: ams.getFunctionByName(data.amsMaskeditComplete) |
|
4073 }; |
|
4074 var settings = $.extend({}, dataOptions, data.amsMaskeditOptions); |
|
4075 settings = ams.executeFunctionByName(data.amsMaskeditInitCallback, mask, settings) || settings; |
|
4076 var plugin = mask.mask(mask.attr('data-mask'), settings); |
|
4077 ams.executeFunctionByName(data.amsMaskeditAfterInitCallback, mask, plugin, settings); |
|
4078 }); |
|
4079 }); |
|
4080 } |
|
4081 }, |
|
4082 |
|
4083 /** |
|
4084 * JQuery input-mask plug-in |
|
4085 * |
|
4086 * Mask value can be set in a "data-input-mask" attribute defined: |
|
4087 * - as a simple string containing mask |
|
4088 * - as a JSON object defining all mask attributes, for example: |
|
4089 * data-input-mask='{"alias": "integer", "allowPlus": false, "allowMinus": false}' |
|
4090 */ |
|
4091 inputmask: function(element) { |
|
4092 var masks = $('input[data-input-mask]', element); |
|
4093 if (masks.length > 0) { |
|
4094 ams.ajax && ams.ajax.check($.fn.inputmask, |
|
4095 ams.baseURL + 'ext/jquery-inputmask-bundle-3.2.8' + ams.devext + '.js', |
|
4096 function() { |
|
4097 masks.each(function() { |
|
4098 var input = $(this); |
|
4099 var data = input.data(); |
|
4100 var dataOptions; |
|
4101 if (typeof (data.inputMask) === 'object') { |
|
4102 dataOptions = data.inputMask; |
|
4103 } else { |
|
4104 dataOptions = { |
|
4105 mask: data.inputMask.toString() |
|
4106 }; |
|
4107 } |
|
4108 var settings = $.extend({}, dataOptions, data.amsInputmaskOptions); |
|
4109 settings = ams.executeFunctionByName(data.amsInputmaskInitCallback, input, settings) || settings; |
|
4110 var plugin = input.inputmask(settings); |
|
4111 ams.executeFunctionByName(data.amsInputmaskAfterInitCallback, input, plugin, settings); |
|
4112 }); |
|
4113 }); |
|
4114 } |
|
4115 }, |
|
4116 |
|
4117 /** |
|
4118 * JQuery date picker |
|
4119 */ |
|
4120 datepicker: function(element) { |
|
4121 var datepickers = $('.datepicker', element); |
|
4122 if (datepickers.length > 0) { |
|
4123 ams.ajax && ams.ajax.check($.fn.datetimepicker, |
|
4124 ams.baseURL + 'ext/jquery-datetimepicker' + ams.devext + '.js', |
|
4125 function(first_load) { |
|
4126 if (first_load) { |
|
4127 ams.dialog && ams.dialog.registerHideCallback(ams.helpers && ams.helpers.datetimepickerDialogHiddenCallback); |
|
4128 } |
|
4129 ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + ams.devext + '.css', |
|
4130 'jquery-datetimepicker', |
|
4131 function() { |
|
4132 datepickers.each(function() { |
|
4133 var input = $(this); |
|
4134 var data = input.data(); |
|
4135 var dataOptions = { |
|
4136 lang: data.amsDatetimepickerLang || ams.lang, |
|
4137 format: data.amsDatetimepickerFormat || 'd/m/y', |
|
4138 datepicker: true, |
|
4139 dayOfWeekStart: 1, |
|
4140 timepicker: false, |
|
4141 closeOnDateSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect, |
|
4142 weeks: data.amsDatetimepickerWeeks |
|
4143 }; |
|
4144 var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions); |
|
4145 settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings; |
|
4146 var plugin = input.datetimepicker(settings); |
|
4147 ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings); |
|
4148 }); |
|
4149 }); |
|
4150 }); |
|
4151 } |
|
4152 }, |
|
4153 |
|
4154 /** |
|
4155 * JQuery datetime picker |
|
4156 */ |
|
4157 datetimepicker: function(element) { |
|
4158 var datetimepickers = $('.datetimepicker', element); |
|
4159 if (datetimepickers.length > 0) { |
|
4160 ams.ajax && ams.ajax.check($.fn.datetimepicker, |
|
4161 ams.baseURL + 'ext/jquery-datetimepicker' + ams.devext + '.js', |
|
4162 function(first_load) { |
|
4163 if (first_load) { |
|
4164 ams.dialog && ams.dialog.registerHideCallback(ams.helpers && ams.helpers.datetimepickerDialogHiddenCallback); |
|
4165 } |
|
4166 ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + ams.devext + '.css', |
|
4167 'jquery-datetimepicker', |
|
4168 function() { |
|
4169 datetimepickers.each(function() { |
|
4170 var input = $(this); |
|
4171 var data = input.data(); |
|
4172 var dataOptions = { |
|
4173 lang: data.amsDatetimepickerLang || ams.lang, |
|
4174 format: data.amsDatetimepickerFormat || 'd/m/y H:i', |
|
4175 datepicker: true, |
|
4176 dayOfWeekStart: 1, |
|
4177 timepicker: true, |
|
4178 closeOnDateSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect, |
|
4179 closeOnTimeSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect, |
|
4180 weeks: data.amsDatetimepickerWeeks |
|
4181 }; |
|
4182 var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions); |
|
4183 settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings; |
|
4184 var plugin = input.datetimepicker(settings); |
|
4185 ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings); |
|
4186 }); |
|
4187 }); |
|
4188 }); |
|
4189 } |
|
4190 }, |
|
4191 |
|
4192 /** |
|
4193 * JQuery time picker |
|
4194 */ |
|
4195 timepicker: function(element) { |
|
4196 var timepickers = $('.timepicker', element); |
|
4197 if (timepickers.length > 0) { |
|
4198 ams.ajax && ams.ajax.check($.fn.datetimepicker, |
|
4199 ams.baseURL + 'ext/jquery-datetimepicker' + ams.devext + '.js', |
|
4200 function(first_load) { |
|
4201 if (first_load) { |
|
4202 ams.dialog && ams.dialog.registerHideCallback(ams.helpers && ams.helpers.datetimepickerDialogHiddenCallback); |
|
4203 } |
|
4204 ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + ams.devext + '.css', |
|
4205 'jquery-datetimepicker', |
|
4206 function() { |
|
4207 timepickers.each(function() { |
|
4208 var input = $(this); |
|
4209 var data = input.data(); |
|
4210 var dataOptions = { |
|
4211 lang: data.amsDatetimepickerLang || ams.lang, |
|
4212 format: data.amsDatetimepickerFormat || 'H:i', |
|
4213 datepicker: false, |
|
4214 timepicker: true, |
|
4215 closeOnTimeSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect |
|
4216 }; |
|
4217 var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions); |
|
4218 settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings; |
|
4219 var plugin = input.datetimepicker(settings); |
|
4220 ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings); |
|
4221 }); |
|
4222 }); |
|
4223 }); |
|
4224 } |
|
4225 }, |
|
4226 |
|
4227 /** |
|
4228 * JQuery color picker |
|
4229 */ |
|
4230 colorpicker: function(element) { |
|
4231 var colorpickers = $('.colorpicker', element); |
|
4232 if (colorpickers.length > 0) { |
|
4233 ams.ajax && ams.ajax.check($.fn.minicolors, |
|
4234 ams.baseURL + 'ext/jquery-minicolors' + ams.devext + '.js', |
|
4235 function() { |
|
4236 ams.getCSS(ams.baseURL + '../css/ext/jquery-minicolors' + ams.devext + '.css', |
|
4237 'jquery-minicolors', |
|
4238 function() { |
|
4239 colorpickers.each(function() { |
|
4240 var input = $(this); |
|
4241 var data = input.data(); |
|
4242 var dataOptions = { |
|
4243 position: data.amsColorpickerPosition || input.closest('.input').data('ams-colorpicker-position') || 'bottom left' |
|
4244 }; |
|
4245 var settings = $.extend({}, dataOptions, data.amsColorpickerOptions); |
|
4246 settings = ams.executeFunctionByName(data.amsColorpickerInitCallback, input, settings) || settings; |
|
4247 var plugin = input.minicolors(settings); |
|
4248 ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings); |
|
4249 }); |
|
4250 }); |
|
4251 }); |
|
4252 } |
|
4253 }, |
|
4254 |
|
4255 /** |
|
4256 * Drag & drop upload plug-in |
|
4257 */ |
|
4258 dndupload: function(element) { |
|
4259 var uploads = $('.dndupload', element); |
|
4260 if (uploads.length > 0) { |
|
4261 ams.ajax && ams.ajax.check($.fn.dndupload, |
|
4262 ams.baseURL + 'ext/jquery-dndupload' + ams.devext + '.js', |
|
4263 function() { |
|
4264 ams.getCSS(ams.baseURL + '../css/ext/jquery-dndupload' + ams.devext + '.css', |
|
4265 'jquery-dndupload', |
|
4266 function() { |
|
4267 uploads.each(function() { |
|
4268 var upload = $(this); |
|
4269 var data = upload.data(); |
|
4270 var dataOptions = { |
|
4271 action: data.amsDnduploadAction || upload.attr('action') || 'upload-files', |
|
4272 fieldname: data.amsDnduploadFieldname || 'files', |
|
4273 autosubmit: data.amsDnduploadAutosubmit |
|
4274 }; |
|
4275 var settings = $.extend({}, dataOptions, data.amsDnduploadOptions); |
|
4276 settings = ams.executeFunctionByName(data.amsDnduploadInitCallback, upload, settings) || settings; |
|
4277 var plugin = upload.dndupload(settings); |
|
4278 ams.executeFunctionByName(data.amsDnduploadAfterInitcallback, upload, plugin, settings); |
|
4279 }); |
|
4280 }); |
|
4281 }); |
|
4282 } |
|
4283 }, |
|
4284 |
|
4285 /** |
|
4286 * JQuery validation plug-in |
|
4287 */ |
|
4288 validate: function(element) { |
|
4289 var forms = $('FORM:not([novalidate])', element); |
|
4290 if (forms.length > 0) { |
|
4291 ams.ajax && ams.ajax.check($.fn.validate, |
|
4292 ams.baseURL + 'ext/jquery-validate-1.17.0' + ams.devext + '.js', |
|
4293 function(first_load) { |
|
4294 if (first_load) { |
|
4295 $.validator.setDefaults({ |
|
4296 highlight: function(element) { |
|
4297 $(element).closest('.form-group, label:not(:parents(.form-group))') |
|
4298 .addClass('state-error'); |
|
4299 }, |
|
4300 unhighlight: function(element) { |
|
4301 $(element).closest('.form-group, label:not(:parents(.form-group))') |
|
4302 .removeClass('state-error'); |
|
4303 }, |
|
4304 errorElement: 'span', |
|
4305 errorClass: 'state-error', |
|
4306 errorPlacement: function(error, element) { |
|
4307 var label = element.parents('label, .input').first(); |
|
4308 if (label.length) { |
|
4309 error.insertAfter(label); |
|
4310 } else { |
|
4311 error.insertAfter(element); |
|
4312 } |
|
4313 } |
|
4314 }); |
|
4315 if (ams.plugins && ams.plugins.i18n) { |
|
4316 for (var key in ams.plugins.i18n.validate) { |
|
4317 if (!ams.plugins.i18n.validate.hasOwnProperty(key)) { |
|
4318 continue; |
|
4319 } |
|
4320 var message = ams.plugins.i18n.validate[key]; |
|
4321 if ((typeof (message) === 'string') && |
|
4322 (message.indexOf('{0}') > -1)) { |
|
4323 ams.plugins.i18n.validate[key] = $.validator.format(message); |
|
4324 } |
|
4325 } |
|
4326 $.extend($.validator.messages, ams.plugins.i18n.validate); |
|
4327 } |
|
4328 } |
|
4329 forms.each(function() { |
|
4330 var form = $(this); |
|
4331 var data = form.data(); |
|
4332 var dataOptions = { |
|
4333 ignore: null, |
|
4334 submitHandler: form.attr('data-async') !== undefined ? |
|
4335 data.amsFormSubmitHandler === undefined ? |
|
4336 function() { |
|
4337 // JQuery-form plug-in must be loaded synchronously!! |
|
4338 // Otherwise, hidden input fields created by jquery-validate plug-in |
|
4339 // and matching named buttons will be deleted (on first form submit) |
|
4340 // before JQuery-form plug-in can get them when submitting the form... |
|
4341 $('.state-error', form).removeClass('state-error'); |
|
4342 ams.ajax && ams.ajax.check($.fn.ajaxSubmit, |
|
4343 ams.baseURL + 'ext/jquery-form-3.49' + ams.devext + '.js'); |
|
4344 return ams.form && ams.form.submit(form); |
|
4345 } |
|
4346 : ams.getFunctionByName(data.amsFormSubmitHandler) |
|
4347 : undefined, |
|
4348 invalidHandler: data.amsFormInvalidHandler === undefined ? |
|
4349 function(event, validator) { |
|
4350 $('.state-error', form).removeClass('state-error'); |
|
4351 for (var index = 0; index < validator.errorList.length; index++) { |
|
4352 var error = validator.errorList[index]; |
|
4353 var tabIndex = $(error.element).parents('.tab-pane').index() + 1; |
|
4354 if (tabIndex > 0) { |
|
4355 var navTabs = $('.nav-tabs', $(error.element).parents('.tabforms')); |
|
4356 $('li:nth-child(' + tabIndex + ')', navTabs) |
|
4357 .removeClassPrefix('state-') |
|
4358 .addClass('state-error'); |
|
4359 $('li.state-error:first a', navTabs).click(); |
|
4360 } |
|
4361 } |
|
4362 } |
|
4363 : ams.getFunctionByName(data.amsFormInvalidHandler) |
|
4364 }; |
|
4365 $('[data-ams-validate-rules]', form).each(function(index) { |
|
4366 if (index === 0) { |
|
4367 dataOptions.rules = {}; |
|
4368 } |
|
4369 dataOptions.rules[$(this).attr('name')] = $(this).data('ams-validate-rules'); |
|
4370 }); |
|
4371 $('[data-ams-validate-messages]', form).each(function(index) { |
|
4372 if (index === 0) { |
|
4373 dataOptions.messages = {}; |
|
4374 } |
|
4375 dataOptions.messages[$(this).attr('name')] = $(this).data('ams-validate-messages'); |
|
4376 }); |
|
4377 var settings = $.extend({}, dataOptions, data.amsValidateOptions); |
|
4378 settings = ams.executeFunctionByName(data.amsValidateInitCallback, form, settings) || settings; |
|
4379 var plugin = form.validate(settings); |
|
4380 ams.executeFunctionByName(data.amsValidateAfterInitCallback, form, plugin, settings); |
|
4381 }); |
|
4382 }); |
|
4383 } |
|
4384 }, |
|
4385 |
|
4386 /** |
|
4387 * JQuery dataTables |
|
4388 */ |
|
4389 datatable: function(element) { |
|
4390 var tables = $('.datatable', element); |
|
4391 if (tables.length > 0) { |
|
4392 ams.ajax && ams.ajax.check($.fn.dataTable, |
|
4393 ams.baseURL + 'ext/jquery-dataTables-1.9.4' + ams.devext + '.js', |
|
4394 function() { |
|
4395 ams.ajax.check($.fn.dataTableExt.oPagination.bootstrap_full, |
|
4396 ams.baseURL + 'myams-dataTables' + ams.devext + '.js', |
|
4397 function() { |
|
4398 $(tables).each(function() { |
|
4399 var table = $(this); |
|
4400 var data = table.data(); |
|
4401 var extensions = (data.amsDatatableExtensions || '').split(/\s+/); |
|
4402 // Check DOM elements |
|
4403 var sDom = data.amsDatatableSdom || |
|
4404 "W" + |
|
4405 ((extensions.indexOf('colreorder') >= 0 || |
|
4406 extensions.indexOf('colreorderwithresize') >= 0) ? 'R' : '') + |
|
4407 "<'dt-top-row'" + |
|
4408 (extensions.indexOf('colvis') >= 0 ? 'C' : '') + |
|
4409 ((data.amsDatatablePagination === false || |
|
4410 data.amsDatatablePaginationSize === false) ? '' : 'L') + |
|
4411 (data.amsDatatableGlobalFilter === false ? '' : 'F') + |
|
4412 ">r<'dt-wrapper't" + |
|
4413 (extensions.indexOf('scroller') >= 0 ? 'S' : '') + |
|
4414 "><'dt-row dt-bottom-row'<'row'<'col-sm-6'" + |
|
4415 (data.amsDatatableInformation === false ? '' : 'i') + |
|
4416 "><'col-sm-6 text-right'p>>"; |
|
4417 |
|
4418 var index; |
|
4419 // Check initial sorting |
|
4420 var sorting = data.amsDatatableSorting; |
|
4421 if (typeof (sorting) === 'string') { |
|
4422 var sortings = sorting.split(';'); |
|
4423 sorting = []; |
|
4424 for (index = 0; index < sortings.length; index++) { |
|
4425 var colSorting = sortings[index].split(','); |
|
4426 colSorting[0] = parseInt(colSorting[0]); |
|
4427 sorting.push(colSorting); |
|
4428 } |
|
4429 } |
|
4430 // Check columns sortings |
|
4431 var columns = []; |
|
4432 var column; |
|
4433 var sortables = $('th', table).listattr('data-ams-datatable-sortable'); |
|
4434 for (index = 0; index < sortables.length; index++) { |
|
4435 var sortable = sortables[index]; |
|
4436 if (sortable !== undefined) { |
|
4437 column = columns[index] || {}; |
|
4438 column.bSortable = typeof (sortable) === 'string' ? JSON.parse(sortable) : sortable; |
|
4439 columns[index] = column; |
|
4440 } else { |
|
4441 columns[index] = columns[index] || {}; |
|
4442 } |
|
4443 } |
|
4444 // Check columns types |
|
4445 var sortTypes = $('th', table).listattr('data-ams-datatable-stype'); |
|
4446 for (index = 0; index < sortTypes.length; index++) { |
|
4447 var sortType = sortTypes[index]; |
|
4448 if (sortType) { |
|
4449 column = columns[index] || {}; |
|
4450 column.sType = sortType; |
|
4451 columns[index] = column; |
|
4452 } else { |
|
4453 columns[index] = columns[index] || {}; |
|
4454 } |
|
4455 } |
|
4456 // Set options |
|
4457 var dataOptions = { |
|
4458 bJQueryUI: false, |
|
4459 bServerSide: data.amsDatatableServerSide || false, |
|
4460 sAjaxSource: data.amsDatatableServerSide === true ? data.amsDatatableAjaxSource : undefined, |
|
4461 sServerMethod: data.amsDatatableServerSide === true ? 'POST' : undefined, |
|
4462 bFilter: data.amsDatatableGlobalFilter !== false || extensions.indexOf('columnfilter') >= 0, |
|
4463 bPaginate: data.amsDatatablePagination !== false, |
|
4464 bInfo: data.amsDatatableInfo !== false, |
|
4465 bSort: data.amsDatatableSort !== false, |
|
4466 aaSorting: sorting, |
|
4467 aoColumns: columns.length > 0 ? columns : undefined, |
|
4468 bDeferRender: true, |
|
4469 bAutoWidth: false, |
|
4470 iDisplayLength: data.amsDatatableDisplayLength || 25, |
|
4471 sPaginationType: data.amsDatatablePaginationType || 'bootstrap_full', |
|
4472 sDom: sDom, |
|
4473 oLanguage: ams.plugins && ams.plugins.i18n.datatables, |
|
4474 fnInitComplete: function(oSettings, json) { |
|
4475 $('.ColVis_Button').addClass('btn btn-default btn-sm') |
|
4476 .html(((ams.plugins && ams.plugins.i18n.datatables.sColumns) || "Columns") + |
|
4477 ' <i class="fa fa-fw fa-caret-down"></i>'); |
|
4478 } |
|
4479 }; |
|
4480 var settings = $.extend({}, dataOptions, data.amsDatatableOptions); |
|
4481 var checkers = []; |
|
4482 var sources = []; |
|
4483 var callbacks = []; |
|
4484 if (extensions.length > 0) { |
|
4485 for (index = 0; index < extensions.length; index++) { |
|
4486 switch (extensions[index]) { |
|
4487 case 'autofill': |
|
4488 checkers.push($.fn.dataTable.AutoFill); |
|
4489 sources.push(ams.baseURL + 'ext/jquery-dataTables-autoFill' + ams.devext + '.js'); |
|
4490 break; |
|
4491 case 'columnfilter': |
|
4492 checkers.push($.fn.columnFilter); |
|
4493 sources.push(ams.baseURL + 'ext/jquery-dataTables-columnFilter' + ams.devext + '.js'); |
|
4494 break; |
|
4495 case 'colreorder': |
|
4496 checkers.push($.fn.dataTable.ColReorder); |
|
4497 sources.push(ams.baseURL + 'ext/jquery-dataTables-colReorder' + ams.devext + '.js'); |
|
4498 break; |
|
4499 case 'colreorderwithresize': |
|
4500 checkers.push(window.ColReorder); |
|
4501 sources.push(ams.baseURL + 'ext/jquery-dataTables-colReorderWithResize' + ams.devext + '.js'); |
|
4502 break; |
|
4503 case 'colvis': |
|
4504 checkers.push($.fn.dataTable.ColVis); |
|
4505 sources.push(ams.baseURL + 'ext/jquery-dataTables-colVis' + ams.devext + '.js'); |
|
4506 callbacks.push(function() { |
|
4507 var cvDefault = { |
|
4508 activate: 'click', |
|
4509 sAlign: 'right' |
|
4510 }; |
|
4511 settings.oColVis = $.extend({}, cvDefault, data.amsDatatableColvisOptions); |
|
4512 }); |
|
4513 break; |
|
4514 case 'editable': |
|
4515 checkers.push($.fn.editable); |
|
4516 sources.push(ams.baseURL + 'ext/jquery-jeditable' + ams.devext + '.js'); |
|
4517 checkers.push($.fn.makeEditable); |
|
4518 sources.push(ams.baseURL + 'ext/jquery-dataTables-editable' + ams.devext + '.js'); |
|
4519 break; |
|
4520 case 'fixedcolumns': |
|
4521 checkers.push($.fn.dataTable.FixedColumns); |
|
4522 sources.push(ams.baseURL + 'ext/jquery-dataTables-fixedColumns' + ams.devext + '.js'); |
|
4523 break; |
|
4524 case 'fixedheader': |
|
4525 checkers.push($.fn.dataTable.Fixedheader); |
|
4526 sources.push(ams.baseURL + 'ext/jquery-dataTables-fixedHeader' + ams.devext + '.js'); |
|
4527 break; |
|
4528 case 'keytable': |
|
4529 checkers.push(window.keyTable); |
|
4530 sources.push(ams.baseURL + 'ext/jquery-dataTables-keyTable' + ams.devext + '.js'); |
|
4531 break; |
|
4532 case 'rowgrouping': |
|
4533 checkers.push($.fn.rowGrouping); |
|
4534 sources.push(ams.baseURL + 'ext/jquery-dataTables-rowGrouping' + ams.devext + '.js'); |
|
4535 break; |
|
4536 case 'rowreordering': |
|
4537 checkers.push($.fn.rowReordering); |
|
4538 sources.push(ams.baseURL + 'ext/jquery-dataTables-rowReordering' + ams.devext + '.js'); |
|
4539 break; |
|
4540 case 'scroller': |
|
4541 checkers.push($.fn.dataTable.Scroller); |
|
4542 sources.push(ams.baseURL + 'ext/jquery-dataTables-scroller' + ams.devext + '.js'); |
|
4543 break; |
|
4544 default: |
|
4545 break; |
|
4546 } |
|
4547 } |
|
4548 } |
|
4549 |
|
4550 function initTable() { |
|
4551 settings = ams.executeFunctionByName(data.amsDatatableInitCallback, table, settings) || settings; |
|
4552 try { // Some settings can easily generate DataTables exceptions... |
|
4553 var plugin = table.dataTable(settings); |
|
4554 ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings); |
|
4555 if (extensions.length > 0) { |
|
4556 for (index = 0; index < extensions.length; index++) { |
|
4557 switch (extensions[index]) { |
|
4558 case 'autofill': |
|
4559 var afSettings = $.extend({}, data.amsDatatableAutofillOptions, settings.autofill); |
|
4560 afSettings = ams.executeFunctionByName(data.amsDatatableAutofillInitCallback, table, afSettings) || afSettings; |
|
4561 table.data('ams-autofill', data.amsDatatableAutofillConstructor === undefined ? |
|
4562 new $.fn.dataTable.AutoFill(table, afSettings) |
|
4563 : ams.executeFunctionByName(data.amsDatatableAutofillConstructor, table, plugin, afSettings)); |
|
4564 break; |
|
4565 case 'columnfilter': |
|
4566 var cfDefault = { |
|
4567 sPlaceHolder: 'head:after' |
|
4568 }; |
|
4569 var cfSettings = $.extend({}, cfDefault, data.amsDatatableColumnfilterOptions, settings.columnfilter); |
|
4570 cfSettings = ams.executeFunctionByName(data.amsDatatableColumnfilterInitCallback, table, cfSettings) || cfSettings; |
|
4571 table.data('ams-columnfilter', data.amsDatatableColumnfilterConstructor === undefined ? |
|
4572 plugin.columnFilter(cfSettings) |
|
4573 : ams.executeFunctionByName(data.amsDatatableColumnfilterConstructor, table, plugin, cfSettings)); |
|
4574 break; |
|
4575 case 'editable': |
|
4576 var edSettings = $.extend({}, data.amsDatatableEditableOptions, settings.editable); |
|
4577 edSettings = ams.executeFunctionByName(data.amsDatatableEditableInitCallback, table, edSettings) || edSettings; |
|
4578 table.data('ams-editable', data.amsDatatableEditableConstructor === undefined ? |
|
4579 table.makeEditable(edSettings) |
|
4580 : ams.executeFunctionByName(data.amsDatatableEditableConstructor, table, plugin, edSettings)); |
|
4581 break; |
|
4582 case 'fixedcolumns': |
|
4583 var fcSettings = $.extend({}, data.amsDatatableFixedcolumnsOptions, settings.fixedcolumns); |
|
4584 fcSettings = ams.executeFunctionByName(data.amsDatatableFixedcolumnsInitCallback, table, fcSettings) || fcSettings; |
|
4585 table.data('ams-fixedcolumns', data.amsDatatableFixedcolumnsConstructor === undefined ? |
|
4586 new $.fn.dataTable.FixedColumns(table, fcSettings) |
|
4587 : ams.executeFunctionByName(data.amsDatatableFixedcolumnsConstructor, table, plugin, fcSettings)); |
|
4588 break; |
|
4589 case 'fixedheader': |
|
4590 var fhSettings = $.extend({}, data.amsDatatableFixedheaderOptions, settings.fixedheader); |
|
4591 fhSettings = ams.executeFunctionByName(data.amsDatatableFixedheadeInitCallback, table, fhSettings) || fhSettings; |
|
4592 table.data('ams-fixedheader', data.amsDatatableFixedheaderConstructor === undefined ? |
|
4593 new $.fn.dataTable.FixedHeader(table, fhSettings) |
|
4594 : ams.executeFunctionByName(data.amsDatatableFixedheaderConstructor, table, plugin, fhSettings)); |
|
4595 break; |
|
4596 case 'keytable': |
|
4597 var ktDefault = { |
|
4598 table: table.get(0), |
|
4599 datatable: plugin |
|
4600 }; |
|
4601 var ktSettings = $.extend({}, ktDefault, data.amsDatatableKeytableOptions, settings.keytable); |
|
4602 ktSettings = ams.executeFunctionByName(data.amsDatatableKeytableInitCallback, table, ktSettings) || ktSettings; |
|
4603 table.data('ams-keytable', data.amsDatatableKeytableConstructor === undefined ? |
|
4604 new KeyTable(ktSettings) |
|
4605 : ams.executeFunctionByName(data.amsDatatableKeytableConstructor, table, plugin, ktSettings)); |
|
4606 break; |
|
4607 case 'rowgrouping': |
|
4608 var rgSettings = $.extend({}, data.amsDatatableRowgroupingOptions, settings.rowgrouping); |
|
4609 rgSettings = ams.executeFunctionByName(data.amsDatatableRowgroupingInitCallback, table, rgSettings) || rgSettings; |
|
4610 table.data('ams-rowgrouping', data.amsDatatableRowgroupingConstructor === undefined ? |
|
4611 table.rowGrouping(rgSettings) |
|
4612 : ams.executeFunctionByName(data.amsDatatableRowgroupingConstructor, table, plugin, rgSettings)); |
|
4613 break; |
|
4614 case 'rowreordering': |
|
4615 var rrSettings = $.extend({}, data.amsDatatableRowreorderingOptions, settings.rowreordering); |
|
4616 rrSettings = ams.executeFunctionByName(data.amsDatatableRowreorderingInitCallback, table, rrSettings) || rrSettings; |
|
4617 table.data('ams-rowreordering', data.amsDatatableRowreorderingConstructor === undefined ? |
|
4618 table.rowReordering(rrSettings) |
|
4619 : ams.executeFunctionByName(data.amsDatatableRowreorderingConstructor, table, plugin, rrSettings)); |
|
4620 break; |
|
4621 default: |
|
4622 break; |
|
4623 } |
|
4624 } |
|
4625 } |
|
4626 if (data.amsDatatableFinalizeCallback) { |
|
4627 var finalizers = data.amsDatatableFinalizeCallback.split(/\s+/); |
|
4628 if (finalizers.length > 0) { |
|
4629 for (index = 0; index < finalizers.length; index++) { |
|
4630 ams.executeFunctionByName(finalizers[index], table, plugin, settings); |
|
4631 } |
|
4632 } |
|
4633 } |
|
4634 } catch (e) { |
|
4635 } |
|
4636 } |
|
4637 |
|
4638 callbacks.push(initTable); |
|
4639 ams.ajax && ams.ajax.check(checkers, sources, callbacks); |
|
4640 }); |
|
4641 }); |
|
4642 }); |
|
4643 } |
|
4644 }, |
|
4645 |
|
4646 /** |
|
4647 * TableDND plug-in |
|
4648 */ |
|
4649 tablednd: function(element) { |
|
4650 var tables = $('.table-dnd', element); |
|
4651 if (tables.length > 0) { |
|
4652 ams.ajax && ams.ajax.check($.fn.tableDnD, |
|
4653 ams.baseURL + 'ext/jquery-tablednd' + ams.devext + '.js', |
|
4654 function() { |
|
4655 tables.each(function() { |
|
4656 var table = $(this); |
|
4657 var data = table.data(); |
|
4658 if (data.amsTabledndDragHandle) { |
|
4659 $('tr', table).addClass('no-drag-handle'); |
|
4660 } else { |
|
4661 $(table).on('mouseover', 'tr', function() { |
|
4662 $(this.cells[0]).addClass('drag-handle'); |
|
4663 }).on('mouseout', 'tr', function() { |
|
4664 $(this.cells[0]).removeClass('drag-handle'); |
|
4665 }); |
|
4666 } |
|
4667 var dataOptions = { |
|
4668 onDragClass: data.amsTabledndDragClass || 'dragging-row', |
|
4669 onDragStart: ams.getFunctionByName(data.amsTabledndDragStart), |
|
4670 dragHandle: data.amsTabledndDragHandle, |
|
4671 scrollAmount: data.amsTabledndScrollAmount, |
|
4672 onAllowDrop: data.amsTabledndAllowDrop, |
|
4673 onDrop: ams.getFunctionByName(data.amsTabledndDrop) || function(dnd_table, row) { |
|
4674 var target = data.amsTabledndDropTarget; |
|
4675 if (target) { |
|
4676 // Disable row click handler |
|
4677 $(row).data('ams-disabled-handlers', 'click'); |
|
4678 try { |
|
4679 var rows = []; |
|
4680 $(dnd_table.rows).each(function() { |
|
4681 var rowId = $(this).data('ams-element-name'); |
|
4682 if (rowId) { |
|
4683 rows.push(rowId); |
|
4684 } |
|
4685 }); |
|
4686 var localTarget = ams.getFunctionByName(target); |
|
4687 if (typeof (localTarget) === 'function') { |
|
4688 localTarget.call(table, dnd_table, rows); |
|
4689 } else { |
|
4690 if (!target.startsWith(window.location.protocol)) { |
|
4691 var location = data.amsLocation; |
|
4692 if (location) { |
|
4693 target = location + '/' + target; |
|
4694 } |
|
4695 } |
|
4696 ams.ajax && ams.ajax.post(target, {names: JSON.stringify(rows)}, function(result, status) { |
|
4697 if (result.status !== 'success') { |
|
4698 ams.ajax.handleJSON(result); |
|
4699 } |
|
4700 }); |
|
4701 } |
|
4702 } finally { |
|
4703 // Restore row click handler |
|
4704 setTimeout(function() { |
|
4705 $(row).removeData('ams-disabled-handlers'); |
|
4706 }, 50); |
|
4707 } |
|
4708 } |
|
4709 return false; |
|
4710 } |
|
4711 }; |
|
4712 var settings = $.extend({}, dataOptions, data.amsTabledndOptions); |
|
4713 settings = ams.executeFunctionByName(data.amsTabledndInitCallback, table, settings) || settings; |
|
4714 var plugin = table.tableDnD(settings); |
|
4715 ams.executeFunctionByName(data.amsTabledndAfterInitCallback, table, plugin, settings); |
|
4716 }); |
|
4717 }); |
|
4718 } |
|
4719 }, |
|
4720 |
|
4721 /** |
|
4722 * Wizard plug-in |
|
4723 */ |
|
4724 wizard: function(element) { |
|
4725 var wizards = $('.wizard', element); |
|
4726 if (wizards.length > 0) { |
|
4727 ams.ajax && ams.ajax.check($.fn.bootstrapWizard, |
|
4728 ams.baseURL + 'ext/bootstrap-wizard-1.4.2' + ams.devext + '.js', |
|
4729 function() { |
|
4730 wizards.each(function() { |
|
4731 var wizard = $(this); |
|
4732 var data = wizard.data(); |
|
4733 var dataOptions = { |
|
4734 withVisible: data.amsWizardWithVisible === undefined ? true : data.amsWizardWithVisible, |
|
4735 tabClass: data.amsWizardTabClass, |
|
4736 firstSelector: data.amsWizardFirstSelector, |
|
4737 previousSelector: data.amsWizardPreviousSelector, |
|
4738 nextSelector: data.amsWizardNextSelector, |
|
4739 lastSelector: data.amsWizardLastSelector, |
|
4740 finishSelector: data.amsWizardFinishSelector, |
|
4741 backSelector: data.amsWizardBackSelector, |
|
4742 onInit: ams.getFunctionByName(data.amsWizardInit), |
|
4743 onShow: ams.getFunctionByName(data.amsWizardShow), |
|
4744 onNext: ams.getFunctionByName(data.amsWizardNext), |
|
4745 onPrevious: ams.getFunctionByName(data.amsWizardPrevious), |
|
4746 onFirst: ams.getFunctionByName(data.amsWizardFirst), |
|
4747 onLast: ams.getFunctionByName(data.amsWizardLast), |
|
4748 onBack: ams.getFunctionByName(data.amsWizardBack), |
|
4749 onFinish: ams.getFunctionByName(data.amsWizardFinish), |
|
4750 onTabChange: ams.getFunctionByName(data.amsWizardTabChange), |
|
4751 onTabClick: ams.getFunctionByName(data.amsWizardTabClick), |
|
4752 onTabShow: ams.getFunctionByName(data.amsWizardTabShow) |
|
4753 }; |
|
4754 var settings = $.extend({}, dataOptions, data.amsWizardOptions); |
|
4755 settings = ams.executeFunctionByName(data.amsWizardInitCallback, wizard, settings) || settings; |
|
4756 var plugin = wizard.bootstrapWizard(settings); |
|
4757 ams.executeFunctionByName(data.amsWizardAfterInitCallback, wizard, plugin, settings); |
|
4758 }); |
|
4759 }); |
|
4760 } |
|
4761 }, |
|
4762 |
|
4763 /** |
|
4764 * TinyMCE plug-in |
|
4765 */ |
|
4766 tinymce: function(element) { |
|
4767 |
|
4768 function cleanEditors() { |
|
4769 $('.tinymce', $(this)).each(function() { |
|
4770 var editor = tinymce.get($(this).attr('id')); |
|
4771 if (editor) { |
|
4772 editor.remove(); |
|
4773 } |
|
4774 }); |
|
4775 } |
|
4776 |
|
4777 var editors = $('.tinymce', element); |
|
4778 if (editors.length > 0) { |
|
4779 var baseURL = ams.baseURL + 'ext/tinymce' + (ams.devmode ? '/dev' : ''); |
|
4780 ams.ajax && ams.ajax.check(window.tinymce, |
|
4781 baseURL + '/tinymce' + ams.devext + '.js', |
|
4782 function(first_load) { |
|
4783 |
|
4784 function initEditors() { |
|
4785 editors.each(function() { |
|
4786 var editor = $(this); |
|
4787 var data = editor.data(); |
|
4788 var dataOptions = { |
|
4789 theme: data.amsTinymceTheme || "modern", |
|
4790 language: ams.lang, |
|
4791 menubar: data.amsTinymceMenubar !== false, |
|
4792 statusbar: data.amsTinymceStatusbar !== false, |
|
4793 plugins: data.amsTinymcePlugins || [ |
|
4794 "advlist autosave autolink lists link charmap print preview hr anchor pagebreak", |
|
4795 "searchreplace wordcount visualblocks visualchars code fullscreen", |
|
4796 "insertdatetime nonbreaking save table contextmenu directionality", |
|
4797 "emoticons paste textcolor colorpicker textpattern autoresize" |
|
4798 ], |
|
4799 toolbar: data.amsTinymceToolbar, |
|
4800 toolbar1: data.amsTinymceToolbar1 === false ? false : data.amsTinymceToolbar1 || |
|
4801 "undo redo | pastetext | styleselect | bold italic | alignleft " + |
|
4802 "aligncenter alignright alignjustify | bullist numlist " + |
|
4803 "outdent indent", |
|
4804 toolbar2: data.amsTinymceToolbar2 === false ? false : data.amsTinymceToolbar2 || |
|
4805 "forecolor backcolor emoticons | charmap link image media | " + |
|
4806 "fullscreen preview print | code", |
|
4807 content_css: data.amsTinymceContentCss, |
|
4808 formats: data.amsTinymceFormats, |
|
4809 style_formats: data.amsTinymceStyleFormats, |
|
4810 block_formats: data.amsTinymceBlockFormats, |
|
4811 valid_classes: data.amsTinymceValidClasses, |
|
4812 image_advtab: true, |
|
4813 image_list: ams.getFunctionByName(data.amsTinymceImageList) || data.amsTinymceImageList, |
|
4814 image_class_list: data.amsTinymceImageClassList, |
|
4815 link_list: ams.getFunctionByName(data.amsTinymceLinkList) || data.amsTinymceLinkList, |
|
4816 link_class_list: data.amsTinymceLinkClassList, |
|
4817 paste_as_text: data.amsTinymcePasteAsText === undefined ? true : data.amsTinymcePasteAsText, |
|
4818 paste_auto_cleanup_on_paste: data.amsTinymcePasteAutoCleanup === undefined ? true : data.amsTinymcePasteAutoCleanup, |
|
4819 paste_strip_class_attributes: data.amsTinymcePasteStripClassAttributes || 'all', |
|
4820 paste_remove_spans: data.amsTinymcePaseRemoveSpans === undefined ? true : data.amsTinymcePasteRemoveSpans, |
|
4821 paste_remove_styles: data.amsTinymcePasteRemoveStyles === undefined ? true : data.amsTinymcePasteRemoveStyles, |
|
4822 height: data.amsTinymceHeight || 50, |
|
4823 min_height: 50, |
|
4824 resize: true, |
|
4825 autoresize_min_height: 50, |
|
4826 autoresize_max_height: 500 |
|
4827 }; |
|
4828 if (data.amsTinymceExternalPlugins) { |
|
4829 var names = data.amsTinymceExternalPlugins.split(/\s+/); |
|
4830 for (var index in names) { |
|
4831 if (!names.hasOwnProperty(index)) { |
|
4832 continue; |
|
4833 } |
|
4834 var pluginSrc = editor.data('ams-tinymce-plugin-' + names[index]); |
|
4835 tinymce.PluginManager.load(names[index], ams.getSource(pluginSrc)); |
|
4836 } |
|
4837 } |
|
4838 var settings = $.extend({}, dataOptions, data.amsTinymceOptions); |
|
4839 settings = ams.executeFunctionByName(data.amsTinymceInitCallback, editor, settings) || settings; |
|
4840 var plugin = editor.tinymce(settings); |
|
4841 ams.executeFunctionByName(data.amsTinymceAfterInitCallback, editor, plugin, settings); |
|
4842 }); |
|
4843 } |
|
4844 |
|
4845 if (first_load) { |
|
4846 ams.getScript(baseURL + '/jquery.tinymce' + ams.devext + '.js', function() { |
|
4847 tinymce.baseURL = baseURL; |
|
4848 tinymce.suffix = ams.devext; |
|
4849 ams.skin && ams.skin.registerCleanCallback(cleanEditors); |
|
4850 initEditors(); |
|
4851 }); |
|
4852 } else { |
|
4853 initEditors(); |
|
4854 } |
|
4855 }); |
|
4856 } |
|
4857 }, |
|
4858 |
|
4859 /** |
|
4860 * HTML editor with syntax highlight |
|
4861 */ |
|
4862 editor: function(element) { |
|
4863 var editors = $('.text-editor textarea', element); |
|
4864 if (editors.length > 0) { |
|
4865 ams.ajax && ams.ajax.check(globals.ace, |
|
4866 ams.baseURL + 'ext/ace/ace.js', |
|
4867 function(first_load) { |
|
4868 |
|
4869 var initEditors = function() { |
|
4870 globals.ace_loaded = true; |
|
4871 editors.each(function() { |
|
4872 |
|
4873 // Find textarea attributes |
|
4874 var textarea = $(this), |
|
4875 widget = textarea.parents('.text-editor'), |
|
4876 data = widget.data(), |
|
4877 modeList = ace.require('ace/ext/modelist'), |
|
4878 mode = data.amsEditorMode || modeList.getModeForPath(data.amsEditorFilename || 'editor.txt').mode; |
|
4879 |
|
4880 // Create editor DIV |
|
4881 var textEditor = $('<div>', { |
|
4882 position: 'absolute', |
|
4883 width: textarea.width(), |
|
4884 height: textarea.height(), |
|
4885 'class': textarea.attr('class') |
|
4886 }).insertBefore(textarea); |
|
4887 textarea.css('display', 'none'); |
|
4888 |
|
4889 // Initialize editor |
|
4890 var editor = ace.edit(textEditor[0]), |
|
4891 dataOptions = { |
|
4892 mode: mode, |
|
4893 tabSize: 4, |
|
4894 useSoftTabs: false, |
|
4895 showGutter: true, |
|
4896 showLineNumbers: true, |
|
4897 printMargin: 132, |
|
4898 showInvisibles: true |
|
4899 }, |
|
4900 settings = $.extend({}, dataOptions, data.amsEditorOptions); |
|
4901 settings = ams.executeFunctionByName(data.amsEditorInitCallback, textarea, settings) || settings; |
|
4902 editor.setOptions(settings); |
|
4903 editor.session.setValue(textarea.val()); |
|
4904 editor.session.on('change', function() { |
|
4905 textarea.val(editor.session.getValue()); |
|
4906 }); |
|
4907 widget.data('editor', editor); |
|
4908 ams.executeFunctionByName(data.amsEditorAfterInitCallback, textarea, editor, settings); |
|
4909 }); |
|
4910 }; |
|
4911 |
|
4912 if (first_load) { |
|
4913 ace.config.set('basePath', ams.baseURL + 'ext/ace'); |
|
4914 ams.ajax.check(globals.ace_loaded, [ |
|
4915 ams.baseURL + 'ext/ace/ext-modelist.js' |
|
4916 ], initEditors); |
|
4917 } else { |
|
4918 initEditors(); |
|
4919 } |
|
4920 }); |
|
4921 } |
|
4922 }, |
|
4923 |
|
4924 /** |
|
4925 * Image area select plug-in |
|
4926 */ |
|
4927 imgareaselect: function(element) { |
|
4928 var images = $('.imgareaselect', element); |
|
4929 if (images.length > 0) { |
|
4930 ams.ajax && ams.ajax.check($.fn.imgAreaSelect, |
|
4931 ams.baseURL + 'ext/jquery-imgareaselect-0.9.11-rc1' + ams.devext + '.js', |
|
4932 function() { |
|
4933 ams.getCSS(ams.baseURL + '../css/ext/jquery-imgareaselect' + ams.devext + '.css', |
|
4934 'jquery-imgareaselect', |
|
4935 function() { |
|
4936 images.each(function() { |
|
4937 var image = $(this); |
|
4938 var data = image.data(); |
|
4939 var parent = data.amsImgareaselectParent ? image.parents(data.amsImgareaselectParent) : 'body'; |
|
4940 var dataOptions = { |
|
4941 instance: true, |
|
4942 handles: true, |
|
4943 parent: parent, |
|
4944 x1: data.amsImgareaselectX1 || 0, |
|
4945 y1: data.amsImgareaselectY1 || 0, |
|
4946 x2: data.amsImgareaselectX2 || data.amsImgareaselectImageWidth, |
|
4947 y2: data.amsImgareaselectY2 || data.amsImgareaselectImageHeight, |
|
4948 imageWidth: data.amsImgareaselectImageWidth, |
|
4949 imageHeight: data.amsImgareaselectImageHeight, |
|
4950 minWidth: 128, |
|
4951 minHeight: 128, |
|
4952 aspectRatio: data.amsImgareaselectRatio, |
|
4953 onSelectEnd: ams.getFunctionByName(data.amsImgareaselectSelectEnd) || function(img, selection) { |
|
4954 var target = data.amsImgareaselectTargetField || 'image_'; |
|
4955 $('input[name="' + target + 'x1"]', parent).val(selection.x1); |
|
4956 $('input[name="' + target + 'y1"]', parent).val(selection.y1); |
|
4957 $('input[name="' + target + 'x2"]', parent).val(selection.x2); |
|
4958 $('input[name="' + target + 'y2"]', parent).val(selection.y2); |
|
4959 } |
|
4960 }; |
|
4961 var settings = $.extend({}, dataOptions, data.amsImgareaselectOptions); |
|
4962 settings = ams.executeFunctionByName(data.amsImgareaselectInitCallback, image, settings) || settings; |
|
4963 var plugin = image.imgAreaSelect(settings); |
|
4964 ams.executeFunctionByName(data.amsImgareaselectAfterInitCallback, image, plugin, settings); |
|
4965 // Add update timeout when plug-in is displayed into a modal dialog |
|
4966 setTimeout(function() { |
|
4967 plugin.update(); |
|
4968 }, 250); |
|
4969 }); |
|
4970 }); |
|
4971 }); |
|
4972 } |
|
4973 }, |
|
4974 |
|
4975 /** |
|
4976 * FancyBox plug-in |
|
4977 */ |
|
4978 fancybox: function(element) { |
|
4979 var fancyboxes = $('.fancybox', element); |
|
4980 if (fancyboxes.length > 0) { |
|
4981 ams.ajax && ams.ajax.check($.fn.fancybox, |
|
4982 ams.baseURL + 'ext/jquery-fancybox-2.1.5' + ams.devext + '.js', |
|
4983 function() { |
|
4984 ams.getCSS(ams.baseURL + '../css/ext/jquery-fancybox-2.1.5' + ams.devext + '.css', |
|
4985 'jquery-fancybox', |
|
4986 function() { |
|
4987 fancyboxes.each(function() { |
|
4988 var fancybox = $(this); |
|
4989 var data = fancybox.data(); |
|
4990 var elements = fancybox; |
|
4991 var index, |
|
4992 helper; |
|
4993 if (data.amsFancyboxElements) { |
|
4994 elements = $(data.amsFancyboxElements, fancybox); |
|
4995 } |
|
4996 var helpers = (data.amsFancyboxHelpers || '').split(/\s+/); |
|
4997 if (helpers.length > 0) { |
|
4998 for (index = 0; index < helpers.length; index++) { |
|
4999 helper = helpers[index]; |
|
5000 switch (helper) { |
|
5001 case 'buttons': |
|
5002 ams.ajax && ams.ajax.check($.fancybox.helpers.buttons, |
|
5003 ams.baseURL + 'ext/fancybox-helpers/fancybox-buttons' + ams.devext + '.js'); |
|
5004 break; |
|
5005 case 'thumbs': |
|
5006 ams.ajax && ams.ajax.check($.fancybox.helpers.thumbs, |
|
5007 ams.baseURL + 'ext/fancybox-helpers/fancybox-thumbs' + ams.devext + '.js'); |
|
5008 break; |
|
5009 case 'media': |
|
5010 ams.ajax && ams.ajax.check($.fancybox.helpers.media, |
|
5011 ams.baseURL + 'ext/fancybox-helpers/fancybox-media' + ams.devext + '.js'); |
|
5012 break; |
|
5013 default: |
|
5014 break; |
|
5015 } |
|
5016 } |
|
5017 } |
|
5018 var dataOptions = { |
|
5019 type: data.amsFancyboxType, |
|
5020 padding: data.amsFancyboxPadding || 10, |
|
5021 margin: data.amsFancyboxMargin || 10, |
|
5022 loop: data.amsFancyboxLoop, |
|
5023 beforeLoad: ams.getFunctionByName(data.amsFancyboxBeforeLoad) || function() { |
|
5024 var title; |
|
5025 if (data.amsFancyboxTitleGetter) { |
|
5026 title = ams.executeFunctionByName(data.amsFancyboxTitleGetter, this); |
|
5027 } |
|
5028 if (!title) { |
|
5029 var content = $('*:first', this.element); |
|
5030 title = content.attr('original-title') || content.attr('title'); |
|
5031 if (!title) { |
|
5032 title = $(this.element).attr('original-title') || $(this.element).attr('title'); |
|
5033 } |
|
5034 } |
|
5035 this.title = title; |
|
5036 }, |
|
5037 afterLoad: ams.getFunctionByName(data.amsFancyboxAfterLoad), |
|
5038 helpers: { |
|
5039 title: { |
|
5040 type: 'inside' |
|
5041 } |
|
5042 } |
|
5043 }; |
|
5044 if (helpers.length > 0) { |
|
5045 for (index = 0; index < helpers.length; index++) { |
|
5046 helper = helpers[index]; |
|
5047 switch (helper) { |
|
5048 case 'buttons': |
|
5049 dataOptions.helpers.buttons = { |
|
5050 position: data.amsFancyboxButtonsPosition || 'top' |
|
5051 }; |
|
5052 break; |
|
5053 case 'thumbs': |
|
5054 dataOptions.helpers.thumbs = { |
|
5055 width: data.amsFancyboxThumbsWidth || 50, |
|
5056 height: data.amsFancyboxThumbsHeight || 50 |
|
5057 }; |
|
5058 break; |
|
5059 case 'media': |
|
5060 dataOptions.helpers.media = true; |
|
5061 break; |
|
5062 } |
|
5063 } |
|
5064 } |
|
5065 var settings = $.extend({}, dataOptions, data.amsFancyboxOptions); |
|
5066 settings = ams.executeFunctionByName(data.amsFancyboxInitCallback, fancybox, settings) || settings; |
|
5067 var plugin = elements.fancybox(settings); |
|
5068 ams.executeFunctionByName(data.amsFancyboxAfterInitCallback, fancybox, plugin, settings); |
|
5069 }); |
|
5070 }); |
|
5071 }); |
|
5072 } |
|
5073 }, |
|
5074 |
|
5075 /** |
|
5076 * Flot charts |
|
5077 */ |
|
5078 chart: function(element) { |
|
5079 var charts = $('.chart', element); |
|
5080 if (charts.length > 0) { |
|
5081 ams.ajax && ams.ajax.check([window.Flot, $.color], |
|
5082 [ams.baseURL + 'ext/flot/jquery.canvaswrapper' + ams.devext + '.js', |
|
5083 ams.baseURL + 'ext/flot/jquery.colorhelpers' + ams.devext + '.js'], |
|
5084 function () { |
|
5085 ams.ajax.check($.fn.plot, |
|
5086 ams.baseURL + 'ext/flot/jquery.flot' + ams.devext + '.js', |
|
5087 function () { |
|
5088 charts.each(function () { |
|
5089 |
|
5090 var chart = $(this), |
|
5091 data = chart.data(), |
|
5092 dataOptions = {}, |
|
5093 plugin, |
|
5094 flotPlugins = (data.amsChartPlugins || '').split(/\s+/); |
|
5095 |
|
5096 function checkPlugin(plugin) { |
|
5097 for (var index in $.plot.plugins) { |
|
5098 if ($.plot.plugins.hasOwnProperty(index)) { |
|
5099 var pluginInfo = $.plot.plugins[index]; |
|
5100 if (pluginInfo.name === plugin) { |
|
5101 return pluginInfo; |
|
5102 } |
|
5103 } |
|
5104 } |
|
5105 return null; |
|
5106 } |
|
5107 |
|
5108 function initChart() { |
|
5109 var settings = $.extend({}, dataOptions, data.amsChartOptions); |
|
5110 settings = ams.executeFunctionByName(data.amsChartInitCallback, chart, settings) || settings; |
|
5111 var chartData = data.amsChartData, |
|
5112 chartDataLoader = data.amsChartDataLoader; |
|
5113 if (chartDataLoader) { |
|
5114 $.getJSON(chartDataLoader, chartData).done(function (data) { |
|
5115 settings = $.extend({}, settings, data.settings); |
|
5116 createChart(data.data, settings); |
|
5117 }); |
|
5118 } else { |
|
5119 createChart(data, settings); |
|
5120 } |
|
5121 } |
|
5122 |
|
5123 function createChart(chartData, settings) { |
|
5124 chartData = ams.executeFunctionByName(data.amsChartInitData, chart, chartData) || chartData; |
|
5125 plugin = chart.plot(chartData, settings); |
|
5126 ams.executeFunctionByName(data.amsChartAfterInitCallback, chart, plugin, settings); |
|
5127 } |
|
5128 |
|
5129 var deferred = []; |
|
5130 if (flotPlugins.length > 0) { |
|
5131 for (var index in flotPlugins) { |
|
5132 if (flotPlugins.hasOwnProperty(index)) { |
|
5133 var pluginName = flotPlugins[index]; |
|
5134 if (!checkPlugin(pluginName)) { |
|
5135 deferred.push(ams.getScript(ams.baseURL + 'ext/flot/jquery.flot.' + pluginName + ams.devext + '.js')); |
|
5136 } |
|
5137 } |
|
5138 } |
|
5139 } |
|
5140 if (deferred.length > 0) { |
|
5141 $.when.apply($, deferred).then(function () { |
|
5142 initChart(); |
|
5143 }) |
|
5144 } else { |
|
5145 initChart(); |
|
5146 } |
|
5147 }); |
|
5148 }); |
|
5149 }); |
|
5150 } |
|
5151 }, |
|
5152 |
|
5153 /** |
|
5154 * Sparkline graphs |
|
5155 */ |
|
5156 graphs: function(element) { |
|
5157 var graphs = $('.sparkline', element); |
|
5158 if (graphs.length > 0) { |
|
5159 ams.ajax && ams.ajax.check(ams.graphs, |
|
5160 ams.baseURL + 'myams-graphs' + ams.devext + '.js', |
|
5161 function() { |
|
5162 ams.graphs.init(graphs); |
|
5163 }); |
|
5164 } |
|
5165 }, |
|
5166 |
|
5167 /** |
|
5168 * Custom scrollbars |
|
5169 */ |
|
5170 scrollbars: function(element) { |
|
5171 var scrollbars = $('.scrollbar', element); |
|
5172 if (scrollbars.length > 0) { |
|
5173 ams.ajax && ams.ajax.check($.event.special.mousewheel, |
|
5174 ams.baseURL + 'ext/jquery-mousewheel.min.js', |
|
5175 function() { |
|
5176 ams.ajax.check($.fn.mCustomScrollbar, |
|
5177 ams.baseURL + 'ext/jquery-mCustomScrollbar' + ams.devext + '.js', |
|
5178 function() { |
|
5179 ams.getCSS(ams.baseURL + '../css/ext/jquery-mCustomScrollbar.css', |
|
5180 'jquery-mCustomScrollbar', |
|
5181 function() { |
|
5182 scrollbars.each(function() { |
|
5183 var scrollbar = $(this); |
|
5184 var data = scrollbar.data(); |
|
5185 var dataOptions = { |
|
5186 theme: data.amsScrollbarTheme || 'light' |
|
5187 }; |
|
5188 var settings = $.extend({}, dataOptions, data.amsScrollbarOptions); |
|
5189 settings = ams.executeFunctionByName(data.amsScrollbarInitCallback, scrollbar, settings) || settings; |
|
5190 var plugin = scrollbar.mCustomScrollbar(settings); |
|
5191 ams.executeFunctionByName(data.amsScrollbarAfterInitCallback, scrollbar, plugin, settings); |
|
5192 }); |
|
5193 }); |
|
5194 }); |
|
5195 }); |
|
5196 } |
|
5197 } |
|
5198 }); |
|
5199 |
|
5200 })(jQuery, this); |
|
5201 |
|
5202 /** |
|
5203 * MyAMS callbacks management |
|
5204 */ |
|
5205 (function($, globals) { |
|
5206 |
|
5207 var ams = globals.MyAMS; |
|
5208 |
|
5209 ams.callbacks = { |
|
5210 |
|
5211 /** |
|
5212 * Initialize list of callbacks |
|
5213 * |
|
5214 * Callbacks are initialized each time a page content is loaded and integrated into page's DOM. |
|
5215 * Unlike plug-ins, callbacks are called once in current's content context but are not kept into |
|
5216 * browser's memory for future use. |
|
5217 * Callbacks are defined via several data attributes: |
|
5218 * - data-ams-callback: name of function callback |
|
5219 * - data-ams-callback-source: source URL of file containing callback's function; can contain variables names |
|
5220 * if enclosed between braces |
|
5221 * - data-ams-callback-options: JSON object containing callback options |
|
5222 */ |
|
5223 init: function(element) { |
|
5224 $('[data-ams-callback]', element).each(function() { |
|
5225 var self = this; |
|
5226 var data = $(self).data(); |
|
5227 try { |
|
5228 var callbacks = JSON.parse(data.amsCallback); |
|
5229 if (!Array.isArray(callbacks)) { |
|
5230 callbacks = [callbacks]; |
|
5231 } |
|
5232 } catch (e) { |
|
5233 callbacks = data.amsCallback.split(/\s+/); |
|
5234 } |
|
5235 for (var index=0; index < callbacks.length; index++) { |
|
5236 var callback = callbacks[index]; |
|
5237 if (typeof(callback) === 'string') { |
|
5238 var callback_func = ams.getFunctionByName(callback); |
|
5239 var callback_options = data.amsCallbackOptions; |
|
5240 if (typeof(callback_options) === 'string') { |
|
5241 callback_options = callback_options.unserialize(); |
|
5242 } |
|
5243 if (callback_func === undefined) { |
|
5244 if (data.amsCallbackSource) { |
|
5245 ams.getScript(data.amsCallbackSource, |
|
5246 (function (cb) { |
|
5247 ams.executeFunctionByName(cb, self, callback_options); |
|
5248 })(callback), { |
|
5249 async: data.amsCallbackAsync === undefined ? true : data.amsCallbackAsync |
|
5250 }); |
|
5251 } else if (console) { |
|
5252 console.warn && console.warn("Undefined callback: " + data.amsCallback); |
|
5253 } |
|
5254 } else { |
|
5255 callback_func.call(self, callback_options); |
|
5256 } |
|
5257 } else { // JSON object |
|
5258 callback_func = ams.getFunctionByName(callback.callback); |
|
5259 callback_options = callback.options; |
|
5260 if (typeof(callback_options) === 'string') { |
|
5261 callback_options = callback_options.unserialize(); |
|
5262 } |
|
5263 if (callback_func === undefined) { |
|
5264 if (callback.source) { |
|
5265 ams.getScript(callback.source, |
|
5266 (function (cb) { |
|
5267 ams.executeFunctionByName(cb.callback, self, cb.options); |
|
5268 })(callback), { |
|
5269 async: callback.async === undefined ? true : callback.async |
|
5270 }); |
|
5271 } else if (console) { |
|
5272 console.warn && console.warn("Undefined callback: " + callback.callback); |
|
5273 } |
|
5274 } else { |
|
5275 callback_func.call(self, callback.options); |
|
5276 } |
|
5277 } |
|
5278 } |
|
5279 }); |
|
5280 }, |
|
5281 |
|
5282 /** |
|
5283 * Standard alert message callback |
|
5284 * |
|
5285 * An alert is an HTML div included on top of a "parent's" body |
|
5286 * Alert options include: |
|
5287 * - a status: 'info', 'warning', 'error' or 'success' |
|
5288 * - a parent: jQuery selector of parent's element |
|
5289 * - a header: alert's title |
|
5290 * - a subtitle |
|
5291 * - a message body |
|
5292 * - a boolean margin marker; if true, a 10 pixels margin will be added to alert's body |
|
5293 */ |
|
5294 alert: function(options) { |
|
5295 var data = $(this).data(); |
|
5296 var settings = $.extend({}, options, data.amsAlertOptions); |
|
5297 var parent = $(data.amsAlertParent || settings.parent || this); |
|
5298 var status = data.amsAlertStatus || settings.status || 'info'; |
|
5299 var header = data.amsAlertHeader || settings.header; |
|
5300 var message = data.amsAlertMessage || settings.message; |
|
5301 var subtitle = data.amsAlertSubtitle || settings.subtitle; |
|
5302 var margin = data.amsAlertMargin === undefined ? (settings.margin === undefined ? false : settings.margin) : data.amsAlertMargin; |
|
5303 ams.skin && ams.skin.alert(parent, status, header, message, subtitle, margin); |
|
5304 }, |
|
5305 |
|
5306 /** |
|
5307 * Standard message box callback |
|
5308 * |
|
5309 * Message boxes are small informations messages displayed on bottom right page's corner |
|
5310 * Message box options include: |
|
5311 * - data-ams-messagebox-status: determines message box color; given as 'info', 'warning', 'error' or 'success' |
|
5312 * - data-ams-messagebox-title: message's title |
|
5313 * - data-ams-messagebox-content: message's HTML content |
|
5314 * - data-ams-messagebox-icon: if given, CSS class of message's icon |
|
5315 * - data-ams-messagebox-number: if given, a small error/message number displayed below message |
|
5316 * - data-ams-messagebox-timeout: if given, the message box will be automatically hidden passed this number |
|
5317 * of milliseconds |
|
5318 * - data-ams-messagebox-callback: a callback's name, which will be called when message box is closed |
|
5319 */ |
|
5320 messageBox: function(options) { |
|
5321 var data = $(this).data(); |
|
5322 var dataOptions = $.extend({}, options, data.amsMessageboxOptions); |
|
5323 var settings = $.extend({}, dataOptions, { |
|
5324 title: data.amsMessageboxTitle || dataOptions.title || '', |
|
5325 content: data.amsMessageboxContent || dataOptions.content || '', |
|
5326 icon: data.amsMessageboxIcon || dataOptions.icon, |
|
5327 number: data.amsMessageboxNumber || dataOptions.number, |
|
5328 timeout: data.amsMessageboxTimeout || dataOptions.timeout |
|
5329 }); |
|
5330 var status = data.amsMessageboxStatus || dataOptions.status || 'info'; |
|
5331 var callback = ams.getFunctionByName(data.amsMessageboxCallback || dataOptions.callback); |
|
5332 ams.skin && ams.skin.messageBox(status, settings, callback); |
|
5333 }, |
|
5334 |
|
5335 /** |
|
5336 * Standard small box callback |
|
5337 * |
|
5338 * Small boxes are notification messages displayed on top right page's corner. |
|
5339 * Small box options include: |
|
5340 * - data-ams-smallbox-status: determines message box color; given as 'info', 'warning', 'error' or 'success' |
|
5341 * - data-ams-smallbox-title: message's title |
|
5342 * - data-ams-smallbox-content: message's HTML content |
|
5343 * - data-ams-smallbox-icon: if given, CSS class of message's icon |
|
5344 * - data-ams-smallbox-icon-small: if given, CSS class of small message's icon |
|
5345 * - data-ams-smallbox-timeout: if given, the message box will be automatically hidden passed this number |
|
5346 * of milliseconds |
|
5347 * - data-ams-smallbox-callback: a callback's name, which will be called when message box is closed |
|
5348 */ |
|
5349 smallBox: function(options) { |
|
5350 var data = $(this).data(); |
|
5351 var dataOptions = $.extend({}, options, data.amsSmallboxOptions); |
|
5352 var settings = $.extend({}, dataOptions, { |
|
5353 title: data.amsSmallboxTitle || dataOptions.title || '', |
|
5354 content: data.amsSmallboxContent || dataOptions.content || '', |
|
5355 icon: data.amsSmallboxIcon || dataOptions.icon, |
|
5356 iconSmall: data.amsSmallboxIconSmall || dataOptions.iconSmall, |
|
5357 timeout: data.amsSmallboxTimeout || dataOptions.timeout |
|
5358 }); |
|
5359 var status = data.amsSmallboxStatus || dataOptions.status || 'info'; |
|
5360 var callback = ams.getFunctionByName(data.amsSmallboxCallback || dataOptions.callback); |
|
5361 ams.skin && ams.skin.smallBox(status, settings, callback); |
|
5362 } |
|
5363 }; |
|
5364 |
|
5365 })(jQuery, this); |
|
5366 |
|
5367 /** |
|
5368 * MyAMS events management |
|
5369 */ |
|
5370 (function($, globals) { |
|
5371 |
|
5372 var ams = globals.MyAMS; |
|
5373 |
|
5374 ams.events = { |
|
5375 |
|
5376 /** |
|
5377 * Initialize events listeners |
|
5378 * |
|
5379 * "data-ams-events-handlers" is a data attribute containing a JSON object where: |
|
5380 * - each key is an event name |
|
5381 * - value is a callback name. |
|
5382 * For example: data-ams-events-handlers='{"change": "MyAPP.events.changeListener"}' |
|
5383 */ |
|
5384 init: function(element) { |
|
5385 $('[data-ams-events-handlers]', element).each(function() { |
|
5386 var element = $(this); |
|
5387 var handlers = element.data('ams-events-handlers'); |
|
5388 if (handlers) { |
|
5389 for (var event in handlers) { |
|
5390 if (handlers.hasOwnProperty(event)) { |
|
5391 element.on(event, ams.getFunctionByName(handlers[event])); |
|
5392 } |
|
5393 } |
|
5394 } |
|
5395 }); |
|
5396 } |
|
5397 }; |
|
5398 |
|
5399 })(jQuery, this); |
|
5400 |
|
5401 /** |
|
5402 * MyAMS containers management |
|
5403 */ |
|
5404 (function($, globals) { |
|
5405 |
|
5406 var ams = globals.MyAMS; |
|
5407 |
|
5408 ams.container = { |
|
5409 |
|
5410 /** |
|
5411 * Change container elements order |
|
5412 * |
|
5413 * This is a callback which may be used with TableDnD plug-in which allows you to |
|
5414 * change order of table rows. |
|
5415 * Rows order is stored in an hidden input which is defined in table's data attribute |
|
5416 * called 'data-ams-input-name' |
|
5417 */ |
|
5418 changeOrder: function(table, names) { |
|
5419 var input = $('input[name="' + $(this).data('ams-input-name') + '"]', $(this)); |
|
5420 input.val(names.join(';')); |
|
5421 }, |
|
5422 |
|
5423 /** |
|
5424 * Delete an element from a container table |
|
5425 * |
|
5426 * @returns {Function} |
|
5427 */ |
|
5428 deleteElement: function() { |
|
5429 return function() { |
|
5430 var link = $(this); |
|
5431 ams.skin && ams.skin.bigBox({ |
|
5432 title: ams.i18n.WARNING, |
|
5433 content: '<i class="text-danger fa fa-fw fa-bell"></i> ' + ams.i18n.DELETE_WARNING, |
|
5434 status: 'info', |
|
5435 buttons: ams.i18n.BTN_OK_CANCEL |
|
5436 }, function(button) { |
|
5437 if (button === ams.i18n.BTN_OK) { |
|
5438 var tr = link.parents('tr').first(); |
|
5439 var table = tr.parents('table').first(); |
|
5440 var location = tr.data('ams-location') || table.data('ams-location') || ''; |
|
5441 if (location) { |
|
5442 location += '/'; |
|
5443 } |
|
5444 var deleteTarget = tr.data('ams-delete-target') || table.data('ams-delete-target') || 'delete-element.json'; |
|
5445 var objectName = tr.data('ams-element-name'); |
|
5446 ams.ajax && ams.ajax.post(location + deleteTarget, {'object_name': objectName}, function(result, status) { |
|
5447 if (result.status === 'success') { |
|
5448 if (table.hasClass('datatable')) { |
|
5449 table.dataTable().fnDeleteRow(tr[0]); |
|
5450 } else { |
|
5451 tr.remove(); |
|
5452 } |
|
5453 if (result.handle_json) { |
|
5454 ams.ajax.handleJSON(result); |
|
5455 } |
|
5456 } else { |
|
5457 ams.ajax.handleJSON(result); |
|
5458 } |
|
5459 }); |
|
5460 } |
|
5461 }); |
|
5462 }; |
|
5463 }, |
|
5464 |
|
5465 /** |
|
5466 * Switch element visibility |
|
5467 */ |
|
5468 switchElementVisibility: function() { |
|
5469 return function() { |
|
5470 var source = $(this); |
|
5471 var cell = source.parents('td').first(); |
|
5472 var row = source.parents('tr').first(); |
|
5473 var table = row.parents('table'); |
|
5474 $('i', source).attr('class', 'fa fa-fw fa-spinner fa-pulse'); |
|
5475 ams.ajax && ams.ajax.post(table.data('ams-location') + '/' + |
|
5476 (cell.data('ams-attribute-switcher') || table.data('ams-attribute-switcher')), |
|
5477 {object_name: row.data('ams-element-name')}, |
|
5478 function(result, status) { |
|
5479 if (result.status === 'success') { |
|
5480 if (result.visible) { |
|
5481 $('i', source).attr('class', 'fa fa-fw fa-eye'); |
|
5482 } else { |
|
5483 $('i', source).attr('class', 'fa fa-fw fa-eye-slash text-danger'); |
|
5484 } |
|
5485 } else { |
|
5486 ams.ajax.handleJSON(result); |
|
5487 } |
|
5488 }); |
|
5489 } |
|
5490 }, |
|
5491 |
|
5492 /** |
|
5493 * Switch element attribute |
|
5494 */ |
|
5495 switchElementAttribute: function() { |
|
5496 return function() { |
|
5497 var source = $(this); |
|
5498 var cell = source.parents('td').first(); |
|
5499 var attribute = cell.data('ams-switcher-attribute-name'); |
|
5500 var row = source.parents('tr').first(); |
|
5501 var table = row.parents('table'); |
|
5502 $('i', source).attr('class', 'fa fa-fw fa-spinner fa-pulse'); |
|
5503 ams.ajax && ams.ajax.post(table.data('ams-location') + '/' + |
|
5504 (cell.data('ams-attribute-switcher') || table.data('ams-attribute-switcher')), |
|
5505 {object_name: row.data('ams-element-name')}, |
|
5506 function(result, status) { |
|
5507 if (result.status === 'success') { |
|
5508 if (result[attribute] || result['on']) { |
|
5509 $('i', source).attr('class', table.data('ams-' + attribute + '-icon-on') || 'fa fa-fw fa-check-square-o'); |
|
5510 } else { |
|
5511 $('i', source).attr('class', table.data('ams-' + attribute + '-icon-off') || 'fa fa-fw fa-check-square txt-color-silver opacity-75'); |
|
5512 } |
|
5513 } else { |
|
5514 ams.ajax.handleJSON(result); |
|
5515 } |
|
5516 }); |
|
5517 } |
|
5518 }, |
|
5519 |
|
5520 /** |
|
5521 * Export table to CSV |
|
5522 */ |
|
5523 exportTableToTSV: function() { |
|
5524 return function() { |
|
5525 var source = $(this); |
|
5526 ams.ajax && ams.ajax.check(globals.saveAs, |
|
5527 ams.baseURL + 'ext/js-filesaver' + ams.devext + '.js', |
|
5528 function() { |
|
5529 var table = $('table.datatable', source.parents('.ams-widget:first')); |
|
5530 var datatable = table.dataTable(); |
|
5531 var output = ''; |
|
5532 $('th', table).each(function(index) { |
|
5533 if (index > 0) { |
|
5534 output += '\t'; |
|
5535 } |
|
5536 output += $(this).text(); |
|
5537 }); |
|
5538 output += '\n'; |
|
5539 $(datatable.fnGetData()).each(function() { |
|
5540 $(this).each(function(index) { |
|
5541 if (index > 0) { |
|
5542 output += '\t'; |
|
5543 } |
|
5544 output += this; |
|
5545 }); |
|
5546 output += '\n'; |
|
5547 }); |
|
5548 var blob = new Blob([output], {type: 'text/tsv; charset=utf-8'}); |
|
5549 saveAs(blob, "export.tsv"); |
|
5550 }); |
|
5551 } |
|
5552 } |
|
5553 }; |
|
5554 |
|
5555 })(jQuery, this); |
|
5556 |
|
5557 /** |
|
5558 * MyAMS tree management |
|
5559 */ |
|
5560 (function($, globals) { |
|
5561 |
|
5562 var ams = globals.MyAMS; |
|
5563 |
|
5564 ams.tree = { |
|
5565 |
|
5566 /** |
|
5567 * Open close tree node inside a table |
|
5568 */ |
|
5569 switchTableNode: function() { |
|
5570 |
|
5571 function removeChildNodes(node_id) { |
|
5572 $('tr[data-ams-tree-node-parent-id="' + node_id + '"]').each(function() { |
|
5573 var row = $(this); |
|
5574 removeChildNodes(row.data('ams-tree-node-id')); |
|
5575 row.remove(); |
|
5576 }) |
|
5577 } |
|
5578 |
|
5579 var node = $(this); |
|
5580 var switcher = $('i.switch', node); |
|
5581 var tr = node.parents('tr').first(); |
|
5582 var table = tr.parents('table').first(); |
|
5583 if (switcher.hasClass('fa-minus-square-o')) { |
|
5584 removeChildNodes(tr.data('ams-tree-node-id')); |
|
5585 switcher.removeClass('fa-minus-square-o') |
|
5586 .addClass('fa-plus-square-o'); |
|
5587 } else { |
|
5588 var location = tr.data('ams-location') || table.data('ams-location') || ''; |
|
5589 var treeNodesTarget = tr.data('ams-tree-nodes-target') || table.data('ams-tree-nodes-target') || 'get-tree-nodes.json'; |
|
5590 var sourceName = tr.data('ams-element-name'); |
|
5591 switcher.removeClass('fa-plus-square-o') |
|
5592 .addClass('fa-cog fa-spin'); |
|
5593 ams.ajax && ams.ajax.post(location + '/' + sourceName + '/' + treeNodesTarget, { |
|
5594 can_sort: !$('td.sorter', tr).is(':empty') |
|
5595 }, function(result, status) { |
|
5596 if (result.length > 0) { |
|
5597 var old_row = tr; |
|
5598 for (var index = 0; index < result.length; index++) { |
|
5599 var new_row = $(result[index]); |
|
5600 new_row.insertAfter(old_row) |
|
5601 .addClass('no-drag-handle'); |
|
5602 ams.initContent && ams.initContent(new_row); |
|
5603 old_row = new_row; |
|
5604 } |
|
5605 if (table.hasClass('table-dnd')) { |
|
5606 table.tableDnDUpdate(); |
|
5607 } |
|
5608 } |
|
5609 switcher.removeClass('fa-cog fa-spin') |
|
5610 .addClass('fa-minus-square-o'); |
|
5611 }); |
|
5612 } |
|
5613 }, |
|
5614 |
|
5615 /** |
|
5616 * Open close all tree nodes |
|
5617 */ |
|
5618 switchTree: function() { |
|
5619 var th = $(this); |
|
5620 var switcher = $('i.switch', th); |
|
5621 var table = $(this).parents('table').first(); |
|
5622 var tableID = table.data('ams-tree-node-id'); |
|
5623 if (switcher.hasClass('fa-minus-square-o')) { |
|
5624 $('tr[data-ams-tree-node-parent-id]').filter('tr[data-ams-tree-node-parent-id!="' + tableID + '"]').remove(); |
|
5625 $('i.switch', table).removeClass('fa-minus-square-o') |
|
5626 .addClass('fa-plus-square-o'); |
|
5627 } else { |
|
5628 var tr = $('tbody tr', table).first(); |
|
5629 var location = table.data('ams-location') || ''; |
|
5630 var target = table.data('ams-tree-nodes-target') || 'get-tree.json'; |
|
5631 switcher.removeClass('fa-plus-square-o') |
|
5632 .addClass('fa-cog fa-spin'); |
|
5633 ams.ajax && ams.ajax.post(location + '/' + target, { |
|
5634 can_sort: !$('td.sorter', tr).is(':empty') |
|
5635 }, function(result, status) { |
|
5636 $('tr[data-ams-tree-node-id]', table).remove(); |
|
5637 var old_row = null; |
|
5638 for (var index = 0; index < result.length; index++) { |
|
5639 var new_row = $(result[index]); |
|
5640 if (old_row === null) { |
|
5641 new_row.appendTo($('tbody', table)); |
|
5642 } else { |
|
5643 new_row.insertAfter(old_row); |
|
5644 } |
|
5645 new_row.addClass('no-drag-handle'); |
|
5646 ams.initContent && ams.initContent(new_row); |
|
5647 old_row = new_row; |
|
5648 } |
|
5649 if (table.hasClass('table-dnd')) { |
|
5650 table.tableDnDUpdate(); |
|
5651 } |
|
5652 $('i.switch', table).removeClass('fa-plus-square-o') |
|
5653 .addClass('fa-minus-square-o'); |
|
5654 switcher.removeClass('fa-cog fa-spin') |
|
5655 .addClass('fa-minus-square-o'); |
|
5656 }); |
|
5657 } |
|
5658 }, |
|
5659 |
|
5660 /** |
|
5661 * Sort and re-parent tree elements |
|
5662 */ |
|
5663 sortTree: function(dnd_table, row) { |
|
5664 var data = $(dnd_table).data(); |
|
5665 var target = data.amsTabledndDropTarget; |
|
5666 if (target) { |
|
5667 // Disable row click handler |
|
5668 row = $(row); |
|
5669 row.data('ams-disabled-handlers', 'click'); |
|
5670 try { |
|
5671 // Get root ID |
|
5672 var tableID = row.parents('table').first().data('ams-tree-node-id'); |
|
5673 // Get moved row ID |
|
5674 var rowID = row.data('ams-tree-node-id'); |
|
5675 var rowParentID = row.data('ams-tree-node-parent-id'); |
|
5676 // Get new parent ID |
|
5677 var parent = row.prev('tr'); |
|
5678 if (parent.exists()) { |
|
5679 // Move below an existing row |
|
5680 var parentID = parent.data('ams-tree-node-id'); |
|
5681 // Check switcher state |
|
5682 var switcher = $('.switch', parent); |
|
5683 if (switcher.hasClass('fa-minus-square-o')) { |
|
5684 // Opened folder: move as child |
|
5685 if (rowParentID === parentID) { |
|
5686 // Don't change parent |
|
5687 var action = 'reorder'; |
|
5688 } else { |
|
5689 // Change parent |
|
5690 action = 'reparent'; |
|
5691 } |
|
5692 } else { |
|
5693 // Closed folder or simple item: move as sibling |
|
5694 parentID = parent.data('ams-tree-node-parent-id'); |
|
5695 if (rowParentID === parentID) { |
|
5696 // Don't change parent |
|
5697 action = 'reorder'; |
|
5698 } else { |
|
5699 // Change parent |
|
5700 action = 'reparent'; |
|
5701 } |
|
5702 } |
|
5703 } else { |
|
5704 // Move to site root |
|
5705 parentID = tableID; |
|
5706 switcher = null; |
|
5707 if (rowParentID === parentID) { |
|
5708 // Already child of site root |
|
5709 action = 'reorder'; |
|
5710 } else { |
|
5711 // Move from inner folder to site root |
|
5712 action = 'reparent'; |
|
5713 } |
|
5714 } |
|
5715 // Call ordering target |
|
5716 var localTarget = ams.getFunctionByName(target); |
|
5717 if (typeof (localTarget) === 'function') { |
|
5718 localTarget.call(table, dnd_table, post_data); |
|
5719 } else { |
|
5720 if (!target.startsWith(window.location.protocol)) { |
|
5721 var location = data.amsLocation; |
|
5722 if (location) { |
|
5723 target = location + '/' + target; |
|
5724 } |
|
5725 } |
|
5726 var post_data = { |
|
5727 action: action, |
|
5728 child: rowID, |
|
5729 parent: parentID, |
|
5730 order: JSON.stringify($('tr[data-ams-tree-node-id]').listattr('data-ams-tree-node-id')), |
|
5731 can_sort: !$('td.sorter', row).is(':empty') |
|
5732 }; |
|
5733 ams.ajax && ams.ajax.post(target, post_data, function(result) { |
|
5734 |
|
5735 function removeChildRows(rowID) { |
|
5736 var childs = $('tr[data-ams-tree-node-parent-id="' + rowID + '"]'); |
|
5737 childs.each(function() { |
|
5738 var childRow = $(this); |
|
5739 var childID = childRow.attr('data-ams-tree-node-id'); |
|
5740 removeChildRows(childID); |
|
5741 childRow.remove(); |
|
5742 }); |
|
5743 } |
|
5744 |
|
5745 if (result.status) { |
|
5746 ams.ajax.handleJSON(result); |
|
5747 } else { |
|
5748 // Remove moved row childrens |
|
5749 var body = $(row).parents('tbody').first(); |
|
5750 removeChildRows(rowID); |
|
5751 if (post_data.action === 'reparent') { |
|
5752 // Remove new parent childrens |
|
5753 removeChildRows(parentID); |
|
5754 row.remove(); |
|
5755 var old_row = $('tr[data-ams-tree-node-id="' + parentID + '"]'); |
|
5756 for (var index = 0; index < result.length; index++) { |
|
5757 var new_row = $(result[index]); |
|
5758 if (old_row.exists()) { |
|
5759 new_row.insertAfter(old_row) |
|
5760 .addClass('no-drag-handle'); |
|
5761 } else { |
|
5762 new_row.prependTo(body) |
|
5763 .addClass('no-drag-handle'); |
|
5764 } |
|
5765 ams.initContent && ams.initContent(new_row); |
|
5766 old_row = new_row; |
|
5767 } |
|
5768 } |
|
5769 $('tr').parents('table').tableDnDUpdate(); |
|
5770 } |
|
5771 }); |
|
5772 } |
|
5773 } finally { |
|
5774 // Restore row click handler |
|
5775 setTimeout(function() { |
|
5776 $(row).removeData('ams-disabled-handlers'); |
|
5777 }, 50); |
|
5778 } |
|
5779 } |
|
5780 return false; |
|
5781 } |
|
5782 }; |
|
5783 |
|
5784 })(jQuery, this); |
|
5785 |
|
5786 /** |
|
5787 * MyAMS skin management |
|
5788 */ |
|
5789 (function($, globals) { |
|
5790 |
|
5791 var ams = globals.MyAMS; |
|
5792 |
|
5793 ams.skin = { |
|
5794 |
|
5795 /** |
|
5796 * Compute navigation page height |
|
5797 */ |
|
5798 _setPageHeight: function() { |
|
5799 var mainHeight = $('#main').height(); |
|
5800 var windowHeight = $(window).height() - ams.navbarHeight; |
|
5801 if (mainHeight > windowHeight) { |
|
5802 ams.root.css('min-height', mainHeight + ams.navbarHeight); |
|
5803 } else { |
|
5804 ams.root.css('min-height', windowHeight); |
|
5805 } |
|
5806 ams.leftPanel.css('min-height', windowHeight); |
|
5807 ams.leftPanel.css('max-height', windowHeight); |
|
5808 }, |
|
5809 |
|
5810 /** |
|
5811 * Check width for mobile devices |
|
5812 */ |
|
5813 _checkMobileWidth: function() { |
|
5814 if ($(window).width() < 979) { |
|
5815 ams.root.addClass('mobile-view-activated'); |
|
5816 } else if (ams.root.hasClass('mobile-view-activated')) { |
|
5817 ams.root.removeClass('mobile-view-activated'); |
|
5818 } |
|
5819 }, |
|
5820 |
|
5821 /** |
|
5822 * Show/hide shortcut buttons |
|
5823 */ |
|
5824 _showShortcutButtons: function() { |
|
5825 ams.shortcuts && ams.shortcuts.animate({ |
|
5826 height: 'show' |
|
5827 }, 200, 'easeOutCirc'); |
|
5828 ams.root.addClass('shortcut-on'); |
|
5829 }, |
|
5830 |
|
5831 _hideShortcutButtons: function() { |
|
5832 ams.shortcuts && ams.shortcuts.animate({ |
|
5833 height: 'hide' |
|
5834 }, 300, 'easeOutCirc'); |
|
5835 ams.root.removeClass('shortcut-on'); |
|
5836 }, |
|
5837 |
|
5838 /** |
|
5839 * Check notification badge |
|
5840 */ |
|
5841 checkNotification: function() { |
|
5842 var badge = $('.badge', '#user-activity >span'); |
|
5843 if (parseInt(badge.text()) > 0) { |
|
5844 badge.removeClass("hidden") |
|
5845 .addClass("bg-color-red bounceIn animated"); |
|
5846 } else { |
|
5847 badge.addClass("hidden") |
|
5848 .removeClass("bg-color-red bounceIn animated"); |
|
5849 } |
|
5850 }, |
|
5851 |
|
5852 refreshNotificationsPanel: function(e) { |
|
5853 var button = $(this); |
|
5854 button.addClass('disabled'); |
|
5855 $('i', button).addClass('fa-spin'); |
|
5856 $('input[name="activity"]:checked', '#user-activity').change(); |
|
5857 $('i', button).removeClass('fa-spin'); |
|
5858 button.removeClass('disabled'); |
|
5859 }, |
|
5860 |
|
5861 /** |
|
5862 * Replace given form with new content |
|
5863 */ |
|
5864 refreshContent: function(options) { |
|
5865 var target = $('[id="' + options.object_id + '"]'); |
|
5866 target.replaceWith($(options.content)); |
|
5867 target = $('[id="' + options.object_id + '"]'); |
|
5868 ams.initContent && ams.initContent(target); |
|
5869 return target; |
|
5870 }, |
|
5871 |
|
5872 /** |
|
5873 * Replace given image from updated source |
|
5874 */ |
|
5875 refreshImage: function(options) { |
|
5876 $('img[src^="' + options.src + '"]').attr('src', options.target); |
|
5877 }, |
|
5878 |
|
5879 /** |
|
5880 * Replace given widget with given content |
|
5881 */ |
|
5882 refreshWidget: function(options) { |
|
5883 var target = $('[id="' + options.parent_id + '"]'); |
|
5884 var widget = $('[name="' + options.widget_name + '"]', target); |
|
5885 if (!widget.exists()) { |
|
5886 widget = $('[name="' + options.widget_name + ':list"]', target); |
|
5887 } |
|
5888 var label = widget.parents('.input').last(); |
|
5889 label.html(options.content); |
|
5890 ams.initContent && ams.initContent(label); |
|
5891 return label; |
|
5892 }, |
|
5893 |
|
5894 /** |
|
5895 * Replace given table with new content |
|
5896 */ |
|
5897 refreshTable: function(options) { |
|
5898 var widget = $('[id="' + options.object_id + '"]').parents('.ams-widget:first'); |
|
5899 widget.replaceWith($(options.table)); |
|
5900 widget = $('[id="' + options.object_id + '"]').parents('.ams-widget:first'); |
|
5901 ams.initContent && ams.initContent(widget); |
|
5902 return widget; |
|
5903 }, |
|
5904 |
|
5905 /** |
|
5906 * Replace given table with new content |
|
5907 * If table is located inside a switched fieldset, fieldset is opened |
|
5908 */ |
|
5909 refreshSwitchedTable: function(options) { |
|
5910 var widget = ams.skin.refreshTable(options); |
|
5911 if (widget) { |
|
5912 var legend = widget.siblings('legend'); |
|
5913 if (legend.parents('fieldset:first').hasClass('switched')) { |
|
5914 legend.click(); |
|
5915 } |
|
5916 } |
|
5917 }, |
|
5918 |
|
5919 /** |
|
5920 * Replace given row with new content |
|
5921 */ |
|
5922 refreshRow: function(options) { |
|
5923 var tr = $('tr[id="' + options.object_id + '"]'); |
|
5924 var table = tr.parents('table').first(); |
|
5925 var new_tr = $(options.row); |
|
5926 tr.replaceWith(new_tr); |
|
5927 ams.initContent && ams.initContent(new_tr); |
|
5928 if (table.hasClass('table-dnd')) { |
|
5929 new_tr.addClass('no-drag-handle'); |
|
5930 table.tableDnDUpdate(); |
|
5931 } |
|
5932 return new_tr; |
|
5933 }, |
|
5934 |
|
5935 /** |
|
5936 * Replace given row cell with new content |
|
5937 */ |
|
5938 refreshRowCell: function(options) { |
|
5939 var tr = $('tr[id="' + options.object_id + '"]'); |
|
5940 var table = tr.parents('table').first(); |
|
5941 var headRow = $('tr', $('thead', table)); |
|
5942 var headCell = $('th[data-ams-column-name="' + options.col_name + '"]', headRow); |
|
5943 var index = $('th', headRow).index(headCell); |
|
5944 if (index > -1) { |
|
5945 var cell = $($('td', tr).get(index)); |
|
5946 cell.html(options.cell); |
|
5947 ams.initContent && ams.initContent(cell); |
|
5948 } |
|
5949 }, |
|
5950 |
|
5951 switchCellContent: function(element) { |
|
5952 var source = $(this); |
|
5953 var switcher = $('i.switch', source); |
|
5954 var td = source.parents('td'); |
|
5955 var innerdiv = $(source.data('ams-switch-target') || '.inner-table-form', td); |
|
5956 var datatype = source.parents('tr'); |
|
5957 if (switcher.hasClass('fa-plus-square-o')) { |
|
5958 var container = datatype.parents('table'); |
|
5959 innerdiv.html('<h1 class="loading"><i class="fa fa-gear fa-spin"></i></h1>'); |
|
5960 ams.ajax && ams.ajax.post(container.data('ams-location') + '/' + source.data('ams-switch-handler'), |
|
5961 {object_name: datatype.data('ams-element-name')}, |
|
5962 function(result) { |
|
5963 innerdiv.html(result); |
|
5964 if (result) { |
|
5965 ams.initContent && ams.initContent(innerdiv); |
|
5966 switcher.removeClass('fa-plus-square-o') |
|
5967 .addClass('fa-minus-square-o'); |
|
5968 } |
|
5969 }); |
|
5970 } else { |
|
5971 ams.skin.cleanContainer(innerdiv); |
|
5972 innerdiv.empty(); |
|
5973 switcher.removeClass('fa-minus-square-o') |
|
5974 .addClass('fa-plus-square-o'); |
|
5975 } |
|
5976 }, |
|
5977 |
|
5978 /** |
|
5979 * Initialize desktop and mobile widgets |
|
5980 */ |
|
5981 _initDesktopWidgets: function(element) { |
|
5982 if (ams.enableWidgets) { |
|
5983 var widgets = $('.ams-widget', element); |
|
5984 if (widgets.length > 0) { |
|
5985 ams.ajax && ams.ajax.check($.fn.MyAMSWidget, |
|
5986 ams.baseURL + 'myams-widgets' + ams.devext + '.js', |
|
5987 function() { |
|
5988 widgets.each(function() { |
|
5989 var widget = $(this); |
|
5990 var data = widget.data(); |
|
5991 var dataOptions = { |
|
5992 deleteSettingsKey: '#deletesettingskey-options', |
|
5993 deletePositionKey: '#deletepositionkey-options' |
|
5994 }; |
|
5995 var settings = $.extend({}, dataOptions, data.amsWidgetOptions); |
|
5996 settings = ams.executeFunctionByName(data.amsWidgetInitcallback, widget, settings) || settings; |
|
5997 widget.MyAMSWidget(settings); |
|
5998 }); |
|
5999 globals.MyAMSWidget.initWidgetsGrid($('.ams-widget-grid', element)); |
|
6000 }); |
|
6001 } |
|
6002 } |
|
6003 }, |
|
6004 |
|
6005 _initMobileWidgets: function(element) { |
|
6006 if (ams.enableMobile && ams.enableWidgets) { |
|
6007 ams.skin._initDesktopWidgets(element); |
|
6008 } |
|
6009 }, |
|
6010 |
|
6011 /** |
|
6012 * Add an alert on top of a container |
|
6013 * |
|
6014 * @parent: parent container where the alert will be displayed |
|
6015 * @status: info, success, warning or danger |
|
6016 * @header: alert header |
|
6017 * @message: main alert message |
|
6018 * @subtitle: optional subtitle |
|
6019 * @margin: if true, a margin will be displayed around alert |
|
6020 */ |
|
6021 alert: function(parent, status, header, message, subtitle, margin) { |
|
6022 if (status === 'error') { |
|
6023 status = 'danger'; |
|
6024 } |
|
6025 $('.alert-' + status, parent).not('.persistent').remove(); |
|
6026 var content = '<div class="' + (margin ? 'margin-10' : '') + ' alert alert-block alert-' + status + ' padding-5 fade in">' + |
|
6027 '<a class="close" data-dismiss="alert"><i class="fa fa-check"></i></a>' + |
|
6028 '<h4 class="alert-heading">' + |
|
6029 '<i class="fa fa-fw fa-warning"></i> ' + header + |
|
6030 '</h4>' + |
|
6031 (subtitle ? ('<p>' + subtitle + '</p>') : ''); |
|
6032 if (typeof (message) === 'string') { |
|
6033 content += '<ul><li>' + message + '</li></ul>'; |
|
6034 } else if (message) { |
|
6035 content += '<ul>'; |
|
6036 for (var index in message) { |
|
6037 if (!$.isNumeric(index)) { // IE check |
|
6038 continue; |
|
6039 } |
|
6040 content += '<li>' + message[index] + '</li>'; |
|
6041 } |
|
6042 content += '</ul>'; |
|
6043 } |
|
6044 content += '</div>'; |
|
6045 $(content).insertBefore(parent); |
|
6046 if (parent.exists) { |
|
6047 ams.skin.scrollTo(parent, {offset: {top: -50}}); |
|
6048 } |
|
6049 }, |
|
6050 |
|
6051 /** |
|
6052 * Big message box |
|
6053 */ |
|
6054 bigBox: function(options, callback) { |
|
6055 ams.ajax && ams.ajax.check(ams.notify, |
|
6056 ams.baseURL + 'myams-notify' + ams.devext + '.js', |
|
6057 function() { |
|
6058 ams.notify.messageBox(options, callback); |
|
6059 }); |
|
6060 }, |
|
6061 |
|
6062 /** |
|
6063 * Medium notification message box, displayed on page's bottom right |
|
6064 */ |
|
6065 messageBox: function(status, options, callback) { |
|
6066 if (typeof (status) === 'object') { |
|
6067 callback = options; |
|
6068 options = status || {}; |
|
6069 status = 'info'; |
|
6070 } |
|
6071 ams.ajax && ams.ajax.check(ams.notify, |
|
6072 ams.baseURL + 'myams-notify' + ams.devext + '.js', |
|
6073 function() { |
|
6074 switch (status) { |
|
6075 case 'error': |
|
6076 case 'danger': |
|
6077 options.color = '#C46A69'; |
|
6078 break; |
|
6079 case 'warning': |
|
6080 options.color = '#C79121'; |
|
6081 break; |
|
6082 case 'success': |
|
6083 options.color = '#739E73'; |
|
6084 break; |
|
6085 default: |
|
6086 options.color = options.color || '#3276B1'; |
|
6087 } |
|
6088 options.sound = false; |
|
6089 ams.notify.bigBox(options, callback); |
|
6090 }); |
|
6091 }, |
|
6092 |
|
6093 /** |
|
6094 * Small notification message box, displayed on page's top right |
|
6095 */ |
|
6096 smallBox: function(status, options, callback) { |
|
6097 if (typeof (status) === 'object') { |
|
6098 callback = options; |
|
6099 options = status || {}; |
|
6100 status = 'info'; |
|
6101 } |
|
6102 ams.ajax && ams.ajax.check(ams.notify, |
|
6103 ams.baseURL + 'myams-notify' + ams.devext + '.js', |
|
6104 function() { |
|
6105 switch (status) { |
|
6106 case 'error': |
|
6107 case 'danger': |
|
6108 options.color = '#C46A69'; |
|
6109 break; |
|
6110 case 'warning': |
|
6111 options.color = '#C79121'; |
|
6112 break; |
|
6113 case 'success': |
|
6114 options.color = '#739E73'; |
|
6115 break; |
|
6116 default: |
|
6117 options.color = options.color || '#3276B1'; |
|
6118 } |
|
6119 options.sound = false; |
|
6120 ams.notify.smallBox(options, callback); |
|
6121 }); |
|
6122 }, |
|
6123 |
|
6124 /** |
|
6125 * Scroll to given element |
|
6126 * |
|
6127 * @param element: the element to which to scroll |
|
6128 * @param options: scroll options |
|
6129 */ |
|
6130 scrollTo: function(element, options) { |
|
6131 ams.ajax && ams.ajax.check($.scrollTo, |
|
6132 ams.baseURL + 'ext/jquery-scrollto-2.1.2' + ams.devext + '.js', |
|
6133 function() { |
|
6134 var body = $('body'); |
|
6135 var offset = options.offset || 0; |
|
6136 if (body.hasClass('fixed-header')) { |
|
6137 offset -= $('#header').height(); |
|
6138 } |
|
6139 if (body.hasClass('fixed-ribbon')) { |
|
6140 offset -= $('#ribbon').height(); |
|
6141 } |
|
6142 options = $.extend({}, options, {offset: offset}); |
|
6143 $.scrollTo(element, options); |
|
6144 }); |
|
6145 }, |
|
6146 |
|
6147 /** |
|
6148 * Initialize breadcrumbs based on active menu position |
|
6149 */ |
|
6150 _drawBreadCrumb: function() { |
|
6151 var crumb = $('OL.breadcrumb', '#ribbon'); |
|
6152 $('li', crumb).not('.parent').remove(); |
|
6153 if (!$('li', crumb).exists()) { |
|
6154 crumb.append($('<li></li>').append($('<a></a>').text(ams.i18n.HOME) |
|
6155 .addClass('padding-right-5') |
|
6156 .attr('href', $('nav a[href!="#"]:first').attr('href')))); |
|
6157 } |
|
6158 $('LI.active >A', 'nav').each(function() { |
|
6159 var menu = $(this); |
|
6160 var body = $.trim(menu.clone() |
|
6161 .children(".badge") |
|
6162 .remove() |
|
6163 .end() |
|
6164 .text()); |
|
6165 var item = $("<li></li>").append(menu.attr('href').replace(/^#/, '') ? |
|
6166 $("<a></a>").html(body).attr('href', menu.attr('href')) |
|
6167 : body); |
|
6168 crumb.append(item); |
|
6169 }); |
|
6170 }, |
|
6171 |
|
6172 /** |
|
6173 * Check URL matching current location hash |
|
6174 */ |
|
6175 checkURL: function() { |
|
6176 |
|
6177 function updateActiveMenus(menu) { |
|
6178 $('.active', nav).removeClass('active'); |
|
6179 menu.addClass('open') |
|
6180 .addClass('active'); |
|
6181 menu.parents('li').addClass('open active') |
|
6182 .children('ul').addClass('active') |
|
6183 .show(); |
|
6184 menu.parents('li:first').removeClass('open'); |
|
6185 menu.parents('ul').addClass(menu.attr('href').replace(/^#/, '') ? 'active' : '') |
|
6186 .show(); |
|
6187 } |
|
6188 |
|
6189 var menu; |
|
6190 var nav = $('nav'); |
|
6191 var hash = location.hash; |
|
6192 var url = hash.replace(/^#/, ''); |
|
6193 if (url) { |
|
6194 var container = $('#content'); |
|
6195 if (!container.exists()) { |
|
6196 container = $('body'); |
|
6197 } |
|
6198 menu = $('A[href="' + hash + '"]', nav); |
|
6199 if (menu.exists()) { |
|
6200 updateActiveMenus(menu); |
|
6201 } |
|
6202 ams.skin.loadURL(url, container, { |
|
6203 afterLoadCallback: function() { |
|
6204 var prefix = $('html head title').data('ams-title-prefix'); |
|
6205 document.title = (prefix ? prefix + ' > ' : '') + |
|
6206 ($('[data-ams-page-title]:first', container).data('ams-page-title') || |
|
6207 menu.attr('title') || |
|
6208 document.title); |
|
6209 } |
|
6210 }); |
|
6211 } else { |
|
6212 var activeUrl = $('[data-ams-active-menu]').data('ams-active-menu'); |
|
6213 if (activeUrl) { |
|
6214 menu = $('A[href="' + activeUrl + '"]', nav); |
|
6215 } else { |
|
6216 menu = $('>UL >LI >A[href!="#"]', nav).first(); |
|
6217 } |
|
6218 if (menu.exists()) { |
|
6219 updateActiveMenus(menu); |
|
6220 if (activeUrl) { |
|
6221 ams.skin._drawBreadCrumb(); |
|
6222 } else { |
|
6223 window.location.hash = menu.attr('href'); |
|
6224 } |
|
6225 } |
|
6226 } |
|
6227 }, |
|
6228 |
|
6229 /** |
|
6230 * List of registered 'cleaning' callbacks |
|
6231 * These callbacks are called before loading a new URL into a given container |
|
6232 * to clean required elements from memory before the DOM elements are removed |
|
6233 */ |
|
6234 _clean_callbacks: [], |
|
6235 |
|
6236 /** |
|
6237 * Register a callback which should be called before a container is replaced |
|
6238 */ |
|
6239 registerCleanCallback: function(callback) { |
|
6240 var callbacks = ams.skin._clean_callbacks; |
|
6241 if (callbacks.indexOf(callback) < 0) { |
|
6242 callbacks.push(callback); |
|
6243 } |
|
6244 }, |
|
6245 |
|
6246 /** |
|
6247 * Remove given callback from registry |
|
6248 */ |
|
6249 unregisterCleanCallback: function(callback) { |
|
6250 var callbacks = ams.skin._clean_callbacks; |
|
6251 var index = callbacks.indexOf(callback); |
|
6252 if (index >= 0) { |
|
6253 callbacks.splice(index, 1); |
|
6254 } |
|
6255 }, |
|
6256 |
|
6257 /** |
|
6258 * Call registered cleaning callbacks on given container |
|
6259 */ |
|
6260 cleanContainer: function(container) { |
|
6261 var callbacks = ams.skin._clean_callbacks; |
|
6262 for (var index = 0; index < callbacks.length; index++) { |
|
6263 callbacks[index].call(container); |
|
6264 } |
|
6265 }, |
|
6266 |
|
6267 /** |
|
6268 * Load given URL into container |
|
6269 */ |
|
6270 loadURL: function(url, container, options, callback) { |
|
6271 if (url.startsWith('#')) { |
|
6272 url = url.substr(1); |
|
6273 } |
|
6274 if (typeof (options) === 'function') { |
|
6275 callback = options; |
|
6276 options = {}; |
|
6277 } else if (options === undefined) { |
|
6278 options = {}; |
|
6279 } |
|
6280 container = $(container); |
|
6281 var defaults = { |
|
6282 type: 'GET', |
|
6283 url: url, |
|
6284 dataType: 'html', |
|
6285 cache: false, |
|
6286 beforeSend: function() { |
|
6287 if (options && options.preLoadCallback) { |
|
6288 ams.executeFunctionByName(options.preLoadCallback, this, options.preLoadCallbackOptions); |
|
6289 } |
|
6290 ams.skin.cleanContainer(container); |
|
6291 container.html('<h1 class="loading"><i class="fa fa-cog fa-spin"></i> ' + ams.i18n.LOADING + ' </h1>'); |
|
6292 if (container[0] === $('#content')[0]) { |
|
6293 ams.skin._drawBreadCrumb(); |
|
6294 var prefix = $('html head title').data('ams-title-prefix'); |
|
6295 document.title = (prefix ? prefix + ' > ' : '') + $('.breadcrumb LI:last-child').text(); |
|
6296 $('html, body').animate({scrollTop: 0}, 'fast'); |
|
6297 } else { |
|
6298 container.animate({scrollTop: 0}, 'fast'); |
|
6299 } |
|
6300 }, |
|
6301 success: function(data, status, request) { |
|
6302 if (callback) { |
|
6303 ams.executeFunctionByName(callback, this, data, status, request, options); |
|
6304 } else { |
|
6305 var response = ams.ajax && ams.ajax.getResponse(request); |
|
6306 if (response) { |
|
6307 var dataType = response.contentType; |
|
6308 var result = response.data; |
|
6309 $('.loading', container).remove(); |
|
6310 switch (dataType) { |
|
6311 case 'json': |
|
6312 ams.ajax.handleJSON(result, container); |
|
6313 break; |
|
6314 case 'script': |
|
6315 break; |
|
6316 case 'xml': |
|
6317 break; |
|
6318 case 'html': |
|
6319 /* falls through */ |
|
6320 case 'text': |
|
6321 /* falls through */ |
|
6322 default: |
|
6323 // Show and init container |
|
6324 container.parents('.hidden').removeClass('hidden'); |
|
6325 $('.alert', container.parents('.alerts-container')).remove(); |
|
6326 container.css({opacity: '0.0'}) |
|
6327 .html(data) |
|
6328 .removeClass('hidden') |
|
6329 .delay(50) |
|
6330 .animate({opacity: '1.0'}, 300); |
|
6331 ams.initContent && ams.initContent(container); |
|
6332 ams.form && ams.form.setFocus(container); |
|
6333 } |
|
6334 if (options && options.afterLoadCallback) { |
|
6335 ams.executeFunctionByName(options.afterLoadCallback, this, options.afterLoadCallbackOptions); |
|
6336 } |
|
6337 ams.stats && ams.stats.logPageview(); |
|
6338 } |
|
6339 } |
|
6340 }, |
|
6341 error: function(request, errorOptions, error) { |
|
6342 container.html('<h3 class="error"><i class="fa fa-warning txt-color-orangeDark"></i> ' + |
|
6343 ams.i18n.ERROR + error + '</h3>' + |
|
6344 request.responseText); |
|
6345 if (options && options.afterErrorCallback) { |
|
6346 ams.executeFunctionByName(options.afterErrorCallback, this); |
|
6347 } |
|
6348 }, |
|
6349 async: options.async === undefined ? true : options.async |
|
6350 }; |
|
6351 var settings = $.extend({}, defaults, options); |
|
6352 $.ajax(settings); |
|
6353 }, |
|
6354 |
|
6355 /** |
|
6356 * Change user language |
|
6357 */ |
|
6358 setLanguage: function(event, options) { |
|
6359 var lang = options.lang; |
|
6360 var handlerType = options.handler_type || 'json'; |
|
6361 switch (handlerType) { |
|
6362 case 'json': |
|
6363 var method = options.method || 'setUserLanguage'; |
|
6364 ams.jsonrpc && ams.jsonrpc.post(method, {lang: lang}, function() { |
|
6365 window.location.reload(true); |
|
6366 }); |
|
6367 break; |
|
6368 case 'ajax': |
|
6369 var href = options.href || 'setUserLanguage'; |
|
6370 ams.ajax && ams.ajax.post(href, {lang: lang}, function() { |
|
6371 window.location.reload(true); |
|
6372 }); |
|
6373 break; |
|
6374 } |
|
6375 }, |
|
6376 |
|
6377 /** |
|
6378 * Go to logout page |
|
6379 */ |
|
6380 logout: function() { |
|
6381 window.location = ams.loginURL; |
|
6382 } |
|
6383 }; |
|
6384 |
|
6385 })(jQuery, this); |
|
6386 |
|
6387 /** |
|
6388 * MyAMS stats management |
|
6389 */ |
|
6390 (function($, globals) { |
|
6391 |
|
6392 var ams = globals.MyAMS; |
|
6393 |
|
6394 ams.stats = { |
|
6395 |
|
6396 /** |
|
6397 * Log current or specified page load |
|
6398 */ |
|
6399 logPageview: function(url) { |
|
6400 if (typeof(globals._gaq) === 'undefined') { |
|
6401 return; |
|
6402 } |
|
6403 var location = globals.window.location; |
|
6404 globals._gaq.push(['_trackPageview', url || location.pathname + location.hash]); |
|
6405 }, |
|
6406 |
|
6407 /** |
|
6408 * Send event to Google Analytics platform |
|
6409 * |
|
6410 * @param category |
|
6411 * @param action |
|
6412 * @param label |
|
6413 */ |
|
6414 logEvent: function(category, action, label) { |
|
6415 if (typeof(globals._gaq) === 'undefined') { |
|
6416 return; |
|
6417 } |
|
6418 if (typeof(category) === 'object') { |
|
6419 action = category.action; |
|
6420 label = category.label; |
|
6421 category = category.category; |
|
6422 } |
|
6423 globals._gaq.push(['_trackEvent', category, action, label]); |
|
6424 } |
|
6425 }; |
|
6426 |
|
6427 })(jQuery, this); |
|
6428 |
|
6429 /** |
|
6430 * MyAMS page initialization |
|
6431 * This code is called once to register global events and callbacks |
|
6432 */ |
|
6433 (function($, globals) { |
|
6434 |
|
6435 var ams = globals.MyAMS; |
|
6436 |
|
6437 ams.initPage = function() { |
|
6438 |
|
6439 var body = $('body'); |
|
6440 |
|
6441 /* Init main components */ |
|
6442 ams.root = body; |
|
6443 ams.leftPanel = $('#left-panel'); |
|
6444 ams.shortcuts = $('#shortcuts'); |
|
6445 ams.plugins.initData(body); |
|
6446 |
|
6447 // Init main AJAX events |
|
6448 var xhr = $.ajaxSettings.xhr; |
|
6449 $.ajaxSetup({ |
|
6450 beforeSend: function(request, options) { |
|
6451 // Check CSRF token for unsafe methods |
|
6452 if (ams.safeMethods.indexOf(options.type) < 0) { |
|
6453 if (globals.Cookies !== undefined) { |
|
6454 var token = Cookies.get(ams.csrfCookieName); |
|
6455 if (token) { |
|
6456 request.setRequestHeader(ams.csrfHeaderName, token); |
|
6457 } |
|
6458 } |
|
6459 } |
|
6460 }, |
|
6461 progress: ams.ajax && ams.ajax.progress, |
|
6462 progressUpload: ams.ajax && ams.ajax.progress, |
|
6463 xhr: function() { |
|
6464 var request = xhr(); |
|
6465 if (request && (typeof(request.addEventListener) === "function")) { |
|
6466 var that = this; |
|
6467 if (that && that.progress) { |
|
6468 request.addEventListener("progress", function (evt) { |
|
6469 that.progress(evt); |
|
6470 }, false); |
|
6471 } |
|
6472 } |
|
6473 return request; |
|
6474 } |
|
6475 }); |
|
6476 $(document).ajaxStart(ams.ajax && ams.ajax.start); |
|
6477 $(document).ajaxStop(ams.ajax && ams.ajax.stop); |
|
6478 $(document).ajaxError(ams.error && ams.error.ajax); |
|
6479 |
|
6480 // Check for minified state in local storage |
|
6481 var state = globals.localStorage && globals.localStorage.getItem('window-state'); |
|
6482 if (state) { |
|
6483 body.addClass(state); |
|
6484 } |
|
6485 |
|
6486 // Check mobile/desktop |
|
6487 if (!ams.isMobile) { |
|
6488 ams.root.addClass('desktop-detected'); |
|
6489 ams.device = 'desktop'; |
|
6490 } else { |
|
6491 ams.root.addClass('mobile-detected'); |
|
6492 ams.device = 'mobile'; |
|
6493 if (ams.enableFastclick) { |
|
6494 ams.ajax && ams.ajax.check($.fn.noClickDelay, |
|
6495 ams.baseURL + '/ext/jquery-smartclick' + ams.devext + '.js', |
|
6496 function() { |
|
6497 $('NAV UL A').noClickDelay(); |
|
6498 $('A', '#hide-menu').noClickDelay(); |
|
6499 }); |
|
6500 } |
|
6501 } |
|
6502 |
|
6503 // Switch shortcuts |
|
6504 $('#show-shortcuts').click(function(e) { |
|
6505 if (ams.shortcuts.is(":visible")) { |
|
6506 ams.skin && ams.skin._hideShortcutButtons(); |
|
6507 } else { |
|
6508 ams.skin && ams.skin._showShortcutButtons(); |
|
6509 } |
|
6510 e.preventDefault(); |
|
6511 }); |
|
6512 ams.shortcuts.click(function(e) { |
|
6513 ams.skin && ams.skin._hideShortcutButtons(); |
|
6514 }); |
|
6515 |
|
6516 $(document).mouseup(function(e) { |
|
6517 if (!ams.shortcuts.is(e.target) && |
|
6518 ams.shortcuts.has(e.target).length === 0) { |
|
6519 ams.skin && ams.skin._hideShortcutButtons(); |
|
6520 } |
|
6521 }); |
|
6522 |
|
6523 // Show & hide mobile search field |
|
6524 $('#search-mobile').click(function() { |
|
6525 ams.root.addClass('search-mobile'); |
|
6526 }); |
|
6527 |
|
6528 $('#cancel-search-js').click(function() { |
|
6529 ams.root.removeClass('search-mobile'); |
|
6530 }); |
|
6531 |
|
6532 // Activity badge |
|
6533 $('.activity-button', '#user-activity').click(function(e) { |
|
6534 var activity = $('#user-activity'); |
|
6535 var dropdown = $('.ajax-dropdown', activity); |
|
6536 if (!dropdown.is(':visible')) { |
|
6537 dropdown.css('left', - dropdown.innerWidth() + activity.innerWidth()) |
|
6538 .fadeIn(150); |
|
6539 activity.addClass('active'); |
|
6540 } else { |
|
6541 dropdown.fadeOut(150); |
|
6542 activity.removeClass('active'); |
|
6543 } |
|
6544 e.preventDefault(); |
|
6545 }); |
|
6546 ams.skin && ams.skin.checkNotification(); |
|
6547 |
|
6548 $(document).mouseup(function(e) { |
|
6549 var dropdown = $('.ajax-dropdown'); |
|
6550 if (!dropdown.is(e.target) && |
|
6551 dropdown.has(e.target).length === 0) { |
|
6552 dropdown.fadeOut(150) |
|
6553 .prev().removeClass("active"); |
|
6554 } |
|
6555 }); |
|
6556 |
|
6557 $('input[name="activity"]').change(function(e) { |
|
6558 var href = $(this).data('ams-url'); |
|
6559 if (href) { |
|
6560 e.preventDefault(); |
|
6561 e.stopPropagation(); |
|
6562 var hrefGetter = ams.getFunctionByName(href); |
|
6563 if (typeof(hrefGetter) === 'function') { |
|
6564 href = hrefGetter.call(this); |
|
6565 } |
|
6566 if (typeof(href) === 'function') { |
|
6567 // Javascript function call |
|
6568 href.call(this); |
|
6569 } else { |
|
6570 var container = $('.ajax-notifications'); |
|
6571 ams.skin && ams.skin.loadURL(href, container); |
|
6572 } |
|
6573 } |
|
6574 }); |
|
6575 |
|
6576 // Logout button |
|
6577 $('a', '#user-menu LI.logout').click(function(e) { |
|
6578 e.preventDefault(); |
|
6579 e.stopPropagation(); |
|
6580 //get the link |
|
6581 ams.loginURL = $(this).attr('href'); |
|
6582 // ask verification |
|
6583 ams.skin && ams.skin.bigBox({ |
|
6584 title : "<i class='fa fa-sign-out txt-color-orangeDark'></i> " + ams.i18n.LOGOUT + |
|
6585 " <span class='txt-color-orangeDark'><strong>" + $('#show-shortcut').text() + "</strong></span> ?", |
|
6586 content : ams.i18n.LOGOUT_COMMENT, |
|
6587 buttons : ams.i18n.BTN_YES_NO |
|
6588 }, function(ButtonPressed) { |
|
6589 if (ButtonPressed === ams.i18n.BTN_YES) { |
|
6590 ams.root.addClass('animated fadeOutUp'); |
|
6591 setTimeout(ams.skin.logout, 1000); |
|
6592 } |
|
6593 }); |
|
6594 }); |
|
6595 |
|
6596 // Initialize left nav |
|
6597 var nav = $('nav'); |
|
6598 $('UL', nav).myams_menu({ |
|
6599 accordion : nav.data('ams-menu-accordion') !== false, |
|
6600 speed : ams.menuSpeed |
|
6601 }); |
|
6602 |
|
6603 // Left navigation hide button |
|
6604 $('#hide-menu').find('>:first-child >A').click(function(e) { |
|
6605 body.toggleClass("hidden-menu"); |
|
6606 if (globals.localStorage) { |
|
6607 if (body.hasClass('hidden-menu')) { |
|
6608 globals.localStorage.setItem('window-state', 'hidden-menu'); |
|
6609 } else { |
|
6610 globals.localStorage.setItem('window-state', ''); |
|
6611 } |
|
6612 } |
|
6613 e.preventDefault(); |
|
6614 }); |
|
6615 |
|
6616 // Left navigation collapser |
|
6617 $('.minifyme').click(function(e) { |
|
6618 body.toggleClass("minified"); |
|
6619 if (globals.localStorage) { |
|
6620 if (body.hasClass('minified')) { |
|
6621 globals.localStorage.setItem('window-state', 'minified'); |
|
6622 } else { |
|
6623 globals.localStorage.setItem('window-state', ''); |
|
6624 } |
|
6625 } |
|
6626 $(this).effect("highlight", {}, 500); |
|
6627 e.preventDefault(); |
|
6628 }); |
|
6629 |
|
6630 // Reset widgets |
|
6631 $('#refresh').click(function(e) { |
|
6632 ams.skin && ams.skin.bigBox({ |
|
6633 title: "<i class='fa fa-refresh' style='color: green'></i> " + ams.i18n.CLEAR_STORAGE_TITLE, |
|
6634 content: ams.i18n.CLEAR_STORAGE_CONTENT, |
|
6635 buttons: '['+ams.i18n.BTN_CANCEL+']['+ams.i18n.BTN_OK+']' |
|
6636 }, function(buttonPressed) { |
|
6637 if (buttonPressed === ams.i18n.BTN_OK && localStorage) { |
|
6638 localStorage.clear(); |
|
6639 location.reload(); |
|
6640 } |
|
6641 }); |
|
6642 e.preventDefault(); |
|
6643 }); |
|
6644 |
|
6645 // Check active pop-overs |
|
6646 body.on('click', function(e) { |
|
6647 var element = $(this); |
|
6648 if (!element.is(e.target) && |
|
6649 element.has(e.target).length === 0 && |
|
6650 $('.popover').has(e.target).length === 0) { |
|
6651 element.popover('hide'); |
|
6652 } |
|
6653 }); |
|
6654 |
|
6655 // Resize events |
|
6656 ams.ajax && ams.ajax.check($.resize, |
|
6657 ams.baseURL + 'ext/jquery-resize' + ams.devext + '.js', |
|
6658 function() { |
|
6659 $('#main').resize(function() { |
|
6660 ams.skin._setPageHeight(); |
|
6661 ams.skin._checkMobileWidth(); |
|
6662 }); |
|
6663 nav.resize(function() { |
|
6664 ams.skin._setPageHeight(); |
|
6665 }); |
|
6666 }); |
|
6667 |
|
6668 // Init AJAX navigation |
|
6669 if (ams.ajaxNav) { |
|
6670 $(document).on('click', 'a[href="#"]', function(e) { |
|
6671 e.preventDefault(); |
|
6672 }); |
|
6673 $(document).on('click', 'a[href!="#"]:not([data-toggle]), [data-ams-url]:not([data-toggle])', function(e) { |
|
6674 var link = $(e.currentTarget); |
|
6675 var handlers = link.data('ams-disabled-handlers'); |
|
6676 if ((handlers === true) || (handlers === 'click') || (handlers === 'all')) { |
|
6677 return; |
|
6678 } |
|
6679 var href = link.attr('href') || link.data('ams-url'); |
|
6680 if (!href || href.startsWith('javascript') || link.attr('target') || (link.data('ams-context-menu') === true)) { |
|
6681 return; |
|
6682 } |
|
6683 e.preventDefault(); |
|
6684 e.stopPropagation(); |
|
6685 |
|
6686 var url, |
|
6687 target, |
|
6688 params; |
|
6689 if (href.indexOf('?') >= 0) { |
|
6690 url = href.split('?'); |
|
6691 target = url[0]; |
|
6692 params = url[1].unserialize(); |
|
6693 } else { |
|
6694 target = href; |
|
6695 params = undefined; |
|
6696 } |
|
6697 var hrefGetter = ams.getFunctionByName(target); |
|
6698 if (typeof(hrefGetter) === 'function') { |
|
6699 href = hrefGetter.call(link, params); |
|
6700 } |
|
6701 if (typeof(href) === 'function') { |
|
6702 // Javascript function call |
|
6703 href.call(link, params); |
|
6704 } else { |
|
6705 // Standard AJAX or browser URL call |
|
6706 // Convert %23 chars to # |
|
6707 href = href.replace(/\%23/, '#'); |
|
6708 if (e.ctrlKey) { |
|
6709 window.open(href); |
|
6710 } else { |
|
6711 var link_target = link.data('ams-target'); |
|
6712 if (link_target) { |
|
6713 if (link_target === '_blank') { |
|
6714 window.open(href); |
|
6715 } else { |
|
6716 ams.form && ams.form.confirmChangedForm(link_target, function () { |
|
6717 ams.skin && ams.skin.loadURL(href, link_target, link.data('ams-link-options'), link.data('ams-link-callback')); |
|
6718 }); |
|
6719 } |
|
6720 } else { |
|
6721 ams.form && ams.form.confirmChangedForm(function() { |
|
6722 if (href.startsWith('#')) { |
|
6723 if (href !== location.hash) { |
|
6724 if (ams.root.hasClass('mobile-view-activated')) { |
|
6725 ams.root.removeClass('hidden-menu'); |
|
6726 window.setTimeout(function() { |
|
6727 window.location.hash = href; |
|
6728 }, 50); |
|
6729 } else { |
|
6730 window.location.hash = href; |
|
6731 } |
|
6732 } |
|
6733 } else { |
|
6734 window.location = href; |
|
6735 } |
|
6736 }); |
|
6737 } |
|
6738 } |
|
6739 } |
|
6740 }); |
|
6741 $(document).on('click', 'a[target="_blank"]', function(e) { |
|
6742 e.preventDefault(); |
|
6743 var target = $(e.currentTarget); |
|
6744 window.open(target.attr('href')); |
|
6745 ams.stats && ams.stats.logEvent(target.data('ams-stats-category') || 'Navigation', |
|
6746 target.data('ams-stats-action') || 'External', |
|
6747 target.data('ams-stats-label') || target.attr('href')); |
|
6748 }); |
|
6749 $(document).on('click', 'a[target="_top"]', function(e) { |
|
6750 e.preventDefault(); |
|
6751 ams.form && ams.form.confirmChangedForm(function() { |
|
6752 window.location = $(e.currentTarget).attr('href'); |
|
6753 }); |
|
6754 }); |
|
6755 |
|
6756 // Check URL when hash changed |
|
6757 $(window).on('hashchange', ams.skin && ams.skin.checkURL); |
|
6758 } |
|
6759 |
|
6760 // Initialize modal dialogs links |
|
6761 $(document).off('click.modal') |
|
6762 .on('click', '[data-toggle="modal"]', function(e) { |
|
6763 var source = $(this); |
|
6764 var handlers = source.data('ams-disabled-handlers'); |
|
6765 if ((handlers === true) || (handlers === 'click') || (handlers === 'all')) { |
|
6766 return; |
|
6767 } |
|
6768 if (source.data('ams-context-menu') === true) { |
|
6769 return; |
|
6770 } |
|
6771 if (source.data('ams-stop-propagation') === true) { |
|
6772 e.stopPropagation(); |
|
6773 } |
|
6774 e.preventDefault(); |
|
6775 ams.dialog && ams.dialog.open(source); |
|
6776 if (source.parents('#shortcut').exists()) { |
|
6777 setTimeout(ams.skin._hideShortcutButtons, 300); |
|
6778 } |
|
6779 }); |
|
6780 |
|
6781 // Initialize form buttons |
|
6782 $(document).on('click', 'button[type="submit"], button.submit', function() { |
|
6783 var button = $(this); |
|
6784 $(button.get(0).form).data('ams-submit-button', button); |
|
6785 }); |
|
6786 |
|
6787 // Initialize main event handlers |
|
6788 ams.initHandlers(document); |
|
6789 |
|
6790 // Submit form when CTRL+Enter key is pressed in textarea |
|
6791 $(document).on('keydown', 'textarea', function(e) { |
|
6792 if ((e.keyCode === 10 || e.keyCode === 13) && (e.ctrlKey || e.metaKey)) { |
|
6793 $(this).closest('form').submit(); |
|
6794 } |
|
6795 }); |
|
6796 |
|
6797 // Handle update on file upload placeholder |
|
6798 $(document).on('change', 'input[type="file"]', function(e) { |
|
6799 e.preventDefault(); |
|
6800 var input = $(this); |
|
6801 var button = input.parent('.button'); |
|
6802 if (button.exists() && button.parent().hasClass('input-file')) { |
|
6803 button.next('input[type="text"]').val(input.val()); |
|
6804 } |
|
6805 }); |
|
6806 |
|
6807 // Always blur readonly inputs |
|
6808 $(document).on('focus', 'input[readonly="readonly"]', function() { |
|
6809 $(this).blur(); |
|
6810 }); |
|
6811 |
|
6812 // Prevent bootstrap dialog from blocking TinyMCE focus |
|
6813 $(document).on('focusin', function(e) { |
|
6814 if ($(e.target).closest('.mce-window').length) { |
|
6815 e.stopImmediatePropagation(); |
|
6816 } |
|
6817 }); |
|
6818 |
|
6819 // Disable clicks on disabled tabs |
|
6820 $(document).on("click", '.nav-tabs a[data-toggle=tab]', function(e) { |
|
6821 if ($(this).parent('li').hasClass("disabled")) { |
|
6822 e.preventDefault(); |
|
6823 return false; |
|
6824 } |
|
6825 }); |
|
6826 |
|
6827 // Automatically set orientation of dropdown menus |
|
6828 $(document).on('show.bs.dropdown', '.btn-group', function() { |
|
6829 var menu = $(this); |
|
6830 var ul = menu.children('.dropdown-menu'); |
|
6831 var menuRect = menu.get(0).getBoundingClientRect(); |
|
6832 var position = menuRect.top; |
|
6833 var buttonHeight = menuRect.height; |
|
6834 var menuHeight = ul.outerHeight(); |
|
6835 if (position > menuHeight && $(window).height() - position < buttonHeight + menuHeight) { |
|
6836 menu.addClass("dropup"); |
|
6837 } |
|
6838 }).on('hidden.bs.dropdown', '.btn-group', function() { |
|
6839 // always reset after close |
|
6840 $(this).removeClass('dropup'); |
|
6841 }); |
|
6842 |
|
6843 // Enable tabs dynamic loading |
|
6844 $(document).on('show.bs.tab', function(e) { |
|
6845 var link = $(e.target); |
|
6846 if (link.exists() && (link.get(0).tagName !== 'A')) { |
|
6847 link = $('a[href]', link); |
|
6848 } |
|
6849 var data = link.data(); |
|
6850 if (data && data.amsUrl) { |
|
6851 if (data.amsTabLoaded) { |
|
6852 return; |
|
6853 } |
|
6854 link.append('<i class="fa fa-spin fa-cog margin-left-5"></i>'); |
|
6855 ams.skin && ams.skin.loadURL(data.amsUrl, link.attr('href'), { |
|
6856 afterLoadCallback: function() { |
|
6857 if (data.amsTabLoadOnce) { |
|
6858 link.data('ams-tab-loaded', true); |
|
6859 } |
|
6860 $('i', link).remove(); |
|
6861 }, |
|
6862 afterErrorCallback: function() { |
|
6863 $('i', link).remove(); |
|
6864 } |
|
6865 }); |
|
6866 } |
|
6867 }); |
|
6868 |
|
6869 // Check modal form dialogs on close |
|
6870 $(document).on('hide.bs.modal', function(e) { |
|
6871 var modal = $(e.target); |
|
6872 ams.form && ams.form.confirmChangedForm(modal, function() { |
|
6873 // Confirm closing if OK |
|
6874 var bsModal = modal.data('modal') || modal.data('bs.modal'); |
|
6875 if (bsModal) { |
|
6876 bsModal.isShown = true; |
|
6877 } |
|
6878 return true; |
|
6879 }, function() { |
|
6880 // Prevent closing if cancelled |
|
6881 e.preventDefault(); |
|
6882 return false; |
|
6883 }); |
|
6884 }); |
|
6885 |
|
6886 // Enable custom MyAMS refresh events |
|
6887 $(document).on('myams.refresh', function(event, options) { |
|
6888 ams.executeFunctionByName(options.handler || (ams.skin && ams.skin.refreshContent), event.target, options); |
|
6889 }); |
|
6890 |
|
6891 // Init page content |
|
6892 ams.initContent(document); |
|
6893 if (ams.ajaxNav && nav.exists()) { |
|
6894 ams.skin && ams.skin.checkURL(); |
|
6895 } |
|
6896 ams.form && ams.form.setFocus(document); |
|
6897 |
|
6898 // Add unload event listener to check for modified forms |
|
6899 $(window).on('beforeunload', ams.form && ams.form.checkBeforeUnload); |
|
6900 |
|
6901 }; |
|
6902 |
|
6903 |
|
6904 /** |
|
6905 * Main content plug-ins initializer |
|
6906 * This code is called to initialize plugins, callbacks and events listeners each time an HTML content |
|
6907 * is loaded dynamically from remote server. |
|
6908 */ |
|
6909 ams.initContent = function(element) { |
|
6910 |
|
6911 // Remove left tips |
|
6912 $('.tipsy').remove(); |
|
6913 |
|
6914 // Activate tooltips and popovers |
|
6915 $("[rel=tooltip]", element).tooltip(); |
|
6916 $("[rel=popover]", element).popover(); |
|
6917 |
|
6918 // Activate popovers with hover states |
|
6919 $("[rel=popover-hover]", element).popover({ |
|
6920 trigger : "hover" |
|
6921 }); |
|
6922 |
|
6923 // Init registered plug-ins and callbacks |
|
6924 ams.plugins && ams.plugins.init(element); |
|
6925 ams.callbacks && ams.callbacks.init(element); |
|
6926 ams.events && ams.events.init(element); |
|
6927 ams.form && ams.form.init(element); |
|
6928 |
|
6929 // Initialize widgets |
|
6930 if (ams.device === 'desktop') { |
|
6931 ams.skin && ams.skin._initDesktopWidgets(element); |
|
6932 } else { |
|
6933 ams.skin && ams.skin._initMobileWidgets(element); |
|
6934 } |
|
6935 ams.skin && ams.skin._setPageHeight(); |
|
6936 |
|
6937 }; |
|
6938 |
|
6939 |
|
6940 $(document).ready(function() { |
|
6941 $ = jQuery.noConflict(); |
|
6942 var html = $('HTML'); |
|
6943 html.removeClass('no-js') |
|
6944 .addClass('js'); |
|
6945 var lang = html.attr('lang') || html.attr('xml:lang'); |
|
6946 if (lang && !lang.startsWith('en')) { |
|
6947 ams.lang = lang; |
|
6948 ams.getScript(ams.baseURL + 'i18n/myams_' + lang.substr(0, 2) + ams.devext + '.js', function () { |
|
6949 ams.initPage(); |
|
6950 }); |
|
6951 } else { |
|
6952 ams.initPage(); |
|
6953 } |
|
6954 }); |
|
6955 |
|
6956 })(jQuery, this); |
|