X-Git-Url: https://git.toastfreeware.priv.at/philipp/winterrodeln/mediawiki_extensions/wrmap.git/blobdiff_plain/71e459fa687d347331f280c7dc7189ad6651974a..1234fddc62ff7e34d1b5b7d2f5f613fc18e45ef1:/wrmap.js diff --git a/wrmap.js b/wrmap.js index d269823..24d4b69 100644 --- a/wrmap.js +++ b/wrmap.js @@ -1,85 +1,399 @@ +"use strict"; +/* +// "User defined" popup class to be able to specify a minimum size for the popup, +// so that Safari 7.0 displays it correctly (see ticket #89). +OpenLayers.Popup.WrInfo = OpenLayers.Class(OpenLayers.Popup.FramedCloud, { + minSize: new OpenLayers.Size(180, 260), + + initialize: function(id, lonlat, contentSize, contentHTML, anchor, closeBox, closeCallback) { + OpenLayers.Popup.FramedCloud.prototype.initialize.apply(this, arguments); + }, + + CLASS_NAME: "OpenLayers.Popup.WrInfo" +}); +*/ + + function init_wrmap(i, jq_map) { + // define constants + var EPSG4326 = ol.proj.get("EPSG:4326"); // lon/lat + var EPSG3857 = ol.proj.get("EPSG:3857"); // google + + // tool functions + function createElement(tagName, attributes) { + var element = $(document.createElement(tagName)); + if (attributes === undefined) return element; + for (var attribute in attributes) { + element.attr(attribute, attributes[attribute]); + } + return element; + } + + function appendElement(parentElement, tagName, attributes) { + if (attributes === undefined) attributes = {}; + var element = createElement(tagName, attributes); + parentElement.append(element); + return element; + } + + + // extract geojson from map element and clear map element's content jq_map = $(jq_map); - var jq_sledruns = jq_map.children(); - jq_sledruns.detach(); - - // Introduce EPSG:3857 as an alias of the built in EPSG:900913 projection (both are the "Google/OSM" projections) - var EPSG4326 = new OpenLayers.Projection("EPSG:4326"); // lon/lat - var EPSG3857 = new OpenLayers.Projection("EPSG:3857"); // google - - // Create the map - var map = new OpenLayers.Map(jq_map.context, { - projection: EPSG3857, - displayProjection: EPSG4326, - units: "m", - theme: null - }); + var ext_path = jq_map.attr('data-ext-path'); // e.g. '/mediawiki/extensions/wrmap' + var img_path = ext_path + '/img'; + var json_string = jq_map.children().last().text(); + jq_map.empty(); // once parsed, remove geojson string from the map element. + var json_js = JSON.parse(json_string); + var format_geojson = new ol.format.GeoJSON(); + var features_all = format_geojson.readFeatures(json_js, {dataProjection: EPSG4326, featureProjection: EPSG3857}); - // Google Layer - var layer_map = new OpenLayers.Layer.Google("Google Physical", { - type: google.maps.MapTypeId.TERRAIN + + // background layer + // ---------------- + + // OSM map + var layer_map = new ol.layer.Tile({ + source: new ol.source.OSM() }); - // // Alternative: OSM map - // var layer_map = new OpenLayers.Layer.OSM(); - - // // Alternative: Microsoft Bing Maps - // var layer_map = new OpenLayers.Layer.Bing({ - // type: "Road", - // key: "AgPH3SlIXAwajrJKf0FORQyhTqsP8KIlvtN6RKfvxe6fOB6q6-HFmg8EOFm7LSOA"}); + + /* + // Microsoft Bing Maps + // var layer_map = new OpenLayers.Layer.Bing({ + // type: "Road", + // key: "AgPH3SlIXAwajrJKf0FORQyhTqsP8KIlvtN6RKfvxe6fOB6q6-HFmg8EOFm7LSOA", + // tileOptions: {crossOriginKeyword: null}}); + + // // Alternative: Base map + // // see: http://www.basemap.at - // Sledrun layer - var layer_sledruns = new OpenLayers.Layer.Vector("Rodelbahnen", { - styleMap: new OpenLayers.StyleMap({ - "default": new OpenLayers.Style({ - externalGraphic: "/vorlagen/gmap_rodelbahn_c.png", - graphicWidth: 17, - graphicHeight: 17, - graphicXOffset: -8, - graphicYOffset: -8, - graphicZIndex: 11, - backgroundGraphic: "/vorlagen/gmap_rodelbahn_c_s.png", - backgroundWidth: 23, - backgroundHeight: 23, - backgroundXOffset: -8, - backgroundYOffset: -8, - backgroundZIndex: 12, - title: "${label}" + // // Alternative: OpenTopoMap + // // see: https://opentopomap.org/about + + // // Alternative: Dummy base layer + // var layer_map = new OpenLayers.Layer.Vector("Base Layer", { + // isBaseLayer: true}); + */ + + + // path layer + // ---------- + + function get_feature_title(feature) { + var title = feature.get('type'); + if (title == 'sledrun') return feature.get('name'); + title = title.charAt(0).toUpperCase() + title.slice(1); // first letter uppercase + if (feature.get('name')) title += ': ' + feature.get('name'); + return title; + } + + // Returns 0 to 5 for features that represent sledruns as their condition + var get_sledrun_condition = function(feature) { + var condition = feature.get('condition'); + if (condition === undefined) return 0; + return condition; + } + + function style_point_function(feature, resolution) { + if (feature.get('type') == 'sledrun') { + let condition = get_sledrun_condition(feature); + let src = img_path + '/marker_c_sledrun_' + condition + 'nn.png'; + let marker_style = new ol.style.Style({ + image: new ol.style.Icon({ + src: src, + imgSize: [17, 17], + anchor: [0.5, 0.5] + }), + }); + let shadow_style = new ol.style.Style({ + image: new ol.style.Icon({ + src: img_path + '/marker_c_shadow.png', + imgSize: [23, 23], + anchor: [0.4, 0.4] + }), + }); + return [shadow_style, marker_style]; + + } else { + let src = img_path + '/marker_p_' + feature.get('type') + '.png'; + let marker_style = new ol.style.Style({ + image: new ol.style.Icon({ + src: src, + imgSize: [20, 34], + anchor: [0.5, 1.0] + }), + }); + return [marker_style]; + } + } + + function style_point_function_selected(feature, resolution) { + let style_array = style_point_function(feature, resolution); + style_array[0].setText(new ol.style.Text({ + text: get_feature_title(feature), + font: 'icon', + offsetY: 14, + stroke: new ol.style.Stroke({ + color: '#ddd', + width: 2, }), - "highlight": new OpenLayers.Style({ - label: "${label}", - labelOutlineColor: "white", - labelYOffset: 12, - fontWeight: "bold" + })); + return style_array; + } + + function style_path_function(feature, resolution) { + var line_color = { + 'rodelbahn': '#014e9a', + 'gehweg': '#e98401', + 'alternative': '#7f7fff', + 'lift': '#000000', + 'anfahrt': '#e1e100' + }; + var color = feature.get('strokeColor') || line_color[feature.get('type')] || '#e7525b'; + var width = (feature.get('type') in ['lift', 'anfahrt']) ? 3 : 6; + return new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: color, + width: width }) + }); + } + + function style_function(feature, resolution) { + if (feature.getGeometry() instanceof ol.geom.Point) return style_point_function(feature, resolution); + return style_path_function(feature, resolution); + }; + function style_function_selected(feature, resolution) { + if (feature.getGeometry() instanceof ol.geom.Point) return style_point_function_selected(feature, resolution); + return style_path_function(feature, resolution); + }; + + + // popup overlay + // ------------- + var popup_container = document.getElementById('popup'); + var popup_content = document.getElementById('popup-content'); + var popup_closer = document.getElementById('popup-closer'); + var popup_overlay = new ol.Overlay({element: popup_container, autoPan: {animation: {duration: 250}}}); + popup_closer.onclick = function() {popup_overlay.setPosition(undefined); popup_closer.blur(); return false;}; + + function create_popup_dom(feature) { + var popup_div = createElement('div'); + + // name + if (feature.get('name') !== undefined && (feature.get('wiki') !== undefined || feature.get('thumb_url') !== undefined)) { + var h2 = appendElement(popup_div, 'h2'); + if (feature.get('wiki') === undefined) h2.text(feature.get('name')); + else appendElement(h2, 'a', {href: feature.get('wiki')}).text(feature.get('name')); + } + + // sledrun information + if (feature.get('type') == 'sledrun') { + var p = appendElement(popup_div, 'p').text('Rodelbahnzustand').append(createElement('br')); + if (feature.get('condition') !== undefined) { + var condition_text = {1: 'Sehr gut', 2: 'Gut', 3: 'Mittelmäßig', 4: 'Schlecht', 5: 'Geht nicht'}; + var year_month_day = feature.get('date_report').split('-'); + p.append(createElement('a', {href: feature.get('wiki') + '#Eintr.C3.A4ge'}).text(condition_text[feature.get('condition')]), ' '); + p.append(createElement('small').text(year_month_day[2] + '.' + year_month_day[1] + '.'), ' '); + p.append(createElement('em').append(createElement('a', {href: feature.get('wiki') + '#Eintragen'}).text('Neu'))); + } else { + p.append(createElement('em').append(createElement('a', {href: feature.get('wiki') + '#Eintragen'}).text('Bitte eintragen'))); + } + } + + // wiki link + if (feature.get('wiki') !== undefined) { + var a = appendElement(appendElement(popup_div, 'p'), 'a', {href: feature.get('wiki')}); + var detail_text = 'Details'; + if (feature.get('type') == 'sledrun') detail_text += ' zur Rodelbahn'; + if (feature.get('type') == 'gasthaus') detail_text += ' zum Gasthaus'; + if (feature.get('thumb_url') === undefined) a.text(detail_text); + else a.append(createElement('img', {src: feature.get('thumb_url'), alt: detail_text, title: detail_text})); + } + + return popup_div; + } + + + /* + // point layer + // ----------- + var filter_point_sledrun = new OpenLayers.Filter.Comparison({ + type: OpenLayers.Filter.Comparison.EQUAL_TO, + property: 'type', + value: 'sledrun' + }); + + + var layer_point = new OpenLayers.Layer.Vector("Point", { + styleMap: new OpenLayers.StyleMap({ + 'default': new OpenLayers.Style({ + graphicZIndex: 12, + backgroundGraphicZIndex: 11, + }, { + context: { + // the following context functions should only be available in the rule that uses them, + // but the rule dependent contexts are ignored by OpenLayers (I think that's a bug) + getCondition: get_sledrun_condition, + getSymbol: function(feature) { + var name = feature.attributes.type; + return name; + } + }, + rules: [ + new OpenLayers.Rule({ + filter: filter_point_sledrun, + symbolizer: { + externalGraphic: img_path + '/marker_c_sledrun_${getCondition}nn.png', + graphicWidth: 17, + graphicHeight: 17, + graphicXOffset: -8, + graphicYOffset: -8, + backgroundGraphic: img_path + '/marker_c_shadow.png', + backgroundWidth: 23, + backgroundHeight: 23, + backgroundXOffset: -8, + backgroundYOffset: -8, + } + }), + new OpenLayers.Rule({ + elseFilter: true, + symbolizer: { + externalGraphic: img_path + '/marker_p_${getSymbol}.png', + graphicWidth: 20, + graphicHeight: 34, + graphicXOffset: -10, + graphicYOffset: -33, + } + }) + ] + }), + highlight: new OpenLayers.Style({ + label: "${getTitle}", + labelOutlineColor: "white", + fontWeight: "bold" + }, { + context: { + getCondition: get_sledrun_condition, + getTitle: function(feature) { + var title = ''; + if (feature.attributes.type != 'point') { + title = feature.attributes.type; + title = title.charAt(0).toUpperCase() + title.slice(1); // First letter uppercase + if (feature.attributes.name !== undefined) title += ': '; + } + if (feature.attributes.name !== undefined) title += feature.attributes.name; + return title; + } + }, + rules: [ + new OpenLayers.Rule({ + filter: filter_point_sledrun, + symbolizer: { + label: "${name}", + labelYOffset: 14, + externalGraphic: img_path + '/marker_c_sledrun_${getCondition}nh.png' + } + }), + new OpenLayers.Rule({ + elseFilter: true, + symbolizer: { + labelYOffset: 40 + } + }) + ] + }), + select: new OpenLayers.Style({ + fillOpacity: 1. + }, { + context: { + getCondition: get_sledrun_condition, + }, + rules: [ + new OpenLayers.Rule({ + filter: filter_point_sledrun, + symbolizer: { + externalGraphic: img_path + '/marker_c_sledrun_${getCondition}nh.png', + backgroundGraphic: false, + graphicXOffset: -6, + graphicYOffset: -6 + } + }), + new OpenLayers.Rule({ + elseFilter: true + }) + ] + }) }), rendererOptions: {yOrdering: true} }); - jq_sledruns.each(function(j, jq_sledrun) { - jq_sledrun = $(jq_sledrun); - var lon = parseFloat(jq_sledrun.attr('data-lon')); - var lat = parseFloat(jq_sledrun.attr('data-lat')); - var point = new OpenLayers.Geometry.Point(lon, lat).transform(EPSG4326, EPSG3857); - layer_sledruns.addFeatures([new OpenLayers.Feature.Vector(point, {label: jq_sledrun.attr('data-title')})]); + +*/ + // map itself + // ---------- + var lon = json_js.properties.lon; + var lat = json_js.properties.lat; + var zoom = json_js.properties.zoom; + var width = json_js.properties.width; + var height = json_js.properties.height; + if (zoom === undefined) zoom = 10; // default zoom + if (width === undefined) width = '100%'; // default width + if (height === undefined) height = 450; // default: 450 pixel + jq_map.width(width); + jq_map.height(height); + + var layer_sledrun_source = new ol.source.Vector({features: features_all}); + var layer_sledrun = new ol.layer.Vector({ + source: layer_sledrun_source, + style: style_function }); - map.addControl(new OpenLayers.Control.SelectFeature(layer_sledruns, { - hover: true, - highlightOnly: true, - autoActivate: true, - renderIntent: "highlight" - })); - - // Center map - map.addLayers([layer_map, layer_sledruns]); - var lon = parseFloat(jq_map.attr('data-center-lon')); - var lat = parseFloat(jq_map.attr('data-center-lat')); - var zoom = parseInt(jq_map.attr('data-zoom')); - map.setCenter(new OpenLayers.LonLat(lon, lat).transform(EPSG4326, map.getProjectionObject()), zoom); -} + var map = new ol.Map({ + target: jq_map[0], + layers: [ + layer_map, + layer_sledrun + ], + overlays: [popup_overlay], + view: new ol.View({ + center: ol.proj.fromLonLat([lon, lat]), + zoom: zoom + }), + controls: ol.control.defaults({ + attributionOptions: { + collapsible: false + } + }), + interactions: ol.interaction.defaults({ + mouseWheelZoom: false + }) + }); + var select_hover = new ol.interaction.Select({ + condition: ol.events.condition.pointerMove, + style: style_function_selected, + }); + map.addInteraction(select_hover); + + var select_click = new ol.interaction.Select({ + condition: ol.events.condition.click, + }); + map.addInteraction(select_click); + select_click.on('select', function(event) { + if (event.selected.length > 0) { + let feature = event.selected[0]; + let coordinates = feature.getGeometry().getCoordinates(); + let popup_dom = create_popup_dom(feature); + if (popup_dom.children().length > 0) { + $(popup_content).empty().append(popup_dom); + popup_overlay.setPosition(coordinates); + } + } + }); +} + function init_wrmaps() { var jq_maps = $('.wrmap'); // all wrmap
elements jq_maps.each(init_wrmap);