/* All scheduleMap behaviors managed by schedule plugin scheduleMapList: Map of mapId => scheduleMap scheduleMap mapId: div map ID map: map poi: Point Of Interest poiSize: # of number clusterLayer: clusterLayer */ var scheduleMapList = {}; var scheduleUseMap = JSINFO['schedule']['useMap']; var scheduleZoom = JSINFO['schedule']['defaultZoom']; var scheduleCenter = JSINFO['schedule']['defaultCenter']; var schedulePoiUri = DOKU_BASE+'lib/plugins/schedule/images/poi.png'; var scheduleSelectedPoiUri = DOKU_BASE+'lib/plugins/schedule/images/poiRed.png'; var scheduleEmptyUri = DOKU_BASE+'lib/plugins/schedule/images/empty.png'; var scheduleIconCalendarUri = DOKU_BASE+'lib/plugins/schedule/images/calendar.png'; var scheduleAjaxPoiUri = DOKU_BASE+"lib/plugins/schedule/ajaxPOI.php"; var schedulePrecision = 5; var locationFormatRE = new RegExp ("^\\s*\\(\\s*([\\-0-9.]+)\\s*\\|\\s*([\\-0-9.]+)\\s*\\)\\s*(.*)$"); var iconStyle; var iconSelectedStyle; /* selected LI on city UL */ var scheduleSelectedCity = null; // ======================================== /* format location */ function scheduleGetLocation (lat, lon) { return "("+ parseFloat (parseFloat (lat).toFixed (schedulePrecision))+"|"+ parseFloat (parseFloat (lon).toFixed (schedulePrecision))+")"; } // ======================================== /* convert and reverse location */ function scheduleGetCoordFromLocation (latLonArray) { return ol.proj.transform ([latLonArray [1], latLonArray [0]], 'EPSG:4326', 'EPSG:3857'); } // ======================================== /* convert and reverse location */ function scheduleGetLocationFromCoord (coord) { var lonLat = ol.proj.transform (coord, 'EPSG:3857', 'EPSG:4326'); return [parseFloat (lonLat[1]).toFixed (schedulePrecision), parseFloat (lonLat [0]).toFixed (schedulePrecision)]; } // ======================================== /* center scheduleMap according POI markers */ function scheduleCenterMap (scheduleMap) { if (!scheduleUseMap) return; if (scheduleMap.poiSize) { scheduleMap.map.getView ().fit (scheduleMap.poi.getExtent (), scheduleMap.map.getSize ()); scheduleMap.map.getView ().setZoom (Math.min (scheduleMap.map.getView ().getZoom ()*.9, scheduleZoom)); return; } scheduleMap.map.getView ().setCenter (scheduleGetCoordFromLocation (scheduleCenter)); scheduleMap.map.getView ().setZoom (6); //scheduleZoom); } // ======================================== /* remove all POI markers */ function scheduleClearMarkers (scheduleMap) { if (!scheduleUseMap) return; scheduleMap.poiSize = 0; if (scheduleMap.poi !== undefined) scheduleMap.poi.clear (); } // ======================================== /* add a wellknown city marker */ function scheduleAddCityMarker (scheduleMap, cityCode) { if (! cityCode) return; var inseeLocation = inseeCityNameLatLon[cityCode]; if (!style) { // XXX not found return; } scheduleAddLatLonCityMarker (scheduleMap, cityCode, inseeCityNameLatLon[cityCode][1], inseeCityNameLatLon[cityCode][2]); } // ======================================== /* add a positioned city marker */ function scheduleAddLatLonCityMarker (scheduleMap, cityCode, lat, lon) { if (!scheduleUseMap) return; scheduleMap.poiSize++; if (scheduleMap.poi === undefined) return; scheduleMap.poi.addFeature (new ol.Feature({ geometry: new ol.geom.Point (scheduleGetCoordFromLocation ([lat, lon])), cityCode: cityCode, location: scheduleGetLocation (lat, lon), lat: lat, lon: lon, selected: false })); } // ======================================== /* highlight all cities on the list of adress */ function scheduleHighlightAddress (locations) { if (!locations) { jQuery ('div.scheduleAddresse').removeClass("poiAdrLight"); return; } jQuery ('div.scheduleAddresse').each (function () { var adrBlock = jQuery (this); var location = adrBlock.attr ('location'); if (location && (','+locations).indexOf (location) >= 0) adrBlock.addClass("poiAdrLight"); else adrBlock.removeClass("poiAdrLight"); }); } function scheduleHighlightLocation (location) { scheduleHighlightAddress (location); scheduleHighlightPOI (location); } // ======================================== /* display cities from a UL */ function scheduleAddAllCityFromUl (scheduleMap, ul) { scheduleClearMarkers (scheduleMap); ul.find ('li').each (function (index) { var li = jQuery (this); scheduleAddLatLonCityMarker (scheduleMap, li.attr ('insee'), li.attr ('lat'), li.attr ('lon')); }); if (!scheduleUseMap) return; if (scheduleMap.poi !== undefined){ scheduleMap.poi.changed (); scheduleMap.map.render (); } } // ======================================== function scheduleAddCityToUl (ul, cityName) { var cityCode = /[0-9AB]{5,}/.exec (cityName); var lat = ""; var lon = ""; if (cityCode != null) cityCode = cityCode[0]; if (!cityCode) cityCode = inseeCityNameInsee [cityName.toLowerCase ()]; if (!cityCode) cityName = cityCode = cityName.replace(/[^A-ZÀÂÆÇÉÈÊËÎÏÑÔŒÙÛÜÿ a-zàâæçéèêëîïñôœùûüÿ'\-]/gi,''); else { cityName = inseeCityNameLatLon[cityCode][0]; lat = inseeCityNameLatLon[cityCode][1]; lon = inseeCityNameLatLon[cityCode][2]; } var recorded = false; ul.find ('li[insee="'+cityCode+'"][lat="'+lat+'"][lon="'+lon+'"]').each (function (index) { recorded = true; scheduleSetSelectCity (jQuery (this)); }); if (recorded) return; var lonLat = (lat && lon) ? ' lat="'+lat+'" lon="'+lon+'"' : ' class="unknown"'; ul.append ('
  • '+ ''+ ' '+ ''+cityName+'
  • '); scheduleSetSelectCity (ul.find ("li").last ()); } // ======================================== /* Sort UL by city name (XXX what about addresse ?) */ function scheduleSortUlCities (ul) { ul.children ('li').sort (function (a, b) { var upa = jQuery (a).find ('span.city').text ().toUpperCase (); var upb = jQuery (b).find ('span.city').text ().toUpperCase (); return (upa < upb) ? -1 : (upa > upb) ? 1 : 0; }).appendTo (ul[0]); } function scheduleAjaxPOILine (action) { if (!scheduleSelectedCity) // XXX dire quelque chose return; var insee = scheduleSelectedCity.attr ('insee'); var lat = scheduleSelectedCity.attr ('lat'); var lon = scheduleSelectedCity.attr ('lon'); var addr = scheduleSelectedCity.find ('span.addresse').html ().replace (/
    /gi, '~br~'); line = new Array (); line.push (insee); line.push (lat); line.push (lon); line.push (addr); jQuery.ajax ({ type: "POST", url: scheduleAjaxPoiUri, cache: true, async: true, data: { action: action, line: line.join ('|') }, success: function (response) { alert (response); } }); } function scheduleAddInsee () { scheduleAjaxPOILine ("add"); } function scheduleRemoveInsee () { scheduleAjaxPOILine ("remove"); } function scheduleTestInsee () { } function scheduleSetSelectCity (li) { scheduleSelectedCity = li; // change autocomplete var cityCode = scheduleSelectedCity.attr ('insee'); var form = scheduleSelectedCity.closest ('.scheduleCitiesForm'); var input = form.find ('input[name="addr"]'); input. val (scheduleSelectedCity.find ('span.addresse').html ().replace (/
    /gi, '~br~')); jQuery.ajax ({ type: "POST", url: scheduleAjaxPoiUri, cache: true, async: true, data: { action: "list", insee: cityCode }, success: function (response) { var db = jQuery.parseJSON (response); source = new Array (); for (var i = 0; i < db.length; i++) { var vals = db[i].split ("|"); source.push ("("+vals[0]+"|"+vals[1]+") "+vals[2]); } input.autocomplete ({ source: source }); } }); } function scheduleFocusCity () { if (!scheduleUseMap) return; var form = scheduleSelectedCity.closest ('.scheduleCitiesForm'); // focus on map form.find ('.scheduleMap').each (function () { var scheduleMap = scheduleMapList [jQuery (this).attr ('id')]; scheduleMap.map.getView ().setCenter (scheduleGetCoordFromLocation ([scheduleSelectedCity.attr ('lat'), scheduleSelectedCity.attr ('lon')])); scheduleMap.map.getView ().setZoom (Math.min (scheduleMap.map.getView ().getZoom (), scheduleZoom)); }); } // ======================================== /* User LI selection and focus on map */ function scheduleSelectCity (item) { scheduleSetSelectCity (jQuery (item).closest ('li')); scheduleFocusCity (); } // ======================================== /* User remove LI */ function scheduleRemoveCity (item) { var li = jQuery (item).closest ('li'); var ul = li.closest ('ul'); li.remove (); scheduleUpdateUlCity (ul); } function scheduleUpdateUlCity (ul) { ul.closest ('.scheduleCitiesForm'). find ('.scheduleMap').each (function () { var scheduleMap = scheduleMapList [jQuery (this).attr ('id')]; scheduleAddAllCityFromUl (scheduleMap, ul); scheduleCenterMap (scheduleMap); }); scheduleCheckInputs (); } // ======================================== /* Find all initial values */ function scheduleInitPOI () { jQuery ('.schedulePOI').each (function () { var poiDiv = jQuery (this); var scheduleMap = scheduleMapList [poiDiv.find ('.scheduleMap').attr ('id')]; scheduleClearMarkers (scheduleMap); poiDiv.find ('span.poiLocations').each (function () { var poiLocations = jQuery (this).text ().split (','); for (var i = 0; i < poiLocations.length; i++) { var latLon = poiLocations[i]; var match = latLon.match (locationFormatRE); if (match) { var lat = parseFloat (match [1]).toFixed (schedulePrecision); var lon = parseFloat (match [2]).toFixed (schedulePrecision); scheduleAddLatLonCityMarker (scheduleMap, "", lat, lon); } else // cityCode = latLon scheduleAddCityMarker (scheduleMap, latLon); } scheduleCenterMap (scheduleMap); }); poiDiv.find ('ul.poiLatLon').each (function () { jQuery (this).find ('li').each (function (index) { var li = jQuery (this); scheduleAddLatLonCityMarker (scheduleMap, li.text (), li.attr ('lat'), li.attr ('lon')); }); scheduleCenterMap (scheduleMap); }); }); jQuery ('.scheduleCitiesForm').each (function () { var scheduleCitiesForm = jQuery (this); var scheduleMapDiv = scheduleCitiesForm.find ('.scheduleMap'); if (scheduleMapDiv[0] === undefined) return; var scheduleMap = scheduleMapList [scheduleMapDiv.attr ('id')]; scheduleAddAllCityFromUl (scheduleMap, jQuery (this).find ('.cities')); scheduleCenterMap (scheduleMap); }); } // ======================================== /* Find all maps */ function scheduleInitMaps () { if (!scheduleUseMap) return; jQuery ('.scheduleMap').each (function () { var mapDiv = jQuery (this).find ('div'); if (mapDiv !== undefined && mapDiv && mapDiv.length) return; var mapId = jQuery (this).attr ('id'); var osm = new ol.layer.Tile ({ source: new ol.source.OSM () }); var poi = new ol.source.Vector ({ features: [] }); iconStyle = new ol.style.Style ({ image: new ol.style.Icon (/** @type {olx.style.IconOptions} */ ({ anchor: [.5, 1], anchorXUnits: 'fraction', anchorYUnits: 'fraction', opacity: 0.75, src: schedulePoiUri })) }); iconSelectedStyle = new ol.style.Style ({ image: new ol.style.Icon (/** @type {olx.style.IconOptions} */ ({ anchor: [.5, 1], anchorXUnits: 'fraction', anchorYUnits: 'fraction', opacity: 0.75, src: scheduleSelectedPoiUri })) }); var clusters = new ol.source.Cluster({ distance: 10, source: poi, }); var styleCache = {false: {}, true: {}}; var clusterLayer = new ol.layer.Vector({ source: clusters, style: function (feature) { var features = feature.get ('features'); var size = features.length; if (size < 2) return features [0].get ('selected') ? iconSelectedStyle : iconStyle; var selected = false; features.forEach (function (item) { if (item.get ('selected')) selected = true; }); var style = styleCache[selected][size]; if (!style) { style = [new ol.style.Style({ image: new ol.style.Icon (/** @type {olx.style.IconOptions} */ ({ anchor: [.5, 1], anchorXUnits: 'fraction', anchorYUnits: 'fraction', opacity: 0.75, src: selected ? scheduleSelectedPoiUri : schedulePoiUri })), text: new ol.style.Text({ text: size.toString (), offsetY: -24 // XXX textpos conf ? }) })]; styleCache[selected][size] = style; } return style; } }); var map = new ol.Map ({ target: mapId, layers: [osm, clusterLayer], //logo: false, controls: ol.control.defaults ({ zoom: true, attribution: false, rotate: false }), view: new ol.View ({ center: ol.proj.fromLonLat (scheduleCenter), zoom: scheduleZoom }) }); if (jQuery (this).hasClass ("scheduleMapDisplay")) map.set ("mapType", "display"); if (jQuery (this).hasClass ("scheduleMapForm")) map.set ("mapType", "form"); if (jQuery (this).hasClass ("scheduleMapCalendar")) map.set ("mapType", "calendar"); map.on ("singleclick", function (evt) { var f; map.forEachFeatureAtPixel (evt.pixel, function (feature) { f = feature; return true; }); switch (map.get ("mapType")) { case "display": if (f) { if (f.get ('features').length) f = f.get ('features')[0]; window.open ("https://www.openstreetmap.org/?mlat="+f.get ('lat')+"&mlon="+f.get ('lon')+"&zoom="+scheduleZoom, "_self"); } break; case "form": var location = scheduleGetLocationFromCoord (evt.coordinate); scheduleSelectedCity.attr ('lat', location[0]); scheduleSelectedCity.attr ('lon', location[1]); scheduleAddAllCityFromUl (scheduleMap, scheduleSelectedCity.closest ('ul')); break; } }); map.on ("pointermove", function (evt) { var locations = new Set (); map.forEachFeatureAtPixel (evt.pixel, function (feature) { feature.get ('features').forEach (function (item) { locations.add (item.get ('location')); }); }); locations = Array.from (locations); scheduleHighlightDays (locations); scheduleHighlightLocation (locations.join (',')); }); var scheduleMap = { mapId: mapId, map: map, poiSize: 0, poi: poi, clusterLayer: clusterLayer }; scheduleMapList[mapId] = scheduleMap; scheduleCenterMap (scheduleMap); }); } // ======================================== /* Initialisation and attach function */ jQuery (function () { jQuery (function () { // create tabs before OpenLayers stuff (important !) jQuery (".scheduleTabForm").tabs ({ active: 0 }); jQuery ("#scheduleHelp").accordion ({ collapsible: true, animated: false, active: false }); jQuery.datepicker.setDefaults ({ showOn: "both", buttonImageOnly: true, buttonImage: scheduleIconCalendarUri, buttonText: "", firstDay: 0 }); jQuery.datepicker.formatDate ("yy-mm-dd"); jQuery (".scheduleTabForm .date").datepicker (); divError = jQuery ("div.schedule").prev ("div.error"); if (divError !== undefined && divError && divError.length) // XXX a tester (avant divError.size ()) scheduleForceCheckInputs (); }); // check and format form request jQuery ('.scheduleFinalForm').submit (function () { var scheduleFinalForm = jQuery (this); if (!scheduleForceCheckInputs ()) return false; var scheduleForm = scheduleFinalForm.closest ('.scheduleTabForm'); var scheduleCitiesForm = scheduleForm.find ('.scheduleCitiesForm'); var cities = new Array (); var lats = new Array (); var lons = new Array (); var addrs = new Array (); scheduleCitiesForm.find ('li').each (function (index) { var li = jQuery (this); cities.push (li.attr ('insee')); lats.push (li.attr ('lat')); lons.push (li.attr ('lon')); addrs.push (li.find ('span.addresse').html ()); }); scheduleFinalForm.append (''); scheduleFinalForm.append (''); scheduleFinalForm.append (''); scheduleFinalForm.append ('/gi, '~br~')+'"/>'); var scheduleMiscForm = scheduleForm.find ('.scheduleMiscForm'); scheduleMiscForm.find ('input[type="text"]').each (function (index) { if (this.value) scheduleFinalForm.append (''); }); scheduleMiscForm.find ('select:not([class="members"])').each (function (index) { scheduleFinalForm.append (''); }); var members = new Array (); scheduleMiscForm.find ('select[class="members"]').each (function (index) { jQuery (this).find ('option:selected').each (function (index) { members.push (jQuery (this).val ()); }); }); if (members.length > 0) scheduleFinalForm.append (''); scheduleMiscForm.find ('textarea').each (function (index) { var val = jQuery (this).val ().replace(/"/gi, "''"); var name = jQuery (this).attr ('name'); scheduleFinalForm.append (''); }); return true; }); // city validation jQuery ('.scheduleCitiesForm input[name="city"]').keypress (function (e) { if (e.which != 13) return; var input = jQuery (this); var form = input.closest ('.scheduleCitiesForm'); var cityName = input.val (); if (!cityName) return false; input.val (""); form.find ('input[name="addr"]').val (""); var ul = form.find ('ul'); scheduleAddCityToUl (ul, cityName); scheduleSortUlCities (ul); scheduleUpdateUlCity (ul); return false; }); // full adress validation jQuery ('.scheduleCitiesForm input[name="addr"]').keypress (function (e) { if (e.which != 13) return; if (!scheduleSelectedCity) return; var input = jQuery (this); var form = input.closest ('.scheduleCitiesForm'); var addr = input.val (); var match = addr.match (locationFormatRE); if (match) { addr = match [3]; scheduleSelectedCity.attr ('lat', parseFloat (match [1]).toFixed (schedulePrecision)); scheduleSelectedCity.attr ('lon', parseFloat (match [2]).toFixed (schedulePrecision)); var scheduleMap = scheduleMapList [form.find ('.scheduleMap').attr ('id')]; scheduleAddAllCityFromUl (scheduleMap, scheduleSelectedCity.closest ('ul')); scheduleFocusCity (); } input.val (addr); scheduleSelectedCity.find ('span.addresse').html (addr.replace (/~br~/gi, '
    ')); }); // default form validation for each text field jQuery ('.scheduleMiscForm input').keypress (function (e) { if (e.which != 13) return; jQuery (this).closest ('.scheduleTabForm').find ('input[type="submit"]').first ().trigger ('click'); }); // init maps scheduleInitMaps (); scheduleInitPOI (); }); // ========================================