diff --git a/data/css/narrative-maps.css b/data/css/narrative-maps.css
index ae926e390..0fb9d1007 100644
--- a/data/css/narrative-maps.css
+++ b/data/css/narrative-maps.css
@@ -66,3 +66,48 @@ div#FamilyMapDetail div#references table.infolist {
div#FamilyMapDetail div#references table.infolist tbody tr td.ColumnPlace {
width: 40%;
}
+
+
+/* Subsection: popup
+------------------------------------------------------ */
+.ol-popup {
+ position: absolute;
+ background-color: white;
+ -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
+ filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
+ padding: 15px;
+ border-radius: 10px;
+ border: 2px solid #111111;
+ bottom: 12px;
+ left: -50px;
+ min-width: 450px;
+}
+.ol-popup:after, .ol-popup:before {
+ top: 100%;
+ border: solid transparent;
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+}
+.ol-popup:after {
+ border-top-color: white;
+ border-width: 10px;
+ left: 48px;
+ margin-left: -10px;
+}
+.ol-popup:before {
+ border-top-color: #cccccc;
+ border-width: 11px;
+ left: 48px;
+ margin-left: -11px;
+}
+.ol-popup-closer {
+ text-decoration: none;
+ position: absolute;
+ top: 2px;
+ right: 8px;
+}
+.ol-popup-closer:after {
+ content: "✖";
+}
diff --git a/gramps/plugins/webreport/basepage.py b/gramps/plugins/webreport/basepage.py
index c7c3ac4f9..831a59ead 100644
--- a/gramps/plugins/webreport/basepage.py
+++ b/gramps/plugins/webreport/basepage.py
@@ -742,7 +742,7 @@ class BasePage: # pylint: disable=C1001
event_date = event.get_date_object()
# 0 = latitude, 1 = longitude, 2 - placetitle,
- # 3 = place handle, 4 = event date, 5 = event type
+ # 3 = place handle, 4 = event
found = any(data[3] == place_handle and data[4] == event_date
for data in place_lat_long)
if not found:
@@ -754,7 +754,7 @@ class BasePage: # pylint: disable=C1001
if latitude is not None:
etype = event.get_type()
place_lat_long.append([latitude, longitude, placetitle,
- place_handle, event_date, etype])
+ place_handle, event])
def _get_event_place(self, person, place_lat_long):
"""
diff --git a/gramps/plugins/webreport/common.py b/gramps/plugins/webreport/common.py
index 1f733f940..324143e1e 100644
--- a/gramps/plugins/webreport/common.py
+++ b/gramps/plugins/webreport/common.py
@@ -120,16 +120,27 @@ DROPMASTERS = """
function addMarker() {
var location = tracelife[iterator];
var myLatLng = new google.maps.LatLng(location[1], location[2]);
+ var infoWindow = new google.maps.InfoWindow;
- markers.push(new google.maps.Marker({
+ var marker = new google.maps.Marker({
position: myLatLng,
map: map,
draggable: true,
title: location[0],
animation: google.maps.Animation.DROP
- }));
+ });
+ markers.push(marker);
iterator++;
- }"""
+ var title = "
" + location[0] + "
"
+ bindInfoWindow(marker, map, infoWindow, title+location[4]);
+ }
+ function bindInfoWindow(marker, map, infoWindow, html) {
+ google.maps.event.addListener(marker, 'click', function() {
+ infoWindow.setContent(html);
+ infoWindow.open(map, marker);
+ });
+ }
+"""
# javascript for Google's Markers...
MARKERS = """
@@ -153,6 +164,7 @@ MARKERS = """
function addMarkers() {
var bounds = new google.maps.LatLngBounds();
+ var infoWindow = new google.maps.InfoWindow;
for (var i = 0; i < tracelife.length; i++) {
var location = tracelife[i];
@@ -165,10 +177,20 @@ MARKERS = """
map: map,
zIndex: location[3]
});
+ var title = "" + location[0] + "
"
+ bindInfoWindow(marker, map, infoWindow, title+location[4]);
bounds.extend(myLatLng);
if ( i > 1 ) { map.fitBounds(bounds); };
}
- }"""
+ }
+ function bindInfoWindow(marker, map, infoWindow, html) {
+ google.maps.event.addListener(marker, 'click', function() {
+ infoWindow.setContent(html);
+ infoWindow.open(map, marker);
+ });
+ }
+
+"""
# javascript for OpenStreetMap's markers...
"""
@@ -178,7 +200,7 @@ https://openlayers.org/en/latest/examples/
OSM_MARKERS = """
function initialize(){
var map;
- var tracelife = %s;
+ var tracelife = %s
var iconStyle = new ol.style.Style({
image: new ol.style.Icon(({
opacity: 1.0,
@@ -193,6 +215,7 @@ OSM_MARKERS = """
geometry: new ol.geom.Point(ol.proj.transform([loc[0], loc[1]],
'EPSG:4326', 'EPSG:3857')),
name: loc[2],
+ data: loc[3],
});
iconFeature.setStyle(iconStyle);
markerSource.addFeature(iconFeature);
@@ -201,11 +224,15 @@ OSM_MARKERS = """
source: markerSource,
style: iconStyle
});
+ tooltip = new ol.layer.Vector({
+ source: markerSource,
+ style: iconStyle
+ });
var centerCoord = new ol.proj.transform([%s, %s], 'EPSG:4326', 'EPSG:3857');
map = new ol.Map({
target: 'map_canvas',
layers: [new ol.layer.Tile({ source: new ol.source.OSM() }),
- markerLayer],
+ markerLayer, tooltip],
view: new ol.View({ center: centerCoord, zoom: %d })
});
"""
@@ -213,85 +240,119 @@ OSM_MARKERS = """
STAMEN_MARKERS = """
function initialize(){
var map;
- var tracelife = %s;
+ var tracelife = %s
var layer = '%s';
var iconStyle = new ol.style.Style({
image: new ol.style.Icon(({
- //anchor: [0.5, 46],
+ anchor: [0.2, 48],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 1.0,
src: marker_png
}))
});
- var markerSource = new ol.Collection();
+ var markerSource = new ol.source.Vector({
+ });
for (var i = 0; i < tracelife.length; i++) {
var loc = tracelife[i];
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([loc[0], loc[1]],
'EPSG:4326', 'EPSG:3857')),
name: loc[2],
+ data: loc[3],
});
iconFeature.setStyle(iconStyle);
- markerSource.push(iconFeature);
+ markerSource.addFeature(iconFeature);
}
var centerCoord = new ol.proj.transform([%s, %s], 'EPSG:4326', 'EPSG:3857');
+ markerLayer = new ol.layer.Vector({
+ source: markerSource,
+ style: iconStyle
+ });
+ tooltip = new ol.layer.Vector({
+ source: markerSource,
+ style: iconStyle
+ });
map = new ol.Map({
target: 'map_canvas',
layers: [
new ol.layer.Tile({ source: new ol.source.Stamen({
- layer: layer
- })
- }),
- new ol.layer.Vector({ source: new ol.source.Vector({
- features: markerSource })
- })
- ],
+ layer: layer }) }),
+ markerLayer, tooltip],
view: new ol.View({ center: centerCoord, zoom: %d })
});
"""
OPENLAYER = """
var element = document.getElementById('popup');
+ var content = document.getElementById('popup-content');
+ var closer = document.getElementById('popup-closer');
+ var tip = document.getElementById('tooltip');
+ var tipcontent = document.getElementById('tooltip-content');
+
var tooltip = new ol.Overlay({
- element: element,
+ element: tip,
positioning: 'bottom-center',
- stopEvent: false
+ offset: [10, 0],
});
map.addOverlay(tooltip);
- var displayFeatureInfo = function(pixel) {
- var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
+
+ var popup = new ol.Overlay({
+ element: element,
+ positioning: 'bottom-center',
+ autoPan: true,
+ autoPanAnimation: { duration: 500 },
+ stopEvent: false
+ });
+ map.addOverlay(popup);
+
+ /**
+ * Add a click handler to hide the popup.
+ * @return {boolean} Don't follow the href.
+ */
+ closer.onclick = function() {
+ popup.setPosition(undefined);
+ closer.blur();
+ return false;
+ };
+
+ map.on('pointermove', function(evt) {
+ evt.preventDefault()
+ var feature = this.forEachFeatureAtPixel(evt.pixel,
+ function(feature, layer) {
return feature;
});
- var info = document.getElementById('popup');
- if (feature) {
- var geometry = feature.getGeometry();
- var coord = geometry.getCoordinates();
- tooltip.setPosition(coord);
- $(element).siblings('.popover').css({ width: '250px' });
- $(element).siblings('.popover').css({ background: '#aaa' });
- $(info).popover({
- 'placement': 'auto',
- 'html': true,
- 'content': feature.get('name')
- });
- $(info).popover('show');
- } else {
- // TODO : some warning with firebug here
- $(info).popover('destroy');
- $('.popover').remove();
- }
- };
- map.on('pointermove', function(evt) {
+ map.getTargetElement().style.cursor = feature ? 'pointer' : '';
if (evt.dragging) {
+ popup.setPosition(undefined);
+ tooltip.setPosition(undefined);
return;
}
- var pixel = map.getEventPixel(evt.originalEvent);
- displayFeatureInfo(pixel);
- });
- map.on('click', function(evt) {
- displayFeatureInfo(evt.pixel);
+ if (feature) {
+ var coordinate = evt.coordinate;
+ tipcontent.innerHTML = feature.get('name');
+ tooltip.setPosition(coordinate);
+ } else {
+ tooltip.setPosition(undefined);
+ }
+
});
+ map.on('singleclick', function(evt) {
+ evt.preventDefault()
+ var feature = map.forEachFeatureAtPixel(evt.pixel,
+ function(feature, layer) {
+ return feature;
+ });
+ if (feature) {
+ var coordinate = evt.coordinate;
+ var title = '' + feature.get('name') + '
';
+ content.innerHTML = title + feature.get('data');
+ popup.setPosition(coordinate);
+ } else {
+ popup.setPosition(undefined);
+ }
+ });
+
};
"""
diff --git a/gramps/plugins/webreport/person.py b/gramps/plugins/webreport/person.py
index 450d0afc2..3016b2c67 100644
--- a/gramps/plugins/webreport/person.py
+++ b/gramps/plugins/webreport/person.py
@@ -52,7 +52,7 @@ import logging
#------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.lib import (ChildRefType, Date, Name, Person, EventRoleType,
- EventType)
+ Event, EventType)
from gramps.gen.lib.date import Today
from gramps.gen.plug.report import Bibliography
from gramps.gen.plug.report import utils
@@ -121,6 +121,7 @@ class PersonPages(BasePage):
self.sort_name = None
self.googleopts = None
self.googlemapkey = None
+ self.stamenopts = None
self.birthorder = None
self.person = None
self.familymappages = None
@@ -617,6 +618,35 @@ class PersonPages(BasePage):
# and close the file
self.xhtml_writer(indivdetpage, output_file, sio, date)
+ def _create_family_tracelife(self, tracelife, placetitle,
+ latitude, longitude, seq_, links):
+ """
+ creates individual family tracelife map events
+
+ @param: person -- person from database
+ @param: links -- used to add links in the popup html page
+ """
+ # are we using Google?
+ if self.mapservice == "Google":
+
+ # are we creating Family Links?
+ if self.googleopts == "FamilyLinks":
+ tracelife += """
+ new google.maps.LatLng(%s, %s),""" % (latitude, longitude)
+
+ # are we creating Drop Markers or Markers?
+ elif self.googleopts in ["Drop", "Markers"]:
+ tracelife += """
+ ['%s', %s, %s, %d, %s],""" % (placetitle.replace("'", "\\'"), latitude,
+ longitude, seq_, links)
+
+ # are we using OpenStreetMap, Stamen...
+ else:
+ tracelife += """
+ [%f, %f, \'%s\', %s],""" % (float(longitude), float(latitude),
+ placetitle.replace("'", "\\'"), links)
+ return tracelife
+
def __create_family_map(self, person, place_lat_long):
"""
creates individual family map page
@@ -640,7 +670,7 @@ class PersonPages(BasePage):
number_markers = len(place_lat_long)
if number_markers > 1:
for (latitude, longitude, placetitle, handle,
- date, etype) in place_lat_long:
+ event) in place_lat_long:
xwidth.append(latitude)
yheight.append(longitude)
xwidth.sort()
@@ -680,8 +710,8 @@ class PersonPages(BasePage):
# 0 = latitude, 1 = longitude, 2 = place title,
# 3 = handle, and 4 = date, 5 = event type...
- # being sorted by date, latitude, and longitude...
- place_lat_long = sorted(place_lat_long, key=itemgetter(4, 0, 1))
+ # being sorted by place_title
+ place_lat_long = sorted(place_lat_long, key=itemgetter(2))
# for all plugins
# if family_detail_page
@@ -730,61 +760,113 @@ class PersonPages(BasePage):
if number_markers > 0:
tracelife = "["
- seq_ = 1
+ seq_ = 0
- for index in range(0, (number_markers - 1)):
- (latitude, longitude, placetitle, handle, date,
- etype) = place_lat_long[index]
+ old_place_title = ""
+ oldevent = None
+ links = ""
+ ln_str = "%s"
+ for index in range(0, number_markers):
+ (latitude, longitude, placetitle, handle,
+ event) = place_lat_long[index]
+ # Do we have several events for this place?
+ if placetitle == old_place_title:
+ evthdle = event.get_handle()
+ bkref_list = self.report.bkref_dict[Event][evthdle]
+ url_fct = self.report.build_url_fname_html
+ if bkref_list:
+ for ref in bkref_list:
+ (bkref_class, bkref_hdle, role) = ref
+ if role == "Primary":
+ url = url_fct(bkref_hdle,
+ "ppl", self.uplink)
+ ppl_fct = self.r_db.get_person_from_handle
+ person = ppl_fct(bkref_hdle)
+ ppl_lnk = ln_str % (url,
+ person.get_gramps_id(),
+ self.get_name(person))
+ url = self.report.build_url_fname_html(event.get_handle(),
+ "evt", self.uplink)
+ evt_type = self._(str(event.get_type()))
+ evt_date = self.rlocale.get_date(event.get_date_object())
+ evt_lnk = ln_str % (url, evt_date, evt_type)
- # are we using Google?
- if self.mapservice == "Google":
+ links += ' + "%s"' % (ppl_lnk + self._(":") + evt_lnk)
+ if index == number_markers - 1:
+ tracelife = self._create_family_tracelife(tracelife,
+ placetitle,
+ latitude,
+ longitude,
+ seq_,
+ links)
+ break
+ continue
+ elif old_place_title != "" and index != 0:
+ (lat, lng, plcetitle, handle_,
+ event_) = place_lat_long[index-1]
+ tracelife = self._create_family_tracelife(tracelife,
+ plcetitle,
+ lat,
+ lng,
+ seq_,
+ links)
+ if old_place_title != placetitle:
+ old_place_title = placetitle
+ evthdle = event.get_handle()
+ bkref_list = self.report.bkref_dict[Event][evthdle]
+ url_fct = self.report.build_url_fname_html
+ if bkref_list:
+ for ref in bkref_list:
+ (bkref_class, bkref_hdle, role) = ref
+ if role == "Primary":
+ url = url_fct(bkref_hdle,
+ "ppl", self.uplink)
+ ppl_fct = self.r_db.get_person_from_handle
+ person = ppl_fct(bkref_hdle)
+ ppl_lnk = ln_str % (url,
+ person.get_gramps_id(),
+ self.get_name(person))
+ url = self.report.build_url_fname_html(event.handle,
+ "evt",
+ self.uplink)
+ evt_type = self._(str(event.get_type()))
+ evt_date = self.rlocale.get_date(event.get_date_object())
+ evt_lnk = ln_str % (url, evt_date, evt_type)
- # are we creating Family Links?
- if self.googleopts == "FamilyLinks":
- tracelife += """
- new google.maps.LatLng(%s, %s),""" % (latitude, longitude)
-
- # are we creating Drop Markers or Markers?
- elif self.googleopts in ["Drop", "Markers"]:
- tracelife += """
- ['%s', %s, %s, %d],""" % (placetitle.replace("'", "\\'"), latitude,
- longitude, seq_)
-
- # are we using OpenStreetMap?
+ links = '"%s"' % (ppl_lnk + self._(":") +
+ evt_lnk)
+ elif index == number_markers:
+ tracelife = self._create_family_tracelife(tracelife,
+ placetitle,
+ latitude,
+ longitude,
+ seq_,
+ links)
else:
- tracelife += """
- [%f, %f, \'%s\'],""" % (float(longitude), float(latitude),
- placetitle.replace("'", "\\'"))
-
+ evthdle = event.get_handle()
+ bkref_list = self.report.bkref_dict[Event][evthdle]
+ url_fct = self.report.build_url_fname_html
+ if bkref_list:
+ for ref in bkref_list:
+ (bkref_class, bkref_hdle, role) = ref
+ if role == "Primary":
+ url = url_fct(bkref_hdle,
+ "ppl", self.uplink)
+ ppl_fct = self.r_db.get_person_from_handle
+ person = ppl_fct(bkref_hdle)
+ ppl_lnk = ln_str % (url,
+ person.get_gramps_id(),
+ self.get_name(person))
+ url = self.report.build_url_fname_html(event.handle,
+ "evt",
+ self.uplink)
+ evt_type = self._(str(event.get_type()))
+ evt_lnk = ln_str % (url, evt_type, evt_type)
+ links = '"%s"' % (ppl_lnk + self._(":") + evt_lnk)
+ old_place_title = placetitle
seq_ += 1
- # FIXME: The last element in the place_lat_long list is treated
- # specially, and the code above is apparently repeated so as to
- # avoid a comma at the end, and get the right closing. This is very
- # ugly.
- (latitude, longitude, placetitle, handle, date,
- etype) = place_lat_long[-1]
-
- # are we using Google?
- if self.mapservice == "Google":
-
- # are we creating Family Links?
- if self.googleopts == "FamilyLinks":
- tracelife += """
- new google.maps.LatLng(%s, %s)
- ];""" % (latitude, longitude)
-
- # are we creating Drop Markers or Markers?
- elif self.googleopts in ["Drop", "Markers"]:
- tracelife += """
- ['%s', %s, %s, %d]
- ];""" % (placetitle.replace("'", "\\'"), latitude, longitude, seq_)
-
- # we are using OpenStreetMap, Stamen...
- else:
- tracelife += """
- [%f, %f, \'%s\']
- ];""" % (float(longitude), float(latitude), placetitle.replace("'", "\\'"))
+ tracelife += "];"
# begin MapDetail division...
with Html("div", class_="content", id="FamilyMapDetail") as mapdetail:
outerwrapper += mapdetail
@@ -872,13 +954,13 @@ class PersonPages(BasePage):
longitude,
latitude,
10,
- )
+ )
else:
jsc += STAMEN_MARKERS % (tracelife,
self.stamenopts,
midy_, midx_,
zoomlevel,
- )
+ )
jsc += OPENLAYER
# if Google and Drop Markers are selected,
@@ -888,8 +970,20 @@ class PersonPages(BasePage):
id="drop", onclick="drop()", inline=True)
# add div for popups.
- with Html("div", id="popup", inline=True) as popup:
- mapdetail += popup
+ if self.mapservice == "Google":
+ with Html("div", id="popup", inline=True) as popup:
+ mapdetail += popup
+ else:
+ with Html("div", id="popup", class_="ol-popup",
+ inline=True) as popup:
+ mapdetail += popup
+ popup += Html("a", href="#", id="popup-closer",
+ class_="ol-popup-closer")
+ popup += Html("div", id="popup-content")
+ with Html("div", id="tooltip", class_="ol-popup",
+ inline=True) as tooltip:
+ mapdetail += tooltip
+ tooltip += Html("div", id="tooltip-content")
# begin place reference section and its table...
with Html("div", class_="subsection", id="references") as section:
@@ -917,11 +1011,16 @@ class PersonPages(BasePage):
tbody = Html("tbody")
table += tbody
- for (latitude, longitude, placetitle, handle, date,
- etype) in place_lat_long:
+ # being sorted by date
+ place_lat_long = sorted(place_lat_long,
+ key=lambda evt:
+ evt[4].get_date_object())
+ for (latitude, longitude, placetitle, handle,
+ event) in place_lat_long:
trow = Html("tr")
tbody += trow
+ date = event.get_date_object()
trow.extend(
Html("td", data, class_=colclass, inline=True)
for data, colclass in [
@@ -929,7 +1028,7 @@ class PersonPages(BasePage):
(self.place_link(handle, placetitle,
uplink=True),
"ColumnPlace"),
- (str(etype), "ColumnType")
+ (str(event.get_type()), "ColumnType")
]
)
diff --git a/gramps/plugins/webreport/place.py b/gramps/plugins/webreport/place.py
index a95e63632..56850be09 100644
--- a/gramps/plugins/webreport/place.py
+++ b/gramps/plugins/webreport/place.py
@@ -426,7 +426,7 @@ class PlacePages(BasePage):
jsc += MARKERS % ([[plce,
latitude,
longitude,
- 1]],
+ 1,""]],
latitude, longitude,
10)
@@ -436,7 +436,7 @@ class PlacePages(BasePage):
jsc += MARKER_PATH % marker_path
jsc += OSM_MARKERS % ([[float(longitude),
float(latitude),
- placetitle]],
+ placetitle,""]],
longitude, latitude, 10)
jsc += OPENLAYER
else: # STAMEN
@@ -445,7 +445,7 @@ class PlacePages(BasePage):
jsc += MARKER_PATH % marker_path
jsc += STAMEN_MARKERS % ([[float(longitude),
float(latitude),
- placetitle]],
+ placetitle,""]],
self.stamenopts,
longitude, latitude, 10)
jsc += OPENLAYER