/*
* Copyright 2003-2006, 2009, 2017, 2020 United States Government, as represented
* by the Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
*
* The NASAWorldWind/WebWorldWind platform is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License
* at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* NASAWorldWind/WebWorldWind also contains the following 3rd party Open Source
* software:
*
* ES6-Promise – under MIT License
* libtess.js – SGI Free Software License B
* Proj4 – under MIT License
* JSZip – under MIT License
*
* A complete listing of 3rd Party software notices and licenses included in
* WebWorldWind can be found in the WebWorldWind 3rd-party notices and licenses
* PDF found in code directory.
*/
/**
* @exports ServersPanel
*/
define(function () {
"use strict";
/**
* Constructs a servers panel.
* @alias ServersPanel
* @constructor
* @classdesc Provides a list of collapsible panels that indicate the layers associated with a WMS or other
* image server. Currently only WMS is supported. The user can select a server's layers and they will be added to
* the WorldWindow's layer list.
* @param {WorldWindow} worldWindow The WorldWindow to associate this layers panel with.
* @param {LayersPanel} layersPanel The layers panel managing the specified WorldWindows layer list.
*/
var ServersPanel = function (worldWindow, layersPanel, timeSeriesPlayer) {
var thisServersPanel = this;
this.wwd = worldWindow;
this.layersPanel = layersPanel;
this.timeSeriesPlayer = timeSeriesPlayer;
this.idCounter = 1;
this.legends = {};
$("#addServerBox").find("button").on("click", function (e) {
thisServersPanel.onAddServerButton(e);
});
$("#addServerText").on("keypress", function (e) {
thisServersPanel.onAddServerTextKeyPress($(this), e);
});
};
ServersPanel.prototype.onAddServerButton = function (event) {
this.attachServer($("#addServerText")[0].value);
$("#addServerText").val("");
};
ServersPanel.prototype.onAddServerTextKeyPress = function (searchInput, event) {
if (event.keyCode === 13) {
searchInput.blur();
this.attachServer($("#addServerText")[0].value);
$("#addServerText").val("");
}
};
ServersPanel.prototype.attachServer = function (serverAddress) {
if (!serverAddress) {
return;
}
serverAddress = serverAddress.trim();
// Search for 'https' or 'http' (case insensitive) and substitute it for lowercase 'https'
serverAddress = serverAddress.replace(/https|http/i, "https");
if (serverAddress.lastIndexOf("https", 0) != 0) {
serverAddress = "https://" + serverAddress;
}
var thisExplorer = this,
request = new XMLHttpRequest(),
url = WorldWind.WmsUrlBuilder.fixGetMapString(serverAddress);
url += "service=WMS&request=GetCapabilities&vers";
request.open("GET", url, true);
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
var xmlDom = request.responseXML;
if (!xmlDom && request.responseText.indexOf(" 0 ? wmsService.title : serverAddress;
//
//var html = '
';
//html += '
';
//html += '
';
//html += '
';
//html += 'This is some text to display in the collapse panel.';
//html += '
';
var topDiv = $(''),
heading = $(''),
title = $(''),
anchor = $('' + panelTitle + ''),
remove = $(''),
bodyParent = $(''),
body = $(''),
treeDiv = this.makeTree(serverAddress, treeId);
remove.on("click", function () {
topDiv.remove();
});
title.append(anchor);
title.append(remove);
heading.append(title);
topDiv.append(heading);
body.append(treeDiv);
bodyParent.append(body);
topDiv.append(bodyParent);
var serversItem = $("#servers");
serversItem.append(topDiv);
var treeRoot = treeDiv.fancytree("getRootNode");
// Don't show the top-level layer if it's a grouping layer with the same title as the server title.
// The NEO server is set up this way, for example.
var layers = wmsCapsDoc.capability.layers;
if ((layers.length === 1) && (layers[0].layers) &&
(layers[0].title === wmsCapsDoc.service.title) && !(layers[0].name && layers[0].name.length > 0)) {
layers = layers[0].layers;
}
treeRoot.addChildren(this.assembleLayers(layers, []));
// Collapse grouping nodes if there are many of them.
var numNodes = 0;
treeRoot.visit(function (node) {
++numNodes;
});
if (numNodes > 10) {
treeRoot.visit(function (node) {
node.setExpanded(false);
});
}
};
ServersPanel.prototype.makeTree = function (serverAddress, treeId) {
var thisServersPanel = this,
treeDivId = "treeDiv" + treeId,
treeDataId = "treeData" + treeId,
treeDiv = $(''),
treeUl = $('
');
treeDiv.append(treeUl);
treeDiv.fancytree({
click: function (event, data) {
var node = data.node,
layer = node.data.layer;
if (layer) {
node.setSelected(false); // only an argument of false causes the select method to be called?
return false;
}
},
select: function (event, data) {
var node = data.node,
layer = node.data.layer;
if (layer) {
if (!node.selected) {
node.data.layer = null;
thisServersPanel.removeLayer(layer);
}
//layer.enabled = node.selected;
} else if (node.selected && node.data.layerCaps && node.data.layerCaps.name) {
node.data.layer = thisServersPanel.addLayer(node.data.layerCaps);
}
thisServersPanel.wwd.redraw();
return false;
}
});
treeDiv.fancytree("option", "checkbox", true);
treeDiv.fancytree("option", "icons", false);
$("form").submit(false);
return treeDiv;
};
ServersPanel.prototype.assembleLayers = function (layers, result) {
for (var i = 0; i < layers.length; i++) {
var layer = layers[i],
subLayers = null,
node = {
title: layer.title,
tooltip: layer.title,
layerCaps: layer
};
if (layer.layers && layer.layers.length > 0) {
subLayers = this.assembleLayers(layer.layers, []);
}
if (!layer.name) {
node.expanded = true;
node.unselectable = true;
node.hideCheckbox = true;
node.folder = true;
}
if (subLayers) {
node.children = subLayers;
}
result.push(node);
}
return result;
};
ServersPanel.prototype.addLayer = function (layerCaps) {
if (layerCaps.name) {
var config = WorldWind.WmsLayer.formLayerConfiguration(layerCaps, null);
var layer;
if (config.timeSequences &&
(config.timeSequences[config.timeSequences.length - 1] instanceof WorldWind.PeriodicTimeSequence)) {
var timeSequence = config.timeSequences[config.timeSequences.length - 1];
config.levelZeroDelta = new WorldWind.Location(180, 180);
layer = new WorldWind.WmsTimeDimensionedLayer(config);
layer.opacity = 0.8;
layer.time = timeSequence.startTime;
this.timeSeriesPlayer.timeSequence = timeSequence;
this.timeSeriesPlayer.layer = layer;
layer.timeSequence = timeSequence;
//for (var t = timeSequence.currentTime; t != null; t = timeSequence.next()) {
// console.log(t.toISOString());
//}
//timeSequence.reset();
}
else if (config.timeSequences &&
(config.timeSequences[config.timeSequences.length - 1] instanceof Date)) {
timeSequence = config.timeSequences[config.timeSequences.length - 1];
config.levelZeroDelta = new WorldWind.Location(180, 180);
layer = new WorldWind.WmsTimeDimensionedLayer(config);
layer.opacity = 0.8;
layer.time = config.timeSequences[0];
this.timeSeriesPlayer.timeSequence = new WorldWind.BasicTimeSequence(config.timeSequences);
this.timeSeriesPlayer.layer = layer;
layer.timeSequence = timeSequence;
}
else {
layer = new WorldWind.WmsLayer(config, null);
this.timeSeriesPlayer.timeSequence = null;
this.timeSeriesPlayer.layer = null;
}
if (layerCaps.styles && layerCaps.styles.length > 0
&& layerCaps.styles[0].legendUrls && layerCaps.styles[0].legendUrls.length > 0) {
layer.companionLayer = this.addLegend(layerCaps.styles[0].legendUrls[0]);
}
layer.enabled = true;
this.wwd.addLayer(layer);
this.wwd.redraw();
this.layersPanel.synchronizeLayerList();
return layer;
}
return null;
};
ServersPanel.prototype.removeLayer = function (layer) {
this.removeLegend(layer.companionLayer);
this.wwd.removeLayer(layer);
//if (layer.companionLayer) {
// this.wwd.removeLayer(layer.companionLayer);
//}
if (this.timeSeriesPlayer && this.timeSeriesPlayer.layer === layer) {
this.timeSeriesPlayer.timeSequence = null;
this.timeSeriesPlayer.layer = null;
}
this.wwd.redraw();
this.layersPanel.synchronizeLayerList();
};
ServersPanel.prototype.addLegend = function (legendCaps) {
var legend = this.legends[legendCaps.url];
if (legend) {
++legend.refCount;
legend.layer.enabled = true;
} else {
legend = {refCount: 1, legendCaps: legendCaps};
legend.layer = new WorldWind.RenderableLayer();
var dummyOffset = new WorldWind.Offset(WorldWind.OFFSET_FRACTION, 0, WorldWind.OFFSET_FRACTION, 0),
screenImage = new WorldWind.ScreenImage(dummyOffset, legendCaps.url);
screenImage.imageOffset =
new WorldWind.Offset(WorldWind.OFFSET_FRACTION, 0, WorldWind.OFFSET_INSET_PIXELS, 0);
legend.layer.addRenderable(screenImage);
legend.layer.hide = true;
legend.layer.refCount = 0;
this.wwd.addLayer(legend.layer);
this.legends[legendCaps.url] = legend;
this.updateLegendOffsets();
}
++legend.layer.refCount;
return legend.layer;
};
ServersPanel.prototype.removeLegend = function (legendLayer) {
for (var legendKey in this.legends) {
if (this.legends.hasOwnProperty(legendKey)) {
var legend = this.legends[legendKey];
if (legend.layer === legendLayer) {
--legend.refCount;
--legend.layer.refCount;
if (legend.refCount <= 0) {
this.wwd.removeLayer(legend.layer);
delete this.legends[legend.legendCaps.url];
}
break;
}
}
}
this.updateLegendOffsets();
};
ServersPanel.prototype.updateLegendOffsets = function () {
var yOffset = 0,
verticalMargin = 5;
for (var legendKey in this.legends) {
if (this.legends.hasOwnProperty(legendKey)) {
var legend = this.legends[legendKey],
screenImage = legend.layer.renderables[0];
screenImage.screenOffset =
new WorldWind.Offset(WorldWind.OFFSET_FRACTION, 0, WorldWind.OFFSET_INSET_PIXELS, yOffset);
yOffset += legend.legendCaps.height + verticalMargin;
}
}
};
return ServersPanel;
});