PageSourceSearch

https://www.lessports.ch/typo3temp/assets/compressed/sitnlayers-4f52ff2f938a1604e18610bddd040318.js?1757417670

js lessports.ch collected 2026-10-06 12:36:57 UTC 24,329 bytes, 709 lines download raw bytes

1/* eslint-disable func-names */
2/* eslint-disable no-param-reassign */
3/* eslint-disable no-loop-func */
4/* eslint-disable no-plusplus */
5/* eslint-disable no-unused-expressions */
6/* eslint-disable no-underscore-dangle */
7/* eslint-disable no-shadow */
8/* global proj4, ol, $ */
9(function (window) {
10  function sitnLayers() {
11    const sitnLayers = {};
12    const _extent = [2420000, 1030000, 2900000, 1350000];
13    const _crs = 'EPSG:2056';
14    const _WMTSurl = 'https://sitn.ne.ch/web_getcapabilities/WMTSGetCapabilities95.xml';
15    const _WMSurl = 'https://sitn.ne.ch/mapserv_proxy?ogcserver=source+for+image%2Fpng';
16    const _drawSource = new ol.source.Vector();
17    const _markerColor = '#8959A8';
18    const _markerSource = new ol.source.Vector();
19    const _sitnBaseLayers = {
20      plan_ville: 'Plan de ville',
21      plan_cadastral: 'Plan cadastral',
22      ortho: 'Images aériennes',
23    };
24    // A dictionnary containing named layers in the form of { layer_name: ol.layer.Image(), }
25    const _sitnWMSLayers = {};
26    let _buttons = [];
27    let _baselayers = [];
28    let _wmslayers = [];
29    let _target;
30    let _selectTarget;
31    let _drawSimpleGeom = false;
32    let _markerImage = '/typo3conf/ext/address/Resources/Public/Medias/marker.svg';
33    let _drawColor = 'cornflowerblue';
34    let _drawFillColor;
35    let _drawWidth = 4;
36    let _pointStyle = 'circle';
37    let _searchColor = 'red';
38    let _map = false;
39    let _minZoom = 0;
40    let _maxZoom = 28;
41
42    sitnLayers.sitnCurrentBaseLayer = new ol.layer.Tile();
43    sitnLayers.sitnDrawLayer = new ol.layer.Vector({
44      source: _drawSource,
45    });
46
47    // projection
48    proj4.defs(_crs,
49      '+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333'
50      + ' +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel '
51      + '+towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs');
52    ol.proj.proj4.register(proj4);
53    const _projection = new ol.proj.Projection({
54      code: _crs,
55      extent: _extent,
56    });
57
58    sitnLayers._createMarkerStyle = function (color) {
59      return new ol.style.Icon({
60        anchor: [0.5, 1],
61        color,
62        opacity: 1,
63        src: _markerImage,
64      });
65    };
66    // TODO: get out source from here when base layer selection will be implemented
67    sitnLayers.setSource = function (layerName) {
68      $.ajax(_WMTSurl).then((response) => {
69        const _parser = new ol.format.WMTSCapabilities();
70        const _result = _parser.read(response);
71        sitnLayers.WMTSOptions = ol.source.WMTS.optionsFromCapabilities(
72          _result, {
73            layer: layerName,
74            matrixSet: _crs,
75          },
76        );
77        const source = new ol.source.WMTS(sitnLayers.WMTSOptions);
78        sitnLayers.sitnCurrentBaseLayer.setSource(source);
79      });
80    };
81
82    sitnLayers.view = new ol.View({
83      projection: _projection,
84      center: ol.proj.fromLonLat([6.80, 47.05], _projection),
85      zoom: 4,
86    });
87
88    /**
89     * Toogles multiple geometry mode, if it's set to simple geometry
90     * and multiple geometries were already drawn -> only keeps the last drawn geometry
91     */
92    sitnLayers.setSimpleGeom = function (value) {
93      _drawSimpleGeom = value;
94      if (_drawSimpleGeom && _drawSource.getFeatures().length > 1) {
95        const lastFeature = _drawSource.getFeatures().slice(-1)[0];
96        _drawSource.clear();
97        _drawSource.addFeature(lastFeature);
98      }
99    };
100
101    /**
102     * Sets color and width to draw layer
103     */
104    sitnLayers.setDrawStyle = function (options) {
105      _drawColor = ol.color.asArray(options.drawColor || _drawColor);
106      _drawWidth = options.drawWidth || _drawWidth;
107      _pointStyle = options.pointStyle || _pointStyle;
108      const _drawFillColor = [
109        _drawColor[0],
110        _drawColor[1],
111        _drawColor[2],
112        _drawColor[3] / 2,
113      ];
114
115      let _imageStyle;
116      if (_pointStyle === 'marker') {
117        _imageStyle = this._createMarkerStyle(_drawColor);
118      } else {
119        _imageStyle = new ol.style.Circle({
120          fill: new ol.style.Fill({ color: _drawFillColor }),
121          stroke: new ol.style.Stroke({ color: _drawColor, width: _drawWidth / 2 }),
122          radius: 5,
123        });
124      }
125      sitnLayers.sitnDrawLayer.setStyle(new ol.style.Style({
126        fill: new ol.style.Fill({ color: _drawFillColor }),
127        stroke: new ol.style.Stroke({ color: _drawColor, width: _drawWidth }),
128        image: _imageStyle,
129      }));
130    };
131
132    sitnLayers.createMap = function (options) {
133      _buttons = options.buttons;
134      _baselayers = options.baseLayers;
135      _wmslayers = options.wmslayers;
136      _target = options.target;
137      _selectTarget = options.selectTarget;
138      _drawSimpleGeom = options.drawSimpleGeom; // controls wether or not an user can draw multiple geometries
139      _drawColor = options.drawColor || _drawColor;
140      _drawWidth = options.drawWidth || _drawWidth;
141      _pointStyle = options.pointStyle || _pointStyle;
142      _markerImage = options.markerImage || _markerImage;
143      _searchColor = options.searchColor || _searchColor;
144      _minZoom = options.minZoom || _minZoom;
145      _maxZoom = options.maxZoom || _maxZoom;
146      _drawFillColor;
147      let _mainbar;
148      sitnLayers.setDrawStyle({});
149
150      if (_wmslayers) {
151        _wmslayers.forEach((layername) => {
152          _sitnWMSLayers[layername] = new ol.layer.Image({
153            extent: _extent,
154            source: new ol.source.ImageWMS({
155              url: _WMSurl,
156              params: { LAYERS: layername },
157              serverType: 'mapserver',
158            }),
159          });
160        });
161      }
162      _map = new ol.Map({
163        target: _target,
164        layers: [
165          sitnLayers.sitnCurrentBaseLayer,
166          ...Object.values(_sitnWMSLayers), // insert array of wms layers
167          sitnLayers.sitnDrawLayer,
168          new ol.layer.Vector({ source: _markerSource }),
169        ],
170        view: sitnLayers.view,
171      });
172      sitnLayers.view.setZoom(options.minZoom || 4);
173      sitnLayers.view.setMinZoom(_minZoom);
174      sitnLayers.view.setMaxZoom(_maxZoom);
175
176      /**
177       * Creates select options, sets first baseLayer as default
178       * or sets plan_ville if no _baselayers are defined
179       */
180      if (_baselayers) {
181        $.each(_baselayers, (key, value) => {
182          $(`#${_selectTarget}`)
183            .append(new Option(_sitnBaseLayers[value], value));
184        });
185        $(`#${_selectTarget}`).change(() => {
186          const newSource = $(`#${_selectTarget} option:selected`).val();
187          sitnLayers.setSource(newSource);
188        });
189        this.setSource(_baselayers[0]);
190      } else {
191        this.setSource('plan_ville');
192      }
193
194      /**
195       * Will set up button bar with editing activated by default
196       */
197      if (_buttons) {
198        _mainbar = new ol.control.Bar();
199        _map.addControl(_mainbar);
200        _mainbar.setPosition('top-left');
201        const editbar = new ol.control.Bar({
202          toggleOne: true, // one control active at the same time
203          group: false, // group controls together
204        });
205        _mainbar.addControl(editbar);
206
207        // Edit control bar
208        if (_buttons.indexOf('edit') !== -1) {
209          // Add selection tool:
210          //  1- a toggle control with a select interaction
211          //  2- an option bar to delete / get information on the selected feature
212          const sbar = new ol.control.Bar();
213          const selectCtrl = new ol.control.Toggle({
214            html: '<small class="fas fa-mouse-pointer"></small>',
215            title: 'Select',
216            interaction: new ol.interaction.Select(),
217            bar: sbar,
218            autoActivate: true,
219            active: true,
220          });
221
222          sbar.addControl(new ol.control.TextButton({
223            html: '<i class="fas fa-trash"></i>',
224            title: 'Effacer',
225            handleClick() {
226              const features = selectCtrl.getInteraction().getFeatures();
227              // if (!features.getLength()) console.log('Select an object first...');
228              // else console.log(`${features.getLength()} object(s) deleted.`);
229              let i = 0;
230              do {
231                _drawSource.removeFeature(features.item(i));
232                i += 1;
233              } while (features.item(i));
234              selectCtrl.getInteraction().getFeatures().clear();
235            },
236          }));
237
238          editbar.addControl(selectCtrl);
239        }
240
241        // Add editing tools
242        if (_buttons.indexOf('createPoint') !== -1) {
243          let active = true;
244          if (_buttons.indexOf('edit') !== -1) {
245            active = false;
246          }
247          const pedit = new ol.control.Toggle({
248            html: '<small class="fas fa-map-pin"></small>',
249            title: 'Point',
250            active,
251            interaction: new ol.interaction.Draw({
252              type: 'Point',
253              source: _drawSource,
254            }),
255          });
256          editbar.addControl(pedit);
257        }
258        if (_buttons.indexOf('createLineString') !== -1) {
259          const ledit = new ol.control.Toggle(
260            {
261              html: '<small class="fas fa-check fa-rotate-270 fa-flip-vertical"></small>',
262              title: 'LineString',
263              interaction: new ol.interaction.Draw({
264                type: 'LineString',
265                source: _drawSource,
266                // Count inserted points
267                geometryFunction(coordinates, geometry) {
268                  let newGeom;
269                  if (geometry) {
270                    geometry.setCoordinates(coordinates);
271                    newGeom = geometry;
272                  } else newGeom = new ol.geom.LineString(coordinates);
273                  this.nbpts = newGeom.getCoordinates().length;
274                  return newGeom;
275                },
276              }),
277              // Options bar associated with the control
278              bar: new ol.control.Bar(
279                {
280                  controls: [new ol.control.TextButton({
281                    html: '<i class="fas fa-undo"></i>',
282                    title: 'Revenir en arrière',
283                    handleClick() {
284                      if (ledit.getInteraction().nbpts > 1) ledit.getInteraction().removeLastPoint();
285                    },
286                  }),
287                  new ol.control.TextButton({
288                    html: '<i class="fas fa-check"></i>',
289                    title: 'Terminer la construction',
290                    handleClick() { // Prevent null objects on finishDrawing
291                      if (ledit.getInteraction().nbpts > 2) ledit.getInteraction().finishDrawing();
292                    },
293                  }),
294                  ],
295                },
296              ),
297            },
298          );
299          editbar.addControl(ledit);
300        }
301
302        if (_buttons.indexOf('createPolygon') !== -1) {
303          const fedit = new ol.control.Toggle(
304            {
305              html: '<small class="fas fa-play fa-rotate-270"></small>',
306              title: 'Polygon',
307              interaction: new ol.interaction.Draw({
308                type: 'Polygon',
309                source: _drawSource,
310                // Count inserted points
311                geometryFunction(coordinates, geometry) {
312                  this.nbpts = coordinates[0].length;
313                  let newGeom = geometry;
314                  if (geometry) {
315                    newGeom.setCoordinates([coordinates[0].concat([coordinates[0][0]])]);
316                  } else newGeom = new ol.geom.Polygon(coordinates);
317                  return newGeom;
318                },
319              }),
320              // Options bar associated with the control
321              bar: new ol.control.Bar(
322                {
323                  controls: [new ol.control.TextButton({
324                    html: '<i class="fas fa-undo"></i>',
325                    title: 'Revenir en arrière',
326                    handleClick() {
327                      if (fedit.getInteraction().nbpts > 1) fedit.getInteraction().removeLastPoint();
328                    },
329                  }),
330                  new ol.control.TextButton({
331                    html: '<i class="fas fa-check"></i>',
332                    title: 'Terminer la construction',
333                    handleClick() { // Prevent null objects on finishDrawing
334                      if (fedit.getInteraction().nbpts > 3) fedit.getInteraction().finishDrawing();
335                    },
336                  }),
337                  ],
338                },
339              ),
340            },
341          );
342          editbar.addControl(fedit);
343        }
344
345        // If this option is enabled, then the user can only draw simple geometries
346        _drawSource.on('addfeature', (event) => {
347          if (_drawSimpleGeom && _drawSource.getFeatures().length > 1) {
348            _drawSource.clear();
349            _drawSource.addFeature(event.feature);
350          }
351        });
352      }
353    };
354
355    sitnLayers.getLayerByName = function (layerName) {
356      return _sitnWMSLayers[layerName];
357    };
358
359    /**
360     * Loads WKT and adds it to _drawsource
361     * @param {String} wkt
362     */
363    sitnLayers.loadWKT = function (wkt) {
364      const format = new ol.format.WKT({
365        splitCollection: true,
366      });
367      const data = wkt;
368      const features = format.readFeatures(data, {
369        dataProjection: _crs,
370        featureProjection: _crs,
371      });
372      _drawSource.addFeatures(features);
373    };
374
375    /**
376     * remove WKT
377     *
378     */
379    sitnLayers.removeWKT = function () {
380      _drawSource.clear();
381    };
382
383    /**
384     * Exports _drawSource as WKT
385     */
386    sitnLayers.getWKTData = function () {
387      const features = _drawSource.getFeatures();
388      if (features) {
389        const wktData = new ol.format.WKT().writeFeatures(features);
390        return wktData;
391      }
392      return '';
393    };
394
395    /**
396     * Exports _drawsource as GeoJSON
397     */
398    sitnLayers.getGeoJSONData = function () {
399      const features = _drawSource.getFeatures();
400      if (features) {
401        const jsonData = new ol.format.GeoJSON().writeFeatures(features);
402        return jsonData;
403      }
404      return '';
405    };
406
407    /**
408     * Adds a marker based on coordinates: an array of 2 numbers
409     * and clears another existing maker before. The color is optional
410     */
411    sitnLayers.addMarker = function (coordinates, color) {
412      _markerSource.clear();
413      const marker = new ol.Feature({
414        geometry: new ol.geom.Point(coordinates),
415      });
416      marker.setStyle(new ol.style.Style({
417        image: this._createMarkerStyle(color || _markerColor),
418      }));
419
420      _markerSource.addFeature(marker);
421
422
423
424
425    };
426
427    /**
428     * Updates marker position based
429     * on coordinates: an array of 2 numbers
430     */
431    sitnLayers.updateMarker = function (coordinates) {
432      sitnLayers.addMarker(coordinates);
433    };
434
435    /**
436     * Removes marker
437     */
438    sitnLayers.removeMarker = function () {
439      _markerSource.clear();
440    };
441
442    /**
443     * Exports _drawSource as WKT
444     */
445    sitnLayers.refresh = function () {
446		_map.updateSize();
447    };
448
449    /**
450     * Exports _drawSource as WKT
451     */
452    sitnLayers.addOverlay = function (o) {
453		_map.addOverlay(o);
454    };
455    /**
456     * Recenters the map based
457     * on coordinates: an array of 2 numbers
458     */
459    sitnLayers.recenterMap = function (coordinates, zoomLevel) {
460      if (_map) {
461        const view = _map.getView();
462        view.setCenter(coordinates);
463        view.setZoom(zoomLevel);
464      }
465    };
466
467    /**
468     * Gets center point of the extent an optionnaly recenters de map
469     */
470    sitnLayers.getCenterPoint = function (recenter) {
471      let center = [0, 0];
472      let extent;
473      if (_drawSource.getFeatures().length > 0) {
474        extent = _drawSource.getExtent();
475        center = ol.extent.getCenter(extent);
476      } else if (_drawSource.getFeatures.length === 0 && _markerSource.getFeatures().length > 0) {
477        extent = _markerSource.getExtent();
478        center = ol.extent.getCenter(_markerSource.getExtent());
479      }
480      if (recenter && center[0] !== 0) {
481        if (Math.round(extent[0]) === Math.round(extent[2])) {
482          sitnLayers.recenterMap(center, 14);
483        } else {
484          _map.getView().fit(extent);
485        }
486      }
487      return center;
488    };
489
490    sitnLayers.searchBox = function (config) {
491      let inputclasses;
492      let resultclasses;
493      let headerclasses;
494      let itemclasses;
495      const searchLayer = new ol.layer.Vector({
496        source: new ol.source.Vector(),
497        style: new ol.style.Style({
498          fill: new ol.style.Fill({ color: 'yellow' }),
499          stroke: new ol.style.Stroke({ color: _searchColor, width: 8 }),
500          image: new ol.style.RegularShape({
501            fill: new ol.style.Fill({ color: 'yellow' }),
502            stroke: new ol.style.Stroke({ color: _searchColor, width: 4 }),
503            points: 4,
504            radius: 10,
505            radius2: 0,
506            angle: Math.PI / 4,
507          }),
508        }),
509        opacity: 0.5,
510      });
511
512      if (_map) {
513        _map.addLayer(searchLayer);
514      }
515      let width = 'auto';
516
517      if (config.width) {
518        width = config.width;
519      }
520
521      if (config) {
522        inputclasses = config.inputclasses || [''];
523        resultclasses = config.resultclasses || ['sitn-search-result'];
524        headerclasses = config.headerclasses || [''];
525        itemclasses = config.itemclasses || [''];
526      }
527
528      // alias list for category names
529      const catClean = {
530        neophytes: 'Plantes invasives',
531        search_satac: 'N° SATAC',
532        search_entree_sortie: 'Entrée/sortie autoroute',
533        rt16_giratoires: 'Giratoires',
534        batiments_ofs: 'Bâtiments regBL et n° egid',
535        axe_mistra: 'Routes et axes',
536        search_arrets_tp: 'Arrêts transports publics',
537        ImmeublesCantonHistorique: 'Biens-fonds historiques',
538        point_interet: "Points d'intérêt",
539        axe_rue: 'Axes et rues',
540        nom_local_lieu_dit: 'Noms locaux et lieux-dits',
541        search_cours_eau: "Cours d'eau",
542        ImmeublesCanton: 'Biens-fonds',
543        search_fo_administrations: 'Administrations forestières',
544        search_uap_publique: "Unité d'aménagement publique",
545        adresses_sitn: 'Adresses',
546        localite: 'Localité',
547        search_fo09: 'Secours en forêt',
548        search_conc_hydr: 'Concessions hydrauliques',
549      };
550
551      // create required divs
552      document.getElementById(config.target).innerHTML = `<input id=placeInput type=text class="${
553        inputclasses.join(' ')}"/>`
554        + `<ol id="selectable" class=" ${resultclasses.join(' ')
555        }"></ol>`;
556      $(`#${config.target}`).width(width);
557
558      // start setting up events
559      $('#placeInput').val('Recherche un lieu ou un objet géographique');
560
561      $('#placeInput').focusin(() => {
562        $('#placeInput').val('');
563        searchLayer.getSource().clear();
564      });
565
566      $('#placeInput').focusout(() => {
567        $('#selectable').hide();
568      });
569
570      $('#selectable').hide();
571      // stop setting up events
572
573      // start get data from server
574      let inputTerm = '';
575      let recCopy = '';
576
577      $('#placeInput').keyup(() => {
578        inputTerm = $('#placeInput').val();
579        if (inputTerm.length > 2) {
580          $.ajax({
581            url: 'https://sitn.ne.ch/search',
582            crossDomain: true,
583            data: {
584              limit: 20,
585              query: inputTerm,
586            },
587            success(rec) {
588              // get the results
589              if (rec.features.length === 0) {
590                document.getElementById('selectable').innerHTML = 'Aucun résultat';
591                $('#selectable').show();
592                return;
593              }
594              // process results: group by categories
595              const itLength = rec.features.length;
596              const cat = [];
597              // get categories
598              for (let i = 0; i < itLength; i++) {
599                cat.push(rec.features[i].properties.layer_name);
600              }
601              // sort categories in ascending order and keep only unique
602              cat.sort();
603              const catUnique = [];
604              catUnique.push(cat[0]);
605              for (let i = 1; i < cat.length; i++) {
606                if (cat[i] !== cat[i - 1]) {
607                  catUnique.push(cat[i]);
608                }
609              }
610              // group the features by categories and fill the ordered list used for place selection
611              recCopy = $.extend(true, {}, rec);
612              let index = 0;
613              let listItems = '';
614              let catTest; let
615                catName;
616              for (let i = 0; i < catUnique.length; i++) {
617                catTest = catUnique[i];
618                $.each(catClean, (key, val) => {
619                  if (catTest === key) {
620                    catName = val;
621                  }
622                });
623                listItems += `<div class="${headerclasses.join(' ')}"><b>${catName}</b></div>`;
624                for (let j = 0; j < itLength; j++) {
625                  if (catUnique[i].toUpperCase() === rec.features[j].properties.layer_name.toUpperCase()) {
626                    recCopy.features[index] = rec.features[j];
627                    listItems += `<li class="${itemclasses.join(' ')}">${
628                      rec.features[j].properties.label}</li>`;
629                    index += 1;
630                  }
631                }
632              }
633              document.getElementById('selectable').innerHTML = listItems;
634              $('#selectable').show();
635            },
636            error() {
637              $('#placeInput').val('Échec de la recherche');
638            },
639          });
640        } else if (!inputTerm) {
641          searchLayer.getSource().clear();
642        }
643      });
644      // stop get data from server
645
646      // fill selectable list and zoom to selected feature
647      $(() => {
648        $('#selectable').selectable({
649          stop() {
650            const result = $('#select-result').empty();
651            $('.ui-selected', this).each(function () {
652              const index = $('#selectable li').index(this);
653              if (index !== -1) {
654                $('#placeInput').val(recCopy.features[index].properties.label);
655                if (_map) {
656                  const geojsonFormat = new ol.format.GeoJSON();
657                  searchLayer.getSource().clear();
658                  const nGeom = recCopy.features[index].geometry.coordinates.length;
659                  // geometry is not empty
660                  if (nGeom !== 0) {
661                    searchLayer.getSource().addFeatures(geojsonFormat.readFeatures(recCopy.features[index]));
662                  } else if (recCopy.features[index].bbox.length > 1) { // geometry is empty
663                    const point = new ol.geom.Point(recCopy.features[index].bbox[0], recCopy.features[index].bbox[1]);
664                    const pointFeature = new ol.Feature(point);
665                    searchLayer.addFeatures(pointFeature);
666                  }
667                  if (recCopy.features[index].geometry.type === 'Point') {
668                    _map.getView().fit(recCopy.features[index].bbox);
669                    _map.getView().setZoom(12);
670                  } else {
671                    _map.getView().fit(recCopy.features[index].bbox);
672                  }
673                }
674                result.append(` #${index + 1}`);
675                $('#selectable').hide();
676              }
677            });
678          },
679        });
680      });
681
682      const css = ' \n'
683      + '.sitn-search-result { \n'
684      + '  position: absolute; \n'
685      + '  top: 100%; \n'
686      + '  left: 0; \n'
687      + '  z-index: 1000; \n'
688      + '  float: left; \n'
689      + '  min-width: 10rem; \n'
690      + '  padding: .5rem 0; \n'
691      + '  margin: .125rem 0 0; \n'
692      + '  text-align: left; \n'
693      + '  list-style: none; \n'
694      + '  background-color: #fff; \n'
695      + '  background-clip: padding-box; \n'
696      + '}';
697      const head = document.head || document.getElementsByTagName('head')[0];
698      const style = document.createElement('style');
699
700      head.appendChild(style);
701
702      style.type = 'text/css';
703      style.appendChild(document.createTextNode(css));
704    };
705    return sitnLayers;
706  }
707
708  window.SitnMap = sitnLayers;
709}(window));

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.