plugins.js 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. // Avoid `console` errors in browsers that lack a console.
  2. (function() {
  3. var method;
  4. var noop = function () {};
  5. var methods = [
  6. 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
  7. 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
  8. 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
  9. 'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
  10. ];
  11. var length = methods.length;
  12. var console = (window.console = window.console || {});
  13. while (length--) {
  14. method = methods[length];
  15. // Only stub undefined methods.
  16. if (!console[method]) {
  17. console[method] = noop;
  18. }
  19. }
  20. }());
  21. //Affiche un message 'message' de type 'type' pendant 'timeout' secondes
  22. $.message = function (type,message,timeout){
  23. message = message.replace(/<\/?script|iframe|object[^>]*>/gim,'');
  24. $.toast({ type: type, content: message, timeout: timeout });
  25. }
  26. //Permet les notifications types toast sans dépendance de librairie/css/html
  27. $.toast = function (options) {
  28. var defaults = {
  29. title: null,
  30. content: '',
  31. type: 'info',
  32. timeout: 3000
  33. };
  34. var o = $.extend(defaults, options);
  35. var css = "word-wrap:break-word;color:#ffffff;border-radius:1px;margin-bottom:10px;text-align:center;width:100%;box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);position:relative;";
  36. var types = {
  37. error: { css: "background:#dc2626;", icon: 'fas fa-exclamation-triangle' },
  38. warning: { css: "background:#ffc107;color:#212529;", icon: 'fas fa-exclamation-circle' },
  39. info: { css: "background:#2AA7EA;", icon: 'fas fa-info-circle' },
  40. success: { css: "background:#28a745;", icon: 'fas fa-check' },
  41. }
  42. css += types[o.type].css;
  43. o.icon = types[o.type].icon;
  44. if ($('.toastContainer').length == 0)
  45. $('body').append('<div class="toastContainer" style="z-index:1100;position:fixed;right:15px;top:65px;width:350px;"></div>');
  46. var popupContainer = $('.toastContainer');
  47. var popup = $('<div style="' + css + '" class="noPrint toast-'+o.type+'"><i class="toastRemove fas fa-times hidden" style="position:absolute;top:5px;right:5px;cursor:pointer;" onclick="$(this).parent().remove();"; style="position:absolute;top:5px;right:5px;cursor:pointer;"></i><h1 class="toastTitle" style="margin:0;padding:10px;"></h1><i class="toastIcon" style="display:inline-block;vertical-align:top;width:30px;font-size:20px;margin:15px 0;"></i><p style="display: inline-block;margin-top: 10px;padding:0 10px 0 10px;width:300px;" class="toastContent"></p><div style="clear:both;"></div></div>');
  48. $(popupContainer).append(popup);
  49. if (o.title) $('.toastTitle', popup).html(o.title);
  50. $('.toastIcon', popup).attr('class', o.icon);
  51. if (!o.title) $('.toastTitle', popup).remove();
  52. $('.toastContent', popup).html(o.content);
  53. popup.removeClass('hidden');
  54. if (o.timeout != 0) {
  55. setTimeout(function () { popup.addClass('hidden'); }, o.timeout);
  56. } else {
  57. popup.find('.toastRemove').removeClass('hidden');
  58. }
  59. }
  60. $.page = function(element){
  61. var path = window.location.pathname.split('/') ;
  62. path = path[path.length-1];
  63. path = path.replace('.php','');
  64. return path;
  65. }
  66. $.getForm= function(element){
  67. return $(element).getForm();
  68. }
  69. $.setForm= function(element,data){
  70. var o = {};
  71. var obj = $(element);
  72. $('input,select,textarea',obj).each(function(i,element){
  73. if(element.id!=null && element.id!=""){
  74. if(data[element.id]!=null){
  75. if($(element).attr("type")=='checkbox' || $(element).attr("type")=='radio'){
  76. $(element).prop("checked",data[element.id]==1 || data[element.id]=='true' ?true:false);
  77. } else {
  78. $(element).val(data[element.id]);
  79. }
  80. }
  81. }
  82. });
  83. return o;
  84. }
  85. //Gestion des tableaux pour le formData
  86. $.form_data = function(formData, key,values){
  87. var hasFile = false;
  88. if(values instanceof File ) hasFile = true;
  89. if( typeof values == 'object' && !(values instanceof File) ){
  90. for(subkey in values)
  91. if($.form_data(formData,key + '[' + subkey + ']',values[subkey])) hasFile = true;
  92. }else{
  93. formData.append(key, values);
  94. }
  95. return hasFile;
  96. }
  97. $.action = function(data,success,error,progress) {
  98. var formData = new FormData();
  99. var defaultSuccess = data.defaultSuccess != undefined ? data.defaultSuccess : true;
  100. // if(data.defaultSuccess !== undefined) delete data.defaultSuccess;
  101. //hasFile determine si un fichier uploadé se trouve dans le tableau des data
  102. // Si c'est le cas, il envois les données en multipart, sinon il les envoie en json classique.
  103. var hasFile = false;
  104. $.each(data, function(key, value){
  105. if($.form_data(formData,key, value) == true) hasFile = true;
  106. });
  107. var request = {
  108. url : 'action.php',
  109. method : 'POST',
  110. success: function(response){
  111. if(response && !response.error){
  112. if(success!=null)success(response);
  113. } else {
  114. if(response.errorCode && response.errorCode=='401') window.location = 'action.php?action=logout';
  115. var errorMessage = 'ERREUR : '+"\n"+response.error;
  116. if(response.trace) errorMessage += "\n<div style='font-size:10px;max-height:200px;overflow:auto;text-align:left;'>"+response.trace+"</div>";
  117. if(defaultSuccess) $.message('error',errorMessage,0);
  118. if(error!=null) error(response);
  119. }
  120. },
  121. error : function(response){
  122. if(response.status == 200 && $.localhost() ){
  123. $('body').append('<div class="debugFrame" style="box-shadow: 0px 0px 10px rgba(0,0,0,0.5);z-index: 10001;padding: 5px;position: fixed;left: 0;top: 0;width: 40%;min-height: 100%;border-right: 2px solid #ff3b00;background: rgba(210, 222, 255, 0.9);overflow-y: auto;height: 100%; word-break: break-word;"><h3>Action debug</h3> <i style="position:absolute; right:10px; top:10px;font-size:1.5em;" onclick="$(this).parent().remove()" class="fas fa-times pointer"></i>'+response.responseText+'</div>');
  124. } else {
  125. if(response.readyState == 0 && error==null) return;
  126. if(error!=null){
  127. if(response.errorCode && response.errorCode=='401') window.location = 'action.php?action=logout';
  128. error(response);
  129. }else{
  130. $.message('error','Erreur indefinie, merci de contacter un administrateur',0);
  131. }
  132. }
  133. },
  134. xhr: function() {
  135. var xhr = new window.XMLHttpRequest();
  136. if(data.downloadResponse) xhr.responseType = 'blob';
  137. xhr.upload.addEventListener("progress", function(evt){
  138. if (evt.lengthComputable) {
  139. var percentComplete = (evt.loaded / evt.total) * 100;
  140. percentComplete = Math.round(percentComplete * 100) / 100;
  141. if(progress) progress(percentComplete,'upload');
  142. }
  143. }, false);
  144. xhr.addEventListener("progress", function(evt){
  145. if (evt.lengthComputable) {
  146. var percentComplete = evt.loaded / evt.total;
  147. if(progress) progress(percentComplete,'download');
  148. }
  149. }, false);
  150. xhr.addEventListener('readystatechange', function(e) {
  151. if(xhr.readyState == 4 && xhr.status == 200) {
  152. if(data.downloadResponse){
  153. var disposition = xhr.getResponseHeader('content-disposition');
  154. var matches = /"([^"]*)"/.exec(disposition);
  155. var filename = (matches != null && matches[1] ? matches[1] : 'file');
  156. var blob = new Blob([xhr.response], { type: xhr.response.type });
  157. var link = document.createElement('a');
  158. link.href = window.URL.createObjectURL(blob);
  159. link.download = filename;
  160. $('body').append(link);
  161. link.click();
  162. link.remove();
  163. window.URL.revokeObjectURL(link);
  164. }
  165. }
  166. });
  167. return xhr;
  168. }
  169. };
  170. if(!hasFile){
  171. request.data = data;
  172. }else{
  173. request.data = formData;
  174. request.processData = false;
  175. request.contentType = false;
  176. }
  177. $.ajax(request);
  178. }
  179. $.localhost = function(){
  180. return (document.location.hostname=='127.0.0.1' || document.location.hostname=='localhost');
  181. }
  182. $.hashData = function(name){
  183. var page = window.location.hash.substring(1);
  184. page += "&"+window.location.search.substring(1);
  185. data = {};
  186. if(page!='' && page!= null){
  187. options = page.split('&');
  188. var data = {};
  189. for(var key in options){
  190. infos = options[key].split('=');
  191. data[infos[0]] = infos[1];
  192. }
  193. }
  194. if(name == null) return data;
  195. if(typeof name === "object"){
  196. data = name;
  197. hashstring = '';
  198. for(var key in data)
  199. hashstring+= "&"+key+"="+data[key];
  200. hashstring = hashstring.substring(1);
  201. window.location.hash = hashstring;
  202. return;
  203. }
  204. return typeof data[name] == "undefined" ? '':data[name];
  205. }
  206. $.urlParam = function (name,value) {
  207. var parameters = window.location.href.match(/[\\?&]([^&#]*)=([^&#]*)/g);
  208. var data = {};
  209. for (var key in parameters) {
  210. var couple = parameters[key].substring(1, parameters[key].length).split('=');
  211. data[couple[0]] = couple[1];
  212. }
  213. if(name == null) return data;
  214. if (value == null)
  215. return data[name] ? data[name] : null;
  216. if (value != false) data[name] = value;
  217. var url = '?';
  218. for (var key in data) {
  219. if (value == false && key == name) continue;
  220. url += key + '=' + data[key]+'&';
  221. }
  222. window.history.pushState('', document.title, url.substring(0, url.length-1));
  223. }
  224. $.fn.extend({
  225. toJson : function(){
  226. return $.getForm(this);
  227. },
  228. getForm : function(){
  229. var o = {};
  230. var obj = $(this);
  231. for(var key in obj.data()){
  232. if(key!="action" && key != "id") continue;
  233. o[key] = obj.attr('data-'+key);
  234. }
  235. $('input,select,textarea',obj).each(function(i,element){
  236. if(element.id!=null && element.id!=""){
  237. if($(element).attr("type")=='checkbox' || $(element).attr("type")=='radio'){
  238. o[element.id] = ($(element).is(':checked')?1:0);
  239. }else{
  240. o[element.id] = $(element).val();
  241. }
  242. }
  243. });
  244. return o;
  245. },
  246. upload: function (options) {
  247. //var options = $.extend(defaults, options);
  248. return this.each(function () {
  249. var o = options;
  250. var droppedFiles = false;
  251. var div = $(this);
  252. var data = div.data();
  253. data.html =!div.attr('data-label') ? '': div.attr('data-label');
  254. data.label = data.html;
  255. div.html('');
  256. var o = $.extend(o, data);
  257. if(o.readonly == false){
  258. var form = $('<form class="box" method="post" action="' + o.action + '" enctype="multipart/form-data"><input type="file" name="'+(o.fileName?o.fileName:div.attr('id'))+'[]" multiple /></form>');
  259. div.append(form);
  260. var input = form.find('input[type="file"]');
  261. var zone = $('<div>' + o.label + '</div>');
  262. div.append(zone);
  263. //test if dnd is enabled n browser
  264. var div = document.createElement('div');
  265. var dragAndDropEnabled = (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && 'FormData' in window && 'FileReader' in window;
  266. //set elements styles
  267. input.attr('style', "width: 0.1px;height: 0.1px;opacity: 0;overflow: hidden; position: absolute;z-index: -1");
  268. zone.css('cursor', "pointer");
  269. //set events
  270. zone
  271. .on('click', function (e) {
  272. form.find('input[type="file"]').trigger('click');
  273. e.preventDefault();
  274. e.stopPropagation();
  275. })
  276. .on('drag dragstart dragend dragover dragenter dragleave drop', function (e) {
  277. e.preventDefault();
  278. e.stopPropagation();
  279. })
  280. .on('dragover dragenter', function () {
  281. if (o.hover) form.addClass(o.hover);
  282. })
  283. .on('dragleave dragend drop', function () {
  284. if (o.hover) form.removeClass(o.hover);
  285. })
  286. .on('drop', function (e) {
  287. droppedFiles = e.originalEvent.dataTransfer.files;
  288. form.trigger('submit');
  289. });
  290. input.on('change', function (e) {
  291. form.trigger('submit');
  292. });
  293. form.on('submit', function (e) {
  294. if (o.start) o.start();
  295. if (dragAndDropEnabled) {
  296. e.preventDefault();
  297. var ajaxData = new FormData();
  298. if (droppedFiles) {
  299. $.each(droppedFiles, function (i, file) {
  300. var ext = file.name.split('.');
  301. ext = ext.pop();
  302. if(o.allowed && $.inArray(ext.toLowerCase(),o.allowed.split(','))===-1){
  303. $.message('error','Extension fichier '+ext+' non permise (autorisé:'+o.allowed+')',0);
  304. return;
  305. }
  306. if(o.size && file.size > o.size){
  307. $.message('error','Taille fichier '+file.size+' octets trop grande (autorisé:'+o.size+' octets)',0);
  308. return;
  309. }
  310. ajaxData.append(input.attr('name'), file);
  311. });
  312. }else{
  313. ajaxData = new FormData(form.get(0));
  314. for(var key in $('input',form).get(0).files){
  315. var file = $('input',form).get(0).files[key];
  316. if(file.name==null || typeof file !='object') continue;
  317. var ext = file.name.split('.');
  318. ext = ext.pop();
  319. if(o.allowed && $.inArray(ext.toLowerCase(),o.allowed.split(','))===-1){
  320. $.message('error','Extension fichier '+ext+' non permise (autorisé:'+o.allowed+')',0);
  321. $('input',form).val();
  322. return;
  323. }
  324. if(o.size && file.size > o.size){
  325. $.message('error','Taille fichier '+file.size+' octets trop grande (autorisé:'+o.size+' octets)',0);
  326. $('input',form).val();
  327. return;
  328. }
  329. }
  330. }
  331. if (o.addData){
  332. var addionalData = o.addData();
  333. for(var k in addionalData){
  334. ajaxData.append(k, addionalData[k]);
  335. }
  336. }
  337. droppedFiles = null;
  338. $.ajax({
  339. url: form.attr('action'),
  340. type: form.attr('method'),
  341. data: ajaxData,
  342. dataType: 'json',
  343. cache: false,
  344. contentType: false,
  345. processData: false,
  346. complete: function (data) {
  347. if (o.complete) o.complete(data.responseJSON);
  348. },
  349. success: function (data) {
  350. if (o.success) o.success(data);
  351. },
  352. error: function (data) {
  353. if (o.error) o.error(data);
  354. }
  355. });
  356. } else {
  357. var iframeName = 'uploadiframe' + new Date().getTime();
  358. iframe = $('<iframe name="' + iframeName + '" style="display: none;"></iframe>');
  359. $('body').append(iframe);
  360. form.attr('target', iframeName);
  361. iframe.one('load', function () {
  362. var data = JSON.parse(iframe.contents().find('body').text());
  363. if (!data.success) alert(data.error);
  364. form.removeAttr('target');
  365. iframe.remove();
  366. if (o.complete) o.complete();
  367. });
  368. }
  369. });
  370. }
  371. });
  372. },
  373. clear: function (){
  374. return this.each(function() {
  375. var obj = $(this);
  376. obj.find('input,select,textarea').val('').prop('checked',false).prop('selected',false);
  377. });
  378. },
  379. addLine: function (rows){
  380. return this.each(function() {
  381. var obj = $(this);
  382. var model = null;
  383. var container = null;
  384. if(obj.prop("tagName") == 'UL'){
  385. container = obj;
  386. model = container.find('li:first-child');
  387. container.find('li:visible').remove();
  388. }else if(obj.prop("tagName") == 'TABLE'){
  389. container = obj.find('tbody');
  390. model = container.find('tr:first-child');
  391. container.find('tr:visible').remove();
  392. }else{
  393. container = obj;
  394. childName = container.children().get(0).nodeName;
  395. model = container.find(childName+':first-child');
  396. container.find(childName+':visible:not(.nofill)').remove();
  397. }
  398. var tpl = model.get(0).outerHTML;
  399. //fix jquery backslahes break
  400. tpl = tpl.replace(/{{##/g,'{{/').replace(/{{\/(.*)}}=""/g,'{{/$1}}');
  401. //fix images url not found on template
  402. tpl = tpl.replace(/(<img\s[^>]*\s)(data-src)/g,'$1src');
  403. for(var key in rows){
  404. var line = $(Mustache.render(tpl,rows[key]));
  405. container.append(line);
  406. line.removeClass('hidden');
  407. }
  408. });
  409. },
  410. //Permet le resize d'un panel vertical
  411. panelResize : function(options){
  412. var obj = $(this);
  413. var o = $.extend({
  414. handlerClass : 'panel-resize-handler',
  415. hoverClass : 'panel-resize-handler-hover',
  416. handlerWidth : 10,
  417. direction : 'right',
  418. minWidth : 30,
  419. maxWidth : 700,
  420. update : function(data){}
  421. }, options);
  422. var handlerId = 'handler-'+generate_uuid(10);
  423. var handler = $('<div id="'+handlerId+'" class="'+o.handlerClass+'" style="cursor:col-resize;opacity:0.1;position:absolute;z-index:1000;height:'+obj.outerHeight()+'px;width:'+o.handlerWidth+'px;"></div>');
  424. var timeout = null;
  425. var left;
  426. if( o.direction== 'right'){
  427. left = obj.position().left+obj.outerWidth()-(o.handlerWidth/2);
  428. }else if (o.direction== 'left'){
  429. left = obj.position().left-(o.handlerWidth/2);
  430. }
  431. handler.css({
  432. left :left,
  433. top : obj.position().top
  434. });
  435. handler.hover(function(){
  436. clearTimeout(timeout);
  437. handler.addClass(o.hoverClass);
  438. },
  439. function(){
  440. timeout = setTimeout(function(){
  441. handler.removeClass(o.hoverClass);
  442. },300);
  443. });
  444. if(!window.handlerActive) window.handlerActive = {};
  445. if(!window.handlerPosition) window.handlerPosition = {};
  446. handler.mousedown(function(){
  447. window.handlerPosition[handlerId] = handler.position().left;
  448. window.handlerPanelWidth = obj.outerWidth();
  449. window.handlerActive[handlerId] = true;
  450. });
  451. $(document).mouseup(function(){
  452. window.handlerActive[handlerId] = false;
  453. var left;
  454. if( o.direction== 'right'){
  455. left = obj.position().left+obj.outerWidth()-(o.handlerWidth/2);
  456. }else if (o.direction== 'left'){
  457. left = obj.position().left-(o.handlerWidth/2);
  458. }
  459. handler.css({left : left});
  460. o.update({
  461. element : obj,
  462. handler : handler,
  463. width : obj.outerWidth()
  464. });
  465. });
  466. $(document).mousemove(function( event ) {
  467. if(!window.handlerActive[handlerId]) return;
  468. var newPosition = (event.pageX-2);
  469. var negativeWidth = window.handlerPosition[handlerId] - newPosition;
  470. var newWidth = window.handlerPanelWidth- (negativeWidth * (o.direction== 'right'?1:-1) );
  471. if(newWidth < o.minWidth || newWidth <1 || newWidth > o.maxWidth ){
  472. return;
  473. }
  474. handler.css({
  475. left : newPosition+'px'
  476. });
  477. obj.css({
  478. width : newWidth+'px',
  479. maxWidth : newWidth+'px'
  480. });
  481. });
  482. obj.after(handler);
  483. },
  484. fill: function (option,callback,progress){
  485. return this.each(function() {
  486. var obj = $(this);
  487. var model = null;
  488. var container = null;
  489. option = $.extend({
  490. differential : false,
  491. showing : function(item){
  492. //permet la personnalisation de l'apparition des lignes ( removeClass('hidden') par defaut)
  493. item.removeClass('hidden');
  494. }
  495. },option);
  496. var preloader = null;
  497. if(option.preloader){
  498. var preloader = $(option.preloader);
  499. preloader.css('position','absolute');
  500. preloader.css('left',(obj.offset().left+obj.width()/2)+'px');
  501. preloader.css('top',(obj.offset().top+30)+'px');
  502. $('body').append(preloader);
  503. }
  504. if(obj.prop("tagName") == 'UL'){
  505. container = obj;
  506. model = container.find('li:first-child');
  507. if(!option.export && !option.differential) container.children('li:visible').remove();
  508. } else if(obj.prop("tagName") == 'TABLE'){
  509. container = obj.find('tbody');
  510. model = container.find('tr:first-child');
  511. if(!option.export && !option.differential) container.children('tr:visible').remove();
  512. } else if(obj.prop("tagName") == "SELECT"){
  513. container = obj;
  514. model = container.find('option[value*="{{"]');
  515. if(model.length==0) model = $('<option class="hidden" value="{{value}}">{{label}}</option>');
  516. if(!option.export && !option.differential) container.find('option:not([value*="{{"])').remove();
  517. } else{
  518. container = obj;
  519. childName = container.children().get(0).nodeName;
  520. model = container.find(childName+':first-child');
  521. if(!option.export && !option.differential) container.find(childName+':visible:not(.nofill)').remove();
  522. }
  523. var tpl = model.get(0).outerHTML;
  524. //fix jquery backslashes break
  525. tpl = tpl.replace(/{{##/g,'{{/').replace(/{{\/(.*)}}=""/g,'{{/$1}}');
  526. //fix images url not found on template
  527. tpl = tpl.replace(/(<img\s[^>]*\s?)(data-src)/g,'$1src');
  528. var pagination = obj.nextAll('.pagination').length ? obj.nextAll('.pagination') : obj.parent().nextAll('.pagination');
  529. if(pagination.length!=0) option.page = $('li.active',pagination).attr('data-value');
  530. tpl = tpl.replace(/(data-style)/g, 'style');
  531. if(option.export)
  532. option.downloadResponse = true;
  533. //on clone l'objet option pour ne transmettre que des datas utiles
  534. data = $.extend({},option);
  535. delete data.showing;
  536. delete data.templating;
  537. $.action(data,function(r){
  538. //On ne gere la pagination et l'affichage tableau que si on est pas en mode export
  539. if(!option.export){
  540. var activeIds = [];
  541. for(var key in r.rows){
  542. var line;
  543. var data = r.rows[key];
  544. var lineTpl = tpl;
  545. if(option.templating) lineTpl = option.templating(data,line,tpl);
  546. if(!option.differential){
  547. line = $(Mustache.render(lineTpl,data));
  548. container.append(line);
  549. option.showing(line,key);
  550. }else{
  551. activeIds.push(data.id);
  552. var existing = $('> [data-id="'+data.id+'"]',container);
  553. //existe en data et pas dans le dom : ajout
  554. if(existing.length == 0){
  555. line = $(Mustache.render(lineTpl,data));
  556. line.attr('data-update-tag',data.updated);
  557. if(key==0){
  558. container.append(line);
  559. }else{
  560. var previousIndex = key-1;
  561. var previous = $('>[data-id]:visible',container).eq(previousIndex);
  562. previous.after(line);
  563. }
  564. option.showing(line,key);
  565. }else{
  566. //existe en data et dans le dom et pas de modification : on passe au suivant
  567. if(existing.attr('data-update-tag') == data.updated){
  568. continue;
  569. //existe en data et dans le dom mais a été modifié : on remplace
  570. }else{
  571. line = $(Mustache.render(lineTpl,data));
  572. line.attr('data-update-tag',data.updated);
  573. existing.after(line);
  574. existing.remove();
  575. option.showing(line,key);
  576. }
  577. }
  578. }
  579. }
  580. //suppression des élements dom qui ne sont plus en db
  581. if(option.differential){
  582. $('>[data-id]:visible',container).each(function(i,line){
  583. var line = $(line);
  584. if(activeIds.indexOf(line.attr('data-id')) == -1){
  585. console.log(line.attr('data-id'));
  586. console.log('suppression ',line);
  587. line.remove();
  588. }
  589. });
  590. }
  591. if(r.pagination){
  592. $('.page-item-previous,.page-item-next').remove();
  593. r.pagination.pages = Math.ceil(r.pagination.pages);
  594. var previewNumber = pagination.attr('data-range') != '' && pagination.attr('data-range') != null ? parseInt(pagination.attr('data-range')) : 5;
  595. previewNumber = previewNumber < 2 ? 2 : previewNumber;
  596. var template = pagination.find('li:not(:visible)');
  597. if(template.length>0 ){
  598. template = template.get(0).outerHTML;
  599. $('li:not(:eq(0))',pagination).remove();
  600. var current = parseInt(r.pagination.current);
  601. var previousPages = current-previewNumber;
  602. var nextPages = current+previewNumber;
  603. var dropDownTpl = '<div data-toggle="dropdown"><i class="fas fa-ellipsis-h pointer"></i></div><div class="dropdown-menu pagination-select">{{#choices}}<span class="dropdown-item">{{.}}</span>{{/choices}}</div>';
  604. for(i=0;i<r.pagination.pages;i++){
  605. var li = $(Mustache.render(template,{value:i,label:i+1}));
  606. if(
  607. (previousPages < i && i < nextPages)
  608. || i==0 || i==r.pagination.pages-1
  609. ){
  610. li.removeClass('hidden');
  611. if(i==current) li.addClass('active');
  612. }else{
  613. if(i==1 || i==r.pagination.pages-2){
  614. var dotli = li.clone()
  615. var start = i==1 ? 2: current+previewNumber+1;
  616. var end = i==1 ? (current+1)-previewNumber : r.pagination.pages-1;
  617. var choices = [];
  618. for(u=start; u<end+1;u++)
  619. choices.push(u);
  620. rightDropDown = $(Mustache.render(dropDownTpl,{choices:choices}));
  621. dotli.removeClass('hidden')
  622. .attr('title','Voir les pages '+(start)+' à '+(end))
  623. .removeAttr('onclick')
  624. .css('position','relative')
  625. .addClass('page-link').html(rightDropDown);
  626. pagination.append(dotli);
  627. }
  628. }
  629. pagination.append(li);
  630. }
  631. if(current!=0){
  632. var prev = $('<li class="page-item page-item-previous"><span class="page-link" ><span><i class="fas fa-angle-left"></i></span></span></li>');
  633. pagination.prepend(prev);
  634. prev.click(function(){
  635. pagination.find('li[data-value="'+(current-1)+'"]').trigger('click');
  636. });
  637. }
  638. if(current<r.pagination.pages-1){
  639. var next = $('<li class="page-item page-item-next"><span class="page-link" ><span><i class="fas fa-angle-right"></i></span></span></li>');
  640. pagination.append(next);
  641. next.click(function(){
  642. pagination.find('li[data-value="'+(current+1)+'"]').trigger('click');
  643. });
  644. }
  645. if(r.pagination.pages>1){
  646. pagination.find('.page-item:not(.hidden):first .page-link').css('border-radius','0.25rem 0 0 0.25rem');
  647. }else{
  648. pagination.find('.page-item:not(.hidden):first .page-link').css('border-radius','0.25rem 0.25rem 0.25rem 0.25rem');
  649. }
  650. $('.pagination-select span',pagination).click(function(){
  651. var selectedPage = (parseInt($(this).text())-1);
  652. pagination.find('li[data-value="'+selectedPage+'"]').trigger('click');
  653. });
  654. }
  655. }
  656. }
  657. if(preloader) preloader.remove();
  658. if(callback!=null)callback(r);
  659. },null,function(percent,type){
  660. if(progress) progress(percent,type);
  661. });
  662. });
  663. },
  664. filters: function (values){
  665. var obj = $(this);
  666. var box = obj.next('.filter-box');
  667. if(values){
  668. if(values.keyword && values.keyword!='')
  669. $('.filter-keyword',box).val(values.keyword);
  670. for(var key in values.advanced){
  671. var filter = values.advanced[key];
  672. filter_add($('.filter-add-button',box),filter);
  673. }
  674. return;
  675. }
  676. var formData = {
  677. keyword : $('.filter-keyword',box).val()
  678. };
  679. formData.advanced = [], formData.multiple = [], formData.custom = {};
  680. $('.filterRow:visible',box).each(function(i,row){
  681. var row = $(row);
  682. if(row.find('.filter-column').val()=='') return;
  683. var filter = {
  684. join : row.find('.filter-join').val(),
  685. column : row.find('.filter-column').val(),
  686. type : row.find('.filter-column option:selected').attr('data-filter-type'),
  687. operator : {},
  688. value : {}
  689. }
  690. if ($('.filter-value-block',row).length > 1) {
  691. $('.filter-value-block',row).each(function(j,block){
  692. var block = $(block);
  693. filter.operator[j] = block.find('.filter-operator').val();
  694. filter.value[j] = block.find('.filter-value').last().val();
  695. });
  696. formData.multiple.push(filter);
  697. } else {
  698. filter.operator = row.find('.filter-operator').val();
  699. values = row.find('.filter-value');
  700. if(values.length > 1){
  701. filter.value = [];
  702. for(var j=0; j<values.length; ++j){
  703. filter.value.push(values.eq(j).val());
  704. }
  705. values.eq(j).attr('data-custom') == 'true' ? formData.custom[filter.column] = filter : formData.advanced.push(filter);
  706. } else {
  707. filter.value = values.val();
  708. values.last().attr('data-custom') == 'true' ? formData.custom[filter.column] = filter : formData.advanced.push(filter);
  709. }
  710. }
  711. });
  712. return formData;
  713. },
  714. enter: function (option){
  715. return this.each(function() {
  716. var obj = $(this);
  717. obj.keydown(function(event){
  718. if(event.keyCode == 13){
  719. option();
  720. return false;
  721. }
  722. });
  723. });
  724. },
  725. sortable_table: function (option){
  726. if(option=='get'){
  727. var obj = $(this);
  728. var response = {};
  729. obj.find('thead th[data-sortable]').each(function(i,th){
  730. var th = $(th);
  731. if(th.attr('data-sort') && th.attr('data-sort')!=""){
  732. response = {
  733. sort : th.attr('data-sort'),
  734. sortable : th.attr('data-sortable')
  735. };
  736. }
  737. });
  738. return response;
  739. }
  740. return this.each(function() {
  741. var obj = $(this);
  742. obj.find('thead th[data-sortable]').click(function(){
  743. var th = $(this);
  744. var data = th.data();
  745. if(!data.sort || data.sort==''){
  746. data.sort = 'asc'
  747. }else if(data.sort == 'asc'){
  748. data.sort ='desc'
  749. }else{
  750. data.sort = '';
  751. }
  752. obj.find('thead th').removeClass('sort-asc').removeClass('sort-desc').removeAttr('data-sort');
  753. if(data.sort!='') th.addClass('sort-'+data.sort);
  754. th.attr('data-sort',data.sort);
  755. if(option.onSort) option.onSort();
  756. });
  757. });
  758. },
  759. autocomplete: function(o){
  760. return this.each(function() {
  761. var obj = $(this);
  762. if(o == 'off') return obj.typeahead('destroy');
  763. obj.attr('autocomplete','off');
  764. var option = obj.data();
  765. option = $.extend(option,o);
  766. obj.typeahead({
  767. items: (o.items) ? o.items : 5,
  768. minLength: o.suggest ? 0 : (o.minLength ? o.minLength : 2) ,
  769. fitToElement: false,
  770. autoSelect : false,
  771. selectOnBlur : false,
  772. displayText : function(item){
  773. return (o.skin) ? o.skin(item) : item.name || item;
  774. },
  775. source: function(keyword, response){
  776. if(o.onKeypress) o.onKeypress(obj);
  777. if(o.dynamicData) o.data = $.extend(o.data,o.dynamicData());
  778. $.action({
  779. action: option.action,
  780. keyword: obj.val(),
  781. data: o.data
  782. },function(r){
  783. if(r.rows != null)
  784. response(r.rows);
  785. });
  786. },
  787. highlighter: function(item){
  788. if(o.highlight) {
  789. return o.highlight(item)
  790. }
  791. else {
  792. var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
  793. return item.replace(new RegExp('('+query+')', 'ig'), function($1, match){
  794. return '<strong>'+match+'</strong>';
  795. });
  796. }
  797. },
  798. matcher: function(r){
  799. if(obj.val() == r.name)
  800. if(o.onClick)
  801. o.onClick(r,obj);
  802. return '<div>'+r.name+'</div>';
  803. },
  804. afterSelect: function(item) {
  805. obj.data('selected',true);
  806. if(o.onClick) o.onClick(item,obj);
  807. obj.trigger("change");
  808. }
  809. }).blur(function(){
  810. if(o.onBlur) o.onBlur(obj);
  811. });
  812. if(o.suggest){
  813. obj.on("click", function () {
  814. ev = $.Event("keydown");
  815. ev.keyCode = ev.which = 40;
  816. $(this).trigger(ev);
  817. return true
  818. });
  819. }
  820. obj.data('typeahead').next = function (event) {
  821. var active = this.$menu.find('.active').removeClass('active');
  822. var next = active.next();
  823. if (!next.length) {
  824. next = $(this.$menu.find($(this.options.item || this.theme.item).prop('tagName'))[0]);
  825. }
  826. while (next.hasClass('divider') || next.hasClass('dropdown-header')) {
  827. next = next.next();
  828. }
  829. next.addClass('active');
  830. var newVal = this.updater(next.data('value'));
  831. this.$element.val(newVal.name || newVal);
  832. };
  833. obj.data('typeahead').prev = function (event) {
  834. var active = this.$menu.find('.active').removeClass('active');
  835. var prev = active.prev();
  836. if (!prev.length){
  837. prev = this.$menu.find($(this.options.item || this.theme.item).prop('tagName')).last();
  838. }
  839. while (prev.hasClass('divider') || prev.hasClass('dropdown-header')) {
  840. prev = prev.prev();
  841. }
  842. prev.addClass('active');
  843. var newVal = this.updater(prev.data('value'));
  844. if (this.changeInputOnMove) this.$element.val(newVal.name || newVal);
  845. };
  846. });
  847. },
  848. location: function (options){
  849. return this.each(function() {
  850. try{
  851. //var options = $.extend({},options);
  852. var obj = $(this);
  853. obj.attr('autocomplete','off');
  854. var data = $('#algolia').data();
  855. var placesAutocomplete = places({
  856. appId: data.api,
  857. apiKey: data.key,
  858. container: obj.get(0)
  859. });
  860. placesAutocomplete.on('change', function(e) {
  861. var m = /[0-9]*/m.exec(e.suggestion.name)
  862. var infos = {
  863. latitude: e.suggestion.latlng.lat,
  864. longitude : e.suggestion.lng,
  865. types : e.suggestion.type,
  866. number : '',
  867. street : e.suggestion.name,
  868. city : e.suggestion.city,
  869. country : e.suggestion.country,
  870. code : e.suggestion.postcode,
  871. picture : '',
  872. map : ''
  873. };
  874. if(m && m.length > 0 ) infos.number = m[0] ;
  875. infos.address = (infos.street && infos.street.length && infos.number && infos.number.length) ? infos.number+' '+infos.street : (infos.street ? infos.street : '');
  876. if(options.select) options.select(infos);
  877. });
  878. }catch(e){
  879. console.warn('Composant Location en erreur, désactivé :'+e);
  880. }
  881. });
  882. },
  883. date: function (options){
  884. return this.each(function() {
  885. var obj = $(this);
  886. obj.on('paste', function(e){
  887. is_valid_date(e.originalEvent.clipboardData.getData('Text')) ? obj.val("") : e.preventDefault();
  888. });
  889. obj.datepicker({
  890. dateFormat: options.dateFormat,
  891. dayNames: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
  892. dayNamesMin: ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"],
  893. dayNamesShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"],
  894. monthNames: ["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"],
  895. monthNamesShort: ["Jan","Fév","Mars","Avr","Mai","Juin","Juil","Aout","Sept","Oct","Nov","Déc"],
  896. firstDay: 1,
  897. minDate: options.beginDate,
  898. maxDate: options.endDate,
  899. changeMonth: true,
  900. yearRange: "-30:+30",
  901. changeYear: true,
  902. onSelect: function(dateText, inst) {
  903. obj.trigger("blur");
  904. }
  905. }).keypress(function(event){
  906. var length = obj.val().length;
  907. if(length == 2 || length == 5) obj.val(obj.val()+'/');
  908. }).blur(function(event){
  909. obj.removeClass('border border-danger');
  910. if(obj.val()=='') return;
  911. var segments = obj.val().split('/');
  912. if(segments.length!=3) return;
  913. if(segments[0] > 31 || segments[1] > 12) obj.addClass('border border-danger');
  914. }).attr('maxlength','10');
  915. obj.attr('placeholder',options.placeholder);
  916. obj.attr('pattern',"^(\\d{2}(?:\\d{2})?)\/(\d{2})\/(\\d{2}(?:\\d{2})?)$");
  917. obj.attr('title','Format '+options.dateFormat);
  918. });
  919. },
  920. hour: function (options){
  921. return this.each(function() {
  922. var obj = $(this);
  923. obj.on('paste', function(e){
  924. is_valid_hour(e.originalEvent.clipboardData.getData('Text')) ? obj.val("") : e.preventDefault();
  925. });
  926. obj.timepicker({
  927. scrollDefault: 'now',
  928. timeFormat: options.timeFormat,
  929. step: options.step,
  930. onSelect: function(timeText, inst) {
  931. obj.trigger("blur");
  932. }
  933. }).keypress(function(e) {
  934. if(!e.key.match(/[0-9:]/)) e.preventDefault();
  935. if(obj.val().length == 2) obj.val(obj.val()+':');
  936. }).blur(function(event){
  937. obj.removeClass('border border-danger')
  938. if(obj.val()=='') return;
  939. var segments = obj.val().split(':');
  940. if(segments.length!=2) return;
  941. if(segments[0] > 23 || segments[1] > 59) obj.addClass('border border-danger');
  942. }).attr('maxlength','5');
  943. obj.attr("placeholder",options.placeholder);
  944. obj.attr('pattern',"(\\d{2})\\:(\\d{2})");
  945. obj.attr('title',"Format hh:mm");
  946. });
  947. },
  948. raiseNumber: function(from,to) {
  949. return this.each(function(){
  950. var obj = $(this);
  951. obj.text(from);
  952. var interval = 800 / (to - from);
  953. var interval = setInterval(function(){
  954. var number = parseFloat(obj.text());
  955. if(number>=to) {
  956. clearInterval(interval);
  957. return;
  958. }
  959. obj.text(number+1);
  960. },interval);
  961. });
  962. }
  963. });