PageSourceSearch

https://atlasddt31.fr/assets/js/artificialisation/artif.js?v2

js atlasddt31.fr collected 2026-10-08 10:36:45 UTC 37,128 bytes, 1,107 lines download raw bytes

1/* Min etmax des données  */
2const conso_min_year = 2013;
3const conso_max_year = 2023;
4
5const num_jenks_classes = 5;
6
7/* Contiendront les bornes des classes de légendes */
8/* Dynamiques car les bornes (min_year max_year sont variables) */
9let jenks_coms = [];
10let jenks_epcis = [];
11
12let current_min_year = conso_min_year;
13let current_max_year = conso_max_year;
14
15/* -- 5 classes green from colorbrewer--  */
16const artif_epci_colors = [
17    {min: 3.8, max: 5.7, color: '#006837'},
18    {min: 5.7, max: 9.8, color: '#31a354'},
19    {min: 9.8, max: 18, color: '#78c679'},
20    {min: 18,  max: 29.4, color: '#c2e699'},
21    {min: 29.4, max: 54, color: '#ffffcc'},
22];
23
24const artif_com_colors = [
25    {min: 0.5, max: 8.1, color: '#006837'},
26    {min: 8.1, max: 15.6, color: '#31a354'},
27    {min: 15.6, max: 26.3, color: '#78c679'},
28    {min: 26.3, max: 42.2, color: '#addd8e'},
29    {min: 42.2, max: 61, color: '#d9f0a3'},
30    {min: 61, max: 82, color: '#ffffcc'},
31];
32
33// Couleurs pour 5 classes de conso d'espace
34//const conso_colors = ['#006837', '#31a354', '#78c679', '#c2e699', '#ffffcc'];
35const conso_colors = ['#ffffd4', '#fed98e', '#fe9929', '#d95f0e', '#993404'];
36
37// Remplissage initial des classes de légendes jenks_coms et jenks_epcis
38set_conso_epcis_classes(); 
39set_conso_coms_classes();
40
41$(function() {
42    // set map
43    const estompage = new ol.layer.Tile({
44        'title':'Relief estompé',
45        visible: true,
46        source: new ol.source.WMTS({
47            url: 'https://data.geopf.fr/wmts',
48            layer: "ELEVATION.ELEVATIONGRIDCOVERAGE.SHADOW",
49            matrixSet: "PM",
50            format: "image/png",
51            style: "estompage_grayscale",
52            tileGrid : new ol.tilegrid.WMTS({
53                origin: [-20037508,20037508], // topLeftCorner
54                resolutions: get_resol(), // résolutions
55                matrixIds: ["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"] // ids des TileMatrix
56            })
57        }), 
58    });
59
60    /* ------------------------------------------------------- Departement layer --- */
61    function createDeptTextStyle(feature, fill, stroke, txt) {
62        return new ol.style.Text({
63          font: '12px "Arial black",sans-serif',
64          text: txt,
65          textAlign:'center',
66          // offsetX:8,
67          fill: new ol.style.Fill({color:fill}),
68          stroke: new ol.style.Stroke({color:stroke, width:2}),
69          overflow: false,
70        });
71    };
72
73    function deptStyleFunction(feature, res) {
74        const datadep = artif31.dep[0];
75        let text = '';
76        let text_color = '#c1c1c1';
77        let stroke_color = 'rgba(150,150,150, 1)';
78        let color = 'transparent';
79        let zIndex = 1;
80
81        if ( feature.getProperties().dep == '31') {
82            color =  get_epci_artifcolor(datadep.tx_art_2013);
83            stroke_color = text_color = 'rgba(0,0,0, 1)';
84            zIndex = 2;
85        }
86
87        if ( res > 250) {
88            text = createDeptTextStyle(feature, text_color, '#fff', feature.getProperties().libgeo);
89        }
90
91        return new ol.style.Style({
92            stroke: new ol.style.Stroke({
93                color: stroke_color,
94                width: 2
95              }),
96              fill: new ol.style.Fill({
97                color: color
98              }),
99              zIndex: zIndex,
100              text:text
101        });
102    }
103
104    function consodeptStyleFunction(feature, res) {
105        const datadep = artif31.dep[0];
106
107        let text = '';
108        let text_color = '#c1c1c1';
109        let stroke_color = 'rgba(150,150,150, 1)';
110        let color = 'transparent';
111        let zIndex = 1;
112
113        if ( feature.getProperties().dep == '31') {
114            // color =  get_epci_artifcolor(datadep.tx_art_2013);
115            color = get_epci_jenks_color(getnafart(datadep)/datadep['surfcom202']);
116            stroke_color = text_color = 'rgba(0,0,0, 1)';
117            zIndex = 2;
118            
119        }
120
121        if ( res > 250) {
122            text = createDeptTextStyle(feature, text_color, '#fff', feature.getProperties().libgeo);
123        }
124
125        return new ol.style.Style({
126            stroke: new ol.style.Stroke({
127                color: stroke_color,
128                width: 2
129              }),
130              fill: new ol.style.Fill({
131                color: color
132              }),
133              zIndex: zIndex,
134              text:text
135        });
136    }
137    
138    const dept_layer = new ol.layer.Vector({
139        'title':'Départements',
140        allwaysOnTop : false,
141        source: new ol.source.Vector({
142        url: base_url + 'get_json/departement/dept_limit31.json',
143        format: new ol.format.GeoJSON(),
144        }),
145        style: deptStyleFunction
146    });
147
148    const dept_layer_conso = new ol.layer.Vector({
149        'title':'Départements',
150        allwaysOnTop : false,
151        source: new ol.source.Vector({
152        url: base_url + 'get_json/departement/dept_limit31.json',
153        format: new ol.format.GeoJSON(),
154        }),
155        style: consodeptStyleFunction
156    });
157
158    /* ------------------------------------------------------- EPCI layer --- */
159    function createTextStyle(feature, fill, stroke, txt) {
160        return new ol.style.Text({
161          font: '11px Calibri,sans-serif',
162          text: txt,
163          textAlign:'center',
164          // offsetX:8,
165          fill: new ol.style.Fill({color:fill}),
166          stroke: new ol.style.Stroke({color:stroke, width:2}),
167          overflow: true,
168        });
169    };
170
171    function epciStyleFunction(feature, res) {
172        const feature_id = feature.getProperties().siren_epci;
173        
174        const dataepci = get_epci_data(feature_id);
175        
176        let text = '';
177        if ( res > 55 && res < 250 ) {
178            //text = createTextStyle(feature,'#000', '#fe3', dataepci['name']);
179            text = createTextStyle(feature,'#000', '#fe3', feature.getProperties().epci);
180        }
181        //const color = scot_colors[feature.getProperties().idscot].replace('alpha', dataepci.evo);
182        const color = get_epci_artifcolor(dataepci.tx_art_2013);
183        const strokecolor = 'rgba(0,0,0,.7)'
184        
185        return new ol.style.Style({
186            stroke: new ol.style.Stroke({
187                color: strokecolor,
188                width: .7
189              }),
190              fill: new ol.style.Fill({
191                color: color
192              }),
193              text:text
194        });
195    }
196
197    function consoepciStyleFunction(feature, res) {
198        const feature_id = feature.getProperties().siren_epci;
199        
200        const dataepci = get_epci_data(feature_id);
201        
202        let text = '';
203        if ( res > 55 && res < 250 ) {
204            text = createTextStyle(feature,'#000', '#fe3', feature.getProperties().epci);
205        }
206
207        const color = get_epci_jenks_color(getnafart(dataepci)/dataepci['surfcom202']);
208
209        const strokecolor = 'rgba(0,0,0,.7)';
210        
211        return new ol.style.Style({
212            stroke: new ol.style.Stroke({
213                color: strokecolor,
214                width: .7
215              }),
216              fill: new ol.style.Fill({
217                color: color
218              }),
219              text:text
220        });
221    }
222
223    const epci_layer = new ol.layer.Vector({
224        'title':'EPCI',
225        allwaysOnTop : false,
226        // visible: false,
227        source: new ol.source.Vector({
228        url: base_url + 'get_json/departement/epci.json',
229        format: new ol.format.GeoJSON(),
230        }),
231        visible:false,
232        style: epciStyleFunction
233    });
234
235    const epci_layer_conso = new ol.layer.Vector({
236        'title':'EPCI',
237        allwaysOnTop : false,
238        // visible: false,
239        source: new ol.source.Vector({
240        url: base_url + 'get_json/departement/epci.json',
241        format: new ol.format.GeoJSON(),
242        }),
243        visible:false,
244        style: consoepciStyleFunction
245    });
246
247
248    /* ------------------------------------------------------- Communes layer --- */
249    function communesStyleFunction(feature, res) { 
250        const feature_id = feature.getProperties().codgeo;
251        const datacom = get_com_data(feature_id);
252
253        if ( datacom === undefined ) {
254            return;
255        }
256        
257        let text = '';
258        if ( res < 55) {
259            text = createTextStyle(feature,'#000', '#fe3', datacom['nom']);
260        }
261
262        const color = get_com_artifcolor(datacom.tx_art_2013);
263        const strokecolor = 'rgba(133,133,133,.7)'
264        
265        return new ol.style.Style({
266            stroke: new ol.style.Stroke({
267                color: strokecolor,
268                width: 1
269              }),
270              fill: new ol.style.Fill({
271                color: color
272              }),
273              text:text
274        });
275    }
276
277    function consocommunesStyleFunction(feature, res) { 
278        const feature_id = feature.getProperties().codgeo;
279        const datacom = get_com_data(feature_id);
280
281        if ( datacom === undefined ) {
282            return;
283        }
284        
285        let text = '';
286        if ( res < 55) {
287            text = createTextStyle(feature,'#000', '#fe3', datacom['nom']);
288        }
289
290        const color = get_com_jenks_color(getnafart(datacom)/datacom['surfcom202']);
291        const strokecolor = 'rgba(133,133,133,.7)'
292        
293        return new ol.style.Style({
294            stroke: new ol.style.Stroke({
295                color: strokecolor,
296                width: 1
297              }),
298              fill: new ol.style.Fill({
299                color: color
300              }),
301              text:text
302        });
303    }
304
305    const communes_layer = new ol.layer.Vector({
306        'title':'Communes',
307        allwaysOnTop : false,
308        // visible: false,
309        source: new ol.source.Vector({
310            url: base_url + 'get_json/departement/communes.json',
311        format: new ol.format.GeoJSON(),
312        }),
313        visible:true,
314        style: communesStyleFunction
315    });
316
317    const communes_layer_conso = new ol.layer.Vector({
318        'title':'Communes',
319        allwaysOnTop : false,
320        // visible: false,
321        source: new ol.source.Vector({
322            url: base_url + 'get_json/departement/communes.json',
323        format: new ol.format.GeoJSON(),
324        }),
325        visible:true,
326        style: consocommunesStyleFunction
327    });
328
329    const artif_overlay = new ol.Overlay({
330        element: document.getElementById('artifpopup'),
331        autoPan: {
332            animation: {
333              duration: 250,
334            }
335        }
336    });
337
338    /* ------------------------------------------------------- Map artificialisation ---  */
339    let map_artif = new ol.Map({
340        interactions: ol.interaction.defaults({mouseWheelZoom:false}),
341        controls: ol.control.defaults().extend([
342            new ol.control.FullScreen()
343        ]),
344        overlays: [artif_overlay],
345        target: 'contmap_artif',
346        view: new ol.View({
347            zoom: 8.9,
348            center: [130742.2,5358235.1],
349            maxZoom: 15,
350            minZoom: 8
351        }),
352        layers: [dept_layer, epci_layer, communes_layer, estompage]
353    });
354
355    const mouseWheelInt = new ol.interaction.MouseWheelZoom();
356    map_artif.addInteraction(mouseWheelInt);
357
358    map_artif.on('wheel', function(evt) {
359        mouseWheelInt.setActive(ol.events.condition.shiftKeyOnly(evt));
360    });
361
362    map_artif.addControl(new ol.control.LayerSwitcher({ trash: false, extent:true, collapsed: false, reordering:true }));
363
364    map_artif.addControl(new ol.control.ScaleLine());
365
366    map_artif.on('singleclick', function (evt) {
367        $('#artifpopup-content').empty();
368        let template = ``;
369        let nbcom = 0;
370        let nbepci = 0;
371        let nbdep = 0;
372        map_artif.forEachFeatureAtPixel(evt.pixel,
373            function(feature, layer) { 
374                if ( nbcom == 0 && layer.getProperties().title == 'Communes' ) {
375                    const datacom = get_com_data(feature.getProperties().codgeo);
376                    template += `<div>Commune de <strong>${datacom.nom}</strong> <small>(${datacom.idcom})</small><div>`;
377                    template += `<div><strong class="soulign">${datacom.tx_art_2013}%</strong> du territoire communal artificialisé en 2013. 
378                        <small class="soulign">≃ ${new Intl.NumberFormat().format(Math.round(datacom.surf_art_2013/10000))} ha</small></div>
379                        <div><small><strong>${new Intl.NumberFormat().format(datacom.pop_2013)}</strong> habitants et 
380                        <strong>${new Intl.NumberFormat().format(datacom.emp_2013)}</strong> emplois en 2013.</small></div> 
381                        <hr>`;
382                    nbcom++;
383                    /*
384                    map_conso.getView().fit(feature.getGeometry().getExtent(), {duration:700});
385                    let prepo = "de";
386                    if ( ['a','e','i','o','u','y'].indexOf(datacom.nom.substr(0,1).toLowerCase()) !== -1 ) {
387                        prepo = "d'";
388                    }
389                    $("#chartconso_title").html(`Commune ${prepo} ${datacom.nom} <small style="font-weight:normal">(${datacom.idcom}), consommation d'espaces entre 2013 et 2023</small>`);
390                    set_conso_chart('com', datacom.idcom);*/
391                }
392                if ( nbepci == 0 && layer.getProperties().title == 'EPCI' ) {
393                    const dataepci = get_epci_data(feature.getProperties().siren_epci);
394                    template += `<div><strong>${dataepci.nom_epci}</strong> <small>(${dataepci.siren_epci})</small><div>`;
395                    template += `<div><strong class="soulign">${dataepci.tx_art_2013}%</strong> du territoire artificialisé en 2013. 
396                        <small class="soulign">≃ ${new Intl.NumberFormat().format(Math.round(dataepci.surf_art_2013/10000))} ha</small></div>
397                        <div><small><strong>${new Intl.NumberFormat().format(dataepci.pop_2013)}</strong> habitants et 
398                        <strong>${new Intl.NumberFormat().format(dataepci.emp_2013)}</strong> emplois en 2013.</small></div> 
399                        <hr>`;
400                    nbepci++;
401                    /*
402                    if ( nbcom == 0 ) { 
403                        map_conso.getView().fit(feature.getGeometry().getExtent(), {duration:700});
404                        $("#chartconso_title").html(`${dataepci.nom_epci} <small style="font-weight:normal">(${dataepci.siren_epci}
404), consommation d'espaces entre 2013 et 2023</small>`);
405                        set_conso_chart('epci', dataepci.siren_epci);
406                    }*/
407                    
408                }
409                if ( nbdep == 0 && layer.getProperties().title == 'Départements' && feature.getProperties().dep == '31') {
410                    const datadep = artif31.dep[0];
411                    template += `<div><strong>${feature.getProperties().libgeo}</strong><div>`;
412                    template += `<div><strong class="soulign">${datadep.tx_art_2013}%</strong> du territoire artificialisé en 2013. 
413                        <small class="soulign">≃ ${new Intl.NumberFormat().format(Math.round(datadep.surf_art_2013/10000))} ha</small></div>
414                        <div><small><strong>${new Intl.NumberFormat().format(datadep.pop_2013)}</strong> habitants et 
415                        <strong>${new Intl.NumberFormat().format(datadep.emp_2013)}</strong> emplois en 2013.</small></div> 
416                        `;
417                    nbdep++;
418                    /*
419                    if (nbcom == 0 && nbepci == 0) {
420                        map_conso.getView().fit(feature.getGeometry().getExtent(), {duration:700});
421                        set_conso_chart('dep');
422                    }*/
423                }
424            });
425
426            if (template.trim() != '') {
427                $('#artifpopup-content').html(template);
428                artif_overlay.setPosition(evt.coordinate);
429            } else {
430                $('#artifpopup-closer').trigger('click');
431            }
432    });
433
434    $(document).on('click', '#artifpopup-closer', function() { 
435        artif_overlay.setPosition(undefined);
436        $(this).blur();
437        return false;
438    });
439
440    $(document).on('click', '#popupconso-closer', function() { 
441        conso_overlay.setPosition(undefined);
442        $(this).blur();
443        return false;
444    });
445
446
447    /* ------------------------------------------------------- Legend Artif --- */
448    const legend = new ol.legend.Legend({
449        title: 'Légende',
450        textStyle: new ol.style.Text({
451            font: 'bold 12px Arial, sans-serif',
452        }),
453        margin: 5,
454        size: [20, 10]
455    })
456
457    const legendCtrl = new ol.control.Legend({ 
458        legend: legend,
459        collapsed: false,
460    });
461
462    map_artif.addControl(legendCtrl);
463
464    legend.addItem({
465        className: 'Communes',
466        title: 'Communes',
467        textStyle: new ol.style.Text({
468            font: 'bold 14px Arial, sans-serif',
469        }),
470        height: 30
471    });
472
473    artif_com_colors.forEach(function(item) {
474
475        legend.addItem({
476            //className: 'at_item',
477            title: 'Entre '+ item['min'] +' et '+ item['max'] +'%',
478            textStyle: new ol.style.Text({
479                font: '11px Arial, sans-serif',
480            }),
481            style: get_legende_rectangle(item['color'], '#0000000'),
482            typeGeom: 'Polygon',
483        });
484    
485    });
486
487    legend.addItem({
488        className: 'EPCI',
489        title: 'EPCI',
490        textStyle: new ol.style.Text({
491            font: 'bold 14px Arial, sans-serif',
492        }),
493        height: 30
494    });
495
496    artif_epci_colors.forEach(function(item) {
497
498        legend.addItem({
499            //className: 'at_item',
500            title: 'Entre '+ item['min'] +' et '+ item['max'] +'%',
501            textStyle: new ol.style.Text({
502                font: '11px Arial, sans-serif',
503            }),
504            style: get_legende_rectangle(item['color'], '#0000000'),
505            typeGeom: 'Polygon',
506        });
507    
508    });
509
510    legend.addItem({
511        className: 'Departement',
512        title: 'Département 31',
513        textStyle: new ol.style.Text({
514            font: 'bold 14px Arial, sans-serif',
515        }),
516        height: 30
517    });
518
519    legend.addItem({
520        //className: 'at_item',
521        title: artif31.dep[0].tx_art_2013 +'%',
522        textStyle: new ol.style.Text({
523            font: '11px Arial, sans-serif',
524        }),
525        style: get_legende_rectangle(get_epci_artifcolor(artif31.dep[0].tx_art_2013), '#0000000'),
526        typeGeom: 'Polygon',
527    });
528
529    /* ------------------------------------------------------- Map artificialisation ---  */
530
531    const conso_overlay = new ol.Overlay({
532        element: document.getElementById('popupconso'),
533        autoPan: {
534            animation: {
535              duration: 250,
536            }
537        }
538    });
539
540    let map_conso = new ol.Map({
541        interactions: ol.interaction.defaults({mouseWheelZoom:false}),
542        /*controls: ol.control.defaults().extend([
543            new ol.control.FullScreen()
544        ]),*/
545        overlays: [conso_overlay],
546        target: 'contmap_conso',
547        view: new ol.View({
548            zoom: 8.3,
549            center: [130742.2,5358235.1],
550            maxZoom: 15,
551            minZoom: 8
552        }),
553        layers: [dept_layer_conso, epci_layer_conso, communes_layer_conso] //dept_layer_conso]
554    });
555
556    const mouseWheelInt2 = new ol.interaction.MouseWheelZoom();
557    map_conso.addInteraction(mouseWheelInt2);
558
559    map_conso.on('wheel', function(evt) {
560        mouseWheelInt2.setActive(ol.events.condition.shiftKeyOnly(evt));
561    });
562
563    map_conso.addControl(new ol.control.LayerSwitcher({ trash: false, extent:true, collapsed: fal
563se, reordering:true }));
564
565    map_conso.addControl(new ol.control.ScaleLine());    
566
567    map_conso.on('singleclick', function (evt) {
568
569        $('#popupconso-content').empty();
570
571        let template = ``;
572        let nbcom = 0;
573        let nbepci = 0;
574        let nbdep = 0;
575        let dataset;
576
577        map_conso.forEachFeatureAtPixel(evt.pixel,
578            function(feature, layer) {
579
580                if ( nbcom == 0 && layer.getProperties().title == 'Communes' ) {
581                    dataset = get_com_data(feature.getProperties().codgeo);
582                    nbcom++;
583
584                    let prepo = "de";
585                    if ( ['a','e','i','o','u','y'].indexOf(dataset.nom.substr(0,1).toLowerCase()) !== -1 ) {
586                        prepo = "d'";
587                    }
588                    $("#chartconso_title").html(`Commune ${prepo} ${dataset.nom} <small style="font-weight:normal">(${dataset.idcom}), consommation d'espaces entre 2013 et 2023</small>`);
589                    set_conso_chart('com', dataset.idcom);
590                }
591
592                if ( nbepci == 0 && layer.getProperties().title == 'EPCI' ) {
593                    dataset = get_epci_data(feature.getProperties().siren_epci);
594                    nbepci++;
595                    if ( nbcom == 0 ) { 
596                        $("#chartconso_title").html(`${dataset.nom_epci} <small style="font-weight:normal">(${dataset.siren_epci}), consommation d'espaces entre 2013 et 2023</small>`);
597                        set_conso_chart('epci', dataset.siren_epci);
598                    }
599                }
600                if ( nbdep == 0 && layer.getProperties().title == 'Départements' && feature.getProperties().dep == '31') {
601                    dataset = artif31.dep[0];
602                    nbdep++;
603                    if ( nbcom == 0 && nbepci == 0 ) { 
604                        set_conso_chart('dep');
605                    }
606                }
607
608            }
609        );
610
611        if (template.trim() != '') {
612            $('#popupconso-content').html(template);
613            conso_overlay.setPosition(evt.coordinate);
614        } else {
615            $('#popupconso-closer').trigger('click');
616        }
617
618    });
619
620    /* ------------------------------------------------------- Legend Artif --- */
621    const consolegend = new ol.legend.Legend({
622        title: 'Légende',
623        textStyle: new ol.style.Text({
624            font: 'bold 12px Arial, sans-serif',
625        }),
626        margin: 3,
627        size: [20, 10]
628    })
629
630    const consolegendCtrl = new ol.control.Legend({ 
631        legend: consolegend,
632        collapsed: false,
633    });
634
635    map_conso.addControl(consolegendCtrl);
636
637    set_conso_legend(consolegend);
638
639    /* ---- Partie conso espaces ---- */
640    $('#min_year').attr({ min: conso_min_year, max: conso_max_year-1}).val(conso_min_year);
641    $('#min_year_txt').text(conso_min_year);
642    $('#max_year').attr({ min: conso_min_year + 1, max: conso_max_year }).val(conso_max_year);
643    $('#max_year_txt').text(conso_max_year);
644
645    $('#min_year, #max_year').on("input", function() {
646        const elem = $(this);
647        $('#' + elem.attr("id") + "_txt").text(elem.val()); 
648    });
649
650    // min_year ne peut pas être supérieur à max_year
651    $('#min_year, #max_year').on("change", function() {
652        
653        if ( $('#min_year').val() >= $('#max_year').val() ) {
654            $('#max_year').val($('#min_year').val()*1+1);
655            $('#max_year_txt').text($('#min_year').val()*1+1);
656        }
657        current_min_year = $('#min_year').val();
658        current_max_year = $('#max_year').val();
659     
660        set_conso_epcis_classes(); 
661        set_conso_coms_classes();
662
663        set_conso_legend(consolegend);
664
665        dept_layer_conso.setStyle(consodeptStyleFunction);
666        epci_layer_conso.setStyle(consoepciStyleFunction);
667        communes_layer_conso.setStyle(consocommunesStyleFunction);
668
669    });
670
671
672    /* Conso chart */
673    set_conso_chart('dep');
674});
675
676function set_conso_chart (what, id) {
677    
678    let dataset;
679    if ( what == 'dep') {
680        dataset = artif31['dep'][0];
681        $("#chartconso_title").html(`Département de Haute-Garonne, <small style="font-weight:normal">
681consommation d'espaces entre 2013 et 2023</small>`);
682    } else if ( what == 'com' ) {
683        dataset = get_com_data(id);
684    }  else if ( what == 'epci' ) {
685        dataset = get_epci_data(id);
686    }
687
688    let ev_pop = dataset.ev_pop > 0 ? '+' + dataset.ev_pop : dataset.ev_pop; 
689    let ev_emp = dataset.ev_emp > 0 ? '+' + dataset.ev_emp : dataset.ev_emp;
690
691    let tb_tmpl = `<table class="table table-sm table-bordered">
692        <tr><td></td><th class="text-end">2013</th><th class="text-end">2020</th><th class="text-end">Evol.</th></tr>
693        <tr><th>Population</th><td class="text-end">${Highcharts.numberFormat(dataset.pop_2013, 0)}</td><td class="text-end">${Highcharts.numberFormat(dataset.pop_2020, 0)}</td><td class="text-end">${ev_pop} %</td></tr>
694        <tr><th>Emploi</th><td class="text-end">${Highcharts.numberFormat(dataset.emp_2013, 0)}</td><td class="text-end">${Highcharts.numberFormat(dataset.emp_2020, 0)}</td><td class="text-end">${ev_emp} %</td></tr>
695    `;
696    
697    $('#popemploi_tb').html(tb_tmpl);
698
699    const cats = Array.from({ length: (conso_max_year - conso_min_year) }, (v, i) => i+conso_min_year);
700    cats.reverse();
701    const series_ord = ['mix','inc','inf','act','hab']; 
702    const series_alias = ['Mixte','Inconnu','Infrastructures','Activité','Habitat'];
703
704    let serie = [];
705
706    for ( s in series_ord ) {
707        let one = {};
708        one.name = series_alias[s];
709        one.data = [];
710        for ( ka in cats ) {
711            let topush = 0;
712            if ( series_ord[s] == 'inf') {
713                topush = dataset['art' + (cats[ka]-2000) + 'rou' + ((cats[ka]+1)-2000)] + dataset['art' + (cats[ka]-2000) + 'fer' + ((cats[ka]+1)-2000)];
714            } else {
715                topush = dataset['art' + (cats[ka]-2000) + series_ord[s] + ((cats[ka]+1)-2000)];
716            }
717            one.data.push(topush);
718        }
719        serie.push(one);
720    } 
721
722    Highcharts.chart('chartconso', {
723        chart: {
724            type: 'bar',
725        },
726        colors: ['#38a800', '#adadad', '#a80000', '#00c5ff', '#ffaa00'],
727        title: {
728            text: undefined,
729        },
730        xAxis: {
731            categories: cats,
732        },
733        yAxis: {
734            min: 0,
735            title: {
736                text: 'Surfaces consommées, en m²'
737            },
738            labels: {
739                formatter: function() {
740                    return Highcharts.numberFormat(this.value,0);
741                }
742            }
743        },
744        legend: {
745            reversed: true
746        },
747        plotOptions: {
748            series: {
749                stacking: 'normal',
750                dataLabels: {
751                    enabled: true,
752                    useHTML: true,
753                    formatter: function() {
754                        if ( this.point.percentage == 0 ) {
755                            return null;
756                        }
757                        return Highcharts.numberFormat(this.point.percentage,0)+'<small>%</small>';
758                    },
759                    zIndex: 1
760                }
761            }
762        },
763        tooltip: {
764            formatter: function() {
765                let s = '<b>'+ this.x +'</b>';
766                s += '<table>'
767                $.each(this.points, function(i, point) {
768                    s += '<tr><th><span style="display:inline-block; width:4px; background-color:' + point.series.color+ '">&nbsp;</span> '+ point.series.name +' <small style="font-weight:normal;">('+ Highcharts.numberFormat(point.percentage,0) +'%)</small></th><td style="text-align:right">'+ Highcharts.numberFormat(point.y, 0) + ' m²</td></tr>';
769                });
770                s += '<tr style="border-top:1px solid #aaa"><th>Total</th><td style="text-align:right">'+ Highcharts.numberFormat(this.points[0].total, 0) + ' m²</td></tr></table>'
771                return s;
772            },
773            shared: true,
774            useHTML:true,
775        },
776        series: serie
777    });
778
779}
780
781
782function set_conso_epcis_classes() {
783    let epcis_vals = [];
784    artif31.epcis.forEach(function(item) {
785        epcis_vals.push(getnafart(item)/item.surfcom202);
786    });
787
788    jenks_epcis = jenks(epcis_vals, num_jenks_classes);
789}
790
791function set_conso_coms_classes() {
792    let coms_vals = [];
793    artif31.coms.forEach(function(item) {
794        coms_vals.push(getnafart(item)/item.surfcom202);
795    });
796
797    jenks_coms = jenks(coms_vals, num_jenks_classes);
798}
799
800/* renvoie la somme des nafart entre 2 années: ex:
801naf13art14 + naf14art15 +naf15art16  entre 2013 et 2016 */
802function getnafart(dataset) {
803    let sum_surf = 0;
804    for ( i = current_min_year; i < current_max_year; i++ ) {
805        const key = 'naf' + (i-2000) + 'art' +(1+(i-2000)*1);
806        sum_surf += dataset[key];
807    }
808    return sum_surf;
809}
810
811/* renvoie la couleur du tableau jenks_epcis 
812correspondant à la valeur envoyée*/
813function get_epci_jenks_color(surf) {
814    let key = 0;
815    for ( let k in jenks_epcis ) {
816        if ( k == 0 && surf <= jenks_epcis[k] ) {
817            key = 1;
818        }
819        else if ( k > 0 && surf <= jenks_epcis[k] ) {
820            key = k;
821            break;
822        }
823    }
824    return conso_colors[key-1];
825}
826
827/* renvoie la couleur du tableau jenks_coms 
828correspondant à la valeur envoyée*/
829function get_com_jenks_color(surf) {
830    let key = 0;
831    for ( let k in jenks_coms ) {
832        if ( k == 0 && surf <= jenks_coms[k] ) {
833            key = 1;
834        }
835        else if ( k > 0 && surf <= jenks_coms[k] ) {
836            key = k;
837            break;
838        }
839    }
840    return conso_colors[key-1];
841}
842
843
844function get_epci_data(id) {
845    return artif31.epcis.find(( {siren_epci} ) => siren_epci == id);
846}
847
848function get_com_data(id) {
849    return artif31.coms.find(( {idcom} ) => idcom == id);
850}
851
852function get_epci_artifcolor(num) {
853    for (let i in artif_epci_colors) {
854        if ( num > artif_epci_colors[i]['min'] && num <= artif_epci_colors[i]['max'] ) {
855            return artif_epci_colors[i]['color'];
856        } 
857    }
858    return '#000000';
859} 
860
861function get_com_artifcolor(num) {
862    for (let i in artif_com_colors) {
863        if ( num > artif_com_colors[i]['min'] && num <= artif_com_colors[i]['max'] ) {
864            return artif_com_colors[i]['color'];
865        } 
866    }
867    return '#000000';
868}
869
870function get_legende_rectangle(fillColor, strokeColor) {
871    return new ol.style.Style({
872        stroke: new ol.style.Stroke({
873            color: strokeColor,
874            width: 0.5
875          }),
876          fill: new ol.style.Fill({
877            color: fillColor
878          })
879    });
880}
881
882
883function set_conso_legend(consolegend) {
884
885    consolegend.getItems().clear();
886
887    consolegend.addItem({
888        className: 'Communes',
889        title: 'Communes',
890        textStyle: new ol.style.Text({
891            font: 'bold 14px Arial, sans-serif',
892        }),
893        height: 30
894    });
895
896    for ( let idx = 0; idx < num_jenks_classes; idx++ ) { 
897        const min = Math.round(jenks_coms[(idx)] * 10000) / 100; // (jenks_epcis[(idx)]*100).toFixed(4);
898        const max = Math.round(jenks_coms[(idx+1)] * 10000) / 100; // Math.round(jenks_epcis[(idx+1)]*100,4);
899
900        consolegend.addItem({
901            //className: 'at_item',
902            title: 'De '+ min +' à '+ max +'%',
903            textStyle: new ol.style.Text({
904                font: '11px Arial, sans-serif',
905            }),
906            style: get_legende_rectangle(conso_colors[idx], '#0000000'),
907            typeGeom: 'Polygon',
908        });  
909
910    }
911
912    consolegend.addItem({
913        title: '',
914        height: 5
915    });
916
917    consolegend.addItem({
918        className: 'EPCI',
919        title: 'EPCI et département',
920        textStyle: new ol.style.Text({
921            font: 'bold 14px Arial, sans-serif',
922        }),
923        height: 30
924    });
925
926    for ( let idx = 0; idx < num_jenks_classes; idx++ ) { 
927        const min = Math.round(jenks_epcis[(idx)] * 10000) / 100; // (jenks_epcis[(idx)]*100).toFixed(4);
928        const max = Math.round(jenks_epcis[(idx+1)] * 10000) / 100; // Math.round(jenks_epcis[(idx+1)]*100,4);
929
930        consolegend.addItem({
931            //className: 'at_item',
932            title: 'De '+ min +' à '+ max +'%',
933            textStyle: new ol.style.Text({
934                font: '11px Arial, sans-serif',
935            }),
936            style: get_legende_rectangle(conso_colors[idx], '#0000000'),
937            typeGeom: 'Polygon',
938        });  
939
940    }
941
942    consolegend.addItem({
943        title: '',
944        height: 8
945    });
946
947    consolegend.addItem({
948        className: 'EPCI',
949        title: 'En % de la surface \n du territoire concerné.',
950        textStyle: new ol.style.Text({
951            font: 'normal 11px Arial, sans-serif',
952        }),
953        //height: 40
954    });
955    
956}
957
958// résolutions fournies par l'IGN pour travailler avec openLayers
959// https://geoservices.ign.fr/documentation/services/utilisation-web/affichage-wmts/openlayers-et-wmts
960
961function get_resol(){
962    return [
963        156543.03392804103,
964        78271.5169640205,
965        39135.75848201024,
966        19567.879241005125,
967        9783.939620502562,
968        4891.969810251281,
969        2445.9849051256406,
970        1222.9924525628203,
971        611.4962262814101,
972        305.74811314070485,
973        152.87405657035254,
974        76.43702828517625,
975        38.218514142588134,
976        19.109257071294063,
977        9.554628535647034,
978        4.777314267823517,
979        2.3886571339117584,
980        1.1943285669558792,
981        0.5971642834779396,
982        0.29858214173896974,
983        0.14929107086948493,
984        0.07464553543474241
985    ];
986}
987
988function jenks(data, n_classes) {
989    if (n_classes > data.length) return null;
990
991    data = data.slice().sort(function (a, b) {
992        return a - b;
993    });
994
995    var matrices = getMatrices(data, n_classes);
996    var lower_class_limits = matrices.lower_class_limits;
997
998    // extract n_classes out of the computed matrices
999    return breaks(data, lower_class_limits, n_classes);
1000
1001}
1002
1003/** 
1004* the second part of the jenks recipe: take the calculated 
1005* matricesand derive an array of n breaks.
1006*/
1007function breaks(data, lower_class_limits, n_classes) {
1008
1009    var k = data.length - 1,
1010        kclass = [],
1011        countNum = n_classes;
1012
1013    // the calculation of classes will never include the upper and
1014    // lower bounds, so we need to explicitly set them
1015    kclass[n_classes] = data[data.length - 1];
1016    kclass[0] = data[0];
1017
1018    // the lower_class_limits matrix is used as indexes into itself
1019    // here: the `k` variable is reused in each iteration.
1020    while (countNum > 1) {
1021        kclass[countNum - 1] = data[lower_class_limits[k][countNum] - 2];
1022        k = lower_class_limits[k][countNum] - 1;
1023        countNum--;
1024    }
1025
1026    return kclass;
1027}
1028
1029/** 
1030* Compute the matrices required for Jenks breaks. These matrices
1031* can be used for any classing of data with `classes <= n_classes`
1032*/
1033function getMatrices(data, n_classes) {
1034    // * lower_class_limits (LC): optimal lower class limits
1035    // * variance_combinations (OP): optimal variance combinations for all classes
1036    var lower_class_limits = [],
1037        variance_combinations = [],
1038        i, j,
1039        variance = 0;
1040
1041    // Initialize matrix's
1042    for (i = 0; i < data.length + 1; i++) {
1043        var tmp1 = [],
1044            tmp2 = [];
1045        for (j = 0; j < n_classes + 1; j++) {
1046            tmp1.push(0);
1047            tmp2.push(0);
1048        }
1049        lower_class_limits.push(tmp1);
1050        variance_combinations.push(tmp2);
1051    }
1052
1053    for (i = 1; i < n_classes + 1; i++) {
1054        lower_class_limits[1][i] = 1;
1055        variance_combinations[1][i] = 0;
1056        for (j = 2; j < data.length + 1; j++) {
1057            variance_combinations[j][i] = Infinity;
1058        }
1059    }
1060
1061    for (var l = 2; l < data.length + 1; l++) {
1062
1063        var sum = 0,
1064            sum_squares = 0,
1065            w = 0,
1066            i4 = 0;
1067
1068        for (var m = 1; m < l + 1; m++) {
1069
1070            var lower_class_limit = l - m + 1,
1071                val = data[lower_class_limit - 1];
1072
1073            // here we're estimating variance for each potential classing
1074            // of the data, for each potential number of classes. `w`
1075            // is the number of data points considered so far.
1076            w++;
1077            sum += val;
1078            sum_squares += val * val;
1079            variance = sum_squares - (sum * sum / w);
1080            i4 = lower_class_limit - 1;
1081
1082            if (i4 === 0) {
1083                continue;
1084            }
1085
1086            for (j = 2; j < n_classes + 1; j++) {
1087                // if adding this element to an existing class
1088                // will increase its variance beyond the limit, break
1089                // the class at this point, setting the lower_class_limit
1090                // at this point.
1091                if (variance_combinations[l][j] >= (variance + variance_combinations[i4][j - 1])) {
1092                    lower_class_limits[l][j] = lower_class_limit;
1093                    variance_combinations[l][j] = variance + variance_combinations[i4][j - 1];
1094                }
1095            }
1096
1097        }
1098
1099        lower_class_limits[l][1] = 1;
1100        variance_combinations[l][1] = variance;
1101    }
1102
1103    return {
1104        lower_class_limits: lower_class_limits,
1105        variance_combinations: variance_combinations
1106    };
1107}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.