1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223 |
- /* COMPOSANT */
- function init_components(selector){
- //Suppression apr defaut des légendes pour les graphiques
- if(window.Chart) Chart.defaults.global.legend.display = false;
- var selected = selector ? $('[data-type]',selector) : '[data-type]';
- $(selected).each(function(i,input){
- var input = $(input);
- switch($(input).attr('data-type')){
- /**
- * data-format : Supporte les formats dd/mm/yyyy ou yyyy/mm/dd avec séparateur "/" ou "-"
- * data-begin : date de début de sélection par rapport à aujourd'hui(peut être en nb de jour, en objet Date ou en string de type dateFormat ou en date relative [+1m +7d]==>Début à 1 mois et 7 jours)
- * data-end : date de début de sélection par rapport à aujourd'hui(peut être en nb de jour, en objet Date ou en string de type dateFormat ou en date relative [+1m +7d]==>Début à 1 mois et 7 jours)
- * data-workdays : si attribut est présent, seuls les jours ouvrés sont sélectionnables
- */
- case 'date':
- //Les séparateurs doivent être similaires entre les éléments de la chaîne
- var dateFormatRegex = /^(dd|yy)([\/|-])(mm)\2(dd|yy)$/;
- var dateFormat = input.attr('data-format') != undefined && input.attr('data-format').match(dateFormatRegex) ? input.attr('data-format').match(dateFormatRegex)[0] : "dd/mm/yy";
- var begin = input.attr('data-begin');
- begin = (begin != undefined && (begin.match(/-?\d+/) || begin.match(/^(\d{2}(?:\d{2})?)\/(\d{2})\/(\d{2}(?:\d{2})?)$/))) ? begin : null ;
- var end = input.attr('data-end');
- end = (end != undefined && (end.match(/-?\d+/) || end.match(/^(\d{2}(?:\d{2})?)[-|\/](\d{2})[-|\/](\d{2}(?:\d{2})?)$/))) ? end : null ;
- input.removeClass('hasDatepicker');
- input.date({
- placeholder: input.attr('placeholder') != undefined ? input.attr('placeholder') : "jj/mm/aaaa",
- dateFormat: dateFormat,
- beginDate: begin,
- endDate: end,
- workdays: input.attr('data-workdays') != null
- }).click(function(event) {
- $(this).select();
- });
- break;
- /**
- * data-format : Supporte les formats dd/mm/yyyy ou yyyy/mm/dd avec séparateur "/" ou "-"
- * data-step : L'intervalle entre 2 valeurs en minutes
- */
- case 'hour':
- var timeFormatRegex = /^(H):(i)$/;
- var timeFormat = input.attr('data-format') != undefined && input.attr('data-format').match(timeFormatRegex) ? input.attr('data-format').match(timeFormatRegex)[0] : "H:i";
- var step = input.attr('data-step');
- input.hour({
- placeholder: input.attr('placeholder') != undefined ? input.attr('placeholder') : "hh:mm",
- timeFormat: timeFormat,
- step: is_numeric(step) && step>0 ? step : 1
- }).click(function(event){
- $(this).select();
- });
- break;
- case 'decimal':
- input.off('keydown').on('keydown',function(e){
- switch(e.key){
- case ',':
- //on interdit la saisie si la chaine contient déja un . ou une ,
- if(input.val().match(/[\.,]/i)) return false;
- //remplace les , par les . pour chiffre valide en db
- input.val(input.val()+'.');
- return false;
- break;
- case '.':
- //on interdit la saisie si la chaine contient déja un . ou une ,
- if(input.val().match(/[\.,]/i)) return false;
- break;
- case 'Backspace':
- case 'ArrowRight':
- case 'ArrowLeft':
- case 'Delete':
- case 'Insert':
- case '-':
- return true
- break;
- default:
- //autorise le coller ctrl+v
- if(e.key == 'v' && e.ctrlKey ) return true;
- //dégage les caractères différents de .,0123456789
- if(!e.key.match(/[\-0-9,\.]/i)) return false;
- break;
- }
- return true;
- });
- //supprime les caracteres pourris sur un coller
- input.off('keyup blur').on('keyup blur',function(e){
- var value = input.val().replace(/[^0-9\-,.]/ig,'');
- //on remplace les "," par les "."
- var value = value.replace(/,/ig,'.');
- //on s'assure qu'il n'existe pas plusieurs "."
- var splits = value.split('.');
- if(splits.length > 1){
- var newValue = '';
- for(var i in splits)
- newValue+= (i!=splits.length-1 ? '' : '.')+splits[i];
- value = newValue;
- }
- //On s'assure que le - est en début ou n'existe pas
- if(value.indexOf('-') !== -1 && value.indexOf('-')!==0 ) value = value.replace('-','');
- input.val(value);
- });
- break;
- case 'color':
- input.colorInput();
- break;
- case 'history':
- var data = input.data();
- if(isNaN(input.attr('data-uid'))) break;
- input.off();
- if(data.showImportant){
- if(!window.componentQueue['history']) window.componentQueue['history'] = {timeout : null,scopes :{} };
- clearTimeout(window.componentQueue['history'].timeout);
- if(!window.componentQueue['history'].scopes[data.scope]) window.componentQueue['history'].scopes[data.scope] = [];
- window.componentQueue['history'].scopes[data.scope].push(data.uid);
- window.componentQueue['history'].timeout = setTimeout(function(){
- $.action({
- action : 'core_history_search',
- scopes : window.componentQueue['history'].scopes,
- showImportant : true
- },function(r){
- var tpl = $('#history-notification-tpl').html();
- for(var k in r.rows){
- var row = r.rows[k];
- var html = Mustache.render(tpl, {number: row.number});
- inputs = $('[data-scope="'+row.scope+'"][data-uid="'+row.uid+'"][data-type="history"][data-show-important="true"]');
- inputs.addClass('position-relative').append(html);
- if(row.number == 0) inputs.find('.history-notification').addClass('hidden');
- init_components(inputs);
- }
- });
- window.componentQueue['history'] = {timeout : null,scopes :{} };
- },50);
- }
- input.click(function(event){
- var data = input.data();
- var panel = $('.history-panel');
- var uid;
- if(panel.hasClass('hidden')) panel.removeClass('hidden');
- panel.toggleClass('fold').one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
- var currentPanel = $(this);
- if(!currentPanel.hasClass('fold')) return;
- currentPanel.addClass('hidden');
- });
- if(panel.hasClass('fold')) return;
- if(input.attr('data-uid')) panel.attr('data-uid',input.attr('data-uid'));
- if(data.scope) panel.attr('data-scope',data.scope);
- core_history_search(function(){
- //Redimensionnement du panel historique
- setTimeout(function(){
- uid = $('.history-panel').panelResize({direction : 'left'});
- }, 100);
- });
- event.stopPropagation();
- //Fermeture du panel au click en dehors du composant
- $(window).click(function(e) {
- var target = $(e.target);
- var panel = target.closest('.history-panel');
- var handler = target.closest('.panel-resize-handler');
- var targetInPanel = panel.length || handler.length;
- //Si un commentaire était en cours d'édition, on le sauvegarde si on a cliqué en dehors du wysiwyg et uniquement s'il n'est pas vide
- if(target.hasClass('history-panel') || target.hasClass('comments') || !targetInPanel){
- $('li.comment:not(.hidden)').each(function(){
- if($(this).find('.history-content .trumbowyg-editor-visible').length && $(this).find('.history-content .trumbowyg-editor').text().length)
- core_history_save(this);
- });
- }
- if(targetInPanel) return;
- $('.history-panel').addClass('fold');
- $('#'+uid).remove();
- });
- });
- break;
- /**
- * data-regex : regex de vérification (defaut : ^[0-9]{10}$, les espaces sont trimés pour vérification)
- * data-spacing : espace automatiquement les chiffre si collés (défaut true)
- * data-empty-field : vide le champs si invalide (défaut false)
- * data-invalid-class : définit la classe a ajouter si invalide (défaut .invalid-value)
- * data-blur : si défini, trigger le blur indiqué après validation du champ (le onblur classique trigger avant)
- * data-type-only : empeche l'utilisateur de taper autre caractere que définis dans cette expression (defaut : [0-9\+\s])
- */
- case 'phone':
- input.phone(input.data());
- break;
- /**
- * data-delete : définit la fonction JS qui sera appelée au clic sur la croix pour supprimer l'image
- * data-save : définit la fonction JS qui sera appelée après le changement de l'image
- * data-default-src : chemin vers l'image par défaut à utiliser
- */
- case 'image':
- console.warn('[DEPRECATED] : Image doit être remplacé par le composant file');
- if(input.hasClass('hidden')) return;
- if(input.closest('.type-image-bloc').length!=0) break;
- input.attr('type', 'file');
- input.wrap( "<div class='type-image-bloc'></div>");
- var save = input.attr('data-save');
- var src = ($(input).attr('value')!='') ? $(input).attr('value') : 'img/default-image-muted.png';
- src += src.indexOf('?')!=-1 ? '&' : '?';
- src += 't='+(Math.random()*1000);
- var thumbnail = $('<img src="'+src+'" >');
- var deleteBtn = !input.attr('data-delete') ? '' : '<div class="btn btn-delete-img noPrint" onclick="'+input.attr('data-delete')+'"><i class="fas fa-times"></i></div>';
- input.before(thumbnail);
- if(thumbnail.attr('src').indexOf('default-') === -1) thumbnail.before(deleteBtn);
- input.addClass('noPrint');
- input.change(function(){
- var reader = new FileReader();
- reader.onload = function (e) {
- thumbnail.attr('src', e.target.result);
- thumbnail.before(deleteBtn);
- }
- reader.readAsDataURL(input.get(0).files[0]);
- if(save) window[save](input);
- });
- break;
- //Sélection de valeurs multiples
- case 'checkbox-list':
- var data = input.data();
- if(!data.depth) data.depth = 1;
- var liClasses = '';
- var isDropDown = data.display == 'dropdown';
- //Si défini à false => bloque le choix multi niveau
- var multiLevelSelect = data.multiLevelSelect;
- var initValues = function(){
- ul.find('li input').prop("checked",false);
- ul.find('li[data-folded="0"]').attr('data-folded','1');
- if(input.val() ){
- var checkeds = input.val().split(',')
- for(var i in checkeds){
- var checkbox = ul.find('li[data-value="'+checkeds[i]+'"] input').eq(0);
- checkbox.prop("checked",true);
- checkbox.closest('ul').parents().attr('data-folded','0');
- }
- refreshLabel();
- }
- }
- var refreshLabel = function(){
- if(!isDropDown) return;
- var checkedLabels = [];
- ul.find('>li input:checked').each(function(){
- checkedLabels.push($(this).closest('li').find('label').eq(0).text());
- });
- var button = container.find('.dropdown-toggle');
- button.html(checkedLabels.length>0 ? checkedLabels.join(',') : data.button);
- $('.checkbox-list-counter',container).text(checkedLabels.length);
- }
- var printChilds = function(childs,level){
- if(!level) level = 1;
- html = '';
- if(level==1){
- html += '<li class="user-select-none border-bottom pb-1 mb-1 checkbox-list-header"><small class="text-muted text-center"><span class="checkbox-list-counter">0</span> Sélection(s) <span class="fa-stack right mt-2 checkbox-list-check-all" title="Tout (dé)cocher"> ';
- html += '<i class="far fa-square fa-stack-2x"></i><i class="fas fa-check-double fa-stack-1x"></i></span></small></li>';
- }
- for(var k in childs){
- var child = childs[k];
- var hasChilds = child.childs && child.childs.length!=0;
- if(!data.multiLevelSelect && level == 1 && hasChilds && (child.childs.length < data.depth)) continue;
- html += '<li class="'+liClasses+' user-select-none" data-folded="1" data-value="'+child.id+'"> ';
- if(level == data.depth){
- html += '<label><input data-type="checkbox" type="checkbox"> '+child.label+'</label>';
- }else{
- if(hasChilds || multiLevelSelect){
- html += '<span class="dropdown-element">'
- html += hasChilds ? '<i class="fas fa-chevron-right fa-fw checkbox-toggle-fold"></i> <label class="label-group">' : '<label>';
- if(level == data.depth || multiLevelSelect) html += '<input data-type="checkbox" type="checkbox"> ';
- html += child.label+'</label>';
- if(hasChilds){
- html += '<span class="fa-stack checkbox-list-check-all hide" title="Tout (dé)cocher"> ';
- html += '<i class="far fa-square fa-stack-2x"></i> ';
- html += '<i class="fas fa-check-double fa-stack-1x"></i></span>';
- }
- html += '</span> ';
- }
- }
- if(hasChilds) html += '<ul>'+printChilds(child.childs,level+1)+'</ul>';
- html += '</li>';
- }
- return html;
- }
- if(!input.data("data-component")){
- container = $('<div class="'+(isDropDown?'dropdown':'')+' '+input.attr('class')+' data-type-checkbox-list"><ul class="'+(isDropDown?'dropdown-menu':'')+'"></ul></div>');
- if(isDropDown){
- data.button = !data.button ? 'Choix': data.button;
- container.append('<div class="dropdown-toggle" type="button" data-toggle="dropdown" >'+data.button+'</div>');
- liClasses += ' dropdown-item ';
- }
- input.before(container);
- input.data("data-component", container);
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- if(input.attr("required")) container.attr("required", "");
- if(input.attr("disabled")) container.attr("disabled", "");
- if(input.attr("readonly")) container.attr("readonly", "");
- var ul = container.find('>ul');
- ul.on('click','>li',function(e){
- e.stopPropagation();
- }).on('click','>li input',function(e){
- e.stopPropagation();
- var checked = [];
- ul.find('>li input:checked').each(function(){
- checked.push($(this).closest('li').attr('data-value'));
- });
- input.val(checked.join(','));
- refreshLabel();
- input.trigger('change');
- });
- }else{
- container = input.data("data-component");
- var ul = container.find('>ul');
- }
- var html = '';
- data.values = input.attr('data-values');
- if(data.values){
- data.values = JSON.parse(input.attr('data-values'));
- for(var k in data.values)
- if(typeof(data.values[k]) === "string") data.values[k] = {id: k, label: data.values[k]};
- html += printChilds(data.values);
- }
- ul.html(html);
- ul.find('[data-type="checkbox"]').removeClass('component-raw-value');
- var initCheckbox = function(ul, callback){
- init_components(ul);
- ul.find('[data-type="checkbox"]').removeClass('component-raw-value');
- ul.find('.checkbox-toggle-fold').click(function(){
- var li = $(this).closest('li');
- li.attr('data-folded',li.attr('data-folded')=='1'?0:1);
- });
- $('.dropdown-element').mouseover(function(){
- $(this).find('.checkbox-list-check-all').eq(0).removeClass('hide');
- });
- $('.dropdown-element').mouseout(function(){
- $(this).find('.checkbox-list-check-all').eq(0).addClass('hide');
- });
- container.find('.checkbox-list-check-all').click(function(event){
- event.stopPropagation();
- var element = $(this);
- var parentContainer = element.parent().parent();
- //cas du checkbox-all racine
- if(parentContainer.hasClass('checkbox-list-header'))
- parentContainer = parentContainer.parent();
- parentContainer.find('input[type="checkbox"]').click();
- var li = element.closest('li');
- li.attr('data-folded',0);
- if(multiLevelSelect) li.find('li').attr('data-folded',0);
- });
- if(callback!=null) callback();
- }
- if(data.slug){
- if(!data.depth) data.depth = 1;
- $.action({
- action: 'core_dictionary_component_load',
- slug: data.slug,
- depth: data.depth,
- multiLevelSelect: data.multiLevelSelect,
- },function(response){
- html = '';
- if(response.content.childs && response.content.childs.length!=0){
- html += printChilds(response.content.childs);
- }else{
- html += '<li class="text-muted text-center"><small><i class="fas fa-exclamation-circle"></i> Liste vide ou introuvable</small></li>';
- }
- ul.append(html);
- initCheckbox(ul, initValues);
- });
- }else{
- initCheckbox(ul, initValues);
- }
- break;
- //Selection de tag
- case 'tag':
- var container;
- var picker;
- var pickerLi;
- if(!input.data("data-component")){
- var placeholder = input.attr("placeholder") != undefined ? input.attr("placeholder") : "";
- container = $('<div class="'+input.attr('class')+' data-type-tag"><ul><li class="tag-picker-li"><input placeholder="'+placeholder+'" type="text"></li></ul></div>');
- input.before(container);
- input.addClass('component-raw-value'); // 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");
- }
- picker = container.find('input:eq(0)');
- pickerLi = container.find('ul li.tag-picker-li');
- if(container.attr('disabled') || container.attr('readonly'))
- pickerLi.find('input').attr('readonly','');
- container.find('.tag-picker-tag').remove();
- pickerLi.removeClass('hidden');
- var methods = {
- //Récuperation des valeurs sélectionnées (objet et id) en fonction des tags visuels présents
- values : function(container){
- var tags = container.find('ul .tag-picker-tag');
- var values = {object:[],id:[]};
- tags.each(function(i,element){
- if($(element).attr('data-value') == '') return;
- var data = $(element).data();
- values['object'].push(data);
- values['id'].push(data.value);
- });
- return values;
- },
- remove : function(tag){
- tag.remove();
- var values = methods.values(container);
- var plainValue = [];
- for(var k in values.object){
- plainValue.push(values.object[k].value);
- }
- input.val(plainValue.length!=0? plainValue.join(',') :'');
- input.data('values',values['object']);
- if((values['id'].length-1) ==1 && input.attr('data-multiple') == null){
- pickerLi.addClass('hidden');
- }else{
- pickerLi.removeClass('hidden');
- }
- //on trigger le change
- input.trigger('change');
- },
- //Ajout d'un tag visuel et mise à jour de l'input brut en fonction de l'objet fournis
- add : function(container,tag){
- pickerLi = container.find('ul li.tag-picker-li');
- if( container.find('li[data-id="'+tag.id+'"]').length>0) return;
- var closeBtn = input.is('[readonly]') || input.is('[disabled]') ? '' : '<i class="fa fa-times btn-remove"></i>';
- var tag = $('<li class="tag-picker-tag" data-value="'+tag.value+'"><div>'+tag.label+closeBtn+'</div></li>');
- pickerLi.before(tag);
- var values = methods.values(container);
- input.val(values['id'].join(','));
- input.data('values',values['object']);
- if((values['id'].length) == 1 && input.attr('data-multiple') == null){
- pickerLi.addClass('hidden');
- }else{
- pickerLi.removeClass('hidden');
- }
- tag.find('.btn-remove').click(function(){
- if(input.is('[readonly]') || input.is('[disabled]')) return;
- methods.remove($(this).closest('.tag-picker-tag'));
- });
- }
- }
- //Gestion des champs déja remplis au chargement de la page
- if(input.val() !=''){
- var id = input.val();
- //picker.addClass('hidden');
- var tags = id.split(',');
- if(input.data('dictionarySlug') && input.data("data-autocomplete-value") != 'label'){
- $.action({
- action : 'core_tag_list_by_id',
- id : id
- },function(response){
- for(var key in response.tags){
- if(response.tags[key] == '') continue;
- methods.add( container,{label:response.tags[key].label,value:response.tags[key].id});
- }
- });
- }else{
- for(var key in tags){
- if(tags[key] == '') continue;
- methods.add( container,{label:tags[key],value:tags[key]});
- }
- }
- }
- picker.off('blur').blur(function(e){
- if(window.tagBlur) clearTimeout(window.tagBlur);
- window.tagBlur = setTimeout(function(){
- var value = picker.val();
- if(value.trim() == '') return;
- methods.add(container,{label:value,value:value});
- picker.val('');
- $('.typeahead.dropdown-menu').hide();
- },500);
- });
- if(!input.data('autocomplete') && input.data('dictionarySlug'))
- input.data('autocomplete','core_tag_list_autocomplete');
- if(input.data('autocomplete')){
- var dictionarySlug = input.data('dictionarySlug');
- $(picker).autocomplete({
- action: input.data('autocomplete'),
- selectEqual : false, //evite le select auto du tag test quand on veux taper test2
- suggest : true,
- dynamicData : function(){
- return dictionarySlug ? { parent : dictionarySlug} : {}
- },
- onClick : function(selected,element){
- if(window.tagBlur) clearTimeout(window.tagBlur);
- methods.add(container,{label:selected.name,value: (input.data("data-autocomplete-value") == 'label' ? selected.name : selected.id) });
- //on vide l'input de saisie
- picker.val('');
- //on trigger le change
- input.trigger('change');
- },
- });
- }
- picker.off('keydown').keydown(function(e){
- var validationChars = ['Enter',' ',',','Tab'];
- if(e.key == 'Backspace' && picker.val() == ''){
- methods.remove($('.tag-picker-tag:last',container));
- return;
- }
- //si appui sur Entrée, virgule ou espace ou tab on valide le tag
- if( validationChars.indexOf(e.key) === -1 || input.is('[readonly]') || input.is('[disabled]') ) return;
- var value = picker.val();
- if(value.trim() == '') return;
- //on cache l'automcomplete si present
- $('.typeahead.dropdown-menu').hide();
- //on ajoute le tag visuel
- methods.add(container,{label:value,value:value});
- //on vide l'input de saisie
- picker.val('');
- //on trigger le change
- input.trigger('change');
- return false;
- });
- break;
- //composant permettant les listes sous
- //form de dropdown avec icones et couleurs
- case 'dropdown-select':
- var container;
- if(!input.data("data-component")){
- container = $('<div class="'+input.attr('class')+' data-type-dropdown-select"> \
- <button '+(input.attr('title')!=null?'title="'+input.attr('title')+'"':'')+' type="button" class="btn btn-small dropdown-toggle-button dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button> \
- <div class="dropdown-menu w-100 p-0 text-center"></div> \
- </div>');
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- input.before(container);
- input.data("data-component", container);
- if(input.attr("required")) container.attr("required","");
- var button = container.find('.dropdown-toggle-button');
- } else {
- container = input.data("data-component");
- var button = container.find('.dropdown-toggle-button');
- }
- container.find('.dropdown-menu').html('');
- var html = '';
- $.each(input.get(0).options, function(i,element){
- var option = $(element);
- var classes = option.attr('class') ? option.attr('class') : '';
- var icon = option.attr("data-icon") ? '<i class="'+option.attr("data-icon")+'"></i> ': '';
- var title = option.attr("data-title") ? 'title="'+option.attr("data-title")+'"': '';
- var backColor = option.get(0).style.getPropertyValue('background-color') ? option.get(0).style.getPropertyValue('background-color') : '#ffffff';
- var fontColor = color_light(backColor) < 50 ? '#ffffff' : '#333333' ;
- html += '<a class="dropdown-item pointer '+classes+'" '+title+' data-value="'+option.val()+'" style="background-color:'+backColor+';color:'+fontColor+'">'+icon+option.html()+'</a>';
- });
- container.find('.dropdown-menu').append(html);
- var changeMenu = function(container,menu){
- $('.dropdown-menu a',container).removeClass('active');
- var item = $('.dropdown-menu a[data-value="'+menu+'"]', container);
- var backColor = item.css('background-color') ? item.css('background-color') : '#ffffff' ;
- var fontColor = color_light(backColor) < 50 ? '#ffffff' : '#333333' ;
- container.find('.dropdown-toggle-button').html(item.html()).css({
- backgroundColor:backColor,
- color:fontColor
- });
- item.addClass('active');
- };
- $('.dropdown-menu a',container).click(function(){
- if(input.attr("readonly") == 'readonly') return;
- var item = $(this);
- changeMenu(container,$(this).attr('data-value'));
- input.val(item.attr('data-value')).trigger('change');
- });
- if(input[0].hasAttribute('data-no-toggle')) button.removeClass('dropdown-toggle');
- var state = input.attr('data-value') != null ? input.attr('data-value') : input.val();
- if(state == '') return;
- var item = $('.dropdown-menu a[data-value="'+state+'"]', container);
- //Utilisation background-color pour fonctionner sous FF
- var backColor = item.get(0) && item.get(0).style.getPropertyValue('background-color') ? item.get(0).style.getPropertyValue('background-color') : '#ffffff' ;
- var fontColor = color_light(backColor) < 50 ? '#ffffff' : '#333333' ;
- button.html(item.html()).css({
- backgroundColor:backColor,
- color:fontColor
- });
- item.addClass('active');
- input.val(item.attr('data-value'));
- input.change(function(){
- changeMenu(container,input.val());
- });
- break;
- case 'firm':
- //autocomplete classique
- input.component_autocomplete('firm',{
- edit : 'core_firm_by_uid',
- autocomplete : 'core_firm_autocomplete'
- });
- break;
- case 'map':
- //on recréé le container a chaque fois car leaflet
- //ne sais pas refresh sans tout recharger (a verifier)
- var container = $('<div></div>');
- container.attr('class',input.attr('class'));
- input.data('container',container);
- input.before(container);
- if(container.height() <1){
- container.css('height',(input.height() <1 ? '300px' : input.height()+'px'));
- container.css('width',(input.width() <1 ? '300px' : input.width()+'px'));
- }
- var data = input.data();
- var json = input.get(0).innerHtml;
- if(!json) json = '[]';
- var points = JSON.parse(json);
- var existingMap = L.DomUtil.get(container.get(0));
- if(existingMap != null)
- existingMap._leaflet_id = null;
- var map = L.map(container.get(0));
- map.invalidateSize();
- //si une latitude/longitude pour la vue global est définie on l'utilise
- if(data.latitude && data.longitude){
- if(!data.zoom) data.zoom = 13;
- map.setView([data.longitude, data.latitude], data.zoom);
- //Sinon on se base sur le groupe de marqueurs proposés pour définie une vue englobante
- }else{
- var pointArray = [];
- if(points.length!=0){
- for(var k in points){
- var point = points[k];
- if(point.longitude && point.latitude)pointArray.push([point.latitude,point.longitude]);
- }
- var markerGroup = new L.LatLngBounds(pointArray);
- map.fitBounds(markerGroup);
- }
- }
- if(data.zoom) map.setZoom(data.zoom);
- L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
- attribution: ''
- }).addTo(map);
- /* var defaultIcon = L.icon({
- iconUrl: 'img/leaflet/marker-icon.png',
- shadowUrl: 'img/leaflet/marker-shadow.png',
- iconSize: [25, 41], // size of the icon
- shadowSize: [41, 41], // size of the shadow
- iconAnchor: [0, 0], // point of the icon which will correspond to marker's location
- shadowAnchor: [0, 0], // the same for the shadow
- popupAnchor: [10, 0] // point from which the popup should open relative to the iconAnchor
- });*/
- map.on('click', function(args){
- if(data.click && window[data.click]) window[data.click]({
- longitude : args.latlng.lng,
- latitude : args.latlng.lat,
- layerX : args.layerPoint.x,
- layerY : args.layerPoint.y,
- x : args.containerPoint.x,
- y : args.containerPoint.y,
- event : args.originalEvent,
- target : args.target,
- sourceTarget : args.sourceTarget
- });
- });
- var mapPoints = {};
- var markers = L.markerClusterGroup();
- for(var k in points){
- var point = points[k];
- if(!point.type) point.type = 'marker';
- switch(point.type){
- case 'marker':
- var currentPoint = L.marker([point.latitude,point.longitude]/*, {icon: defaultIcon}*/);
- break;
- case 'circle':
- if(!point.borderColor) point.borderColor = '#38f';
- if(!point.backgroundColor) point.backgroundColor = '#38f';
- if(!point.opacity) point.opacity = 0.5;
- if(!point.radius) point.radius = 500;
- var currentPoint = L.circle([point.latitude,point.longitude], {
- color: point.borderColor,
- fillColor: point.backgroundColor,
- fillOpacity: point.opacity,
- radius: point.radius
- });
- break;
- case 'polygon':
- if(!point.borderColor) point.borderColor = '#38f';
- if(!point.backgroundColor) point.backgroundColor = '#38f';
- if(!point.opacity) point.opacity = 0.5;
- if(!point.radius) point.radius = 500;
- var currentPoint = L.polygon(point.points, {
- color: point.borderColor,
- fillColor: point.backgroundColor,
- fillOpacity: point.opacity,
- radius: point.radius
- });
- break;
- }
- markers.addLayer(currentPoint);
- if(point.label) currentPoint.bindPopup(point.label);
- currentPoint.id = k;
- if(point.id) currentPoint.id = point.id ;
- mapPoints[currentPoint.id] = currentPoint;
- //currentPoint.addTo(map);
- }
- map.addLayer(markers);
- input.data('points',mapPoints);
- break;
- case 'contact':
- //autocomplete classique
- input.component_autocomplete('contact',{
- edit : 'core_contact_by_uid',
- autocomplete : 'core_contact_autocomplete',
- skin : function(item){
- var html = '';
- var re = new RegExp(input.val(),"gi");
- name = item.label.replace(re, function (x) {
- return '<strong>'+x+'</strong>';
- });
- html += '<div class="'+slug+'-infos"><span>'+name+'</span>';
- if(item.job) html += '<div class="text-muted '+slug+'-job"><span>'+item.job+'</span>';
- html += '<div class="clear"></div>';
- return html;
- },
- data : function(){
- return {scope : input.attr('data-scope'),uid : input.attr('data-uid')? input.attr('data-uid').split(','):[] };
- }
- });
- break;
- case 'user':
- var userContainer;
- var userPicker;
- var pickerLi;
- if(!input.data("data-component")){
- userContainer = $('<div class="'+input.attr('class')+' data-type-user"><ul><li class="unfold"><i class="fas fa-ellipsis-h" title="Agrandir le champ" data-tooltip></i></li><li class="user-picker-li"><input type="text" '+(input.attr('placeholder')!=null?'placeholder="'+input.attr('placeholder')+'"':'')+'></li></ul></div>');
- input.before(userContainer);
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- input.data("data-component", userContainer);
- if(input.attr("required")) userContainer.attr("required","");
- if(input.attr("disabled")) userContainer.attr("disabled","");
- if(input.attr("readonly")) userContainer.attr("readonly","");
- } else {
- userContainer = input.data("data-component");
- }
- userPicker = userContainer.find('input:eq(0)');
- pickerLi = userContainer.find('ul li.user-picker-li');
- if(userContainer.attr('disabled') || userContainer.attr('readonly'))
- pickerLi.find('input').attr('readonly','');
- userContainer.find('.user-picker-tag').remove();
- pickerLi.removeClass('hidden');
- var pickerFunctions = {
- //Récuperation des valeurs sélectionnées (objet et uid) en fonction des tags visuels présents
- getValues : function(userContainer){
- var tags = userContainer.find('ul .user-picker-tag');
- var values = {object:[],uid:[]};
- tags.each(function(i,element){
- if($(element).attr('data-uid') == '') return;
- var object = $(element).data();
- values['object'].push(object);
- values['uid'].push(object.uid);
- });
- return values;
- },
- checkComponentOverflow : function(container){
- var overflow = container.get(0).scrollHeight > container.outerHeight();
- overflow ? container.addClass('overflowing') : container.removeClass('overflowing');
- },
- //Ajout d'un tag visuel et mise à jour de l'input brut en fonction de l'objet user fournis
- addTag : function(userContainer,user,input){
- pickerLi = userContainer.find('ul li.user-picker-li');
- if(userContainer.find('li[data-uid="'+user.uid+'"]').length>0) return;
- var closeBtn = userContainer.attr('disabled') || userContainer.attr('readonly') ? '' : '<i class="fa fa-times"></i>';
- var tag = $('<li class="user-picker-tag" data-entity="'+user.type+'" data-fullname="'+user.fullname+'" data-uid="'+user.uid+'"><div title="'+(user.type=='rank'?'Rang':'Utilisateur')+'">'+user.name+closeBtn+'</div></li>');
- pickerLi.before(tag);
- var values = pickerFunctions.getValues(userContainer);
- input.val(values['uid'].join(','));
- input.data('values',values['object']);
- if((values['uid'].length) == 1 && input.attr('data-multiple') == null){
- pickerLi.addClass('hidden');
- }else{
- pickerLi.removeClass('hidden');
- }
- pickerFunctions.checkComponentOverflow(userContainer);
- tag.find('i').click(function(){
- if(userContainer.attr('disabled') || userContainer.attr('readonly')) return;
- $(this).closest('.user-picker-tag').remove();
- var values = pickerFunctions.getValues(userContainer);
- input.val(values['uid'].join(','));
- input.data('values',values['object']);
- pickerLi = userContainer.find('ul li.user-picker-li');
- if((values['uid'].length-1) ==1 && input.attr('data-multiple') == null){
- pickerLi.addClass('hidden');
- }else{
- pickerLi.removeClass('hidden');
- }
- input.trigger('change');
- pickerFunctions.checkComponentOverflow(userContainer);
- });
- if(userContainer.find('ul li.user-picker-tag'))
- userContainer.find('ul li.user-picker-li input').removeAttr('placeholder');
- }
- }
- //Gestion des champs déja remplis au chargement de la page
- if(input.val() !=''){
- var uid = input.val();
- if(!window.componentQueue.user) window.componentQueue.user = {timeout : null,components : [],uids :{} };
- clearTimeout(window.componentQueue.user.timeout);
- var uids = uid.split(',');
- for(var k in uids)
- window.componentQueue.user.uids[uids[k]] = 1;
- window.componentQueue.user.components.push({
- input : input,
- picker : userPicker,
- container : userContainer,
- values : uids
- });
- userContainer.find('ul').append('<li class="user-picker-loader"><i class="fas fa-spinner fa-pulse"></i> Chargement</li>');
- userPicker.addClass('hidden');
- window.componentQueue.user.timeout = setTimeout(function(){
- $.action({
- action : 'core_user_by_uid',
- uids : Object.keys(window.componentQueue.user.uids)
- },function(r){
- for(var key in window.componentQueue.user.components){
- var component = window.componentQueue.user.components[key];
- component.container.find('.user-picker-loader').remove();
- component.picker.removeClass('hidden');
- input = window.componentQueue.user.components[key].input;
- for(var i in component.values){
- var value = component.values[i];
- if(!r.users[value]) continue;
- pickerFunctions.addTag(component.container,r.users[value],input);
- }
- delete window.componentQueue.user.components[key];
- }
- });
- },50);
- }
- userContainer.find('.unfold').click(function(e){
- e.stopPropagation();
- var position = userContainer.position();
- var width = userContainer.outerWidth();
- userContainer
- .addClass('unfolded')
- .css({
- top: position.top+'px',
- width: width+'px',
- left: position.left+'px'
- });
- $(document).mousedown(function(e){
- if($(e.target).closest('div.data-type-user').length || !userContainer.hasClass('unfolded')) return;
- window.userPickerTimeout = userContainer.removeClass('unfolded')
- .css({
- top: 'inherit',
- width: 'inherit',
- left: 'inherit'
- });
- pickerFunctions.checkComponentOverflow(userContainer);
- });
- });
- //Sélectionne l'input d'auto-completion ou que l'on clique dans le composant
- userContainer.find('ul').click(function(e){
- if(input.attr("readonly") == "readonly") return;
- userPicker.focus();
- e.stopPropagation();
- });
- //Selectionne l'item dropdown actif lors de l'appui sur entrée
- userPicker.keyup(function(e){
- if(e.keyCode!=13 || input.is('[readonly]') || input.is('[disabled]')) return;
- if(input.attr("readonly") == "readonly") return;
- var active = $('.user-picker-li .dropdown-menu .active');
- if(active.length==0) return;
- active.trigger('click').trigger('change');
- });
- var types = ['user'];
- if(input.data('types') && input.data('types')!='')
- types = input.data('types').split(',');
- //aucompletion sur le nom des users / rangs
- userPicker.autocomplete({
- action : 'core_user_autocomplete',
- data : {
- types : types,
- scope : input.attr('data-scope')
- },
- skin : function(item){
- var html = '';
- var re = new RegExp(escape_regex_chars(userPicker.val()),"gi");
- name = item.name.replace(re, function (x) {
- return '<strong>'+x+'</strong>';
- });
- if(item.type=='user'){
- if(item.avatar) html += '<div class="user-logo"><img src="'+item.avatar+'" class="avatar-mini avatar-rounded"></div>';
- html += '<div class="user-infos"><span>'+name+'</span> <small class="text-muted">- Utilisateur (@'+item.id+')</small>';
- html += item.function ? '<br/><small>'+item.function+'</small></div>' : '</div>';
- html += '<div class="clear"></div>';
- }else{
- html += '<div class="rank-logo"><i class="far fa-address-card"></i></div>';
- html += '<div class="rank-infos"><span>'+name+'</span> <small class="text-muted">- Rang</small>';
- html += item.description ? '<br/><small>'+item.description+'</small></div>' : '</div>';
- html += '<div class="clear"></div>';
- }
- return html;
- },
- highlight : function(item){
- return item;
- },
- onClick : function(selected,element){
- clearTimeout(window.userPickerTimeout);
- userPicker.val('');
- pickerFunctions.addTag(userContainer,selected,input);
- input.trigger('click').trigger('change');
- },
- onBlur : function(selected){
- if(input.attr('data-force')!='false' && input.val() == '') userPicker.val('');
- }
- });
- break;
- /**
- * data-labels : tableau des libellés entre double quotes eg : ["Libellé 1","Libellé 2"]
- * data-values : taleau des valeurs eg : [12,13]
- * data-colors : taleau des couleurs entre double quotes eg : ["#cecece","#222222"]
- */
- case 'doughnut':
- var data = input.data();
- if(data.height) $(input).attr('height',data.height);
- var myChart = new Chart(input.get(0).getContext('2d'), {
- type: 'doughnut',
- data: {
- labels: data.labels,
- datasets: [{
- data: data.values,
- backgroundColor: data.colors
- }]
- },
- options: {
- cutoutPercentage:80,
- legend: {
- display: (data.legend && data.legend===true)
- }
- }
- });
- break;
- /**
- * data-labels : tableau des libellés entre double quotes eg : ["Libellé1","Libellé 2"]
- * data-values : taleau des valeurs eg : [12,13]
- * data-colors : taleau des couleurs entre double quotes eg : ["#cecece","#222222"]
- */
- case 'bar':
- var data = input.data();
- var myChart = new Chart(input.get(0).getContext('2d'), {
- type: 'bar',
- data: {
- labels: data.labels,
- datasets: [{
- label : input.html(),
- data: data.values,
- backgroundColor: data.colors
- }]
- },
- options: {
- scales: {
- xAxes: [{
- ticks: {
- beginAtZero:true,
- autoSkip:false,
- maxRotation:90,
- minRotation:80
- }
- }],
- yAxes: [{
- ticks: {
- beginAtZero:true,
- autoSkip:false
- }
- }]
- },
- legend: {
- display: (data.legend && data.legend==true)
- }
- }
- });
- break;
- /**
- * data-labels : tableau des 2 libellés courant et max entre double quotes eg : ["Atteint","A Atteindre"]
- * data-values : taleau des valeurs courant et max : [50,100] (donne une jauge allant de 0 à 100 remplie a 50%)
- * data-colors : taleau des 2 couleurs "remplis" et "non remplis" entre double quotes eg : ["#cecece","#222222"] (optionnel)
- * data-unity : unité à affher a coté des libellé min, max et courant
- */
- case 'gauge':
- var data = input.data();
- Chart.pluginService.register({
- beforeDraw: function(chart) {
- // Get ctx from string
- var ctx = chart.chart.ctx;
- if(chart.config.options.elements.center){
- // Get options from the center object in options
- var centerConfig = chart.config.options.elements.center;
- var sidePaddingCalculated = (centerConfig.sidePadding / 100) * (chart.innerRadius * 2);
- // Get the width of the string and also the width of the element minus 10 to give it 5px side padding
- var stringWidth = ctx.measureText(centerConfig.text).width;
- var elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;
- var centerWidth = stringWidth;
- // Find out how much the font can grow in width.
- var widthRatio = elementWidth / stringWidth;
- var newFontSize = Math.floor(30 * widthRatio);
- var elementHeight = (chart.innerRadius * 2);
- // Pick a new font size so it will not be larger than the height of label.
- var fontSizeToUse = Math.min(newFontSize, elementHeight, centerConfig.maxFontSize);
- // Set font settings to draw it correctly.
- ctx.textAlign = 'center';
- ctx.textBaseline = 'middle';
- var centerX = ((chart.chartArea.left + chart.chartArea.right) / 2);
- var centerY = ((chart.chartArea.top + chart.chartArea.bottom) / 2) + 20;
- ctx.font = "1.7em Arial";
- ctx.fillStyle = centerConfig.color;
- ctx.fillText(centerConfig.text, centerX, centerY);
- }
- if(chart.config.options.elements.minimum){
- // Get options from the center object in options
- var minimumConfig = chart.config.options.elements.minimum;
- var sidePaddingCalculated = (minimumConfig.sidePadding / 100) * (chart.innerRadius * 2);
- // Get the width of the string and also the width of the element minus 10 to give it 5px side padding
- var stringWidth = ctx.measureText(minimumConfig.text).width;
- var elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;
- // Find out how much the font can grow in width.
- var widthRatio = elementWidth / stringWidth;
- var newFontSize = Math.floor(30 * widthRatio);
- var elementHeight = (chart.innerRadius * 2);
- // Pick a new font size so it will not be larger than the height of label.
- var fontSizeToUse = Math.min(newFontSize, elementHeight, minimumConfig.maxFontSize);
- // Set font settings to draw it correctly.
- ctx.textAlign = 'center';
- ctx.textBaseline = 'center';
- var minimumX = chart.radiusLength +20;
- var minimumY = chart.height - chart.offsetY - 8;
- ctx.font = "1em Arial";
- ctx.fillStyle = minimumConfig.color;
- ctx.fillText(minimumConfig.text, minimumX, minimumY);
- }
- if(chart.config.options.elements.maximum){
- // Get options from the center object in options
- var maximumConfig = chart.config.options.elements.maximum;
- var sidePaddingCalculated = (maximumConfig.sidePadding / 100) * (chart.innerRadius * 2);
- // Get the width of the string and also the width of the element minus 10 to give it 5px side padding
- var stringWidth = ctx.measureText(maximumConfig.text).width;
- var elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;
- // Find out how much the font can grow in width.
- var widthRatio = elementWidth / stringWidth;
- var newFontSize = Math.floor(30 * widthRatio);
- var elementHeight = (chart.innerRadius * 2);
- // Pick a new font size so it will not be larger than the height of label.
- var fontSizeToUse = Math.min(newFontSize, elementHeight, maximumConfig.maxFontSize);
- // Set font settings to draw it correctly.
- ctx.textAlign = 'left';
- ctx.textBaseline = 'center';
- var maximumX = chart.width - chart.radiusLength - 15 - stringWidth;
- var maximumY = chart.height - chart.offsetY - 8;
- ctx.font = "1em Arial";
- ctx.fillStyle = maximumConfig.color;
- ctx.fillText(maximumConfig.text, maximumX, maximumY);
- }
- }
- });
- if(data.height) $(input).attr('height',data.height);
- if (!data.colors){
- var doneColor = '#e74c3c';
- var percentage = data.values[0] * 100 / data.values[1];
- percentage = percentage > 100 ? 100 : percentage;
- //Calcul de la couleur en fonction du pourcentage de progression
- if(percentage<=20) doneColor = '#e74c3c';
- if(percentage>20 && percentage<=40) doneColor = '#e67e22';
- if(percentage>40 && percentage<=60) doneColor = '#2980b9';
- if(percentage>60 && percentage<=80) doneColor = '#16a085';
- if(percentage>80) doneColor = '#27ae60';
- //[couleur du fait,couleur du restant
- data.colors = [doneColor,'#bdc3c7'];
- }
- var myChart = new Chart(input.get(0).getContext('2d'), {
- type: 'doughnut',
- data: {
- labels: [data.labels[0],data.labels[1]],
- datasets: [{
- data: [percentage,100-percentage],
- backgroundColor: data.colors
- }],
- realDatasets : [data.values[0],data.values[1]]
- },
- options: {
- tooltips : {
- callbacks : {
- title: function(tooltipItem, data) {
- return data['labels'][tooltipItem[0]['index']];
- },
- label: function(tooltipItem, data) {
- return data['realDatasets'][tooltipItem['index']];
- },
- afterLabel: function(tooltipItem, data) {
- return '('+data['datasets'][0]['data'][tooltipItem['index']]+'%)';
- }
- }
- },
- elements: {
- minimum: {
- text: '0'+data.unity,
- color: '#333333', // Default is #000000
- sidePadding: 20, // Default is 20 (as a percentage)
- minFontSize: 12, // Default is 20 (in px), set to false and text will not wrap.
- lineHeight: 12 // Default is 25 (in px), used for when text wraps
- },
- center: {
- text: data.values[0]+data.unity,
- color: '#333333', // Default is #000000
- sidePadding: 20, // Default is 20 (as a percentage)
- minFontSize: 32, // Default is 20 (in px), set to false and text will not wrap.
- lineHeight: 12 // Default is 25 (in px), used for when text wraps
- },
- maximum: {
- text: data.values[1]+data.unity,
- color: '#333333', // Default is #000000
- sidePadding: 20, // Default is 20 (as a percentage)
- minFontSize: 12, // Default is 20 (in px), set to false and text will not wrap.
- lineHeight: 12 // Default is 25 (in px), used for when text wraps
- }
- },
- circumference: Math.PI ,
- rotation: -Math.PI ,
- cutoutPercentage:75,
- legend: {
- display: (data.legend && data.legend===true)
- }
- }
- });
- break;
- /**
- * data-labels : tableau des libellés entre double quotes eg : ["Libellé1","Libellé 2"]
- * data-values : taleau des valeurs eg : [12,13]
- * data-color : couleurs eg : #cecece
- */
- case 'line':
- var data = input.data();
- var myChart = new Chart(input.get(0).getContext('2d'), {
- type: 'line',
- data: {
- labels: data.labels,
- datasets: [{
- label : input.html(),
- data: data.values,
- borderColor: [data.color]
- }]
- },
- options: {
- scales: {
- xAxes: [{
- ticks: {
- beginAtZero:true,
- autoSkip:false,
- maxRotation:90,
- minRotation:80
- }
- }],
- yAxes: [{
- ticks: {
- beginAtZero:true,
- autoSkip:false
- }
- }]
- }
- }
- });
- break;
- /**
- * data-table : tableau dynamique js tri, recherche, pagination...
- * data-pageLength : nombre de résultats à afficher
- */
- case 'data-table':
- var data = input.data();
- var options = {
- pageLength: input.attr('data-pageLength') != null ? input.attr('data-pageLength') : 20,
- destroy: true,
- pagingType: "simple_numbers",
- fixedHeader: true,
- lengthMenu: [ [10, 20, 40, -1], [10, 20, 40, "Tous"] ],
- language: {
- url: "plugin/statistic/js/dataTables.fr.translation.json"
- },
- order: [], // Disable on load sort
- ordering: 'true' // Manage orderable options
- };
- options = $.extend(options,data);
- input.DataTable(options);
- break;
- /**
- * data-filter-country : filtre par pays à rechercher séparés par virgule (format ISO 3 numériques, ex : FRA)
- * data-filter-items : nb de résultats à retourner
- * data-filter-language : langue dans laquelle retourner les résultats
- *
- * data-select-callback : fonction de callback appelée lors de la sélection d'un élément
- *
- * data-filter-geocode : retourne les infos complémentaires de l'élément sélectionné (latitude, longitude,etc...)
- * data-geocode-callback : fonction de callback appelée pour traiter les infos retournées via geocode
- */
- case 'location':
- input.location({
- items: input.attr('data-filter-items'),
- language: input.attr('data-filter-language'),
- country: input.attr('data-filter-country'),
- geocode: input.attr('data-filter-geocode') != null ? true : false,
- select: function(location){
- if(input.attr('data-select-callback')!=null && input.attr('data-select-callback').length) {
- var select = input.attr('data-select-callback').replace(/[^a-z0-9]/i,'_');
- if(window[select] !=null) window[select](location);
- }
- },
- geocode: function(location){
- $.action({
- action: 'core_location_detail_search',
- locationId: location.locationId
- }, function(r){
- if(input.attr('data-geocode-callback')!=null && input.attr('data-geocode-callback').length) {
- var geocode = input.attr('data-geocode-callback').replace(/[^a-z0-9]/i,'_');
- if(window[geocode] !=null) window[geocode](r);
- }
- });
- }
- });
- var data = input.data();
- input.removeData();
- input.data({
- type : data.type,
- country : data.country,
- zip : data.zip,
- city : data.city,
- complement : data.complement,
- street : data.street
- });
- break;
- /**
- * data-source : tableau de clés / valeurs au format json base 64 encodé
- * data-value : la valeur de l'entité à récup en base (clé de l'item)
- */
- /*case 'list':
- var source = input.attr('data-source');
- if(source != '' && source != null && btoa(atob(source)) == source){
- input.html('');
- input.append('<option value=""> - </option>');
- var items = JSON.parse(atob(source));
- //boucle sur les entrées possibles de sources de données
- for(const [key, source] of Object.entries(items))
- //boucle sur les couples clés valeurs de la source de données
- for(const [index, value] of Object.entries(source))
- input.append('<option value="'+index+'" '+(index == input.attr('data-value') ? "selected" : '')+'>'+value+'</option>');
- }
- break;*/
- /**
- * data-depth : nb de profondeur de liste (ex: 2, affichera 2 select au maximum), 1 par défaut
- * data-slug : le slug de la liste mère à afficher, listes primaires par défaut
- * data-value : la valeur de l'entité à récup en base
- * data-disable-label : cache le label de sous-liste si mentionné
- * data-hierarchy : si mentionné à false, ne récupère pas
- * data-parent-id : l'id de la liste parente associée
- * data-output : id/slug définit la valueur de sortie de l'input (slug de la liste ou id de la liste (defaut))
- */
- case 'dictionary':
- var data = input.data();
- var slug = input.attr('data-slug') ? input.attr('data-slug') : "";
- var parentId = input.attr('data-parent-id') && input.attr('data-parent-id').length ? input.attr('data-parent-id') : "";
- //if (!slug.match(/^[a-z\d\-_]+$/i) && parentId == '') return;
- data.output = data.output ? data.output : 'id';
- $.action({
- action : 'core_dictionary_component_load',
- slug: slug,
- parentId : parentId,
- depth : data.depth,
- hierarchy : input.attr('data-hierarchy') == 'false' ? 0 : 1,
- value: input.attr('data-value')
- },function(r){
- var children = r.content && r.content.childs ? r.content.childs : r.content;
- input.attr('onchange', 'get_sub_dictionary(this, "'+input.attr('name')+'",'+1+');');
- input.html('');
- input.append('<option value=""> - </option>');
- $.each(children, function (index, value){
- if (value.selected) {
- input.append('<option value="'+value[data.output]+'" data-slug="'+value.slug+'" data-parent="'+value.parent+'" data-sublabel="'+value.sublistlabel+'" selected>'+value.label+'</option>');
- get_selected_values(input, value);
- }else{
- input.append('<option value="'+value[data.output]+'" data-slug="'+value.slug+'" data-parent="'+value.parent+'" data-sublabel="'+value.sublistlabel+'">'+value.label+'</option>');
- }
- });
- });
- break;
- /**
- * data-label : le label affiché dans la zone
- * data-delete : méthode de suppression de doc de l'entité
- * data-save : méthode de sauvegarde de doc de l'entité (si mentionné, save automatique)
- * data-readonly: Empeche l'ajout/suppression de documents
- * data-allowed : les extensions de fichier acceptées
- */
- case 'dropzone':
- console.warn('[DEPRECATED] : Dropzone doit être remplacé par le composant file');
- if(input.find('form').length != 0 || input.find('ul>li').length) break;
- if(!input.attr('data-action')) input.attr('data-action','action.php?action=core_temporary_file_upload');
- var readonly = input.attr('data-readonly') == "true" ? true : false;
- if(!input.get(0).hasAttribute('id')) input.attr('id',generate_uuid(10));
- var customTpl = input.find('> *:not(:visible)');
- var customActions = '';
- if(customTpl && customTpl.length){
- $.each(customTpl, function(i, action){
- if(i>2) return;
- var valCalc = readonly ? i*28+3 : i*28+25;
- customActions += $(action).removeClass('hidden').css('right', valCalc).get(0).outerHTML;
- });
- }
- var preview = '<li data-path="{{path}}" data-ext="{{ext}}" data-url="{{url}}" data-name="{{name}}" data-last-modification="{{lastModification}}">'+
- '<a {{#url}}href="{{url}}"{{/url}} target="_blank" title="{{name}}" class="text-decoration-none media">';
- preview += input.get(0).hasAttribute('data-preview') ? '<img style="margin: 0 5px;float: left;max-height:100px;max-width:80px;" src="{{url}}"/>' : '<i class="{{icon}} mx-1 align-self-top pt-1"></i>';
- preview += ' <span class="media-body">{{name}}{{lastModification}}</span></a>'+customActions+' <i class="fas fa-times pointer '+(input.attr('data-delete')?'':'hidden')+'" onclick="{{#temporary}}dropzone_delete_file(this);{{/temporary}}{{^temporary}}'+input.attr('data-delete')+'(this){{/temporary}}"></i><div class="clear"></div></li>';
- var valueFiles = input.html()!='' && is_json_string(input.text()) ? JSON.parse(input.text()) : [];
- input.html('');
- var allowed = input.attr('data-allowed');
- if(allowed) allowed = allowed.split(',');
- var save = input.attr('data-save');
- var size = input.attr('data-max-size');
- var maxFile = input.attr('data-max-files');
- maxFile = 100; //maxFile=='' || ! maxFile ? 0 : maxFile;
- input.upload({
- allowed : allowed,
- size : size == '' ? 0 : size,
- readonly: readonly,
- addData: function(){
- return {index: input.attr('id')};
- },
- start: function(){
- isProcessing = true;
- if(maxFile!=0 && $('li:visible',files).length >=maxFile ) return -1;
- preload.removeClass('hidden');
- },
- success: function(response){
- isProcessing = false;
- if(response.error){
- preload.addClass('hidden');
- $.message('error', response.error, 0);
- return;
- }
- if(response.previews.length && response.previews[0].name) {
- var inputTemp = $('#'+input.attr('id')+'_temporary');
- var currVal = inputTemp.val().length ? JSON.parse(inputTemp.val()) : [];
- for(var i in response.previews){
- files.append(Mustache.render(preview,response.previews[i]));
- currVal.push(response.previews[i]);
- }
- inputTemp.val(JSON.stringify(currVal));
- if(save) window[save](response.previews);
- }
- preload.addClass('hidden');
- },
- complete: function(){
- isProcessing = false;
- preload.addClass('hidden');
- },
- error: function(){
- isProcessing = false;
- preload.addClass('hidden');
- },
- });
- var preload = $('<div class="preload progress-bar progress-bar-striped progress-bar-animated hidden"></div>');
- input.append(preload);
- var files = $('<ul class="my-auto mx-0 w-100 pb-0"></ul>');
- input.append(files);
- var filesValues = $('<input type="hidden" name="'+input.attr('id')+'_temporary" id="'+input.attr('id')+'_temporary">');
- input.append(filesValues);
- for(var i in valueFiles) {
- files.append(Mustache.render(preview,valueFiles[i]));
- if(readonly) files.find('li > i.fa-times').remove();
- }
- if(!valueFiles.length && readonly)
- input.append('<div>Aucun document</div>');
- break;
- case 'file':
- if(!input.get(0).hasAttribute('data-id')) input.attr('data-id',generate_uuid(10));
- var droppedFiles = false;
- //Récuperation des data attributs de l'input
- var data = input.data();
- //extra données (eg.id de l'entité liée)
- if(input.attr('data-data')){
- try{
- data.data = input.attr('data-data') ? JSON.parse(input.attr('data-data')) : {};
- }catch(e){
- data.data = {};
- }
- }
- var options = $.extend({
- allStart : function(files){return true},
- allComplete : function(){},
- fileStart : function(file){return true},
- fileComplete : function(file){},
- fileError : function(file){},
- fileProgress : function(file){},
- over : 'file-hover',
- label : 'Faites glisser vos fichiers ici',
- data : {},
- limit : 0,
- readonly : false,
- onVisible : true
- },data);
- if(input.hasAttr('readonly')) options.readonly = true;
- var component = data.component;
- //initialisation du composant et liaison à l'input si pas déja fait
- if(!component){
- var component = $($('#component-file-template').get(0).outerHTML);
- component.attr('class',input.attr('class')).removeClass('hidden').removeAttr('id');
- input.after(component).data('component',component);
- input.attr('data-multiple-values','true');
- }
- if(options.onVisible === true && !component.is(':visible')) break;
- var lineTpl = $('#component-file-template .upload-list').html();
- var removeLine = function(element){
- form.find('input[type="file"]').val('');
- if(element.attr('data-path')==''){
- element.remove();
- component.attr('data-file-number',uploadList.find('>li').length);
- return;
- }
- $.action({
- action: data.action,
- type: 'delete',
- path: atob(element.attr('data-path')),
- data: data.data
- },function(r){
- updateValue(input,{path:element.attr('data-path')},true);
- element.remove();
- component.attr('data-file-number',uploadList.find('>li').length);
- });
- }
- //Ajout d'une ligne fichier
- var addLine = function(tpl,data){
- var component = input.data('component');
- if(data.path) data.path = btoa(data.path);
- var line = $(Mustache.render(tpl,data));
- if(options.buttons) line.find('.file-button').html($(options.buttons).html());
- component.find('.upload-list').append(line);
- //affichage du preview avec pré-chargement pour eviter le blink
- if(data.preview){
- $('<img/>').attr('src', data.preview).on('load', function() {
- $(this).remove();
- line.find('.file-preview').attr('style','background-image:url('+data.preview+')');
- line.addClass('preview-loaded');
- });
- }else{
- line.addClass('no-preview');
- }
- line.find('.btn-delete').click(function(){
- if(!line.hasClass('.upload-error')){
- if(!confirm('Êtes-vous sûr de vouloir supprimer ce fichier ?')) return;
- }
- removeLine(line);
- input.trigger('change');
- });
- return line;
- }
- //Ajout d'un ensemble de fichiers
- var refreshFiles = function(tpl,input,data){
- var component = input.data('component');
- component.find('.upload-list li').remove();
- for (var k in data.files) {
- addLine(tpl,data.files[k]);
- }
- }
- var updateValue = function(input,data,toDelete){
- var jsonValue = JSON.parse(input.val()?input.val():'[]');
- if(toDelete){
- //delete
- for(var k in jsonValue)
- if(btoa(jsonValue[k].path) == data.path) jsonValue.splice(k,1);
- }else{
- //add
- data.path = atob(data.path);
- jsonValue.push(data);
- }
- input.val(JSON.stringify(jsonValue));
- }
- if(input.hasAttr('required')) component.attr('required','');
- if(!options.data.id && $.urlParam('id')) options.data.id = $.urlParam('id');
- //Récuperation des extensions, de la taille, des fichiers existants
- $.action({
- action : options.action,
- type : 'search',
- data : options.data
- },function(r){
- if(r.options) options = $.extend(options,r.options);
- refreshFiles(lineTpl,input,{files : r.files});
- component.attr('data-file-number',r.files.length);
- });
- //formulaire d'envois
- var form = component.find('form');
- //input d'upload caché
- var fileInput = form.find('input[type="file"]');
- //drop & click zone
- var uploadZone = component.find('.upload-zone');
- //liste des fichiers
- var uploadList = component.find('.upload-list');
- form.attr('action','action.php?action='+options.action+'&type=upload');
- uploadZone.find('.file-upload-label').html(options.label);
- component.attr('data-file-number',0);
- if(options.readonly !== false) component.addClass('readonly');
- //test if d&d 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 events
- if(options.readonly === false){
- uploadZone
- .off('click drag dragstart dragend dragenter dragleave drop dragover').on('click', function (e) {
- fileInput.trigger('click');
- e.preventDefault();
- e.stopPropagation();
- })
- .on('drag dragstart dragend dragover dragenter dragleave drop', function (e) {
- e.preventDefault();
- e.stopPropagation();
- })
- .on('dragover dragenter', function () {
- form.addClass(options.hover);
- })
- .on('dragleave dragend drop', function () {
- form.removeClass(options.hover);
- })
- .on('drop', function (e) {
- droppedFiles = e.originalEvent.dataTransfer.files;
- form.trigger('submit');
- });
- }
- //si l'input file change (on a choisis un fichier) on lance la soumission du formulaire
- fileInput.off('change').on('change', function (e) {
- form.trigger('submit');
- });
- //sur soumission du formulaire
- form.off('submit').on('submit', function (e) {
- e.preventDefault();
- //fonctionnement browser modernes
- if (!dragAndDropEnabled) throw 'Drag & drop non fonctionnel, veuillez mettre à jour votre navigateur';
- var fileProcessed = [];
- //si pas de drop mode, on récuepre le mode click
- if(!droppedFiles) droppedFiles = $('input',form).get(0).files;
- var fileQueue = [];
- var allowedExtensions = options.extension ? options.extension.split(',') : [];
- $.each(droppedFiles, function (i, file) {
- //line data
- var lineData = {
- extension : file.name.split('.').pop(),
- label : file.name,
- sort : i
- };
- if(options.limit!=0 && i > options.limit) return;
- //dom element
- var fileLine = addLine(lineTpl,lineData);
- //ajout a la file d'upload
- fileQueue.push({
- file : file,
- data : lineData,
- element : fileLine
- });
- });
- droppedFiles = null;
- if(!options.allStart(fileQueue)) return;
- for(var k in fileQueue) {
- var file = fileQueue[k].file;
- fileQueue[k].element.attr('data-sort',k);
- try{
- if(allowedExtensions.length !=0 && allowedExtensions.indexOf(fileQueue[k].data.extension.toLowerCase()) === -1 )
- throw "Extension non permise, autorisé : "+allowedExtensions.join(', ');
- if(options.size && file.size > options.size)
- throw "Taille fichier "+file.size+" octets trop grande (max autorisé:"+options.size+" octets";
- var ajaxData = new FormData();
- ajaxData.append(input.attr('data-id'), file);
- ajaxData.append('index', input.attr('data-id'));
- ajaxData.append('sort', k);
- if(!options.fileStart(fileQueue[k])) continue;
- $.ajax({
- url: form.attr('action'),
- type: form.attr('method'),
- data: ajaxData,
- dataType: 'json',
- cache: false,
- contentType: false,
- processData: false,
- complete: function (data) {
- var response = data.responseJSON ? data.responseJSON : {error :data.responseText,sort:-1 };
- if(response.sort!=-1){
- var currentFile = fileQueue[response.sort];
- if(response.error) currentFile.element.addClass('upload-error').find('.error-message').html(response.error).attr('title',response.error);
- currentFile.element.addClass('upload-complete');
- }else{
- if(response.error) $.message('error',response.error);
- }
- fileQueue[response.sort] = true;
- var completed = 0;
- for(var u in fileQueue){
- if(fileQueue[u]===true) completed++;
- }
- if(fileQueue.length == completed){
- if(window[options.allComplete]) window[options.allComplete](response);
- input.trigger('change');
- }
- },
- success: function (data) {
- var currentFile = fileQueue[data.sort];
- options.fileComplete(currentFile);
- var newElement = addLine(lineTpl,data);
- currentFile.element.replaceWith(newElement);
- updateValue(input,data);
- var lines = uploadList.find('>li');
- if(options.limit != 0 && lines.length > options.limit){
- uploadList.find('>li').each(function(i,li){
- if(i < lines.length - options.limit ) $(li).remove();
- });
- }
- component.attr('data-file-number',lines.length);
- newElement.addClass('upload-success');
- },
- error: function (data) {
- var response = data.responseJSON ? data.responseJSON : {error :data.responseText,sort:-1 };
- if(response.sort!=-1){
- var currentFile = fileQueue[data.sort];
- options.fileError(currentFile);
- currentFile.element.addClass('upload-error');
- fileQueue[response.sort] = true;
- }else{
- $.message('error',response.error);
- }
- },
- xhr: function() {
- var xhr = new window.XMLHttpRequest();
- xhr.sort = k;
- xhr.upload.addEventListener("progress", function(evt){
- if (evt.lengthComputable) {
- var percentComplete = (evt.loaded / evt.total) * 100;
- percentComplete = Math.round(percentComplete * 100) / 100;
- currentFile = fileQueue[xhr.sort];
- options.fileProgress(fileQueue[xhr.sort],percentComplete);
- var progressBar = $('.progress-bar',currentFile.element)
- .css('width',percentComplete+'%');
- if(percentComplete >= 100) currentFile.element.addClass('upload-process');
- }
- }, false);
- return xhr;
- }
- });
- }catch(e){
- options.fileError(fileQueue[k],e);
- fileQueue[k].element.addClass('upload-error').find('.error-message').html(e).attr('title',e);
- fileQueue[k] = true;
- continue;
- }
- };
- });
- break;
- /*
- Composant table regroupant a terme toutes les options de "table avancée" :
- * les colonnes dynamiques
- * les multi select checkbox
- * les colonnes sortables
- * futures features tableau (ex: filtre sur les colonnes façon excel)
- ce composant est voué a être un composant core un fois rodé
- */
- case 'search-table':
- var SearchTable = function(table,options){
- var table = $(table);
- table.data('searchTable',this);
- this.table = table;
- this.options = options;
- this.slug = options.slug;
- this.actionButton = $(this.options.checkboxAction);
- var object = this;
- //Gestion des checkbox
- var globalCheckBox = object.table.find('.table_checkbox_global');
- if(globalCheckBox.length==0 && object.options.checkboxAction){
- var globalCheckBox =
- object.table.find('thead > tr:eq(0)').prepend('<th class="align-middle text-center"><input type="checkbox" class="table_checkbox_global" data-type="checkbox"></th>');
- globalCheckBox = object.table.find('.table_checkbox_global');
- globalCheckBox.click(function(){
- object.table.find('tbody td:visible input[type="checkbox"]').click();
- });
- object.table.find('tbody > tr:eq(0)').prepend('<td class="align-middle text-center"><input class="table_checkbox_line" type="checkbox" data-type="checkbox"></td>');
- object.table.on('click','tr:visible input.table_checkbox_line',function(){
- var element = $(this);
- var checked = element.prop('checked');
- var tr = element.closest('tr');
- var id = tr.attr('data-id');
- if(!id) return;
- var ids = object.checkboxes();
- if(checked) {
- ids.push(id);
- }else{
- var i = ids.indexOf(id);
- if(i > -1) ids.splice(i, 1);
- }
- object.checkboxes(ids)
- object.refreshActionButton();
- });
- }
- if(object.table.attr('data-loaded')!=1){
- var search = window[options.entitySearch];
- //Activation du tri colonne si au moins une en-tete contient le data-sortable
- if(object.table.find('[data-sortable]').length>0){
- object.table.sortable_table({
- onSort : function(){search({keepChecked:true})}
- });
- }
- //lancement de la recherche automatique
- if(search) search();
- object.table.attr('data-loaded',1);
- }
- }
- SearchTable.prototype.refreshActionButton = function(){
- var ids = this.checkboxes();
- this.actionButton.attr('data-count',ids.length).find('span.count').text(ids.length);
- };
- SearchTable.prototype.resetCheckbox = function(){
- this.checkboxes([]);
- this.refreshActionButton();
- };
- SearchTable.prototype.fillCheckbox = function(){
- var selected = this.checkboxes();
- for(var k in selected)
- $('tr:visible[data-id="'+selected[k]+'"] input.table_checkbox_line',this.table).prop('checked',true);
- };
- SearchTable.prototype.resetGlobalCheckbox = function(){
- this.table.find('.table_checkbox_global').prop('checked',false);
- };
- SearchTable.prototype.checkboxes = function(data){
- var tablesearch = localStorage.getItem('component.tablesearch.checked');
- tablesearch = !tablesearch ? {} : JSON.parse(tablesearch);
- if(!data)
- return tablesearch[this.slug] ? tablesearch[this.slug] : [];
- tablesearch[this.slug] = data;
- localStorage.setItem('component.tablesearch.checked', JSON.stringify(tablesearch));
- };
- var searchTable = new SearchTable(input,input.data());
- break;
- /**
- * data-simple : Si "true" alors interface avec moins de boutons
- * data-minimal: Si présent alors affichage simple en mode input inline
- */
- case 'wysiwyg':
- var buttons = [
- ['strong','em','underline','del'],
- ['foreColor', 'backColor'],
- ['fontfamily'],
- ['fontsize'],
- ['undo', 'redo'], // Only supported in Blink browsers
- ['formatting'],
- ['superscript', 'subscript'],
- ['link'],
- ['insertImage'],
- ['table'],
- ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'],
- ['unorderedList', 'orderedList'],
- ['horizontalRule'],
- ['removeformat'],
- ['fullscreen'],
- ['viewHTML']
- ]
- if(input.attr('data-simple')!=null || input.attr('data-simple') == 'true'){
- buttons = [
- ['strong','em','underline','del'],
- ['foreColor', 'backColor'],
- ['undo', 'redo'], // Only supported in Blink browsers
- ['formatting'],
- ['link'],
- ['unorderedList', 'orderedList'],
- ['insertImage']
- ]
- }
- if(input.attr('data-buttons')!=null && input.attr('data-buttons')!='') {
- buttons = is_json_string(input.attr('data-buttons')) ? JSON.parse(input.attr('data-buttons')) : [ input.attr('data-buttons').split(',') ];
- }
- var defaultOptions = {
- btns: buttons,
- lang: 'fr',
- autogrow: input.attr('data-minimal') == null,
- semantic: false,
- plugins : {}
- };
- var data = input.data();
- defaultOptions.tagsToRemove= ['script', 'link'];
- var scriptAllow = input.get(0).hasAttribute('data-script-allow');
- if(scriptAllow) defaultOptions.tagsToRemove= [];
- // gestion des mentions
- defaultOptions.plugins.mention = {keys : {}};
- if(input.attr('data-mention-user') && input.attr('data-mention-user') != ''){
- //mention @
- defaultOptions.plugins.mention.keys['@'] = {
- load : function(data){
- data.event.preventDefault();
- document.execCommand('insertHTML', false, '<b class="mention-user-picker-container">@<input type="text" data-type="user" data-types="'+input.attr('data-mention-user')+'" class="mention-user-picker d-inline-block" value=""></b>');
- var inputContainer = $('.mention-user-picker-container');
- init_components(inputContainer);
- var picker = $('.mention-user-picker-container input');
- picker.focus();
- var timeout = null;
- picker.click(function(){
- clearTimeout(timeout);
- var value = $(this).val();
- inputContainer.remove();
- data.editor.focus();
- data.textarea.trumbowyg('restoreRange');
- document.execCommand('insertHTML', false, '<span class="data-mention-user" data-mention-type="user" data-mention-value="'+value+'">@'+value+'</span> ');
- data.editor.trigger('keyup');
- }).blur(function(){
- //on supprime le composant si blur sans valeur (attente de 200 ms car le blur est trigger avant le click)
- timeout = setTimeout(
- function(){
- inputContainer.remove();
- data.editor.trigger('keyup');
- },200);
- });
- picker.keydown(function(e){
- var code = e.keyCode || e.which;
- //Si appuis sur espace ça casse l'autocompletion
- if(code == 32){
- e.preventDefault();
- var value = picker.val();
- $('.mention-user-picker-container').remove();
- data.editor.focus();
- data.textarea.trumbowyg('restoreRange');
- document.execCommand('insertHTML', false, '@'+value+' ');
- data.editor.trigger('keyup');
- }
- });
- }
- };
- }
- if(input.attr('data-mention-object') && input.attr('data-mention-object') != ''){
- //mention #
- defaultOptions.plugins.mention.keys['#'] = {
- load : function(data){
- data.event.preventDefault();
- document.execCommand('insertHTML', false, '<b class="mention-object-picker-container">#<input type="text" class="mention-object-picker" value=""></b>');
- var picker = $('.mention-object-picker');
- picker.focus();
- picker.keydown(function(e){
- var code = e.keyCode || e.which;
- //Si appuis sur espace ça casse l'autocompletion
- if(code == 32){
- e.preventDefault();
- var value = picker.val();
- $('.mention-object-picker-container').remove();
- data.editor.focus();
- data.textarea.trumbowyg('restoreRange');
- document.execCommand('insertHTML', false, '#'+value+' ');
- data.editor.trigger('keyup');
- }
- });
- var timeout = null;
- picker.autocomplete({
- action : input.attr('data-mention-object'),
- skin : function(item){
- var html = '';
- var re = new RegExp(picker.val(),"gi");
- name = item.name.replace(re, function (x) {
- return '<strong>'+x+'</strong>';
- });
- html += '<div class="pointer"><span>'+name+'</span>';
- html += '<div class="clear"></div>';
- return html;
- },
- highlight : function(item){
- return item;
- },
- onClick : function(selected,element){
- clearTimeout(timeout);
- picker.val('');
- $('.mention-object-picker-container').remove();
- data.textarea.trumbowyg('restoreRange');
- slug = selected.slug ? selected.slug : selected.name;
- document.execCommand('insertHTML', false, '<span class="data-mention-object" data-mention-type="object" title="'+selected.name+'" data-mention-value="'+selected.id+'">#'+slug+'</span> ');
- data.editor.trigger('keyup');
- },
- onBlur : function(selected){
- if(input.val() == '') picker.val('');
- timeout = setTimeout(function(){
- $('.mention-object-picker-container').remove();
- data.editor.trigger('keyup');
- },200);
- }
- });
- }
- };
- }
- var options = $.extend(defaultOptions,data);
- options = $.extend(options, input.data());
- var obj = input.trumbowyg(options);
- //fix pour accepter les tags non sémantiques dans la gestion du highlight de bouttons
- trumb = input.data('trumbowyg');
- trumb.tagToButton['b'] = 'strong';
- trumb.tagToButton['i'] = 'em';
- trumb.tagToButton['u'] = 'underline';
- input.data('trumbowyg',trumb);
- obj.data('trumbowyg',trumb);
- obj.on('tbwblur', function(){ input.trigger('blur'); });
- obj.on('tbwchange', function(){ input.trigger('keypress'); });
- var trumbowygBox = $(input).closest('div.trumbowyg-box');
- trumbowygBox.addClass(input.attr('class')).removeClass('trumbowyg-textarea');
- if(input.attr('required')) trumbowygBox.attr('required', true);
- if(input.attr('readonly')) obj.trumbowyg('disable');
- if(input.val()!='')
- input.trumbowyg('html', input.val());
- if(input.attr('data-minimal') != null){
- trumbowygBox.addClass('trumbowyg-minimal');
- var btnPane = trumbowygBox.find('.trumbowyg-button-pane');
- var editor = trumbowygBox.find('.trumbowyg-editor');
- btnPane.addClass('hidden');
- editor.removeAttr('style').keydown(function(e) {
- $(this).find('*').removeProp('font-size');
- switch (e.keyCode) {
- case 13:
- return false;
- break;
- default:
- return true;
- break;
- }
- }).on('paste',function(e){
- e.preventDefault();
- e.stopImmediatePropagation();
- var text = (e.originalEvent || e).clipboardData.getData('text/plain');
- document.execCommand("insertHTML", false, text);
- });
- }
- break;
- /**
- * Permet la recherche combinatoire multi critères.
- * Voir filter.component.js pour plus d'infos.
- */
- case 'filter':
- var box = new FilterBox(input,input.data());
- break;
- /**
- * Ouvre une popup de definition des droits ciblée sur une entité, une section, un id
- data-scope : section / partie de code ou de module concerné par le droit (defaut : core)
- data-uid : Id spécifique d'entité concerné par le droit (defaut : $.urlParam('id'))
- data-edit : Afficher la case edition (defaut : true)
- data-read : Afficher la case lecture (defaut : true)
- data-recursive : Afficher la case récursif (defaut : false)
- data-configure : Afficher la case configuration (defaut : false)
- data-firm : Scoper sur un établissement, cache la selection d'établissement si définit (defaut : null)
- data-saveAction : Définir une action de save custom du droit (defaut : core_right_save)
- data-deleteAction : Définir une action de delete custom du droit (defaut : core_right_delete)
- */
- case 'right':
- input.off('click').click(function(){
- var data = $.extend({
- scope : 'core',
- uid : $.urlParam('id'),
- edit : true,
- read : true,
- recursive : false,
- configure : false,
- firm : null,
- saveAction : 'core_right_save',
- deleteAction : 'core_right_delete'
- },input.data());
- core_right_edit(data);
- });
- break;
- /**
- * data-table (ex : #contacts) : id de la table de résultat liée
- * data-value (ex: 20) : valeur initiale d'item par page si rien dans le local storage
- * data-step (ex: 5) : valeur du pas entre chaque proposition du nb d'item par page
- * data-items (ex: 10,25,50,150) : liste des items proposés pour la préférence de pagination séparés par virgule
- * data-max-item (ex: 50) : valeur maximum possible d'item par pages
- */
- case 'pagination-preference':
- var pagination = localStorage.getItem('pagination') ? JSON.parse(localStorage.getItem('pagination')) : {};
- var table = $(input.attr('data-table'));
- var container = input.data('container');
- var items = input.data('items');
- var uid = ($.urlParam('module')?$.urlParam('module'):'main')+'-'+($.urlParam('page')?$.urlParam('page') :'main')+'-'+table.attr('id');
- if(!container){
- var finalItems = [];
- if(!items) {
- var step = parseInt(input.attr('data-step'));
- for(var i=parseInt(input.attr('data-max-item')), j=1; i>=j; i-=(step?step:10))
- finalItems.push({number:i});
- } else {
- var items = items.split(',');
- for(var i=0; i<items.length; i++)
- finalItems.push({number:items[i]});
- }
- var initial = pagination[uid] ? pagination[uid] : input.attr('data-value');
- var container = $(Mustache.render($('#pagination-preference-template').html(),{initial:initial, items:finalItems}));
- input.append(container);
- input.data('container',container);
- } else {
- container = $(container);
- }
- container.find('.dropdown-item').click(function(){
- var button = $(this);
- var toggle = button.parent().parent().find('.dropdown-toggle');
- toggle.text(button.text());
- pagination[uid] = button.text();
- localStorage.setItem('pagination',JSON.stringify(pagination));
- if(window[table.attr('data-column-search')]) window[table.attr('data-column-search')]();
- });
- break;
- /**
- * data-toggle-event : Pour le moment, que "hover", de base au click
- * data-show-strength: Si indiqué, affiche la barre de force du mot de passe renseigné dans l'input
- * data-length : Si indiqué, le generateur de mot de passe se cantonnera à la longueur spécifiée
- * data-forbidden : Si indiqué (sous forme de string), le generateur de mot de passe n'utilisera pas ces caractères
- * data-generator : Si indiqué, affiche une icône pour générer un mdp sécurisé
- */
- case 'password':
- if(input.closest('.password-field').length) return;
- input.attr('type', 'password');
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- input.wrap(function() {return '<div class="data-type-password password-field"></div>';});
- input.data('data-component',input.parent());
- var container = input.parent('.password-field');
- container.append('<i class="fas fa-eye-slash noPrint password-toggler" title="Afficher/Masquer le mot de passe"></i>');
- container.find('i.password-toggler').attr((input.attr('data-toggle-event') == 'hover')?{
- 'onmouseover': 'toggle_password(this);',
- 'onmouseleave': 'toggle_password(this);'
- }:{'onclick': 'toggle_password(this);'});
- if(input.attr('data-generator') !== undefined) {
- container.append('<i class="fas fa-shield-alt noPrint password-generator" title="Générer un mot de passe"></i>')
- container.find('i.password-generator').on('click', function(){
- if(input.val()!='' && !confirm('Attention, un mot de passe est déjà défini.\nVoulez-vous quand même en générer un nouveau ?')) return;
- //Longueur attendue (12 par défaut)
- var length = input.attr('data-length') !== undefined && input.attr('data-length').length ? parseInt(input.attr('data-length')) : 12;
- //Regex norme ANSSI
- var strong = new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[=/\()%ยง!@#$%^&*])(?=.{'+length+',})');
- var forbidden = input.attr('data-forbidden') !== undefined && input.attr('data-forbidden').length ? input.attr('data-forbidden') : '';
- do {
- password = generate_password(length, forbidden);
- } while(!strong.test(password))
- input.val(password).trigger('change');
- if(input.attr('data-show-strength') !== undefined)
- check_password_strength(input);
- });
- function generate_password(length,forbidden){
- var charset = get_characters_set();
- var length = length ? length : 12+get_random_int(6);
- var forbidden = forbidden!=null ? forbidden : '';
- var password = "";
- for(var i=0; i<forbidden.length; i++){
- var index = charset.indexOf(forbidden[i]);
- if(index > -1) charset.splice(index, 1);
- }
- for (var i=0; i<length; ++i)
- password += charset[get_random_int(charset.length)];
- return password;
- }
- }
- if(input.attr('data-show-strength') !== undefined) {
- input.parent('.password-field').append('<div class="strength-lines"><div class="line"></div><div class="line"></div><div class="line"></div></div>');
- // Strength validation on keyup-event
- input.on("keyup mouseup", function(e) {
- check_password_strength($(this));
- });
- //Check password strength
- function check_password_strength(input) {
- var value = $(input).val();
- var container = $(input).closest('.password-field');
- $(".line", container).removeClass("strength-low strength-medium strength-hard").addClass("strength-transparent");
- if(!value.length) return;
- var strongRegex = new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[=/\()%ยง!@#$%^&*])(?=.{12,})'),
- mediumRegex = new RegExp('^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})');
- if(strongRegex.test(value)) {
- $(".line", container).removeClass("strength-transparent").addClass("strength-hard");
- } else if (mediumRegex.test(value)) {
- $(".line:not(:last-of-type)", container).removeClass("strength-transparent").addClass("strength-medium");
- } else {
- $(".line:nth-child(1)", container).removeClass("strength-transparent").addClass("strength-low");
- }
- }
- }
- break;
- case 'url':
- if(input.closest('.url-field').length) return;
- var container = $('<div class="data-type-url url-field '+(!input[0].hasAttribute("data-no-lock") ? 'haslock' : '')+'">'+(!input[0].hasAttribute("data-no-lock")?'<i class="fas fa-lock url-icon"></i> ':'')+
- (!input[0].hasAttribute("data-no-link")?'<i class="fas fa-globe noPrint url-link" title="Afficher le site internet"></i>':'')+'</div>');
- input.after(container);
- container.prepend(input.detach());
- input.data('data-component',container);
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- var link = $('.url-link',container);
- var icon = $('.url-icon',container);
- var keyActions = function(){
- var value = input.val();
- if(!value){
- link.addClass('hidden');
- }else{
- link.removeClass('hidden');
- }
- if(value.match('https://')){
- icon.removeClass('text-muted').addClass('text-success').attr('title','Site sécurisé');
- }else{
- icon.removeClass('text-success').addClass('text-muted').attr('title','Site non sécurisé');
- }
- }
- keyActions();
- input.keyup(keyActions);
- var scheme = input.attr('data-default-scheme');
- if(scheme){
- input.blur(function(){
- if(input.val() && !input.val().match('https?://')){
- input.val(scheme+'://'+input.val());
- keyActions();
- }
- });
- }
- container.find('i.url-link').click(function(){
- window.open(input.val());
- });
- break;
- case 'icon':
- input.addClass('hidden');
- input.next('.component-icon').remove();
- var data = {
- value : input.val(),
- choices : []
- };
- var icons = $.fontAwesome();
- var line = [];
- for(var key in icons){
- if(line.length==15){
- data.choices.push(line);
- line = [];
- }
- line.push(icons[key].icon);
- }
- var selector = input.data('data-component');
- if(!selector){
- var selector = $(Mustache.render($('.component-icon.hidden').get(0).outerHTML,data));
- selector.addClass(input.attr('class'));
- selector.removeClass('hidden form-control');
- input.data('data-component',selector);
- input.after(selector);
- }
- selector.on('show.bs.dropdown', function () {
- if(input.is('[readonly]') || input.is('[disabled]')){
- selector.find('.dropdown-menu').addClass('hidden');
- }else{
- selector.find('.dropdown-menu').removeClass('hidden');
- }
- setTimeout(function(){selector.find('input.form-control').focus();},0);
- })
- selector.find('.dropdown-icon-item').click(function(){
- selector.find('.dropdown-icon-item').removeClass('hidden');
- selector.find('input.form-control').val('');
- var icon = $(this).attr('data-icon');
- input.val(icon);
- selector.find('.dropdown-toggle i').attr('class',icon);
- input.trigger('change');
- });
- selector.find('input.form-control').keyup(function(){
- var value = $(this).val();
- $('.dropdown-icon-item i',selector).each(function(i,iconElement){
- iconElement = $(iconElement);
- parent = iconElement.parent();
- iconElement.attr('class').indexOf(value)!=-1 ? parent.removeClass('hidden') : parent.addClass('hidden');
- });
- });
- if(input.hasAttr('required')) selector.attr('required','');
- if(input.hasAttr('readonly')) selector.attr('readonly','');
- break;
- /**
- * data-title (*) : Le titre du modal
- * data-loaded (*): fonction callback appelée auprès le chargement du modal (bien pour setter des actions custom sur les boutons dans le modal par exemple)
- * data-params : Les paramètres utilisés pour l'appel du callback
- * data-action (*) : Appel de la modal par action et non par ajax
- * data-precall : fonction appelée avant le chargement du modal (méthode de check sur l'UI par exemple)
- * Pour customiser l'icône du quickform, il suffit de placer le contenu que l'on veut dans la div de data-type="quickform"
- */
- case 'quickform':
- if(input.find('span').length) return;
- if(input.attr('disabled')) return;
- var cbLoaded = input.attr('data-loaded');
- // var params = input.attr('data-params') ? input.attr('data-params').split(',') : [];
- var params = input.attr('data-params') ? JSON.parse(input.attr('data-params')) : [];
- var preCb = input.attr('data-precall') ? input.attr('data-precall') : '';
- if(input.find('> *').length){
- input.find('> *').wrap('<span class="tooltip-warning">');
- } else {
- input.append('<span class="tooltip-warning"><i title="Création rapide" class="fas fa-plus-square"></i></span');
- }
- $(document).ready(function(e){
- $('span.tooltip-warning').tooltip({
- track: true,
- tooltipClass: 'quickform-tooltip',
- });
- input.on('click', function(e){
- if(preCb.length && !window[preCb]()) return;
- $.action({
- action: input.attr('data-action'),
- data: params
- }, function(r){
- var modal = $('#quickform-modal');
- var title = (r.title && r.title.length ? r.title : (input.attr('data-title')!=null ? input.attr('data-title') : 'Création rapide :'));
- $('#quickform-modal-label', modal).text(title);
- $('.modal-body', modal).html('').append(r.content);
- $('.modal-footer > div:first-of-type', modal).nextAll().remove();
- modal.clear();
- $('form', modal).attr('data-id','');
- if(cbLoaded) window[cbLoaded](params);
- modal.modal('show');
- init_components('#quickform-modal');
- });
- });
- });
- break;
- case 'checkbox':
- //3 cas possibles :
- // - input sans rien, data-type="checkbox" --> on fait tout
- // - input avec coquille sans data-uuid, --> on génère simplement un data-uuid et maj valeur
- // - input avec coquille et data-uuid --> on maj simplement sa valeur
- if(input.get(0).hasAttribute('data-uuid')) return;
- if(input.attr('type') != 'checkbox') input.attr('type', 'checkbox');
- if(!input.closest('label.check-component').length) {
- var labelBox = $('<label class="check-component"></label>');
- var checkbox = $('<div class="box"></div>');
- var id = input.attr('id');
- var title = input.attr('title');
- var customClass = input.attr('data-class');
- if(id) labelBox.attr('for', id);
- if(title) labelBox.attr('title', title);
- if(input.attr('class')) labelBox.addClass(input.attr('class'));
- if(customClass) labelBox.addClass(customClass);
- if(input.prop('disabled') == true) labelBox.attr('disabled', true);
- input.removeAttr('title data-class').wrap(labelBox);
- input.after(checkbox);
- }
- var uuid = generate_uuid(15);
- input.attr('data-uuid', uuid);
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- if(input.hasAttr('required')) input.closest('label.check-component').attr('required','');
- if(input.hasAttr('readonly')) input.closest('label.check-component').attr('readonly','');
- if(input.hasAttr('readonly')) input.closest('label.check-component').click(function(e){ e.preventDefault()});
- if(input.get(0).hasAttribute('id')) return;
- input.closest('label.check-component').off('click','div.box').on('click','div.box',function(e){
- if(input.hasAttr('readonly')) return e.preventDefault();
- var checkboxInput = $('input[data-uuid="'+uuid+'"]');
- checkboxInput.prop('checked', checkboxInput.prop('checked'));
- });
- break;
- /**
- * data-label : Libellé affiché à côté de l'input radio
- * name (*) : Le nom du groupe dont fait partie l'input radio
- */
- case 'radio':
- if(input.get(0).hasAttribute('data-uuid')) return;
- if(input.attr('type') != 'radio') input.attr('type', 'radio');
- var uuid = generate_uuid(15);
- var id = input.get(0).hasAttribute('id')? input.attr('id') : '';
- var title = input.get(0).hasAttribute('title') ? input.attr('title') : '';
- var label = input.attr('data-label');
- var labelBox = $('<label data-uid="'+uuid+'"></label>');
- labelBox.attr({
- 'for': id,
- 'title': title
- });
- if(input.prop('disabled') == true) labelBox.attr('disabled', true);
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- input.addClass('radio-component').removeAttr('title data-label').attr('data-uuid', uuid);
- input.after(labelBox);
- if(label) labelBox.after('<label for="'+id+'">'+label+'</label>');
- if(input.attr('id') && input.attr('id').length) return;
- labelBox.click(function(e){
- var radioInput = $('input[data-uuid="'+uuid+'"]');
- var name = radioInput.attr('name');
- $('input[name="'+name+'"]').prop('checked', false).removeAttr('checked');
- if(radioInput.prop('disabled') != true) radioInput.prop('checked', true);
- $(input).change();
- });
- break;
- /**
- * data-action : l'action php pour récupérer l'UI de la card
- * data-parameters : paramètres à passer avec l'action json encodés
- */
- case 'card':
- if(!input.is(':visible')) return;
- var action = input.attr('data-action');
- if(!action) {
- console.warn('CARD COMPONENT: Need "data-action" to get card content');
- return;
- }
- var showDelay = input.attr('data-show-delay') ? input.attr('data-show-delay') : 250;
- var hideDelay = input.attr('data-hide-delay') ? input.attr('data-hide-delay') : 600;
- input.addClass('card-component-container').attr('data-uuid', generate_uuid());
- var timeout;
- input.off('mouseenter').mouseenter(function(event){
- var e = event.target || event.relatedTarget;
- if (e.parentNode != this && e != this) return;
- event.stopImmediatePropagation();
- event.stopPropagation();
- $('*[data-type="card"]').find('.card-component')
- .addClass('card-component-hide')
- .removeClass('card-component-hover')
- .one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
- var card = $(this);
- if(card.closest('.card-component-container').attr('data-uuid') == input.attr('data-uuid')) return;
- card.closest('.wrapper').remove();
- });
- var parameters = input.attr('data-parameters');
- var data = parameters!=null && parameters.length ? JSON.parse(parameters) : {};
- data.action = action;
- timeout = setTimeout(function(){
- var currInput = input;
- if(!currInput.find('.card-component').length) {
- $.action(data, function(r){
- if(!r.content) return;
- //On utilise un wrapper pour gérer les overflows "out of the box"
- var card = $(r.content);
- var topOffset = currInput.offset().top;
- currInput.append(card);
- var position = {};
- var cardWidth = card.outerWidth();
- card.wrap($('<div class="wrapper"></div>'));
- card.addClass('card-component card-component-hover');
- if($('body').width() < (currInput.offset().left + cardWidth))
- position['right'] = cardWidth;
- else
- position['left'] = 0;
- //Gestion des overflows pour positionnement de la card
- var cardHeight = card.outerHeight();
- var htmlHeight = $('html').height();
- if(htmlHeight-100 < (topOffset + cardHeight)){
- var spaceBottom = htmlHeight-topOffset;
- var height = 0;
- if(spaceBottom > topOffset){
- if(cardHeight > spaceBottom) height = (spaceBottom-100);
- } else {
- position['top'] = -cardHeight;
- if(cardHeight > topOffset){
- height = (topOffset-100);
- position['top'] = -(topOffset-100);
- }
- }
- if(height!=0){
- card.css({
- height: height+'px',
- 'overflow-y': 'auto',
- 'overflow-x': 'hidden'
- });
- }
- }
- currInput.find('.wrapper').css(position);
- init_components(currInput.find('.wrapper'));
- });
- } else {
- var card = $(currInput.find('.card-component'));
- card.addClass('card-component-hover').removeClass('card-component-hide');
- }
- clearTimeout(currInput.data('tOutbox'));
- }, showDelay);
- });
- input.add(input.find('.card-component')).off('mouseleave').mouseleave(function(e){
- // e.stopImmediatePropagation();
- // e.stopPropagation();
- var input = $(this),
- card = input.find('.card-component'),
- tOutbox = setTimeout(function(){
- if(!$('.card-component:hover').length) {
- card.addClass('card-component-hide').removeClass('card-component-hover');
- card.one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
- $(this).closest('.wrapper').remove();
- });
- }
- }, hideDelay);
- //Clear du timeout d'apparition
- clearTimeout(timeout);
- //Set du l'id de timeout, permet de clear ce trigger si la souris revient sur l'input
- input.data('tOutbox', tOutbox);
- });
- break;
- case 'choice':
- if(input.get(0).tagName !='INPUT') return console.warn('Choice autorisé sur input uniquement');
- var data = input.data();
- var container;
- if(!input.data("data-component")){
- container = $('<div class="'+input.attr('class')+' data-type-choice"></div>');
- input.before(container);
- input.data("data-component", container);
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- }
- container = input.data("data-component");
- //récuperation du name servant d'id de groupe pour les radio
- var name = input.attr('name');
- if(!name) name = data.name;
- if(!name) name = input.attr('id');
- if(!name) name = Math.floor(Math.random() * 100);
- //rafraichissement des options possibles
- if(!data.values) return;
- html = '';
- for(var k in data.values){
- html+='<label class="pointer">'
- html+= '<input type="radio" data-type="radio" name="'+name+'" value="'+k+'">';
- html+= ' '+data.values[k]+'</label> ';
- }
- container.html(html);
- $('input',container).change(function(){
- input.val($(this).val());
- input.change();
- });
- init_components(container);
- //supprime les component-raw-value généré par l'utilisation des data-type = radio
- //pour les filtres on ne veut que l'input du choice
- container.find('.component-raw-value').removeClass('component-raw-value');
- //set de la valeur si définie dans l'input
- if(input.val()){
- $('input',container).prop('checked',false);
- $('input[value="'+input.val()+'"]',container).prop('checked',true);
- }
- if(input.hasAttr("required")) container.attr('required','');
- break;
- case 'jsontable':
- if(input.get(0).tagName !='INPUT') return;
- var data = input.data();
- if(data.format!='key-value' && data.format!='multiple-values') return console.warn('seul les formats key-value et multiple-values sont implémentés sur le composant jsontable');
- var container;
- if(!input.data("data-component")){
- container = $('<table class="table table-striped '+input.attr('class')+' data-type-json">\
- <thead><tr></tr></thead><tbody></tbody>\
- </table>');
- input.before(container);
- input.data("data-component", container);
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- }
- container = input.data("data-component");
- var head = $('thead tr',container);
- var body = $('tbody',container);
- var refreshTable = function(){
- head.find('th:not(.option-head)').remove();
- body.find('tr').remove();
- var html = '';
- if(data.format == 'key-value') data.columns = {"key":"Clé","value":"Valeur"};
- for(var k in data.columns){
- html+= '<th data-key="'+k+'">'+data.columns[k]+'</th>';
- }
- html+= '<th></th>';
- head.prepend(html);
- var values = {};
- try{
- values = input.val();
- values = JSON.parse(input.val());
- }catch(e){
- values = {};
- }
- var columnLength = Object.keys(data.columns).length+1;
- body.append('<tr><td colspan="'+columnLength+'" class="center pointer btn-add-line"><i class="fas fa-plus text-success "></i> <span class="text-muted font-weight-bold">AJOUTER</span></td></tr>');
- for(var k in values){
- line = values[k];
- if(data.format == 'key-value') line = {key:k,value:values[k]};
- addLine(line,data.columns);
- }
- $('.btn-add-line',container).click(function(){
- addLine(null,data.columns);
- });
- if(input.hasAttr('required')) container.attr('required','');
- }
- var addLine = function(data,header){
- if(!data){
- for(var k in header)header[k] = '';
- data = header;
- }
- var html = '<tr class="line">';
- for(var key in data)
- html += '<td><input type="text" class="form-control" data-key="'+key+'" value="'+data[key]+'"></td>';
- html +='<td><i class="fas fa-trash text-muted pointer btn-remove"></i></td>';
- html += '</tr>';
- var line = $(html);
- body.find('tr:last-child').before(line);
- $('.btn-remove',line).click(function(){
- removeLine($(this).closest('tr'));
- });
- $('input',line).change(function(){
- refreshInput();
- input.change();
- });
- refreshInput();
- input.change();
- }
- var removeLine = function(element){
- $(element).remove();
- refreshInput();
- input.change();
- }
- var refreshInput = function(){
- var json = data.format=='multiple-values' ? [] : {};
- body.find('tr.line').each(function(){
- var tr = $(this);
- if(data.format=='key-value'){
- json[tr.find('td:eq(0) input').val()] = tr.find('td:eq(1) input').val();
- }else if(data.format=='multiple-values'){
- var line = {};
- tr.find('td').each(function(){
- var td = $(this);
- var inputValue = td.find('input');
- if(inputValue.length==0) return;
- line[inputValue.attr('data-key')] = inputValue.val();
- });
- json.push(line);
- }
- });
- input.val(JSON.stringify(json));
- }
- refreshTable();
- if(input.hasAttr('readonly')){
- container.attr('readonly','');
- container.find('tbody input').attr('readonly','');
- }
- break;
- case 'entitypicker':
- var component = input.data('data-component');
- var modal = $('#entitypicker-modal');
- if(!component){
- var component = $('<div class="'+input.attr('class')+' data-type-entitypicker"><i class="fas fa-database"></i> <span></span> <i class="entitypicker-clear fas fa-times text-muted"></i></div>');
- input.data('data-component',component);
- input.after(component);
- if(modal.length!=0) modal.remove();
- modal = $('<div class="modal fade entitypicker-modal" id="entitypicker-modal" aria-hidden="true">\
- <div class="modal-dialog modal-xl"> \
- <div class="modal-content"> \
- <div class="modal-header"> \
- <h5 class="modal-title">Sélection d\'une entitée</h5>\
- <button type="button" class="close" data-dismiss="modal" aria-label="Fermer">\
- <span aria-hidden="true">×</span>\
- </button>\
- </div>\
- <div class="modal-body">\
- <div class="row">\
- <div class="col-md-6 plugin-list-container">\
- <ul class="plugin-list list-group">\
- <li class="hidden pointer plugin list-group-item {{className}}" data-label="{{name}}" data-path="{{folder.path}}"><i class="far fa-folder"></i> <span>{{name}} <small class="text-muted">{{description}}</small></span></li>\
- </ul>\
- </div>\
- <div class="col-md-6">\
- <ul class="entity-list list-group">\
- <li class="hidden entity list-group-item {{className}} pointer" data-label="{{label}}" data-path="{{path}}"><i class="fas fa-border-all"></i> <span>{{label}}</span></li>\
- </ul>\
- </div>\
- </div>\
- </div>\
- <div class="modal-footer">\
- <button type="button" class="btn btn-primary btn-select">Sélectionner</button>\
- </div>\
- </div>\
- </div>\
- </div>');
- $('body').append(modal);
- }
- modal = $('#entitypicker-modal');
- var searchEntities = function(){
- var plugin = $('.plugin.active',modal).attr('data-path');
- if(!plugin) return;
- $('.entity-list').fill({
- action:'core_entity_search',
- plugin : plugin
- },function(){
- $('.entity-list .entity').click(function(){
- input.val($(this).attr('data-path'));
- refreshValue();
- modal.modal('hide');
- input.change();
- });
- });
- };
- var refreshValue = function(){
- var value = input.val();
- if(!value) return $('>span',component).html('');
- $.action({
- action : 'core_entity_edit',
- path : value
- },function(response){
- $('>span',component).html('<span class="text-muted">'+response.plugin.name+'</span> <i class="fas fa-chevron-right"></i> '+response.label);
- });
- }
- $(component).off('click').click(function(){
- modal.modal('show');
- $('.plugin-list',modal).fill({action:'core_plugin_search',includeCore : true},function(){
- $('.plugin',modal).click(function(){
- $('.plugin',modal).removeClass('active');
- $(this).addClass('active');
- searchEntities();
- });
- });
- });
- $('.entitypicker-clear',component).click(function(event){
- event.stopPropagation();
- input.val('');
- refreshValue();
- });
- refreshValue();
- break;
- case 'filepicker':
- if(input.get(0).tagName !='INPUT') return;
- var data = input.data();
- var container;
- var refreshComponent = function (){
- var folders = input.val().split('/');
- var html = '';
- for (var i in folders) {
- var folder = folders[i];
- if(!folder) continue;
- html += '<li><i class="fas fa-slash text-muted""></i><span class="pathlabel" '+(input.hasAttr('readonly') || !data.editable ?'':' contenteditable="true"')+' >'+folder+'</span></li>';
- }
- container.find('>ul').html(html);
- $('.pathlabel',container).click(function(event){
- event.stopPropagation();
- if(!input.hasAttr('readonly')) $('.filepicker-browse',container).click();
- }).keyup(function(){
- if(input.hasAttr('readonly') || !data.editable) return;
- var folders = input.val().split('/');
- folders[$(this).closest('li').index()] = $(this).text();
- input.val(folders.join('/'));
- });
- }
- if(!input.data("data-component")){
- container = $('<div class="'+input.attr('class')+' data-type-filepicker"><i class="far fa-folder"></i><ul></ul> <i class="filepicker-browse far fa-window-restore text-muted"></i> <i class="filepicker-clear fas fa-times text-muted"></i></div>');
- input.before(container);
- input.data("data-component", container);
- input.addClass('component-raw-value'); // utilisé par les filtres / etc.. pour dissocier la valeur brute du composant
- $('.filepicker-clear',container).click(function(event){
- event.stopPropagation();
- input.val('');
- refreshComponent();
- input.change();
- });
- container.click(function(){
- if(input.hasAttr('readonly')) return;
- $('#filepicker-modal').remove();
- var modal = $('<div class="modal fade filepicker-modal" id="filepicker-modal" aria-hidden="true">\
- <div class="modal-dialog"> \
- <div class="modal-content"> \
- <div class="modal-header"> \
- <h5 class="modal-title">Sélection d\'un élement</h5>\
- <button type="button" class="close" data-dismiss="modal" aria-label="Fermer">\
- <span aria-hidden="true">×</span>\
- </button>\
- </div>\
- <div class="modal-body">\
- <ul class="tree-folders folders-container">\
- <li class="hidden folder {{className}}" data-label="{{label}}" data-path="{{path}}"><i class="far fa-folder"></i> <span>{{label}}</span><ul class="folders-container"></ul></li>\
- </ul>\
- </div>\
- <div class="modal-footer">\
- <button type="button" class="btn btn-primary btn-select">Sélectionner</button>\
- </div>\
- </div>\
- </div>\
- </div>');
- $('body').append(modal);
- $('.tree-folders',modal).on('click','li',function(event){
- var li = $(this);
- if(li.hasClass('folder-focused')){
- var parent = li.parent().parent();
- treeSearch(parent.attr('data-path') == null ? '.' : parent.attr('data-path'));
- }else{
- treeSearch(li.attr('data-path'));
- }
- if(event) event.stopPropagation();
- });
- $('.btn-select',modal).click(function(){
- var path = $('.folder-focused',modal).attr('data-path');
- if(!path) return $.message('error','Aucun chemin n\'est sélectionné');
- input.val(path);
- refreshComponent();
- modal.modal('hide');
- input.change();
- });
- var treeSearch = function(folderPath){
- $.action({
- action: 'core_file_search',
- keyword : '',
- //sort : sort,
- root :data.root,
- folder : folderPath ? folderPath : ''
- },function(r){
- var tree = $('ul.tree-folders',modal);
- $('li:not(:eq(0))',tree).remove();
- var tpl = $('li:not(:visible)',tree).get(0).outerHTML;
- tree.find('li:visible').remove();
- var selected = folderPath ? folderPath : '' ;
- if(selected.length>=2 && selected.substring(0,2) == './') selected = selected.substring(2);
- for(var k in r.tree){
- var path = r.tree[k];
- var parts = path.split('/');
- var recipient = tree.parent();
- for(var i in parts){
- var part = parts[i];
- var path = parts.slice(0,parseInt(i)+1).join('/');
- var element = $('> .folders-container > li[data-path="'+path+'"]',recipient);
- if(element.length ==0){
- var classes = '';
- if(selected==path) classes+= ' folder-focused ';
- if(selected && (selected.indexOf(path+'/')!==-1 || selected==path) ) classes+= ' folder-open ';
- var row = {
- path : path,
- label : part,
- className : classes
- };
- var element = $(Mustache.render(tpl,row));
- element.removeClass('hidden');
- recipient.find('> .folders-container').append(element);
- }
- recipient = element;
- }
- }
- });
- }
- treeSearch(input.val());
- modal.modal('show');
- });
- }else{
- container = input.data("data-component");
- }
- if(input.hasAttr('readonly')){
- container.attr('readonly','');
- }else{
- container.removeAttr('readonly');
- }
- if(input.hasAttr('required')) container.attr('required','');
- if(input.val()) refreshComponent();
- break;
- /**
- * data-dictionary : Le slug du dictionary à utiliser
- */
- case 'dictionary-table':
- if(input.hasClass('component-dictionary-table')) return;
- if(!input.attr('data-dictionary') || !input.attr('data-dictionary').length) return;
- var tpl = $('.component-dictionary-table').get(0).outerHTML;
- var inputData = input.data();
- $.action({
- action: 'core_dictionary_component_load',
- slug : input.attr('data-dictionary')
- },function(r){
- if(!r.content) {
- input.append('<div class="alert alert-warning mb-0"><i class="fas fa-exclamation-triangle mr-2"></i>Liste spécifiée inexistante</div>');
- return;
- }
- var list = $(Mustache.render(tpl,{label:'{{label}}', slug:'{{slug}}', id:'{{id}}',parent:r.content}));
- input.append(list);
- list.removeClass('hidden');
- dictionary_table_refresh(list);
- //Save
- input.on('click','thead .btn-success',function(){
- var line = $(this).closest('tr');
- var data = {
- action: inputData.saveAction ? inputData.saveAction : 'core_dictionary_table_save',
- label: line.find('input.list-label').val(),
- id: list.attr('data-id'),
- list: list.attr('data-dictionary')
- };
- if(list.find('input.list-slug')) data.slug = $('input.list-slug', list).val();
- $.action(data, function(r){
- list.attr('data-id', '');
- line.find('input').val('');
- $.message('success','Enregistré');
- dictionary_table_refresh(list);
- });
- });
- //Suppression
- input.on('click','tbody tr .btn-danger',function(){
- if(!confirm('Êtes-vous sûr de vouloir supprimer cet élément de liste ?')) return;
- var line = $(this).closest('tr');
- $.action({
- action: inputData.deleteAction ? inputData.deleteAction : 'core_dictionary_delete',
- id: line.attr('data-id')
- },function(r){
- line.remove();
- line.closest('.edit-field').val('');
- $.message('info', 'Élément de liste supprimé');
- });
- });
- //Édition
- input.on('click','tbody tr .btn-edit',function(){
- var line = $(this).closest('tr');
- $.action({
- action: inputData.editAction ? inputData.editAction : 'core_dictionary_edit',
- id: line.attr('data-id')
- },function(r){
- list.find('input.list-label').val(r.label);
- if(list.find('input.list-slug')) $('input.list-slug', list).val(r.slug);
- list.attr('data-id',r.id);
- });
- });
- });
- break;
- //Permet aux plugins d'ajouter leurs composants
- //via la fonction init_components_nomcomposant(input);
- default:
- var type = input.attr('data-type').replace(/[^a-z0-9]/i,'_');
- if(window['init_components_'+type] !=null) window['init_components_'+type](input);
- break;
- }
- });
- init_tooltips();
- }
- /** TOOLTIPS **/
- function init_tooltips(selector){
- //Clean des tooltip qui restent en suspend sans hover de la souris
- $('div.tooltip[role="tooltip"]').tooltip('dispose');
- var selected = selector ? $('[data-tooltip]',selector) : '[data-tooltip]';
- $(selected).each(function(){
- var element = $(this);
- var options = {html:true};
- if(element.attr('data-placement')) options.placement = element.attr('data-placement');
- element.tooltip('dispose');
- element.tooltip(options);
- });
- }
|