Commit d5c6648c authored by Piotr Gawron's avatar Piotr Gawron
Browse files

Merge remote-tracking branch 'origin/master' into...

Merge remote-tracking branch 'origin/master' into 1529-introduce-uniform-checkstyle-validation-as-gitlab-job
parents d17d39dc 46fee41d
Pipeline #46983 failed with stage
in 12 minutes and 29 seconds
minerva (16.1.0~alpha.0) stable; urgency=medium minerva (16.1.0~alpha.0) stable; urgency=medium
* Small improvement: API provides information about modifier type (#1085)
* Small improvement: map file for JavaScript is properly referenced (#1545)
* Bug fix: api endpoints were exposed without 'api' prefix * Bug fix: api endpoints were exposed without 'api' prefix
* Bug fix: anonymous user could upload file using API * Bug fix: anonymous user could upload file using API
* Bug fix: when passing JSON in patch/post methods contentType was not * Bug fix: when passing JSON in patch/post methods contentType was not
checked checked
-- Piotr Gawron <piotr.gawron@uni.lu> Thu, 9 Sep 2021 13:00:00 +0200
minerva (16.0.0~beta.2) stable; urgency=medium
* Small improvement: backgrounds are separated from general overlays (#1532)
* Small improvement: layout of pin popup window is slitghly improved (#1493)
* Small improvement: search results are grouped by submap with hits (#1505)
* Bug fix: correct background order for old projects restored (#1533)
* Bug fix: search chemicals by target returned chemicals not bounded by
disease (#1535)
* Bug fix: problem with export map with submaps fixed (#1540)
* Bug fix: clear does not show warning about missing disease ID (#1541)
* Bug fix: removing user removed backgrounds in projects created by user
(#1527)
* Bug fix: removing background did not remove images from server (#1526)
* Bug fix: two genomic data overlay with two different reference genomes
caused issue (#1546)
* Bug fix: search results were limited to 10 elements
-- Piotr Gawron <piotr.gawron@uni.lu> Thu, 9 Sep 2021 11:00:00 +0200
minerva (16.0.0~beta.1) stable; urgency=medium minerva (16.0.0~beta.1) stable; urgency=medium
* Backward incompatibility: layout parameter in minerva url is not supported * Backward incompatibility: layout parameter in minerva url is not supported
anymore anymore
......
...@@ -5,6 +5,7 @@ import java.util.ArrayList; ...@@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Set;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
...@@ -329,4 +330,12 @@ public class Chemical implements Serializable, TargettingStructure { ...@@ -329,4 +330,12 @@ public class Chemical implements Serializable, TargettingStructure {
} }
} }
public boolean containsTarget(MiriamData miriamTarget) {
boolean result = false;
for (Target target : getTargets()) {
result |= target.getGenes().contains(new MiriamData(miriamTarget.getDataType(), miriamTarget.getResource()));
}
return result;
}
} }
...@@ -9,6 +9,10 @@ import org.apache.commons.lang3.StringUtils; ...@@ -9,6 +9,10 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lcsb.mapviewer.annotation.data.serializer.MeSHSerializer;
/** /**
* This class represents <a href="http://www.nlm.nih.gov/cgi/mesh//">MeSH</a> * This class represents <a href="http://www.nlm.nih.gov/cgi/mesh//">MeSH</a>
* object. * object.
...@@ -17,6 +21,7 @@ import org.apache.logging.log4j.Logger; ...@@ -17,6 +21,7 @@ import org.apache.logging.log4j.Logger;
* *
*/ */
@XmlRootElement @XmlRootElement
@JsonSerialize(using = MeSHSerializer.class)
public class MeSH implements Serializable { public class MeSH implements Serializable {
/** /**
......
package lcsb.mapviewer.annotation.data.serializer;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lcsb.mapviewer.annotation.data.MeSH;
public class MeSHSerializer extends JsonSerializer<MeSH> {
@Override
public void serialize(final MeSH mesh, final JsonGenerator gen, final SerializerProvider serializers)
throws IOException {
gen.writeStartObject();
gen.writeStringField("name", mesh.getName());
gen.writeStringField("id", mesh.getMeSHId());
gen.writeStringField("description", mesh.getDescription());
gen.writeObjectField("synonyms", mesh.getSynonyms());
gen.writeEndObject();
}
}
\ No newline at end of file
...@@ -43,7 +43,7 @@ public class PubmedParser extends CachableInterface implements IExternalService ...@@ -43,7 +43,7 @@ public class PubmedParser extends CachableInterface implements IExternalService
/** /**
* Version of the remote API that is supported by this connecting class. * Version of the remote API that is supported by this connecting class.
*/ */
static final String SUPPORTED_VERSION = "6.5"; static final String SUPPORTED_VERSION = "6.6";
static final String API_URL = "https://www.ebi.ac.uk/europepmc/webservices/rest/"; static final String API_URL = "https://www.ebi.ac.uk/europepmc/webservices/rest/";
/** /**
* Length of {@link #PUBMED_PREFIX} string. * Length of {@link #PUBMED_PREFIX} string.
......
...@@ -2,7 +2,15 @@ package lcsb.mapviewer.annotation.services.dapi; ...@@ -2,7 +2,15 @@ package lcsb.mapviewer.annotation.services.dapi;
import java.io.IOException; import java.io.IOException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -14,10 +22,14 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -14,10 +22,14 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import lcsb.mapviewer.annotation.data.Chemical; import lcsb.mapviewer.annotation.data.Chemical;
import lcsb.mapviewer.annotation.data.Target; import lcsb.mapviewer.annotation.data.Target;
import lcsb.mapviewer.annotation.services.dapi.dto.*; import lcsb.mapviewer.annotation.services.dapi.dto.ChemicalEntityDto;
import lcsb.mapviewer.annotation.services.dapi.dto.ChemicalEntityDtoConverter;
import lcsb.mapviewer.annotation.services.dapi.dto.ListChemicalEntityDto;
import lcsb.mapviewer.common.exception.InvalidArgumentException; import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.model.Project; import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.map.*; import lcsb.mapviewer.model.map.BioEntity;
import lcsb.mapviewer.model.map.MiriamData;
import lcsb.mapviewer.model.map.MiriamType;
import lcsb.mapviewer.model.map.model.ModelData; import lcsb.mapviewer.model.map.model.ModelData;
import lcsb.mapviewer.model.map.model.ModelSubmodelConnection; import lcsb.mapviewer.model.map.model.ModelSubmodelConnection;
...@@ -137,8 +149,10 @@ public class ChemicalParser { ...@@ -137,8 +149,10 @@ public class ChemicalParser {
ListChemicalEntityDto dto = objectMapper.readValue(content, ListChemicalEntityDto.class); ListChemicalEntityDto dto = objectMapper.readValue(content, ListChemicalEntityDto.class);
List<Chemical> chemicals = fetchChemicals(dto, disease); List<Chemical> chemicals = fetchChemicals(dto, disease);
for (Chemical drug : chemicals) { for (Chemical chemical : chemicals) {
result.put(drug.getChemicalId(), drug); if (chemical.containsTarget(target)) {
result.put(chemical.getChemicalId(), chemical);
}
} }
} }
return new ArrayList<>(result.values()); return new ArrayList<>(result.values());
...@@ -183,8 +197,10 @@ public class ChemicalParser { ...@@ -183,8 +197,10 @@ public class ChemicalParser {
} }
Set<String> names = new HashSet<>(); Set<String> names = new HashSet<>();
for (MiriamData hgncSymbol : hgncSymbols) { for (MiriamData hgncSymbol : hgncSymbols) {
// fetching all chemicals for big map is very memory exhaustive, therefore do it // fetching all chemicals for big map is very memory exhaustive, therefore
// step by step to prevent storing everything in the memory at single point // do it
// step by step to prevent storing everything in the memory at single
// point
List<Chemical> chemicals = getChemicalListByTarget(hgncSymbol, diseaseMiriam); List<Chemical> chemicals = getChemicalListByTarget(hgncSymbol, diseaseMiriam);
for (Chemical chemical : chemicals) { for (Chemical chemical : chemicals) {
names.add(chemical.getChemicalName()); names.add(chemical.getChemicalName());
......
...@@ -2,6 +2,7 @@ package lcsb.mapviewer.annotation.services.dapi; ...@@ -2,6 +2,7 @@ package lcsb.mapviewer.annotation.services.dapi;
import java.util.List; import java.util.List;
import lcsb.mapviewer.annotation.services.dapi.dto.DapiDatabase;
import lcsb.mapviewer.annotation.services.dapi.dto.ReleaseDto; import lcsb.mapviewer.annotation.services.dapi.dto.ReleaseDto;
import lcsb.mapviewer.annotation.services.dapi.dto.UserDto; import lcsb.mapviewer.annotation.services.dapi.dto.UserDto;
...@@ -20,7 +21,7 @@ public interface DapiConnector { ...@@ -20,7 +21,7 @@ public interface DapiConnector {
void resetConnection(); void resetConnection();
List<String> getDatabases() throws DapiConnectionException; List<DapiDatabase> getDatabases() throws DapiConnectionException;
List<ReleaseDto> getReleases(String database) throws DapiConnectionException; List<ReleaseDto> getReleases(String database) throws DapiConnectionException;
......
...@@ -32,6 +32,7 @@ import com.google.gson.JsonArray; ...@@ -32,6 +32,7 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import lcsb.mapviewer.annotation.cache.CachableInterface; import lcsb.mapviewer.annotation.cache.CachableInterface;
import lcsb.mapviewer.annotation.services.dapi.dto.DapiDatabase;
import lcsb.mapviewer.annotation.services.dapi.dto.ListReleaseDto; import lcsb.mapviewer.annotation.services.dapi.dto.ListReleaseDto;
import lcsb.mapviewer.annotation.services.dapi.dto.ReleaseDto; import lcsb.mapviewer.annotation.services.dapi.dto.ReleaseDto;
import lcsb.mapviewer.annotation.services.dapi.dto.UserDto; import lcsb.mapviewer.annotation.services.dapi.dto.UserDto;
...@@ -237,9 +238,9 @@ public class DapiConnectorImpl extends CachableInterface implements DapiConnecto ...@@ -237,9 +238,9 @@ public class DapiConnectorImpl extends CachableInterface implements DapiConnecto
} }
@Override @Override
public List<String> getDatabases() throws DapiConnectionException { public List<DapiDatabase> getDatabases() throws DapiConnectionException {
try { try {
List<String> result = new ArrayList<>(); List<DapiDatabase> result = new ArrayList<>();
String url = DAPI_BASE_URL + "database/"; String url = DAPI_BASE_URL + "database/";
String content = getWebPageDownloader().getFromNetwork(url); String content = getWebPageDownloader().getFromNetwork(url);
JsonArray array = new JsonParser() JsonArray array = new JsonParser()
...@@ -249,7 +250,7 @@ public class DapiConnectorImpl extends CachableInterface implements DapiConnecto ...@@ -249,7 +250,7 @@ public class DapiConnectorImpl extends CachableInterface implements DapiConnecto
.getAsJsonArray(); .getAsJsonArray();
for (int i = 0; i < array.size(); i++) { for (int i = 0; i < array.size(); i++) {
result.add(array.get(i).getAsJsonObject().get("name").getAsString()); result.add(new DapiDatabase(array.get(i).getAsJsonObject().get("name").getAsString()));
} }
return result; return result;
} catch (Exception e) { } catch (Exception e) {
......
package lcsb.mapviewer.annotation.services.dapi.dto;
public class DapiDatabase {
public String name;
public DapiDatabase(String name) {
this.name = name;
}
}
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version> <version>${jackson.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
"main": "minerva.js", "main": "minerva.js",
"scripts": { "scripts": {
"build:css": "node scripts/build-css.js", "build:css": "node scripts/build-css.js",
"build:js": "browserify --debug --standalone minerva src/main/js/minerva.js | exorcist dist/minerva.js.map > dist/minerva.js ", "build:js": "browserify --debug --standalone minerva src/main/js/minerva.js | exorcist dist/minerva.js.map --url 'minerva.js.map.xhtml?ln=js' > dist/minerva.js ",
"build-browser-check:js": "browserify --debug --standalone BrowserCheck src/main/js/BrowserCheck.js | exorcist dist/BrowserCheck.js.map > dist/BrowserCheck.js ", "build-browser-check:js": "browserify --debug --standalone BrowserCheck src/main/js/BrowserCheck.js | exorcist dist/BrowserCheck.js.map --url 'BrowserCheck.js.map.xhtml?ln=js' > dist/BrowserCheck.js ",
"//": "rm -rf dist & rmdir /q /s dist & mkdir dist & browserify --debug --standalone minerva src/main/js/minerva.js | exorcist dist/minerva.js.map > dist/minerva.js & uglifyjs --compress --mangle --in-source-map dist/minerva.js.map --source-map-include-sources --source-map dist/minerva.min.js.map -o dist/minerva.min.js dist/minerva.js", "//": "rm -rf dist & rmdir /q /s dist & mkdir dist & browserify --debug --standalone minerva src/main/js/minerva.js | exorcist dist/minerva.js.map --url 'minerva.js.map.xhtml?ln=js' > dist/minerva.js & uglifyjs --compress --mangle --in-source-map dist/minerva.js.map --source-map-include-sources --source-map dist/minerva.min.js.map -o dist/minerva.min.js dist/minerva.js",
"build-deploy": "npm run build && npm run deploy", "build-deploy": "npm run build && npm run deploy",
"build": "npm run clean && npm run build:css && npm run build:js && npm run build-browser-check:js", "build": "npm run clean && npm run build:css && npm run build:js && npm run build-browser-check:js",
"clean": "node scripts/clean.js", "clean": "node scripts/clean.js",
......
...@@ -124,16 +124,16 @@ GenericSearchPanel.prototype.createTableElement = function (element, icon) { ...@@ -124,16 +124,16 @@ GenericSearchPanel.prototype.createTableElement = function (element, icon) {
var result = document.createElement("div"); var result = document.createElement("div");
var table = document.createElement("table"); var table = document.createElement("table");
var expandStyle = "fa-eye"; var expandStyle = "fa-eye";
var headerDiv; var label = "";
if (element.getModelId() !== self.getMap().getId()) { if (element.getModelId() !== self.getMap().getId()) {
headerDiv = guiUtils.createSubMapLink({ label = "Submap: ";
label: "Submap: ",
mapId: element.getModelId()
});
} else { } else {
headerDiv = document.createElement("div"); label = "Top map: ";
$(headerDiv).css("height", "21px");
} }
var headerDiv = guiUtils.createSubMapLink({
label: label + "("+element.getBioEntities().length + " hits): ",
mapId: element.getModelId()
});
$(headerDiv).css("padding", "5px"); $(headerDiv).css("padding", "5px");
$(table).hide(); $(table).hide();
result.appendChild(headerDiv); result.appendChild(headerDiv);
...@@ -189,13 +189,7 @@ GenericSearchPanel.prototype.addResultTab = function (query, elements) { ...@@ -189,13 +189,7 @@ GenericSearchPanel.prototype.addResultTab = function (query, elements) {
groupsByMap[element.getModelId()].addBioEntity(element); groupsByMap[element.getModelId()].addBioEntity(element);
} }
} }
return AbstractDbPanel.prototype.addResultTab.call(this, query, groups).then(function () { return AbstractDbPanel.prototype.addResultTab.call(this, query, groups);
var contentElement = self.getControlElement(PanelControlElementType.SEARCH_RESULTS_CONTENT_TAB);
var links = $(".table div>a.minerva-toggle-hide-show", contentElement);
if (links.length > 0) {
links[0].onclick();
}
});
} }
/** /**
......
...@@ -114,6 +114,27 @@ OverlayPanel.prototype.constructor = OverlayPanel; ...@@ -114,6 +114,27 @@ OverlayPanel.prototype.constructor = OverlayPanel;
* @private * @private
*/ */
OverlayPanel.prototype._createOverlayPanelGui = function () { OverlayPanel.prototype._createOverlayPanelGui = function () {
var backgroundsDiv = Functions.createElement({
type: "div",
name: "backgroundsOverlays",
className: "searchPanel"
});
this.getElement().appendChild(backgroundsDiv);
var backgroundsTitle = Functions.createElement({
type: "h5",
content: "BACKGROUNDS:"
});
backgroundsDiv.appendChild(backgroundsTitle);
var backgroundsTableDiv = Functions.createElement({
type: "table",
name: "backgroundsTab",
className: "table table-bordered",
style: "width:100%"
});
backgroundsDiv.appendChild(backgroundsTableDiv);
var generalOverlaysDiv = Functions.createElement({ var generalOverlaysDiv = Functions.createElement({
type: "div", type: "div",
name: "generalOverlays", name: "generalOverlays",
...@@ -338,8 +359,6 @@ OverlayPanel.prototype.createBackgroundRow = function (background, checked) { ...@@ -338,8 +359,6 @@ OverlayPanel.prototype.createBackgroundRow = function (background, checked) {
result.appendChild(viewTd); result.appendChild(viewTd);
var dataTd = document.createElement("td");
result.appendChild(dataTd);
result.title = background.getDescription(); result.title = background.getDescription();
return result; return result;
}; };
...@@ -572,13 +591,25 @@ OverlayPanel.prototype.refresh = function (showDefault) { ...@@ -572,13 +591,25 @@ OverlayPanel.prototype.refresh = function (showDefault) {
} else { } else {
customOverlays.push(overlay); customOverlays.push(overlay);
} }
} }
var table = self.getControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_TABLE);
table.appendChild(self.createTableHeader());
var table = $("[name='backgroundsTab']", self.getElement())[0];
table.innerHTML = "<thead><tr><th>Name</th><th>View</th></tr></thead>";
var body = document.createElement("tbody"); var body = document.createElement("tbody");
table.appendChild(body); table.appendChild(body);
for (i = 0; i < backgrounds.length; i++) {
var background = backgrounds[i];
body.appendChild(self.createBackgroundRow(background, background === selectedBackground));
}
table = self.getControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_TABLE);
table.appendChild(self.createTableHeader());
body = document.createElement("tbody");
table.appendChild(body);
generalOverlays.sort(function (o1, o2) { generalOverlays.sort(function (o1, o2) {
var val1 = o1.getId(); var val1 = o1.getId();
var val2 = o2.getId(); var val2 = o2.getId();
...@@ -594,14 +625,15 @@ OverlayPanel.prototype.refresh = function (showDefault) { ...@@ -594,14 +625,15 @@ OverlayPanel.prototype.refresh = function (showDefault) {
} }
return 0; return 0;
}); });
for (i = 0; i < backgrounds.length; i++) {
var background = backgrounds[i];
body.appendChild(self.createBackgroundRow(background, background === selectedBackground));
}
for (i = 0; i < generalOverlays.length; i++) { for (i = 0; i < generalOverlays.length; i++) {
overlay = generalOverlays[i]; overlay = generalOverlays[i];
body.appendChild(self.createOverlayRow(overlay, selectedOverlay[overlay.getId()], false)); body.appendChild(self.createOverlayRow(overlay, selectedOverlay[overlay.getId()], false));
} }
if (generalOverlays.length > 0) {
$(table.parentNode).show();
} else {
$(table.parentNode).hide();
}
var title = self.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TITLE); var title = self.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TITLE);
var addButton = $("[name='addOverlay']", self.getElement()); var addButton = $("[name='addOverlay']", self.getElement());
......
...@@ -47,7 +47,9 @@ ChemicalDbOverlay.prototype.getElementsByQueryFromServer = function (param) { ...@@ -47,7 +47,9 @@ ChemicalDbOverlay.prototype.getElementsByQueryFromServer = function (param) {
if (self.getMap().getProject().getDisease() !== undefined && self.getMap().getProject().getDisease() !== null) { if (self.getMap().getProject().getDisease() !== undefined && self.getMap().getProject().getDisease() !== null) {
return ServerConnector.getChemicalsByQuery(param); return ServerConnector.getChemicalsByQuery(param);
} else { } else {
GuiConnector.warn("Cannot search for chemicals in a project without defined disease."); if (param.query !== "") {
GuiConnector.warn("Cannot search for chemicals in a project without defined disease.");
}
return Promise.resolve([]); return Promise.resolve([]);
} }
}; };
......
...@@ -464,11 +464,11 @@ AbstractInfoWindow.prototype._createTargetInfoDiv = function (params) { ...@@ -464,11 +464,11 @@ AbstractInfoWindow.prototype._createTargetInfoDiv = function (params) {
result.appendChild(titleElement); result.appendChild(titleElement);
if (overlay.allowGeneralSearch()) { if (overlay.allowGeneralSearch()) {
var checkboxDiv = document.createElement("div"); var checkboxDiv = document.createElement("div");
checkboxDiv.style.textAlign = "center";
var showAllButton = document.createElement("button");
var hideAllButton = document.createElement("button");
var checkbox = document.createElement("input"); var toggleAll = function (show) {
checkbox.type = "checkbox";
checkbox.checked = self.isOverlayFullView(overlay.getName());
checkbox.onclick = function () {
var ie = new IdentifiedElement(self.alias); var ie = new IdentifiedElement(self.alias);
result.removeChild(table); result.removeChild(table);
var messageImg = Functions.createElement({ var messageImg = Functions.createElement({
...@@ -476,20 +476,42 @@ AbstractInfoWindow.prototype._createTargetInfoDiv = function (params) { ...@@ -476,20 +476,42 @@ AbstractInfoWindow.prototype._createTargetInfoDiv = function (params) {
src: 'resources/images/icons/ajax-loader.gif' src: 'resources/images/icons/ajax-loader.gif'
}); });
result.appendChild(messageImg); result.appendChild(messageImg);
return overlay.getDetailDataByIdentifiedElement(ie, this.checked).then(function (data) { return overlay.getDetailDataByIdentifiedElement(ie, show).then(function (data) {
table = self._createTableForTargetDiv(data, overlay); table = self._createTableForTargetDiv(data, overlay);
result.appendChild(table); result.appendChild(table);
}).finally(function () { }).finally(function () {
result.removeChild(messageImg); result.removeChild(messageImg);
if (show) {
$(showAllButton).hide();
$(hideAllButton).show();
} else {
$(hideAllButton).hide();
$(showAllButton).show();
}
}) })
}; };
checkboxDiv.appendChild(checkbox); showAllButton.style.display = "inline-block";
showAllButton.innerHTML = "Click to show all " + overlay.getName() + "s for ths element";
showAllButton.onclick = function () {
toggleAll(true);
}
checkboxDiv.appendChild(showAllButton);
hideAllButton.style.display = "inline-block";
hideAllButton.innerHTML = "Click to hide all " + overlay.getName() + "s for ths element";
hideAllButton.onclick = function () {