// Avoid `console` errors in browsers that lack a console. (function() { var method; var noop = function () {}; var methods = [ 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', 'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn' ]; var length = methods.length; var console = (window.console = window.console || {}); while (length--) { method = methods[length]; // Only stub undefined methods. if (!console[method]) { console[method] = noop; } } }()); //Affiche un message 'message' de type 'type' pendant 'timeout' secondes and $.message = function (type,message,timeout,addClass){ message = message.replace(/<\/?script|iframe|object[^>]*>/gim,''); var types = { error: 'ERREUR', warning: 'ATTENTION', info: 'INFORMATION', } var data = { type: type, content: message, timeout: timeout, progress: true, addClass:addClass }; if(types[type]) data.title = types[type]; $.toast(data); } //appelle un hook js $.callHook = function (hook,args){ if(!window.hooks) window.hooks = {}; if(!window.hooks[hook]) window.hooks[hook] = []; for(var k in window.hooks[hook]){ var method = window.hooks[hook][k]; method(args); } } //Définis un hook js $.addHook = function (hook,callback){ if(!window.hooks) window.hooks = {}; if(!window.hooks[hook]) window.hooks[hook] = []; window.hooks[hook].push(callback); } //Permet les notifications types toast sans dépendance de librairie/css/html $.toast = function (options) { var o = $.extend({ title: null, content: '', type: 'info', timeout: 3000, addClass: '' }, options); var toastFunctions = { hideToast: function(toast, timeout){ setTimeout(function(){ toast.addClass('hidden'); setTimeout(function(){ toast.remove(); },100); }, timeout); }, updateProgress: function(){ var percentage = ((progress.hideEta - (new Date().getTime())) / progress.maxHideTime) * 100; progressBar.width(percentage + '%'); } }; var progress = { toastInterval: null, hideEta: null, maxHideTime: null }; if($('.toastContainer').length == 0) $('body').append('
'); var popupContainer = $('.toastContainer'); var popup = $(''); popupContainer.append(popup); if(o.title) $('.toastTitle > span', popup).html(o.title); $('.toastMessage', popup).html(o.content); //Apparition du toast setTimeout(function(){ popup.removeClass('hidden'); }, 50); var progressBar = $('
'); clearTimeout(progress.toastInterval); //Cache le toast en fonction d'un timeout ou non if(o.timeout > 0) { if(o.progress) { toastInterval = setTimeout(function(){toastFunctions.hideToast(popup);}, o.timeout); progress.maxHideTime = parseFloat(o.timeout); progress.hideEta = new Date().getTime() + progress.maxHideTime; popup.append(progressBar); progress.toastInterval = setInterval(toastFunctions.updateProgress, 10); } //Au terme du timeout, on cache le toast toastFunctions.hideToast(popup, o.timeout); } else { popup.find('.toastRemove').removeClass('hidden'); } } //Permet l'utilisation du json dans les local storage $.storage = function(key,value){ var json = localStorage.getItem(key); json = !json ? {} : JSON.parse(json); if(!value) return json; localStorage.setItem(key,JSON.stringify(value)); } $.page = function(element){ var path = window.location.pathname.split('/') ; path = path[path.length-1]; path = path.replace('.php',''); return path; } $.getForm = function(element){ return $(element).getForm(); } $.setForm = function(element,data){ var o = {}; var obj = $(element); $('input,select,textarea',obj).each(function(i,element){ var input = $(element); var id = element.id!=null && element.id!="" ? element.id : ''; if(!id && input.attr('data-id')) id = input.attr('data-id'); if(!id || data[id]==null) return; if(input.attr("type")=='checkbox' || input.attr("type")=='radio'){ input.prop("checked",data[id]==1 || data[id]=='true' ?true:false); } else { input.val(data[id]); } }); return o; } //Gestion des tableaux pour le formData $.form_data = function(formData, key,values){ var hasFile = false; if(values instanceof File) hasFile = true; if(typeof values == 'object' && !(values instanceof File)){ for(subkey in values) if($.form_data(formData,key + '[' + subkey + ']',values[subkey])) hasFile = true; }else{ formData.append(key, values); } return hasFile; } $.action = function(data,success,error,progress) { var formData = new FormData(); var defaultSuccess = data.defaultSuccess != undefined ? data.defaultSuccess : true; var async = data.async != undefined ? data.async : true ; // if(data.defaultSuccess !== undefined) delete data.defaultSuccess; //hasFile determine si un fichier uploadé se trouve dans le tableau des data // Si c'est le cas, il envois les données en multipart, sinon il les envoie en json classique. var hasFile = false; $.each(data, function(key, value){ if($.form_data(formData,key, value) == true) hasFile = true; }); var request = { url : 'action.php', method : 'POST', async :async, success: function(response){ $('.btn-preloader').removeClass('btn-preloader'); //Debug des erreur php non catchées if(window.location.host=='127.0.0.1'){ var debugRegex = /Erreur : <\/strong>(.*)- (.*\.php) L([0-9]*)/gm; while ((m = debugRegex.exec(response)) !== null) { if (m.index === debugRegex.lastIndex) debugRegex.lastIndex++; var path = m[2].split('/'); path = path.slice(-3).join('/'); var filePath = m[2].replace(/\//ig,'\\'); var link = 'w2d://'+btoa(JSON.stringify({action:'alias',alias:'sublime',arguments:filePath+'":'+m[3]})); var html = ''+path+'
L'+m[3]+'
'+m[1]+'
('+data.action+')
'; $.message('warning',html,0); } } if(response && !response.error){ if(success!=null)success(response); } else { if(response.errorCode && response.errorCode=='401') core_logout(); var errorMessage = ''; if(response.file){ var filePath = response.file.replace(/\//ig,'\\'); var link = 'w2d://'+btoa(JSON.stringify({action:'alias',alias:'sublime',arguments:filePath+'":'+response.line})); errorMessage += ''+response.file.replace('/var/www/html/','')+'
L'+response.line+'
'; } errorMessage += "
"+response.error; if(response.trace) errorMessage += ""; if(defaultSuccess) $.message('error',errorMessage,0); if(error!=null) error(response); } }, error : function(response){ $('.btn-preloader').removeClass('btn-preloader'); if(response.status == 200 && $.localhost() ){ $('body').append('
ACTION DEBUG
'+response.responseText+'
'); } else { if(response.readyState == 0 && error==null) return; if(error!=null){ if(response.errorCode && response.errorCode=='401') core_logout(); error(response); }else{ $.message('error','Erreur indefinie, merci de contacter un administrateur',0); } } }, xhr: function() { var xhr = new window.XMLHttpRequest(); if(data.downloadResponse) xhr.responseType = 'blob'; xhr.upload.addEventListener("progress", function(evt){ if (evt.lengthComputable) { var percentComplete = (evt.loaded / evt.total) * 100; percentComplete = Math.round(percentComplete * 100) / 100; if(progress) progress(percentComplete,'upload'); } }, false); xhr.addEventListener("progress", function(evt){ if (evt.lengthComputable) { var percentComplete = evt.loaded / evt.total; if(progress) progress(percentComplete,'download'); } }, false); xhr.addEventListener('readystatechange', function(e) { if(xhr.readyState == 4 && xhr.status == 200) { if(data.downloadResponse){ var disposition = xhr.getResponseHeader('content-disposition'); var matches = /"([^"]*)"/.exec(disposition); var filename = (matches != null && matches[1] ? matches[1] : 'file'); var blob = new Blob([xhr.response], { type: xhr.response.type }); var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = filename; $('body').append(link); link.click(); link.remove(); window.URL.revokeObjectURL(link); } } }); return xhr; } }; if(!hasFile){ request.data = data; }else{ request.data = formData; request.processData = false; request.contentType = false; } $.ajax(request); } $.localhost = function(){ return (document.location.hostname=='127.0.0.1' || document.location.hostname=='localhost'); } $.hashData = function(name){ var page = window.location.hash.substring(1); page += "&"+window.location.search.substring(1); data = {}; if(page!='' && page!= null){ options = page.split('&'); var data = {}; for(var key in options){ infos = options[key].split('='); data[infos[0]] = infos[1]; } } if(name == null) return data; if(typeof name === "object"){ data = name; hashstring = ''; for(var key in data) hashstring+= "&"+key+"="+data[key]; hashstring = hashstring.substring(1); window.location.hash = hashstring; return; } return typeof data[name] == "undefined" ? '':data[name]; } $.urlParam = function (name,value,forceValue) { var parameters = window.location.href.match(/[\\?&]([^&#]*)=([^&#]*)/g); var data = {}; for (var key in parameters) { var couple = parameters[key].substring(1, parameters[key].length).split('='); data[couple[0]] = couple[1]; } if(name == null) return data; if (value == null && !forceValue) return data[name] ? data[name] : null; if (value !== false) data[name] = ''+value; var url = '?'; for (var key in data) { if (value == false && !forceValue && key == name) continue; url += key + '=' + data[key]+'&'; } window.history.pushState('', document.title, url.substring(0, url.length-1)); } $.fn.extend({ fromJson : function(data){ $.setForm(this,data); return $(this); }, toJson : function(){ return $.getForm(this); }, hasAttr : function(attr){ if(this.length==0) return false; return this.get(0).hasAttribute(attr) }, fitText: function(ratio, options) { var compressor = ratio || 1, settings = $.extend({ 'minFontSize' : Number.NEGATIVE_INFINITY, 'maxFontSize' : Number.POSITIVE_INFINITY }, options); return this.each(function(){ var element = $(this); var resizer = function() { element.css('font-size', Math.max(Math.min(element.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize))); }; resizer(); $(window).on('resize.fittext orientationchange.fittext', resizer); }); }, getForm: function(){ var o = {}; var obj = $(this); for(var key in obj.data()){ if(key!="action" && key != "id") continue; o[key] = obj.attr('data-'+key); } $('input,select,textarea',obj).each(function(i,element){ var element = $(element); var id = element.attr('id'); if(!id) id = element.attr('data-id'); if(!id && element.attr("type")=='radio') id = element.attr('name'); if(!id) return; if(element.attr("type")=='checkbox'){ o[id] = (element.is(':checked')?1:0); }else if(element.attr("type")=='radio' && element.is(':checked')){ o[id] = element.val(); } else if(element.attr("type")=='file'){ if(!element[0].files.length) return; if(element[0].files.length == 1){ o[id] = element[0].files[0]; } else { //Attention, le passage de multiples fichiers //entraine une modification de la structure du //tableau $_FILES dans le php (voir fonction normalize_php_files()) o[id] = {}; for(var i=0; i'); div.append(form); var input = form.find('input[type="file"]'); var zone = $('
' + o.label + '
'); div.append(zone); //test if dnd is enabled n browser var div = document.createElement('div'); var dragAndDropEnabled = (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && 'FormData' in window && 'FileReader' in window; //set elements styles input.attr('style', "width: 0.1px;height: 0.1px;opacity: 0;overflow: hidden; position: absolute;z-index: -1"); //set events zone.on('click', function (e) { form.find('input[type="file"]').trigger('click'); e.preventDefault(); e.stopPropagation(); }) .on('drag dragstart dragend dragover dragenter dragleave drop', function (e) { e.preventDefault(); e.stopPropagation(); }) .on('dragover dragenter', function () { if (o.hover) form.addClass(o.hover); }) .on('dragleave dragend drop', function () { if (o.hover) form.removeClass(o.hover); }) .on('drop', function (e) { droppedFiles = e.originalEvent.dataTransfer.files; form.trigger('submit'); }); input.on('change', function (e) { form.trigger('submit'); }); form.on('submit', function (e) { e.preventDefault(); if (o.start){ var result = o.start(); if(result == -1) return; } if (dragAndDropEnabled) { var ajaxData = new FormData(); if (droppedFiles) { $.each(droppedFiles, function (i, file) { var ext = file.name.split('.'); ext = ext.pop(); if(o.allowed && $.inArray(ext.toLowerCase(),o.allowed.split(','))===-1){ $.message('error','Extension fichier '+ext+' non permise (autorisé:'+o.allowed+')',0); isProcessing = false; return; } if(o.size && file.size > o.size){ $.message('error','Taille fichier '+file.size+' octets trop grande (autorisé:'+o.size+' octets)',0); isProcessing = false; return; } ajaxData.append(input.attr('name'), file); }); }else{ ajaxData = new FormData(form.get(0)); for(var key in $('input',form).get(0).files){ var file = $('input',form).get(0).files[key]; if(file.name==null || typeof file !='object') continue; var ext = file.name.split('.'); ext = ext.pop(); if(o.allowed && $.inArray(ext.toLowerCase(),o.allowed.split(','))===-1){ $.message('error','Extension fichier '+ext+' non permise (autorisé:'+o.allowed+')',0); $('input',form).val(); isProcessing = false; return; } if(o.size && file.size > o.size){ $.message('error','Taille fichier '+file.size+' octets trop grande (autorisé:'+o.size+' octets)',0); $('input',form).val(); isProcessing = false; return; } } } if (o.addData){ var addionnalData = o.addData(); for(var k in addionnalData) ajaxData.append(k, addionnalData[k]); } droppedFiles = null; $.ajax({ url: form.attr('action'), type: form.attr('method'), data: ajaxData, dataType: 'json', cache: false, contentType: false, processData: false, complete: function (data) { if (o.complete) o.complete(data.responseJSON); }, success: function (data) { if (o.success) o.success(data); }, error: function (data) { if (o.error) o.error(data); } }); } else { var iframeName = 'uploadiframe' + new Date().getTime(); iframe = $(''); $('body').append(iframe); form.attr('target', iframeName); iframe.one('load', function () { var data = JSON.parse(iframe.contents().find('body').text()); if (!data.success) alert(data.error); form.removeAttr('target'); iframe.remove(); if (o.complete) o.complete(); }); } }); } }); }, shiftCheckboxes: function() { var instance = this; this.on('click', function(e) { var checkbox = $(e.target); if(e.shiftKey && instance.last) { var from = instance.index(instance.last); var to = instance.index(checkbox); instance.slice(Math.min(from, to), Math.max(from, to) + 1) .filter(':not(:disabled)') .prop('checked', checkbox.prop('checked')) .trigger('change'); } instance.last = checkbox; }); }, clear: function(){ return this.each(function() { var obj = $(this); obj.find('input,textarea').not(':input[type=checkbox], :input[type=radio]').val('') obj.find('input').prop('checked',false).prop('selected',false); obj.find('select').prop('selectedIndex',0); obj.find('*[contenteditable="true"]').text(''); }); }, //Rends le formulaire et ses inputs en lecture seule uniquement ou pas en fonction du booleen donné readonly: function(enableReadOnly){ return this.each(function() { var obj = $(this); if(enableReadOnly){ obj.find('input,textarea,select').attr('readonly','readonly'); obj.find('textarea[data-type="wysiwyg"]').trumbowyg('disable'); obj.find('input[data-type],select[data-type],textarea[data-type]').each(function(){ var input = $(this); var component = input.data("data-component"); if(input.attr('data-type') == 'wysiwyg'){ component = input.data('trumbowyg').$box; input.data('trumbowyg').$ed.attr('contenteditable',false); } if(component) component.attr('readonly','readonly'); }); }else{ obj.find('input,textarea,select').removeAttr('readonly'); obj.find('textarea[data-type="wysiwyg"]').trumbowyg('enable'); obj.find('input[data-type],select[data-type],textarea[data-type]').each(function(){ var input = $(this); var component = input.data("data-component"); if(input.attr('data-type') == 'wysiwyg'){ component = input.data('trumbowyg').$box; input.data('trumbowyg').$ed.attr('contenteditable',true); } if(component) component.removeAttr('readonly'); }); } }); }, //@TODO: // - Voir pour fusionner avec $.fill // - Voir pour respecter la sémantique (addLine supprime les anciennes lignes...) addLine: function (rows){ return this.each(function() { var obj = $(this); var model = null; var container = null; if(obj.prop("tagName") == 'UL'){ container = obj; model = container.find('li:first-child'); container.find('li:visible').remove(); }else if(obj.prop("tagName") == 'TABLE'){ container = obj.find('tbody'); model = container.find('tr:first-child'); container.find('tr:visible').remove(); }else{ container = obj; childName = container.children().get(0).nodeName; model = container.find(childName+':first-child'); container.find(childName+':visible:not(.nofill)').remove(); } var tpl = model.get(0).outerHTML; //fix jquery backslahes break tpl = tpl.replace(/{{##/g,'{{/').replace(/{{\/(.*)}}=""/g,'{{/$1}}'); //fix images url not found on template tpl = tpl.replace(/(]*\s)(data-src)/g,'$1src'); for(var key in rows){ var line = $(Mustache.render(tpl,rows[key])); container.append(line); line.removeClass('hidden'); } }); }, //Retourne un node jquery visible à partir d'un //modèle de template invisible + données mustache template: function(data){ return $(Mustache.render($(this).get(0).outerHTML,data)).removeClass('hidden'); }, //Permet le resize d'un panel vertical panelResize : function(options){ var obj = $(this); var o = $.extend({ handlerClass : 'panel-resize-handler', hoverClass : 'panel-resize-handler-hover', handlerWidth : 10, direction : 'right', minWidth : 30, maxWidth : 700, update : function(data){} }, options); var handlerId = 'handler-'+generate_uuid(10); var handler = $('
'); var timeout = null; var left; if(o.direction == 'right'){ left = obj.offset().left + obj.outerWidth() - (o.handlerWidth/2); }else if (o.direction == 'left'){ left = obj.offset().left - (o.handlerWidth/2); } handler.css({ left : left, top : obj.offset().top }); handler.hover(function(){ clearTimeout(timeout); handler.addClass(o.hoverClass); },function(){ timeout = setTimeout(function(){ handler.removeClass(o.hoverClass); },300); }); if(!window.handlerActive) window.handlerActive = {}; if(!window.handlerPosition) window.handlerPosition = {}; handler.mousedown(function(){ window.handlerPosition[handlerId] = handler.offset().left; window.handlerPanelWidth = obj.outerWidth(); window.handlerActive[handlerId] = true; }); $(document).mouseup(function(){ window.handlerActive[handlerId] = false; var left; if(o.direction == 'right'){ left = obj.offset().left + obj.outerWidth() - (o.handlerWidth/2); }else if (o.direction == 'left'){ left = obj.offset().left-(o.handlerWidth/2); } handler.css({left : left}); o.update({ element : obj, handler : handler, width : obj.outerWidth() }); }); $(document).mousemove(function( event ) { if(!window.handlerActive[handlerId]) return; var newPosition = (event.pageX-2); var negativeWidth = window.handlerPosition[handlerId] - newPosition; var newWidth = window.handlerPanelWidth- (negativeWidth * (o.direction== 'right'?1:-1) ); if(newWidth < o.minWidth || newWidth <1 || newWidth > o.maxWidth ){ return; } handler.css({ left : newPosition+'px' }); obj.css({ width : newWidth+'px', maxWidth : newWidth+'px' }); }); obj.append(handler); return handlerId; }, fill: function (option,callback,progress){ return this.each(function() { var obj = $(this); var model = null; var container = null; option = $.extend({ differential : false, showing : function(item,key,data){ //permet la personnalisation de l'apparition des lignes (removeClass('hidden') par defaut) item.removeClass('hidden'); } },option); var preloader = null; if(option.preloader){ var preloader = $(option.preloader); preloader.css('position','absolute'); preloader.css('left',(obj.offset().left+obj.width()/2)+'px'); preloader.css('top',(obj.offset().top+30)+'px'); $('body').append(preloader); } var paginationPreferenceUid = ($.urlParam('module')?$.urlParam('module'):'main')+'-'+($.urlParam('page')?$.urlParam('page') :'main')+'-'+obj.attr('id'); var paginationPreference = $.storage('pagination'); if(paginationPreference[paginationPreferenceUid]){ //si une valeur est présente dans le localstorage on la prend option.itemPerPage = paginationPreference[paginationPreferenceUid]; }else{ //si pas de valeur en local storage mais une valeur par defaut, on la prend var paginationPreference = $('[data-type="pagination-preference"][data-table="#'+obj.attr('id')+'"]'); if(paginationPreference.length >0) option.itemPerPage = paginationPreference.attr('data-value'); } //Permet l'affichage d'un élément HTML si aucun résultat ne ressort if(option.empty) $(option.empty+':not(.hidden)').remove(); if(obj.prop("tagName") == 'UL'){ container = obj; model = container.find('li:first-child'); if(!option.export && !option.differential) container.children('li:not(.hidden)').remove(); } else if(obj.prop("tagName") == 'TABLE'){ container = $('>tbody',obj); model = container.find('tr:first-child'); if(!option.export && !option.differential) container.children('tr:not(.hidden)').remove(); /** début colonnes dynamiques **/ var slug = obj.attr('data-slug'); if(slug){ //Refresh du dropdown de colonnes var dynamic_table_refresh_menu = function(table){ var picker = $('.dynamic-table-picker .dropdown-menu',table); picker.html(''); var columns = dynamic_table_columns(table,true); for(var i in columns.deleted){ var th = columns.deleted[i]; if(!th.hasClass('hidden')) continue; picker.append(''); }; if(!picker.html().length) picker.append(''); }; //Enregistrement de l'affichage des colonnes var dynamic_table_save = function(table,callback){ var columns = dynamic_table_columns(table); if($('#loginHeader').attr('data-connected') == ''){ var localColumns = $.storage('component.tablesearch.columns'); localColumns[table.attr('data-slug')] = columns.added; $.storage('component.tablesearch.columns',localColumns); if(callback) callback(); }else{ $.action({ action : 'core_table_colum_save', slug : table.attr('data-slug'), added : columns.added },function(){ if(callback) callback(); }); } } //Récupération de l'état des colonnes affichées/masquées var dynamic_table_columns = function(table,getElement){ table = $(table); var columns = {added:[],deleted:[]}; $('th[data-available]',table).each(function(){ var th = $(this); var thSlug = th.attr('data-available'); if(th.hasClass('hidden')) { columns.deleted.push(!getElement ? thSlug : th); }else{ columns.added.push(!getElement ? thSlug : th); } }); return columns; } option.columns = dynamic_table_columns(obj); var plusButton = $('.dynamic-table-picker',obj); if(!plusButton.length){ plusButton = $(''); $('thead tr:eq(0) th:last-child',obj).append(plusButton); $('thead tr:eq(0) th[data-available]',obj).append(''); //Gestion events $('.dynamic-table-delete',obj).click(function(){ element = $(this).closest('th'); var th = $('>thead th[data-available="'+element.attr('data-available')+'"]',obj); th.addClass('hidden'); $('> tbody > tr',obj).each(function(){ $('> td:eq('+th.index()+')',this).addClass('hidden'); }); dynamic_table_refresh_menu(obj); dynamic_table_save(obj); }); $(plusButton).off('click').on('click','.dropdown-item[data-slug]',function(){ element = $(this); var th = $('thead th[data-available="'+element.attr('data-slug')+'"]',obj); th.removeClass('hidden'); $('tbody tr',obj).each(function(){ $('td:eq('+th.index()+')',this).removeClass('hidden'); }); dynamic_table_refresh_menu(obj); dynamic_table_save(obj,function(){ if(obj.attr('data-column-search')) window[obj.attr('data-column-search')](); }); }); } var addDynamicColumns = function(added){ $('th[data-available]',obj).each(function(){ var th = $(this); var td = $('tbody tr td:eq('+th.index()+')',obj); if(added.indexOf(th.attr('data-available')) !== -1) { th.removeClass('hidden'); td.removeClass('hidden'); return; } th.addClass('hidden'); td.addClass('hidden'); }); dynamic_table_refresh_menu(obj); } if($('#loginHeader').attr('data-connected') == ''){ var localColumns = $.storage('component.tablesearch.columns'); var added = localColumns[slug] ? localColumns[slug] : []; addDynamicColumns(added); }else{ $.action({ action : 'core_table_colum_search', async : false, },function(preferences){ plusButton.addClass('btn-preloader'); var added = preferences[slug] ? preferences[slug] : []; addDynamicColumns(added); }); } } /** fin colonnes dynamiques **/ } else if(obj.prop("tagName") == "SELECT"){ container = obj; model = container.find('option[value*="{{"]'); if(model.length==0) model = $(''); if(!option.export && !option.differential) container.find('option:not([value*="{{"])').remove(); } else{ container = obj; childName = container.children().get(0).nodeName; model = container.find(childName+':first-child'); if(!option.export && !option.differential) container.find(childName+':visible:not(.nofill)').remove(); } var tpl = model.get(0).outerHTML; //fix jquery backslashes break tpl = tpl.replace(/{{##/g,'{{/').replace(/{{\/(.*)}}=""/g,'{{/$1}}'); //fix images url not found on template tpl = tpl.replace(/(]*\s?)(data-src)/g,'$1src'); var pagination = obj.attr('data-pagination')!=null && $(obj.attr('data-pagination')).length ? $(obj.attr('data-pagination')) : (obj.nextAll('.pagination').length ? obj.nextAll('.pagination') : obj.parent().nextAll('.pagination') ); if(pagination.length!=0) { var activePage = $('li.active', pagination); if($.urlParam('p')==null || $.urlParam('p') <= 0 || activePage.length > 0) option.page = activePage.attr('data-value'); else option.page = parseInt($.urlParam('p') - 1); } tpl = tpl.replace(/(data-style)/g, 'style'); if(option.export) option.downloadResponse = true; //on clone l'objet option pour ne transmettre que des datas utiles data = $.extend({},option); delete data.showing; delete data.templating; $.action(data,function(r){ //On ne gere la pagination et l'affichage tableau que si on est pas en mode export if(!option.export){ if(option.differential){ //suppression des élements dom qui ne sont plus en db $('>[data-id]:visible',container).each(function(i,line){ var line = $(line); toDelete = true; for(var key in r.rows){ if(line.attr('data-id') == r.rows[key].id){ toDelete = false; break; } } if(toDelete) line.remove(); }); } //var activeIds = []; for(var key in r.rows){ var line; var data = r.rows[key]; var lineTpl = tpl; if(option.templating) lineTpl = option.templating(data,line,tpl); if(!option.differential){ line = $(Mustache.render(lineTpl,data)); container.append(line); option.showing(line,key,data); }else{ //activeIds.push(data.id); var existing = $('> [data-id="'+data.id+'"]',container); //existe en data et pas dans le dom : ajout if(existing.length == 0){ line = $(Mustache.render(lineTpl,data)); line.attr('data-update-tag',data.updated); if(key==0){ container.append(line); }else{ var previousIndex = key-1; var previous = $('>[data-id]:visible',container).eq(previousIndex); previous.after(line); } option.showing(line,key,data); }else{ //existe en data et dans le dom et pas de modification : on passe au suivant if(existing.attr('data-update-tag') == data.updated){ continue; //existe en data et dans le dom mais a été modifié : on remplace }else{ line = $(Mustache.render(lineTpl,data)); line.attr('data-update-tag',data.updated); existing.after(line); existing.remove(); option.showing(line,key,data); } } } } if(!r.rows || !r.rows.length && option.empty) obj.after($(option.empty).removeClass('hidden')); if(option.differential){ var existingDom = []; for(var key in r.rows){ var data = r.rows[key]; var line = $('>[data-id="'+r.rows[key].id+'"]',container); var index = line.index() -1; if(key != index){ var prevIndex = (key-1); if(prevIndex<0){ container.prepend(line.detach()); }else{ var prevElement = $('>[data-id]:visible()',container).eq(prevIndex); prevElement.after(line.detach()); } } } } if(r.pagination){ $('.page-item-previous,.page-item-next').remove(); r.pagination.pages = Math.ceil(r.pagination.pages); var previewNumber = pagination.attr('data-range') != null && pagination.attr('data-range').length ? parseInt(pagination.attr('data-range')) : 5; previewNumber = previewNumber < 2 ? 2 : previewNumber; //Possible values: simple, numbers, full var controls = pagination.attr('data-control') != null && pagination.attr('data-control').length ? pagination.attr('data-control') : "full"; var template = pagination.find('li:not(:visible)'); if(template.length>0 ){ template = template.get(0).outerHTML; $('li:not(:eq(0))',pagination).remove(); var current = parseInt(r.pagination.current); var previousPages = current-previewNumber; var nextPages = current+previewNumber; var dropDownTpl = '
'; for(i=0;i'); pagination.prepend(prev); prev.click(function(e){ if ($(e.target).closest('span.page-link').hasClass('disabled')) return; pagination.find('li[data-value="'+(current-1)+'"]').trigger('click'); }); } if(current'); pagination.append(next); next.click(function(e){ if ($(e.target).closest('span.page-link').hasClass('disabled')) return; pagination.find('li[data-value="'+(current+1)+'"]').trigger('click'); }); } //Affiche uniquement les flèches précédent / suivant de contrôle de la pagination if(controls == "simple") pagination.find('li[data-value]:not(.hidden)').addClass('hidden'); //Affiche uniquement les n° de page de contrôle de la pagination if(controls == "numbers") pagination.find('li:not([data-value]):not(.hidden)').addClass('hidden'); var visiblePageCount = pagination.find('.page-item:not(.hidden)').length; if(visiblePageCount>1){ pagination.find('.page-item:not(.hidden):first .page-link').css('border-radius','0.25rem 0 0 0.25rem'); pagination.find('.page-item:not(.hidden):last .page-link').css('border-radius','0 0.25rem 0.25rem 0'); }else{ pagination.find('.page-item:not(.hidden):first .page-link').css('border-radius','0.25rem 0.25rem 0.25rem 0.25rem'); } $('.pagination-select span',pagination).click(function(){ var selectedPage = (parseInt($(this).text())-1); pagination.find('li[data-value="'+selectedPage+'"]').trigger('click'); }); } } } if(preloader) preloader.remove(); if(callback!=null)callback(r); },null,function(percent,type){ if(progress) progress(percent,type); }); }); }, enter: function (option){ return this.each(function() { var obj = $(this); obj.keydown(function(event){ if(event.keyCode == 13){ option(); return false; } }); }); }, sortable_table: function (option){ if(option=='get'){ var obj = $(this); var response = {}; obj.find('thead th[data-sortable]').each(function(i,th){ var th = $(th); if(th.attr('data-sort') && th.attr('data-sort')!=""){ response = { sort : th.attr('data-sort'), sortable : th.attr('data-sortable') }; } }); return response; } return this.each(function() { var obj = $(this); obj.find('thead th[data-sortable]').click(function(e){ if($(e.target).hasClass('dynamic-table-delete')) return; var th = $(this); var data = th.data(); if(!data.sort || data.sort==''){ data.sort = 'asc' }else if(data.sort == 'asc'){ data.sort ='desc' }else{ data.sort = ''; } obj.find('thead th').removeClass('sort-asc').removeClass('sort-desc').removeAttr('data-sort'); if(data.sort!='') th.addClass('sort-'+data.sort); th.attr('data-sort',data.sort); if(option.onSort) option.onSort(); }); }); }, autocomplete: function(o){ return this.each(function() { var obj = $(this); if(o == 'off') return obj.typeahead('destroy'); obj.attr('autocomplete','new-password'); var option = obj.data(); option = $.extend(option,o); if(!option.delay) option.delay = 1; var timeout = null; obj.typeahead({ items: (o.items) ? o.items : 5, minLength: o.suggest ? 0 : (o.minLength ? o.minLength : 2) , fitToElement: false, autoSelect : false, selectOnBlur : false, displayText : function(item){ return (o.skin) ? o.skin(item,obj) : item.name || item; }, source: function(keyword, response){ if (timeout) clearTimeout(timeout) ; timeout = setTimeout(function() { if(o.onKeypress) o.onKeypress(obj); if(o.dynamicData) o.data = $.extend(o.data,o.dynamicData()); if(o.data) o.data.limit = (o.items) ? o.items : 5; $.action({ action: option.action, keyword: obj.val(), data: o.data },function(r){ if(r.rows != null) response(r.rows); }); },option.delay); }, highlighter: function(item){ if(o.highlight) { return o.highlight(item) } else { var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&') return item.replace(new RegExp('('+query+')', 'ig'), function($1, match){ return ''+match+''; }); } }, matcher: function(r){ if(obj.val() == r.name && o.selectEqual!==false) if(o.onClick) o.onClick(r,obj); return '
'+r.name+'
'; }, afterSelect: function(item) { obj.data('selected',true); if(o.onClick) o.onClick(item,obj); obj.trigger("change"); } }).blur(function(){ if(o.onBlur) o.onBlur(obj); }); if(o.suggest){ obj.off("click").on("click", function () { if(typeof o.suggest === 'function' && !o.suggest()) return; ev = $.Event("keydown"); ev.keyCode = ev.which = 40; $(this).trigger(ev); return true }); } obj.data('typeahead').next = function (event) { var active = this.$menu.find('.active').removeClass('active'); var next = active.next(); if (!next.length) { next = $(this.$menu.find($(this.options.item || this.theme.item).prop('tagName'))[0]); } while (next.hasClass('divider') || next.hasClass('dropdown-header')) { next = next.next(); } next.addClass('active'); var newVal = this.updater(next.data('value')); this.$element.val(newVal.name || newVal.label || newVal); }; obj.data('typeahead').prev = function (event) { var active = this.$menu.find('.active').removeClass('active'); var prev = active.prev(); if (!prev.length){ prev = this.$menu.find($(this.options.item || this.theme.item).prop('tagName')).last(); } while (prev.hasClass('divider') || prev.hasClass('dropdown-header')) { prev = prev.prev(); } prev.addClass('active'); var newVal = this.updater(prev.data('value')); if (this.changeInputOnMove) this.$element.val(newVal.name || newVal.label || newVal); }; }); }, location: function (options){ return this.each(function() { var obj = $(this); var o = $.extend({},options); obj.off('keyup').on('keyup', function(event) { if(!$(this).val().length) return; }); obj.autocomplete({ action: 'core_location_search', delay : 300, force: (o.force ? o.force : false), items: (o.items ? o.items : 8), data: { maxresults: (o.items ? o.items : 8), language: (o.language ? o.language : "fr"), country: (o.country ? o.country : ""), }, skin : function(item){ var html = ''; var re = new RegExp(obj.val(),"gi"); name = item.label.replace(re, function (x) { return ''+x+''; }); html += name+''; return html; }, highlight : function(item){ return item; }, onClick : function(selected,element){ obj.val(selected.label); if(!is_empty_obj(selected.address)) { var infos = { number: selected.address.houseNumber ? selected.address.houseNumber : '', street: selected.address.street ? selected.address.street : '', district: selected.address.district ? selected.address.district : '', city: selected.address.city ? selected.address.city : '', county: selected.address.county ? selected.address.county : '', state: selected.address.state ? selected.address.state : '', country: selected.address.country ? selected.address.country : '', zip: selected.address.postalCode ? selected.address.postalCode : '', }; infos.address = (infos.street && infos.street.length && infos.number && infos.number.length) ? infos.number+' '+infos.street : (infos.street ? infos.street : ''); obj.removeData(); obj.data(infos); if(o.select) o.select(infos); if(o.geocode) o.geocode(selected); } }, onBlur : function(selected,element){ }, onCancel : function(element){ obj.val(''); } }); }); }, colorInput: function (options) { return this.each(function () { var o = $.extend({ choices : [ '#34495e','#9b59b6','#3498db','#2ecc71','#1abc9c', '#95a5a6','#ecf0f1','#e74c3c','#e67e22','#f1c40f', '#d35400','#55E6C1','#EAB543','#F8EFBA','#FD7272', '#3B3B98','#B33771','#6c5ce7','#0984e3','#00cec9', '#fd79a8','#d63031','#a29bfe','#55efc4' ] },options); var input = $(this); input.hide(); var component = input.data('data-component'); if(component){ //reload }else{ var component = $('
'); //load input.data('data-component',component); input.after(component); component.append(input.detach()); init_tooltips(component); } var picker = $('.component-color-picker',component); var palette = $('.component-color-palette',component); var thumb = $('.component-color-thumb',component); thumb.css('backgroundColor',input.val()); var html = '
    '; for(var k in o.choices){ html += '
  • '; } html += '
  • '; html += '
'; picker.html(html); $('.other-color',component).click( function(){ palette.click(); }); palette.change(function(){ input.val(palette.val()).change(); picker.addClass('hidden'); }); input.change(function(){ thumb.css('backgroundColor',input.val()); }); component.click(function(e){ e.stopPropagation(); if(input.is('[readonly]') || input.is('[disabled]')) return; if($(e.target).closest('.component-color-picker').length || $(e.target).closest('.component-color-palette').length) return; picker.removeClass('active'); setTimeout(function(){ picker.removeClass('hidden'); setTimeout(function(){picker.addClass('active')},50); },150); }); $('.color-choice',picker).click(function(e){ e.stopPropagation(); picker.removeClass('active'); setTimeout(function(){picker.addClass('hidden')},200); input.val($(this).attr('data-color')).change(); }); $(document).click(function() { picker.removeClass('active'); setTimeout(function(){picker.addClass('hidden')},200); }); if(input.hasAttr('required')) component.attr('required',''); if(input.hasAttr('readonly')) component.attr('readonly',''); }); }, date: function (options){ return this.each(function(){ var obj = $(this); obj.on('paste', function(e){ is_valid_date(e.originalEvent.clipboardData.getData('Text')) ? obj.val("") : e.preventDefault(); }); //Jours ouvrés var minDate = options.beginDate; var beforeShowDay = ''; if(options.workdays){ var minDate = new Date(); var daysToAdd = [0, 0, 2, 2, 2, 2, 1]; minDate.setDate(minDate.getDate()+parseInt(options.beginDate)+daysToAdd[minDate.getDay()]); beforeShowDay = $.datepicker.noWeekends; } obj.datepicker({ dateFormat: options.dateFormat, dayNames: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"], dayNamesMin: ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"], dayNamesShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"], monthNames: ["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"], monthNamesShort: ["Jan","Fév","Mars","Avr","Mai","Juin","Juil","Aout","Sept","Oct","Nov","Déc"], firstDay: 1, minDate: minDate, beforeShowDay: beforeShowDay, maxDate: options.endDate, changeMonth: true, yearRange: "-100:+30", changeYear: true, onSelect: function(dateText, inst){ obj.trigger("blur"); obj.trigger("change"); }, beforeShow: function(){ if(obj.is('[readonly]')) return false; } }).keypress(function(event){ if(event.key=='/') event.preventDefault(); var length = obj.val().length; if(length == 2 || length == 5) obj.val(obj.val()+'/'); }).blur(function(event){ obj.removeClass('border border-danger'); if(obj.val()=='') return; var segments = obj.val().split('/'); if(segments.length!=3) return; if(segments[0] > 31 || segments[1] > 12) obj.addClass('border border-danger'); }).attr('maxlength','10'); obj.attr('placeholder',options.placeholder); obj.attr('pattern',"^(\\d{2}(?:\\d{2})?)\/(\\d{2})\/(\\d{2}(?:\\d{2})?)$"); obj.attr('title','Format '+options.dateFormat); }); }, phone: function (options){ return this.each(function(){ var obj = $(this); options = $.extend({ regex: '^[0-9]{10}$', emptyField: false, spacing: true, typeOnly: '[0-9\+\s]', invalidClass: 'invalid-value', },options); if(options.typeOnly){ obj.keydown(function(event){ if((event.ctrlKey && ['v','a','c','x'].indexOf(event.key) !== -1) || ['Backspace','ArrowLeft','ArrowRight',' '].indexOf(event.key) !== -1) return true; var regexType = RegExp(options.typeOnly, 'g'); return regexType.test(event.key); }); } obj.blur(function(event){ var value = obj.val() .trim() .replace(/\s/ig,'') .replace(/\+33/ig,'0'); if(value=='') return obj.removeClass(options.invalidClass);; var regex = RegExp(options.regex, 'g'); if(!regex.test(value)){ obj.addClass(options.invalidClass); if(options.emptyField) value = ''; } else { if(options.spacing) value = value.match(/.{1,2}/g).join(' '); obj.val(value); obj.removeClass(options.invalidClass); } if(obj.data('blur')) eval(obj.data('blur')); }); }); }, hour: function (options){ return this.each(function() { var obj = $(this); obj.on('paste', function(e){ is_valid_hour(e.originalEvent.clipboardData.getData('Text')) ? obj.val("") : e.preventDefault(); }); obj.timepicker({ scrollDefault: 'now', timeFormat: options.timeFormat, step: options.step, onSelect: function(timeText, inst) { obj.trigger("blur"); obj.trigger("change"); } }).keydown(function(e) { //Si c'est pas un chiffre ou : if(!input_number_control(e)) return false; //Si on efface et qu'on est après les deux points, on les supprime et le chiffre qui précède aussi if(e.key=='Backspace' && obj.val().substr(obj.val().length-1)==':'){ e.preventDefault(); obj.val(obj.val().substring(0, obj.val().length-2)); //Premier digit avant les deux points supérieur à 2, on ajoute un 0 devant } else if((obj.val().length==0 || get_selected_text(obj).length == obj.val().length) && e.key>2) { e.preventDefault(); obj.val('0'+e.key+':'); //Gestion des deux points entre heures et minutes } else if(obj.val().length==1 && e.key.match(/[0-9:]/)) { e.preventDefault(); obj.val(obj.val()+e.key+':'); //Si le 1er digit après les deux points est supérieur à 5, on bloque } else if(obj.val().length==3 && e.key>5 && get_selected_text(obj).length<2) { e.preventDefault(); } }).blur(function(event){ obj.removeClass('border border-danger') if(obj.val()=='') return; var segments = obj.val().split(':'); if(!segments[1]){ obj.val(obj.val()+'00'); segments[1] = '00'; } if(segments.length!=2)return; if(segments[0] > 23 || segments[1] > 59) obj.addClass('border border-danger'); }).attr('maxlength','5'); obj.attr("placeholder",options.placeholder); obj.attr('title',"Format hh:mm"); }); }, raiseNumber: function(from,to,time) { return this.each(function(){ var obj = $(this); obj.text(from); time = time!=null ? time : 100; var ratio = (from<=to) ? to/time : from/time; var increment = Math.round(ratio)<1 ? 1 : Math.round(ratio); increment = (from<=to) ? increment : increment*-1; var updateCount = function(obj, increment){ var count = parseInt(obj.text()); if((from<=to && countto && count>=to)) { obj.text(count + increment); setTimeout(function(){updateCount(obj,increment);}, 1); } else { obj.text(to); } }; updateCount(obj,increment); }); }, component_autocomplete : function(slug,options){ if(!slug) $.message('error','Slug non définis pour un composant autocomplete'); var options = $.extend({ edit : slug+'_by_uid', autocomplete : slug+'_autocomplete', force : true, nullChars : ['0'], data : function(){ return {}; }, editData : function(){ return {}; } },options); return this.each(function(){ var input = $(this); var container; if(!input.data("data-component")){ container = $(''); input.before(container); input.addClass('component-raw-value hidden'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant input.data("data-component", container); if(input.attr("required")) container.attr("required",""); if(input.attr("disabled")) container.attr("disabled",""); if(input.attr("readonly")) container.attr("readonly",""); } else { container = input.data("data-component"); } if(!options.skin){ options.skin = function(item){ var html = ''; var re = new RegExp(container.val(),"gi"); name = item.label.replace(re, function (x) { return ''+x+''; }); html += '
'+name+''; html += '
'; return html; } } if(!options.onClick){ options.onClick = function(selected,element){ input.val(selected.id); container.val(selected.label); input.trigger('click').trigger('change'); } } if(!options.onLoad){ options.onLoad = function(component,item){ component.container.val(item.label); } } //Gestion des champs déja remplis au chargement de la page if(input.val() !='' && options.nullChars.indexOf(input.val())==-1){ var uid = input.val(); if(!window.componentQueue[slug]) window.componentQueue[slug] = {timeout : null,components : [],uids :{} }; clearTimeout(window.componentQueue[slug].timeout); var uids = uid.split(','); for(var k in uids) window.componentQueue[slug].uids[uids[k]] = 1; window.componentQueue[slug].components.push({ input : input, container : container, values : uids }); container.val('Chargement...'); window.componentQueue[slug].timeout = setTimeout(function(){ $.action({ action : options.edit, data : options.editData(slug), items : Object.keys(window.componentQueue[slug].uids) },function(r){ if(window.componentQueue[slug]){ for(var key in window.componentQueue[slug].components){ var component = window.componentQueue[slug].components[key]; input = window.componentQueue[slug].components[key].input; for(var i in component.values){ var value = component.values[i]; if(!r.items[value]) continue; options.onLoad(component,r.items[value]); //component.container.val(r.items[value].label); } } delete window.componentQueue[slug]; } }); },50); } container.keyup(function(e){ if (e.ctrlKey || e.key == "Control" || e.key == "ArrowUp" || e.key == "ArrowDown" || e.key == "ArrowLeft" || e.key == "ArrowRight" || e.key == "Shift" || e.key == "CapsLock" || e.key == "Tab" || e.key == "Alt" || e.key == "Home" || e.key == "End") return; input.val(''); }); //autocompletion container.autocomplete({ action : options.autocomplete, suggest : function(){ return !input.is('[readonly]') && !input.is('[disabled]')}, dynamicData : options.data, skin : options.skin, highlight : function(item){ return item; }, onClick : function(selected,element){ container.val(selected.label); options.onClick(selected,element); }, onBlur : function(selected){ if((input.attr('data-force')!='false' || options.force) && input.val() == ''){ container.val(''); input.trigger('click').trigger('change'); } input.trigger('blur'); } }); }); }, //Chargement des images en dynamique au scroll //Par défaut check sur scroll de window sinon sur celui du parent indiqué lazyLoad : function(parent, callback) { var obj = this; var parent = parent!=null ? $(parent) : $(window); this.lazyload = function(elem, parent, callback){ var viewportHeight = parent.height(); if(!elem.filter(':not([data-lazy=""])').length) return; elem.filter(':not([data-lazy=""])').each(function() { var element = $(this); var elemOffsetTop = element.offset().top; //Si parent est $(window) on récupère la valeur du scrollTop, sinon on prend la valeur du offsetTop du parent var viewportOffset = viewportHeight + ((parent.get(0)===parent.get(0).window) ? parent.scrollTop() : parent.offset().top); //Check si l'image se situe (en px) à 1/3 de sa taille ou moins du bas du viewport du parent pour le requêter if(elemOffsetTop - element.height()/3 < viewportOffset && element.attr('data-lazy')){ var srcImg = element.attr('data-lazy'); element.removeAttr('data-lazy'); //Check pour ajouter attribut src (tag IMG) ou mettre en background-image (tag autre) element.is('img') ? element.attr({src: srcImg}) : element.css({"background-image": 'url('+srcImg+')'}); if(callback!=null) { elementEvent = !element.is('img') ? $('').attr('src', srcImg) : element; elementEvent.one("load", function() { if(!element.is('img')) $(this).remove(); callback(element); }).each(function() { if(this.complete) $(this).trigger('load'); }); } } }); } //Initialisation this.lazyload(obj,parent,callback); //Appel qd parent scroll parent.off('scroll').on('scroll', function(){ if(window.scrollTimer) clearTimeout(window.scrollTimer); //Ajout timeout pour éviter de trigger à //chaque scroll, on attend que le user stabilise window.scrollTimer = setTimeout(function(){ obj.lazyload(obj,parent,callback); }, 25); }); //Appel sur resize $(window).resize(function(){ if(window.scrollTimer) clearTimeout(window.scrollTimer); window.scrollTimer = setTimeout(function(){ obj.lazyload(obj,parent,callback); }, 25); }); } });