Skip to content

Commit

Permalink
Merge pull request #45 from aarranz/feature/support-updating-popovers
Browse files Browse the repository at this point in the history
Update popovers of selected PoIs
  • Loading branch information
aarranz committed Jul 23, 2021
2 parents 072ec2c + 3da25b6 commit 8ef4499
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 34 deletions.
1 change: 1 addition & 0 deletions src/doc/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Repaint popovers when moving/zooming the map (when using sticky events).
- Fix placement of popovers when icon anchor is different to `[0.5, 1]`
- Switch code to use let and const
- Update popover contents when the selected PoI is updated


## v1.2.3 (2021-03-25)
Expand Down
100 changes: 71 additions & 29 deletions src/js/ol3-map-widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
const update_selected_feature = function update_selected_feature(feature) {
if (this.selected_feature != feature) {
this.selected_feature = feature;
if (this.popover != null) {
if (feature == null && this.popover != null) {
this.popover.hide();
this.popover = null;
}
Expand Down Expand Up @@ -397,6 +397,27 @@
};

Widget.prototype.init = function init() {
this.refpos = {
getBoundingClientRect: () => {
const feature = this.selected_feature;
const marker_coordinates = ol.extent.getCenter(feature.getGeometry().getExtent());
const marker_position = this.map.getPixelFromCoordinate(marker_coordinates);
const marker_style = feature.getStyle()(feature);
const marker_image = marker_style.getImage();
let marker_size;
if (marker_image != null && (marker_size = marker_image.getSize()) != null) {
const marker_scale = marker_image.getScale();
let marker_anchor = marker_image.getAnchor();
marker_size = marker_size.map((value) => value * marker_scale);
marker_anchor = marker_anchor.map((value) => value * marker_scale);
const top = marker_position[1] - marker_anchor[1];
const left = marker_position[0] - marker_anchor[0];
return new DOMRect(left, top, marker_size[0], marker_size[1]);
} else {
return new DOMRect(marker_position[0], marker_position[1], 0, 0);
}
}
};

const layers_button = document.getElementById('button');
layers_button.addEventListener('click', (event) => {
Expand Down Expand Up @@ -575,8 +596,7 @@
} else if (this.selected_feature != null && this.selected_feature.get('content') == null) {
unselect.call(this, this.selected_feature);
update_selected_feature.call(this, null);
} else if (feature !== this.selected_feature && this.popover != null) {
this.popover.hide();
} else if (feature !== this.selected_feature) {
update_selected_feature.call(this, null);
}
}.bind(this));
Expand Down Expand Up @@ -690,6 +710,24 @@
iconFeature.setStyle(style);

if (this.selected_feature === iconFeature) {
if (this.popover != null) {
if ("update" in this.popover) {
// WireCloud 1.4+
this.popover.update(
iconFeature.get("title"),
new StyledElements.Fragment(iconFeature.get("content"))
);
} else {
// Workaround for WireCloud 1.3 and below
const popover = this.popover;
this.popover = null;
popover.hide().hide();
this.popover = popover;
popover.options.title = iconFeature.get("title");
popover.options.content = new StyledElements.Fragment(iconFeature.get("content"));
popover.show(this.refpos);
}
}
MashupPlatform.widget.outputs.poiOutput.pushEvent(iconFeature.get('data'));
}
};
Expand All @@ -702,14 +740,39 @@
Widget.prototype.replacePoIs = function replacePoIs(poi_info) {
this.vector_source.clear();
poi_info.forEach(this.registerPoI, this);

if (this.selected_feature != null) {
if (this.popover != null) {
this.popover.hide();
}
const new_selected_feature = this.vector_source.getFeatureById(this.selected_feature.getId());
if (new_selected_feature != null) {
this.select_feature(new_selected_feature);
const poi_info = new_selected_feature.get('data');
const style = parse_marker_definition.call(this, poi_info.iconHighlighted || poi_info.icon, poi_info.styleHighlighted || poi_info.style);
new_selected_feature.setStyle(style);
}

if (this.popover != null) {
if (new_selected_feature != null) {
if ("update" in this.popover) {
// WireCloud 1.4+
this.popover.update(
new_selected_feature.get("title"),
new StyledElements.Fragment(new_selected_feature.get("content"))
);
} else {
// Workaround for WireCloud 1.3 and below
const popover = this.popover;
this.popover = null;
popover.hide().hide();
this.popover = popover;
popover.options.title = new_selected_feature.get("title");
popover.options.content = new StyledElements.Fragment(new_selected_feature.get("content"));
popover.show(this.refpos);
}
} else {
this.popover.hide();
this.popover = null;
}
}
update_selected_feature.call(this, new_selected_feature);
}
};

Expand Down Expand Up @@ -1226,29 +1289,8 @@
return;
}

const refpos = {
getBoundingClientRect: () => {
const marker_coordinates = ol.extent.getCenter(feature.getGeometry().getExtent());
const marker_position = this.map.getPixelFromCoordinate(marker_coordinates);
const marker_style = feature.getStyle()(feature);
const marker_image = marker_style.getImage();
let marker_size;
if (marker_image != null && (marker_size = marker_image.getSize()) != null) {
const marker_scale = marker_image.getScale();
let marker_anchor = marker_image.getAnchor();
marker_size = marker_size.map((value) => value * marker_scale);
marker_anchor = marker_anchor.map((value) => value * marker_scale);
const top = marker_position[1] - marker_anchor[1];
const left = marker_position[0] - marker_anchor[0];
return new DOMRect(left, top, marker_size[0], marker_size[1]);
} else {
return new DOMRect(marker_position[0], marker_position[1], 0, 0);
}
}
};

update_selected_feature.call(this, feature);
this.popover.show(refpos);
this.popover.show(this.refpos);
}, 100);
}
};
Expand Down
159 changes: 154 additions & 5 deletions tests/js/OpenlayersWidgetSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -972,10 +972,85 @@
MashupPlatform.widget.outputs.poiOutput.reset();
widget.registerPoI(poi_info);

expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledTimes(1);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledWith(poi_info);
expect(widget.selected_feature).toBe(feature_mock);
});

it("updates popovers when updating the selected PoI", () => {
const feature_mock = new ol.Feature();
widget.init();
widget.selected_feature = feature_mock;
widget.popover = {
update: jasmine.createSpy("update")
};
spyOn(feature_mock, 'set');
spyOn(feature_mock, 'setGeometry');
spyOn(feature_mock, 'setStyle');
spyOn(widget.vector_source, 'addFeature');
spyOn(widget.vector_source, 'getFeatureById').and.returnValue(feature_mock);
const poi_info = deepFreeze({
id: '1',
data: {},
title: "testtitle",
infoWindow: "testcontent",
location: {
type: 'Point',
coordinates: [0, 0]
}
});
spyOn(feature_mock, "get").and.callFake((attr) => {
if (attr == "conent") {
return poi_info.infoWindow;
} else {
return poi_info[attr];
}
});
widget.registerPoI(poi_info);

expect(widget.popover.update).toHaveBeenCalledTimes(1);
expect(widget.popover.update).toHaveBeenCalledWith(poi_info.title, jasmine.any(StyledElements.Fragment));
expect(widget.selected_feature).toBe(feature_mock);
});

it("updates popovers when updating the selected PoI (WireCloud 1.3 and below)", () => {
const feature_mock = new ol.Feature();
widget.init();
widget.selected_feature = feature_mock;
const mock_popover = widget.popover = {
options: {},
hide: jasmine.createSpy("hide").and.callFake(() => mock_popover),
show: jasmine.createSpy("show")
};
spyOn(feature_mock, 'set');
spyOn(feature_mock, 'setGeometry');
spyOn(feature_mock, 'setStyle');
spyOn(widget.vector_source, 'addFeature');
spyOn(widget.vector_source, 'getFeatureById').and.returnValue(feature_mock);
const poi_info = deepFreeze({
id: '1',
data: {},
title: "testtitle",
infoWindow: "testcontent",
location: {
type: 'Point',
coordinates: [0, 0]
}
});
spyOn(feature_mock, "get").and.callFake((attr) => {
if (attr == "conent") {
return poi_info.infoWindow;
} else {
return poi_info[attr];
}
});
widget.registerPoI(poi_info);

expect(widget.popover.hide).toHaveBeenCalledTimes(2);
expect(widget.popover.show).toHaveBeenCalledTimes(1);
expect(widget.selected_feature).toBe(feature_mock);
});

describe("handles the style option:", () => {
const test = function (style, expected) {
return () => {
Expand Down Expand Up @@ -1180,12 +1255,39 @@

expect(widget.registerPoI).not.toHaveBeenCalled();
expect(widget.selected_feature).toBe(null);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).not.toHaveBeenCalled();
});

it("supports cleaning current PoIs (having a selected poi)", () => {
widget.init();
const initial_feature_mock = new ol.Feature();
initial_feature_mock.setId("1");
widget.selected_feature = initial_feature_mock;
const popover = widget.popover = {
update: jasmine.createSpy("update"),
hide: jasmine.createSpy("hide")
};
spyOn(widget, "registerPoI");
spyOn(widget, "select_feature");
spyOn(widget.vector_source, "clear");

widget.replacePoIs([]);

expect(widget.registerPoI).not.toHaveBeenCalled();
expect(widget.select_feature).not.toHaveBeenCalled();
expect(popover.update).not.toHaveBeenCalled();
expect(popover.hide).toHaveBeenCalledWith();
expect(widget.popover).toBe(null);
expect(widget.selected_feature).toBe(null);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledTimes(1);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledWith(null);
});

it("should maintain current selection if it exists on the new status", () => {
const poi_info = deepFreeze({
id: '1',
data: {},
title: "test",
location: {
type: 'Point',
coordinates: [0, 0]
Expand All @@ -1195,11 +1297,50 @@
const initial_feature_mock = new ol.Feature();
initial_feature_mock.setId("1");
widget.selected_feature = initial_feature_mock;
widget.popover = {
hide: jasmine.createSpy('hide')
const popover = widget.popover = {
update: jasmine.createSpy("update"),
hide: jasmine.createSpy("hide")
};
const new_feature_mock = new ol.Feature();
spyOn(new_feature_mock, "get").and.callFake((attr) => attr == "data" ? poi_info : poi_info[attr]);
spyOn(widget, "registerPoI");
spyOn(widget, "select_feature");
spyOn(widget.vector_source, 'clear');
spyOn(widget.vector_source, 'getFeatureById').and.returnValue(new_feature_mock);

widget.replacePoIs([poi_info]);

expect(widget.registerPoI).toHaveBeenCalledTimes(1);
expect(widget.vector_source.getFeatureById).toHaveBeenCalledTimes(1);
expect(widget.vector_source.getFeatureById).toHaveBeenCalledWith("1");
expect(widget.popover).toBe(popover);
expect(popover.update).toHaveBeenCalledWith("test", jasmine.any(StyledElements.Fragment));
expect(widget.selected_feature).toBe(new_feature_mock);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledTimes(1);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledWith(poi_info);
});

it("should maintain current selection if it exists on the new status (WireCloud 1.3 and below)", () => {
const poi_info = deepFreeze({
id: '1',
data: {},
title: "test",
location: {
type: 'Point',
coordinates: [0, 0]
}
});
widget.init();
const initial_feature_mock = new ol.Feature();
initial_feature_mock.setId("1");
widget.selected_feature = initial_feature_mock;
const popover = widget.popover = {
options: {},
hide: jasmine.createSpy("hide").and.callFake(() => popover),
show: jasmine.createSpy("show")
};
const new_feature_mock = new ol.Feature();
spyOn(new_feature_mock, "get").and.returnValue(poi_info);
spyOn(new_feature_mock, "get").and.callFake((attr) => attr == "data" ? poi_info : poi_info[attr]);
spyOn(widget, "registerPoI");
spyOn(widget, "select_feature");
spyOn(widget.vector_source, 'clear');
Expand All @@ -1210,7 +1351,12 @@
expect(widget.registerPoI).toHaveBeenCalledTimes(1);
expect(widget.vector_source.getFeatureById).toHaveBeenCalledTimes(1);
expect(widget.vector_source.getFeatureById).toHaveBeenCalledWith("1");
expect(widget.select_feature).toHaveBeenCalledWith(new_feature_mock);
expect(widget.popover).toBe(popover);
expect(popover.hide).toHaveBeenCalledTimes(2);
expect(popover.show).toHaveBeenCalledTimes(1);
expect(widget.selected_feature).toBe(new_feature_mock);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledTimes(1);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledWith(poi_info);
});

it("should clean current selection if it does not exist on the new status", () => {
Expand Down Expand Up @@ -1239,6 +1385,9 @@
expect(widget.vector_source.getFeatureById).toHaveBeenCalledTimes(1);
expect(widget.vector_source.getFeatureById).toHaveBeenCalledWith("5");
expect(popover.hide).toHaveBeenCalledTimes(1);
expect(widget.popover).toBe(null);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledTimes(1);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledWith(null);
});

});
Expand Down Expand Up @@ -1360,7 +1509,7 @@
expect(widget.map.getView().fit).not.toHaveBeenCalled();
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledTimes(1);
expect(MashupPlatform.widget.outputs.poiOutput.pushEvent).toHaveBeenCalledWith(poi_info2);
expect(widget.popover).toBe(null);
expect(widget.popover).not.toBe(null);
expect(widget.selected_feature).toBe(feature);
done();
});
Expand Down

0 comments on commit 8ef4499

Please sign in to comment.