mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-25 12:25:52 -08:00
Compare commits
4 Commits
v3.7.3-bet
...
ui-discove
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28869645cd | ||
|
|
da8eb6f76e | ||
|
|
0e3a359108 | ||
|
|
af89535a91 |
4
assets/icons/folder.svg
Normal file
4
assets/icons/folder.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 1H5L8 3H13V5H3.7457L2.03141 11H4.11144L5.2543 7H16L14 14H0V1Z" fill="#000000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 322 B |
15
assets/icons/swap.svg
Normal file
15
assets/icons/swap.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>swap-vertical-circle</title>
|
||||
<g id="Layer_2" data-name="Layer 2">
|
||||
<g id="invisible_box" data-name="invisible box">
|
||||
<rect width="48" height="48" fill="none"/>
|
||||
</g>
|
||||
<g id="icons_Q2" data-name="icons Q2">
|
||||
<path d="M19.4,36.4l5-4.9a2.1,2.1,0,0,0,.2-2.7,1.9,1.9,0,0,0-3-.2L20,30.2V15a2,2,0,0,0-4,0V30.2l-1.6-1.6a1.9,1.9,0,0,0-3,.2,2.1,2.1,0,0,0,.2,2.7l5,4.9A1.9,1.9,0,0,0,19.4,36.4Z"/>
|
||||
<path d="M32,33V17.8l1.6,1.6a1.9,1.9,0,0,0,3-.2,2.1,2.1,0,0,0-.2-2.7l-5-4.9a1.9,1.9,0,0,0-2.8,0l-5,4.9a2.1,2.1,0,0,0-.2,2.7,1.9,1.9,0,0,0,3,.2L28,17.8V33a2,2,0,0,0,4,0Z"/>
|
||||
<path d="M24,42A18,18,0,1,1,42,24,18.1,18.1,0,0,1,24,42m0,4A22,22,0,1,0,2,24,21.9,21.9,0,0,0,24,46Z"/>
|
||||
</g>
|
||||
</g>
|
||||
|
After Width: | Height: | Size: 948 B |
@@ -8,8 +8,8 @@
|
||||
"dateModified": "2023-01-31",
|
||||
"issueTracker": "https://github.com/cds-astro/aladin-lite/issues",
|
||||
"name": "Aladin Lite",
|
||||
"version": "3.7.2-beta",
|
||||
"softwareVersion": "3.7.2-beta",
|
||||
"version": "3.7.3-beta",
|
||||
"softwareVersion": "3.7.3-beta",
|
||||
"description": "An astronomical HiPS visualizer in the browser.",
|
||||
"identifier": "10.5281/zenodo.7638833",
|
||||
"applicationCategory": "Astronomy, Visualization",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
A.init.then(() => {
|
||||
let aladin = A.aladin('#aladin-lite-div', {fov: 70,projection: "AIT"});
|
||||
let aladin = A.aladin('#aladin-lite-div', {target: "23 28 32.46 -00 10 38.9", fov: 4, projection: "AIT"});
|
||||
|
||||
let hsc = aladin.newImageSurvey("P/HSC/DR2/deep/g", {colormap:"Purples", imgFormat: "fits"});
|
||||
aladin.setBaseImageLayer(hsc);
|
||||
|
||||
@@ -37,7 +37,10 @@
|
||||
colorPicker.value = cat.color;
|
||||
colorPicker.addEventListener('input', function (e) {
|
||||
// Change the color of the catalog
|
||||
cat.updateShape({color: this.value});
|
||||
console.log(this.value)
|
||||
cat.updateShape({color: () => {
|
||||
return '#00ff00'
|
||||
}});
|
||||
})
|
||||
|
||||
// Define the box
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<script type="text/javascript">
|
||||
var aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {fullScreen: true, cooFrame: "ICRSd", showSimbadPointerControl: true, showShareControl: true, showShareControl: true, survey: 'https://jafar.astro.unistra.fr/data/jafar_hips/Surveys/CFIS/IC0750/asinh_0_1/', fov: 180, showContextMenu: true});
|
||||
aladin = A.aladin('#aladin-lite-div', {fullScreen: true, cooFrame: "ICRSd", showSimbadPointerControl: true, showShareControl: true, showShareControl: true, fov: 180, showContextMenu: true});
|
||||
// manage URL parameters
|
||||
const searchParams = new URL(document.location).searchParams;
|
||||
if (searchParams.has('baseImageLayer')) {
|
||||
|
||||
@@ -553,6 +553,7 @@ impl App {
|
||||
/*let is_there_new_available_tiles = self
|
||||
.downloader
|
||||
.get_resolved_tiles(/*&available_tiles, */&mut self.hipss);*/
|
||||
//self.tile_fetcher.clear();
|
||||
|
||||
if self.request_for_new_tiles
|
||||
&& Time::now() - self.last_time_request_for_new_tiles > DeltaTime::from(500.0)
|
||||
@@ -564,18 +565,18 @@ impl App {
|
||||
}
|
||||
|
||||
// Tiles are fetched if:
|
||||
let fetch_tiles =
|
||||
// * the user is not panning the view
|
||||
// * or the user is but did not move for at least 100ms
|
||||
//(Time::now() - self.camera.get_time_of_last_move() >= DeltaTime(100.0) || !self.dragging) &&
|
||||
// * no inertia action is in progress
|
||||
//self.inertia.is_none() &&
|
||||
// * the user is not zooming
|
||||
!self.camera.has_zoomed();
|
||||
//let fetch_tiles =
|
||||
// * the user is not panning the view
|
||||
// * or the user is but did not move for at least 100ms
|
||||
//(Time::now() - self.camera.get_time_of_last_move() >= DeltaTime(100.0) || !self.dragging) &&
|
||||
// * no inertia action is in progress
|
||||
//self.inertia.is_none() &&
|
||||
// * the user is not zooming
|
||||
// !self.camera.has_zoomed();
|
||||
|
||||
if fetch_tiles {
|
||||
self.tile_fetcher.notify(self.downloader.clone(), None);
|
||||
}
|
||||
//if fetch_tiles {
|
||||
self.tile_fetcher.notify(self.downloader.clone(), None);
|
||||
//}
|
||||
}
|
||||
|
||||
let rscs_received = self.downloader.borrow_mut().get_received_resources();
|
||||
@@ -1114,10 +1115,6 @@ impl App {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn rename_layer(&mut self, layer: &str, new_layer: &str) -> Result<(), JsValue> {
|
||||
self.layers.rename_layer(layer, new_layer)
|
||||
}
|
||||
|
||||
pub(crate) fn swap_layers(
|
||||
&mut self,
|
||||
first_layer: &str,
|
||||
|
||||
@@ -315,11 +315,7 @@ impl CameraViewPort {
|
||||
}
|
||||
|
||||
pub fn compute_ndc_to_clip_factor(&mut self, proj: &ProjectionType) {
|
||||
self.ndc_to_clip = if self.height < self.width {
|
||||
Vector2::new(1.0, (self.height as f64) / (self.width as f64))
|
||||
} else {
|
||||
Vector2::new((self.width as f64) / (self.height as f64), 1.0)
|
||||
};
|
||||
self.ndc_to_clip = Vector2::new(1.0, (self.height as f64) / (self.width as f64));
|
||||
|
||||
let bounds_size_ratio = proj.bounds_size_ratio();
|
||||
self.ndc_to_clip.y *= bounds_size_ratio;
|
||||
|
||||
@@ -372,12 +372,6 @@ impl WebClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = renameLayer)]
|
||||
pub fn rename_layer(&mut self, layer: String, new_layer: String) -> Result<(), JsValue> {
|
||||
// Deserialize the hips objects that compose the hips
|
||||
self.app.rename_layer(&layer, &new_layer)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = swapLayers)]
|
||||
pub fn swap_layers(
|
||||
&mut self,
|
||||
|
||||
@@ -351,29 +351,6 @@ impl Layers {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename_layer(&mut self, layer: &str, new_layer: &str) -> Result<(), JsValue> {
|
||||
let err_layer_not_found =
|
||||
JsValue::from_str(&format!("Layer {layer:?} not found, so cannot be removed."));
|
||||
|
||||
// layer from layers does also need to be removed
|
||||
let id_layer = self
|
||||
.layers
|
||||
.iter()
|
||||
.position(|l| layer == l)
|
||||
.ok_or(err_layer_not_found.clone())?;
|
||||
|
||||
self.layers[id_layer] = new_layer.to_string();
|
||||
|
||||
let meta = self.meta.remove(layer).ok_or(err_layer_not_found.clone())?;
|
||||
let id = self.ids.remove(layer).ok_or(err_layer_not_found)?;
|
||||
|
||||
// Add the new
|
||||
self.meta.insert(new_layer.to_string(), meta);
|
||||
self.ids.insert(new_layer.to_string(), id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn swap_layers(&mut self, first_layer: &str, second_layer: &str) -> Result<(), JsValue> {
|
||||
let id_first_layer =
|
||||
self.layers
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,44 @@
|
||||
--aladin-color-border: #fff;
|
||||
}
|
||||
|
||||
.aladin-tree {
|
||||
width: 100%;
|
||||
border-top: 1px solid white;
|
||||
border-bottom: 2px solid white;
|
||||
}
|
||||
|
||||
.aladin-tree .aladin-directory-path {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
width: 100%;
|
||||
border-bottom: 2px solid white;
|
||||
}
|
||||
|
||||
.aladin-tree ul {
|
||||
padding:0;
|
||||
margin:0;
|
||||
overflow-y: scroll;
|
||||
height: 300px;
|
||||
}
|
||||
.aladin-link {
|
||||
list-style-type: none;
|
||||
padding: 0.5em 0px;
|
||||
cursor:pointer;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.aladin-tree li:hover {
|
||||
color: yellowgreen;
|
||||
}
|
||||
|
||||
.aladin-tree li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.aladin-tree li {
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
.aladin-dark-theme {
|
||||
background-color: black;
|
||||
color: white;
|
||||
@@ -239,18 +277,15 @@
|
||||
font-family: monospace;
|
||||
background: #fff;
|
||||
|
||||
line-height: 1.3;
|
||||
color: #222;
|
||||
/*box-shadow: 0 0 6px rgba(0,0,0,0.2);*/
|
||||
|
||||
/* Allow scrolling but disable scroll bar */
|
||||
-ms-overflow-style: none; /* for Internet Explorer, Edge */
|
||||
scrollbar-width: none; /* for Firefox */
|
||||
/*overflow-y: auto;*/
|
||||
overflow-y: none;
|
||||
max-height: 500px;
|
||||
/*max-width: fit-content;*/
|
||||
height: fit-content;
|
||||
height: min-content;
|
||||
width: min-content;
|
||||
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.aladin-container canvas {
|
||||
@@ -319,7 +354,7 @@
|
||||
.aladin-box-separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #d2d2d2;
|
||||
margin: 5px 0px 5px -4px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.aladin-restore {
|
||||
@@ -509,11 +544,11 @@
|
||||
}
|
||||
|
||||
.aladin-vertical-list > *:first-child {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.aladin-vertical-list > * {
|
||||
margin-top: 0.5rem;
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.aladin-horizontal-list {
|
||||
@@ -1124,6 +1159,7 @@ otherwise it fits its content options. If those are too big the select can go ou
|
||||
|
||||
.aladin-link:hover {
|
||||
color: greenyellow;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.aladin-simbadPointer-control {
|
||||
@@ -1160,9 +1196,13 @@ otherwise it fits its content options. If those are too big the select can go ou
|
||||
.aladin-stack-box {
|
||||
width: 17rem;
|
||||
}
|
||||
.aladin-item-selected {
|
||||
border: 1px solid orange;
|
||||
}
|
||||
|
||||
.aladin-HiPS-filter-box {
|
||||
margin-top: 0.4rem;
|
||||
/*width: 250px;*/
|
||||
}
|
||||
|
||||
.aladin-HiPS-filter-box .aladin-horizontal-list {
|
||||
|
||||
@@ -2004,7 +2004,7 @@ export let Aladin = (function () {
|
||||
* </ul>
|
||||
*/
|
||||
Aladin.prototype.setBaseImageLayer = function (urlOrHiPSOrFITS) {
|
||||
return this.setOverlayImageLayer(urlOrHiPSOrFITS, "base");
|
||||
return this.setOverlayImageLayer(urlOrHiPSOrFITS, (this.view.overlayLayers && this.view.overlayLayers[0]) || Utils.uuidv4());
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2014,7 +2014,7 @@ export let Aladin = (function () {
|
||||
* @returns {HiPS|Image} - Returns the image layer corresponding to the base layer
|
||||
*/
|
||||
Aladin.prototype.getBaseImageLayer = function () {
|
||||
return this.view.getImageLayer("base");
|
||||
return this.view.getImageLayer(this.view.overlayLayers && this.view.overlayLayers[0]);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3003,7 +3003,7 @@ aladin.customizeShareURLFunction(() => {return 'https://sky.esa.int/esasky/?targ
|
||||
* @param {Function} [successCallback=<center the view on the FITS file>] - The callback function to be executed on a successful display.
|
||||
* The callback gives the ra, dec, and fov of the image; By default, it centers the view on the FITS file loaded.
|
||||
* @param {Function} [errorCallback] - The callback function to be executed if an error occurs during display.
|
||||
* @param {string} [layer="base"] - The name of the layer. If not specified, it will be replace the base layer.
|
||||
* @param {string} [layer] - The name of the layer. If not specified, it will be replace the base layer.
|
||||
*
|
||||
* @example
|
||||
aladin.displayFITS(
|
||||
@@ -3027,7 +3027,7 @@ aladin.displayFITS(
|
||||
options,
|
||||
successCallback,
|
||||
errorCallback,
|
||||
layer = "base"
|
||||
layer
|
||||
) {
|
||||
successCallback =
|
||||
successCallback ||
|
||||
@@ -3041,6 +3041,7 @@ aladin.displayFITS(
|
||||
successCallback,
|
||||
errorCallback
|
||||
);
|
||||
layer = layer || (this.view.overlayLayers && this.view.overlayLayers[0])
|
||||
return this.setOverlayImageLayer(image, layer);
|
||||
};
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ export class MocServer {
|
||||
//expr: "dataproduct_type=image",
|
||||
get: "record",
|
||||
fmt: "json",
|
||||
fields: "ID,hips_creator,hips_copyright,hips_order,hips_tile_width,hips_frame,hips_tile_format,obs_title,obs_description,obs_copyright,obs_regime",
|
||||
fields: "ID,hips_creator,hips_copyright,hips_order,hips_tile_width,hips_frame,hips_tile_format,obs_title,obs_description,obs_copyright,obs_regime,client_category",
|
||||
//fields: "ID,hips_initial_fov,hips_initial_ra,hips_initial_dec,hips_pixel_bitpix,hips_creator,hips_copyright,hips_frame,hips_order,hips_order_min,hips_tile_width,hips_tile_format,hips_pixel_cut,obs_title,obs_description,obs_copyright,obs_regime,hips_data_range,hips_service_url",
|
||||
};
|
||||
|
||||
|
||||
@@ -384,7 +384,6 @@ Utils.fetch = function(params) {
|
||||
// localhost url
|
||||
url = params.url;
|
||||
}
|
||||
|
||||
|
||||
let request = new Request(url, {
|
||||
method: params.method || 'GET',
|
||||
|
||||
@@ -256,7 +256,7 @@ export let View = (function () {
|
||||
// some variables for mouse handling
|
||||
this.dragging = false;
|
||||
this.dragCoo = null;
|
||||
this.selectedLayer = 'base';
|
||||
this.selectedLayer = undefined;
|
||||
|
||||
this.needRedraw = true;
|
||||
|
||||
@@ -1784,6 +1784,27 @@ export let View = (function () {
|
||||
// register its promise
|
||||
this.imageLayersBeingQueried.set(layer, imageLayer);
|
||||
|
||||
// Check whether this layer already exist
|
||||
const idxOverlayLayer = this.overlayLayers.findIndex(overlayLayer => overlayLayer == layer);
|
||||
let alreadyPresentImageLayer;
|
||||
if (idxOverlayLayer == -1) {
|
||||
// it does not exist so we add it to the stack
|
||||
this.overlayLayers.push(layer);
|
||||
} else {
|
||||
// it exists
|
||||
alreadyPresentImageLayer = this.imageLayers.get(layer);
|
||||
|
||||
if (alreadyPresentImageLayer) {
|
||||
if (alreadyPresentImageLayer.added === true) {
|
||||
ALEvent.HIPS_LAYER_REMOVED.dispatchedTo(this.aladinDiv, { layer: alreadyPresentImageLayer });
|
||||
}
|
||||
|
||||
alreadyPresentImageLayer.added = false;
|
||||
}
|
||||
// Notify that this image layer has been replaced by the wasm part
|
||||
this.imageLayers.delete(layer);
|
||||
}
|
||||
|
||||
this.addImageLayer(imageLayer, layer);
|
||||
|
||||
return imageLayer;
|
||||
@@ -1793,33 +1814,13 @@ export let View = (function () {
|
||||
View.prototype._addLayer = function(imageLayer) {
|
||||
// Keep the JS frontend in-line with the wasm state
|
||||
const layerName = imageLayer.layer;
|
||||
// Check whether this layer already exist
|
||||
const idxOverlayLayer = this.overlayLayers.findIndex(overlayLayer => overlayLayer == layerName);
|
||||
let alreadyPresentImageLayer;
|
||||
if (idxOverlayLayer == -1) {
|
||||
// it does not exist so we add it to the stack
|
||||
this.overlayLayers.push(layerName);
|
||||
} else {
|
||||
// it exists
|
||||
alreadyPresentImageLayer = this.imageLayers.get(layerName);
|
||||
|
||||
// Notify that this image layer has been replaced by the wasm part
|
||||
if (alreadyPresentImageLayer && alreadyPresentImageLayer.added === true) {
|
||||
ALEvent.HIPS_LAYER_REMOVED.dispatchedTo(this.aladinDiv, { layer: alreadyPresentImageLayer });
|
||||
}
|
||||
|
||||
alreadyPresentImageLayer.added = false;
|
||||
this.imageLayers.delete(layerName);
|
||||
}
|
||||
|
||||
imageLayer.added = true;
|
||||
|
||||
this.imageLayers.set(layerName, imageLayer);
|
||||
|
||||
// select the layer if he is on top
|
||||
//if (idxOverlayLayer == -1) {
|
||||
this.selectLayer(layerName);
|
||||
//}
|
||||
this.selectLayer(layerName);
|
||||
|
||||
ALEvent.HIPS_LAYER_ADDED.dispatchedTo(this.aladinDiv, { layer: imageLayer });
|
||||
}
|
||||
@@ -1877,7 +1878,7 @@ export let View = (function () {
|
||||
// Remove the settled promise
|
||||
this.promises.splice(idx, 1);
|
||||
|
||||
const noMoreLayersToWaitFor = this.promises.length === 0;
|
||||
/*const noMoreLayersToWaitFor = this.promises.length === 0;
|
||||
|
||||
if (noMoreLayersToWaitFor) {
|
||||
if (self.empty) {
|
||||
@@ -1887,48 +1888,19 @@ export let View = (function () {
|
||||
// it the best I can do if the MOCServer is out
|
||||
self.aladin.setBaseImageLayer("https://alaskybis.cds.unistra.fr/DSS/DSSColor/");
|
||||
} else {
|
||||
// there is surveys that have been queried
|
||||
// rename the first overlay layer to "base"
|
||||
self.renameLayer(this.overlayLayers[0], "base");
|
||||
//self.renameLayer(this.overlayLayers[0], "base");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
})
|
||||
}
|
||||
|
||||
// The survey at layer must have been added to the view!
|
||||
View.prototype.renameLayer = function(layer, newLayer) {
|
||||
if (layer === newLayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Throw an exception if either the first or the second layers are not in the stack
|
||||
this.wasm.renameLayer(layer, newLayer);
|
||||
|
||||
let imageLayer = this.imageLayers.get(layer);
|
||||
imageLayer.layer = newLayer;
|
||||
|
||||
// Change in overlaylayers
|
||||
const idx = this.overlayLayers.findIndex(overlayLayer => overlayLayer == layer);
|
||||
this.overlayLayers[idx] = newLayer;
|
||||
// Change in imageLayers
|
||||
this.imageLayers.delete(layer);
|
||||
this.imageLayers.set(newLayer, imageLayer);
|
||||
|
||||
if (this.selectedLayer === layer) {
|
||||
this.selectedLayer = newLayer;
|
||||
}
|
||||
|
||||
// Tell the layer hierarchy has changed
|
||||
ALEvent.HIPS_LAYER_RENAMED.dispatchedTo(this.aladinDiv, { layer, newLayer });
|
||||
}
|
||||
|
||||
View.prototype.swapLayers = function(firstLayer, secondLayer) {
|
||||
// Throw an exception if either the first or the second layers are not in the stack
|
||||
this.wasm.swapLayers(firstLayer, secondLayer);
|
||||
|
||||
// Swap in overlaylayers
|
||||
const idxFirstLayer = this.overlayLayers.findIndex(overlayLayer => overlayLayer == firstLayer);
|
||||
const idxSecondLayer = this.overlayLayers.findIndex(overlayLayer => overlayLayer == secondLayer);
|
||||
const idxFirstLayer = this.overlayLayers.indexOf(firstLayer);
|
||||
const idxSecondLayer = this.overlayLayers.indexOf(secondLayer);
|
||||
|
||||
const tmp = this.overlayLayers[idxFirstLayer];
|
||||
this.overlayLayers[idxFirstLayer] = this.overlayLayers[idxSecondLayer];
|
||||
@@ -1967,7 +1939,7 @@ export let View = (function () {
|
||||
this.overlayLayers.splice(idxOverlaidLayer, 1);
|
||||
|
||||
if (this.overlayLayers.length === 0) {
|
||||
this.empty = true;
|
||||
//this.empty = true;
|
||||
} else if (this.selectedLayer === layer) {
|
||||
// If the layer removed was selected then we select the last layer
|
||||
this.selectLayer(this.overlayLayers[this.overlayLayers.length - 1]);
|
||||
@@ -1976,12 +1948,12 @@ export let View = (function () {
|
||||
ALEvent.HIPS_LAYER_REMOVED.dispatchedTo(this.aladinDiv, { layer: imageLayer });
|
||||
|
||||
// check if there are no more surveys
|
||||
const noMoreLayersToWaitFor = this.promises.length === 0;
|
||||
/*const noMoreLayersToWaitFor = this.promises.length === 0;
|
||||
if (noMoreLayersToWaitFor && this.empty) {
|
||||
// no promises to launch!
|
||||
const dssId = Aladin.DEFAULT_OPTIONS.survey;
|
||||
this.aladin.setBaseImageLayer(dssId);
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
View.prototype.contains = function(survey) {
|
||||
@@ -2028,7 +2000,8 @@ export let View = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
View.prototype.getImageLayer = function (layer = "base") {
|
||||
View.prototype.getImageLayer = function (layer) {
|
||||
layer = layer || (this.overlayLayers && this.overlayLayers[0]);
|
||||
let imageLayerQueried = this.imageLayersBeingQueried.get(layer);
|
||||
let imageLayer = this.imageLayers.get(layer);
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ import { Utils } from "../../Utils.ts";
|
||||
import { ActionButton } from "../Widgets/ActionButton.js";
|
||||
import infoIconUrl from "../../../../assets/icons/info.svg"
|
||||
import { Icon } from "../Widgets/Icon.js";
|
||||
import { Tree } from "../Widgets/Tree.js";
|
||||
import { ALEvent } from "../../events/ALEvent.js";
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
@@ -44,32 +46,114 @@ import { Icon } from "../Widgets/Icon.js";
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
function fillHiPSHierarchy(name, hips, path, hierarchy) {
|
||||
let folders = path.split('/')
|
||||
let curFolder = folders.shift()
|
||||
|
||||
if(curFolder === 'Image') {
|
||||
let newPath = folders.join('/')
|
||||
fillHiPSHierarchy(name, hips, newPath, hierarchy);
|
||||
} else {
|
||||
// Some exceptions because the MOCServer client_category field may contain some typos
|
||||
if (['X', 'X-ray', 'Xray'].includes(curFolder)) {
|
||||
curFolder = 'X-ray'
|
||||
}
|
||||
|
||||
if (['Radion', 'Radio'].includes(curFolder)) {
|
||||
curFolder = 'Radio'
|
||||
}
|
||||
|
||||
if (curFolder === "Deprecated")
|
||||
return;
|
||||
|
||||
hierarchy[curFolder] = hierarchy[curFolder] || {};
|
||||
if (folders.length == 0) {
|
||||
hierarchy[curFolder][name] = hips
|
||||
} else {
|
||||
let newPath = folders.join('/')
|
||||
fillHiPSHierarchy(name, hips, newPath, hierarchy[curFolder])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class HiPSBrowserBox extends Box {
|
||||
static HiPSList = {};
|
||||
|
||||
constructor(aladin, options) {
|
||||
let self;
|
||||
|
||||
let filter = (item, params) => {
|
||||
if (params.regime) {
|
||||
if (!item.obs_regime)
|
||||
return false;
|
||||
|
||||
if (params.regime.toLowerCase() !== item.obs_regime.toLowerCase()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (params.resolution) {
|
||||
if (!item.hips_tile_width || !item.hips_order) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let pixelHEALPixOrder = Math.log2(item.hips_tile_width) + (+item.hips_order);
|
||||
let resPixel = Math.sqrt(Math.PI / (3*Math.pow(4, pixelHEALPixOrder)));
|
||||
|
||||
if (resPixel > params.resolution)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params.title) {
|
||||
if (!item.obs_title)
|
||||
return false;
|
||||
|
||||
if (!item.obs_title.toLowerCase().includes(params.title.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// Search tree
|
||||
let searchTree = new Tree({
|
||||
// a JS object describing the tree to show
|
||||
label: (item) => {
|
||||
let name = item.obs_title.replace(/:|\'/g, '');
|
||||
return name;
|
||||
},
|
||||
// a callback called when the user selects a leaf item of the tree
|
||||
click: (item) => {
|
||||
let image = item.ID || item.hips_service_url;
|
||||
let name = item.obs_title || item.ID;
|
||||
self._addHiPS(image, name)
|
||||
},
|
||||
// a callback called for filtering
|
||||
filter,
|
||||
});
|
||||
|
||||
MocServer.getAllHiPSes().then((HiPSes) => {
|
||||
HiPSBrowserBox.HiPSList = {}
|
||||
|
||||
self.HiPSTree = {};
|
||||
let hipsHierarchy = {};
|
||||
// Fill the HiPSList from the MOCServer
|
||||
|
||||
// Build a hierarchy w.r.t sorted by regime
|
||||
HiPSes.forEach((h) => {
|
||||
let name = h.obs_title;
|
||||
name = name.replace(/:|\'/g, '');
|
||||
|
||||
HiPSBrowserBox.HiPSList[name] = h;
|
||||
|
||||
self.HiPSTree[h.obs_regime] = self.HiPSTree[h.obs_regime] || {};
|
||||
if (self.HiPSTree[h.obs_regime]) {
|
||||
self.HiPSTree[h.obs_regime][name] = h
|
||||
if (h.client_category) {
|
||||
let path = h.client_category
|
||||
|
||||
fillHiPSHierarchy(name, h, path, hipsHierarchy)
|
||||
}
|
||||
});
|
||||
|
||||
console.log("jkjk", self.HiPSTree)
|
||||
|
||||
self.searchTree.setHierarchy(hipsHierarchy)
|
||||
|
||||
// Initialize the autocompletion without any filtering
|
||||
self._filterHiPSList({})
|
||||
@@ -98,7 +182,6 @@ export class HiPSBrowserBox extends Box {
|
||||
|
||||
if (image) {
|
||||
self._addHiPS(image, name)
|
||||
self.searchDropdown.update({title: value});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,14 +211,11 @@ export class HiPSBrowserBox extends Box {
|
||||
disable: true,
|
||||
})
|
||||
|
||||
self.searchTree.triggerFilter({title: e.target.value});
|
||||
|
||||
searchDropdown.removeClass('aladin-valid')
|
||||
searchDropdown.removeClass('aladin-not-valid')
|
||||
},
|
||||
change(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault()
|
||||
_parseHiPS(e)
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -193,13 +273,9 @@ export class HiPSBrowserBox extends Box {
|
||||
},
|
||||
toggled: false,
|
||||
actionOn: (e) => {
|
||||
self.filterBox._show({
|
||||
position: {
|
||||
nextTo: filterBtn,
|
||||
direction: "bottom",
|
||||
aladin,
|
||||
},
|
||||
});
|
||||
self.filterBox._show({position: {
|
||||
anchor: 'right center'
|
||||
}});
|
||||
},
|
||||
actionOff: (e) => {
|
||||
self.filterBox._hide();
|
||||
@@ -216,15 +292,17 @@ export class HiPSBrowserBox extends Box {
|
||||
size: 'medium',
|
||||
url: hipsIconUrl,
|
||||
monochrome: true,
|
||||
}), "HiPS browser"])
|
||||
},
|
||||
onDragged: () => {
|
||||
if (self.filterBtn.toggled) {
|
||||
self.filterBtn.toggle();
|
||||
}
|
||||
}), "HiPS browser"]),
|
||||
draggable: true,
|
||||
},
|
||||
//onDragged: () => {
|
||||
//if (self.filterBtn.toggled) {
|
||||
//self.filterBtn.toggle();
|
||||
//}
|
||||
//},
|
||||
classList: ['aladin-HiPS-browser-box'],
|
||||
content: Layout.vertical([
|
||||
searchTree,
|
||||
Layout.horizontal(["Search:", searchDropdown, infoCurrentHiPSBtn]),
|
||||
Layout.horizontal(["Filter:", Layout.horizontal([filterEnabler, filterBtn, filterNumberElt])]),
|
||||
]),
|
||||
@@ -233,6 +311,9 @@ export class HiPSBrowserBox extends Box {
|
||||
aladin.aladinDiv
|
||||
);
|
||||
|
||||
self = this;
|
||||
|
||||
this.searchTree = searchTree;
|
||||
this.filterBox = new HiPSFilterBox(aladin, {
|
||||
callback: (params) => {
|
||||
self._filterHiPSList(params);
|
||||
@@ -247,48 +328,42 @@ export class HiPSBrowserBox extends Box {
|
||||
|
||||
this.infoCurrentHiPSBtn = infoCurrentHiPSBtn;
|
||||
|
||||
self = this;
|
||||
|
||||
this.filterCallback = (HiPS, params) => {
|
||||
if (params.regime) {
|
||||
if (!HiPS.obs_regime)
|
||||
return false;
|
||||
|
||||
if (params.regime.toLowerCase() !== HiPS.obs_regime.toLowerCase()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (params.spatial) {
|
||||
if (!HiPS.ID)
|
||||
return false;
|
||||
|
||||
if (Array.isArray(params.spatial) && !(params.spatial.includes(HiPS.ID))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (params.resolution) {
|
||||
if (!HiPS.hips_tile_width || !HiPS.hips_order) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let pixelHEALPixOrder = Math.log2(HiPS.hips_tile_width) + (+HiPS.hips_order);
|
||||
let resPixel = Math.sqrt(Math.PI / (3*Math.pow(4, pixelHEALPixOrder)));
|
||||
|
||||
if (resPixel > params.resolution)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
this.filter = filter;
|
||||
|
||||
filterEnabler.action({target: {checked: true}});
|
||||
|
||||
this._addListeners();
|
||||
|
||||
this._requestMOCServer();
|
||||
}
|
||||
|
||||
_addListeners() {
|
||||
const requestMOCServerDebounced = Utils.debounce(() => {
|
||||
this._requestMOCServer()
|
||||
}, 500);
|
||||
|
||||
ALEvent.POSITION_CHANGED.listenedBy(this.aladin.aladinDiv, requestMOCServerDebounced);
|
||||
ALEvent.ZOOM_CHANGED.listenedBy(this.aladin.aladinDiv, requestMOCServerDebounced);
|
||||
}
|
||||
|
||||
_requestMOCServer() {
|
||||
if (this.isHidden && this.searchTree) {
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
MocServer.getAllHiPSesInsideView(this.aladin)
|
||||
.then((HiPSes) => {
|
||||
let HiPSIDs = HiPSes.map((x) => x.ID);
|
||||
self.searchTree.highlightNodes(HiPSIDs)
|
||||
})
|
||||
}
|
||||
|
||||
_addHiPS(id, name) {
|
||||
let self = this;
|
||||
|
||||
self.searchDropdown.update({value: name, title: name});
|
||||
|
||||
let hips = A.imageHiPS(id, {
|
||||
name,
|
||||
successCallback: (hips) => {
|
||||
@@ -414,8 +489,8 @@ export class HiPSBrowserBox extends Box {
|
||||
let HiPS = HiPSBrowserBox.HiPSList[key];
|
||||
// apply filtering
|
||||
if (
|
||||
self.filterCallback &&
|
||||
self.filterCallback(HiPS, params)
|
||||
self.filter &&
|
||||
self.filter(HiPS, params)
|
||||
) {
|
||||
// search with the name or id
|
||||
let name = HiPS.obs_title;
|
||||
@@ -425,14 +500,15 @@ export class HiPSBrowserBox extends Box {
|
||||
}
|
||||
}
|
||||
|
||||
if (self.searchTree) {
|
||||
self.searchTree.triggerFilter(params);
|
||||
}
|
||||
|
||||
self.searchDropdown.update({ options: HiPSIDs });
|
||||
self.filterNumberElt.innerHTML = HiPSIDs.length + "/" + Object.keys(HiPSBrowserBox.HiPSList).length;
|
||||
}
|
||||
|
||||
_hide() {
|
||||
if (this.filterBox)
|
||||
this.filterBox.signalBrowserStatus(true)
|
||||
|
||||
if (this.filterBtn && this.filterBtn.toggled) {
|
||||
this.filterBtn.toggle();
|
||||
}
|
||||
@@ -441,12 +517,10 @@ export class HiPSBrowserBox extends Box {
|
||||
}
|
||||
|
||||
_show(options) {
|
||||
this._requestMOCServer();
|
||||
|
||||
// Regenerate a new layer name
|
||||
this.layer = (options && options.layer) || Utils.uuidv4();
|
||||
|
||||
if (this.filterBox)
|
||||
this.filterBox.signalBrowserStatus(false)
|
||||
|
||||
super._show(options)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,17 +19,11 @@
|
||||
|
||||
import { Box } from "../Widgets/Box.js";
|
||||
import { Form } from "../Widgets/Form.js";
|
||||
import { MocServer } from "../../MocServer.js";
|
||||
import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
import { Layout } from "../Layout.js";
|
||||
import { Angle } from "../../libs/astro/angle.js";
|
||||
import { ALEvent } from "../../events/ALEvent.js";
|
||||
import { Utils } from "../../Utils.ts";
|
||||
import { AladinUtils } from "../../AladinUtils.js";
|
||||
import { Input } from "../Widgets/Input.js";
|
||||
import freqIconUrl from '../../../../assets/icons/freq.svg';
|
||||
import inViewIconUrl from '../../../../assets/icons/inside.svg';
|
||||
import targetIconUrl from '../../../../assets/icons/target.svg';
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
@@ -45,120 +39,96 @@ export class HiPSFilterBox extends Box {
|
||||
constructor(aladin, options) {
|
||||
let self;
|
||||
|
||||
let regimeBtn = new TogglerActionButton({
|
||||
content: 'Freq',
|
||||
icon: {
|
||||
monochrome: true,
|
||||
size: 'medium',
|
||||
url: freqIconUrl,
|
||||
},
|
||||
tooltip: {content: 'Observation bandwidth', position: {direction: 'bottom'}},
|
||||
toggled: false,
|
||||
actionOn: () => {
|
||||
self._triggerFilteringCallback();
|
||||
},
|
||||
actionOff: () => {
|
||||
let regimeBtn = Input.checkbox({
|
||||
name: 'Freq',
|
||||
tooltip: {content: 'Observation bandwidth', position: {direction: 'left'}},
|
||||
type: 'checkbox',
|
||||
checked: false,
|
||||
click(e) {
|
||||
self._triggerFilteringCallback();
|
||||
}
|
||||
});
|
||||
let spatialBtn = new TogglerActionButton({
|
||||
content: 'In view',
|
||||
icon: {
|
||||
monochrome: true,
|
||||
size: 'medium',
|
||||
url: inViewIconUrl,
|
||||
},
|
||||
tooltip: {content: 'Survey in view only!', position: {direction: 'bottom'}},
|
||||
toggled: false,
|
||||
actionOn: () => {
|
||||
self._requestMOCServer();
|
||||
},
|
||||
actionOff: () => {
|
||||
self._triggerFilteringCallback();
|
||||
}
|
||||
});
|
||||
let resolutionBtn = new TogglerActionButton({
|
||||
content: 'Resolution',
|
||||
icon: {
|
||||
monochrome: true,
|
||||
size: 'medium',
|
||||
url: targetIconUrl,
|
||||
},
|
||||
tooltip: {content: 'Check for HiPS with a specific pixel resolution.', position: {direction: 'bottom'}},
|
||||
toggled: false,
|
||||
actionOn: () => {
|
||||
self._triggerFilteringCallback();
|
||||
},
|
||||
actionOff: () => {
|
||||
let resolutionBtn = Input.checkbox({
|
||||
name: 'Resolution',
|
||||
tooltip: {content: 'Check for HiPS with a specific pixel resolution.', position: {direction: 'left'}},
|
||||
type: 'checkbox',
|
||||
checked: false,
|
||||
click(e) {
|
||||
self._triggerFilteringCallback();
|
||||
}
|
||||
});
|
||||
|
||||
let logSlider = new Input({
|
||||
let regimeOption = Layout.horizontal({
|
||||
tooltip: {
|
||||
content: "Observation regime",
|
||||
position: { direction: "right" },
|
||||
},
|
||||
label: 'Freq: ',
|
||||
layout: [Input.select({
|
||||
value: "Optical",
|
||||
options: [
|
||||
"Radio",
|
||||
"Infrared",
|
||||
"Millimeter",
|
||||
"Optical",
|
||||
"UV",
|
||||
"EUV",
|
||||
"X-ray",
|
||||
"Gamma-ray",
|
||||
],
|
||||
change: (e) => {
|
||||
let regime = e.target.value;
|
||||
self.params["regime"] = regime;
|
||||
|
||||
self._triggerFilteringCallback();
|
||||
},
|
||||
}), regimeBtn]
|
||||
});
|
||||
|
||||
let resolutionOption = Layout.horizontal({
|
||||
label: "Max resolution [°/px]:",
|
||||
name: "res",
|
||||
value: 0.1,
|
||||
type: 'range',
|
||||
cssStyle: {
|
||||
width: '100%'
|
||||
},
|
||||
tooltip: {content: AladinUtils.degreesToString(0.1), position: {direction: 'bottom'}},
|
||||
ticks: [0.1 / 3600, 1 / 3600, 1 / 60, 0.1],
|
||||
stretch: "log",
|
||||
min: 0.1 / 3600,
|
||||
max: 0.1,
|
||||
reversed: true,
|
||||
change: (e, slider, deg) => {
|
||||
slider.update({value: e.target.value, tooltip: {content: AladinUtils.degreesToString(deg), position:{direction:'bottom'}}});
|
||||
layout: [
|
||||
new Input({
|
||||
name: "res",
|
||||
value: 0.1,
|
||||
type: 'range',
|
||||
cssStyle: {
|
||||
width: '200px'
|
||||
},
|
||||
tooltip: {content: AladinUtils.degreesToString(0.1), position: {direction: 'bottom'}},
|
||||
ticks: [0.1 / 3600, 1 / 3600, 1 / 60, 0.1],
|
||||
stretch: "log",
|
||||
min: 0.1 / 3600,
|
||||
max: 0.1,
|
||||
reversed: true,
|
||||
change: (e, slider, deg) => {
|
||||
slider.update({value: e.target.value, tooltip: {content: AladinUtils.degreesToString(deg), position:{direction:'bottom'}}});
|
||||
|
||||
let resolution = new Angle(deg);
|
||||
self.params["resolution"] = resolution.degrees();
|
||||
let resolution = new Angle(deg);
|
||||
self.params["resolution"] = resolution.degrees();
|
||||
|
||||
self._triggerFilteringCallback();
|
||||
},
|
||||
self._triggerFilteringCallback();
|
||||
},
|
||||
}),
|
||||
resolutionBtn,
|
||||
]
|
||||
});
|
||||
super(
|
||||
{
|
||||
classList: ['aladin-HiPS-filter-box'],
|
||||
header: {
|
||||
title: 'Filter tags',
|
||||
draggable: false,
|
||||
},
|
||||
close: false,
|
||||
classList: ['aladin-HiPS-filter-box'],
|
||||
content: Layout.vertical([
|
||||
'<b>Filter by:</b>',
|
||||
Layout.horizontal([regimeBtn, spatialBtn, resolutionBtn]),
|
||||
'<b>Details:</b>',
|
||||
new Form({
|
||||
subInputs: [
|
||||
{
|
||||
type: "group",
|
||||
subInputs: [
|
||||
{
|
||||
label: "Freq:",
|
||||
name: "regime",
|
||||
value: "Optical",
|
||||
type: 'select',
|
||||
options: [
|
||||
"Radio",
|
||||
"Infrared",
|
||||
"Millimeter",
|
||||
"Optical",
|
||||
"UV",
|
||||
"EUV",
|
||||
"X-ray",
|
||||
"Gamma-ray",
|
||||
],
|
||||
change: (e) => {
|
||||
let regime = e.target.value;
|
||||
self.params["regime"] = regime;
|
||||
|
||||
//regimeBtn.update({content: regime});
|
||||
|
||||
self._triggerFilteringCallback();
|
||||
},
|
||||
tooltip: {
|
||||
content: "Observation regime",
|
||||
position: { direction: "right" },
|
||||
},
|
||||
},
|
||||
logSlider
|
||||
regimeOption,
|
||||
resolutionOption
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -170,60 +140,28 @@ export class HiPSFilterBox extends Box {
|
||||
|
||||
self = this;
|
||||
|
||||
this.browserClosed = false;
|
||||
|
||||
this.callback = options.callback;
|
||||
|
||||
this.regimeBtn = regimeBtn;
|
||||
this.spatialBtn = spatialBtn;
|
||||
this.resolutionBtn = resolutionBtn;
|
||||
|
||||
this.params = {
|
||||
regime: "Optical",
|
||||
spatial: true,
|
||||
highlight: true,
|
||||
resolution: 1, // 1°/pixel
|
||||
};
|
||||
this.on = false;
|
||||
this.aladin = aladin;
|
||||
this._addListeners();
|
||||
}
|
||||
|
||||
_addListeners() {
|
||||
const requestMOCServerDebounced = Utils.debounce(() => {
|
||||
this._requestMOCServer()
|
||||
}, 500);
|
||||
|
||||
ALEvent.POSITION_CHANGED.listenedBy(this.aladin.aladinDiv, requestMOCServerDebounced);
|
||||
ALEvent.ZOOM_CHANGED.listenedBy(this.aladin.aladinDiv, requestMOCServerDebounced);
|
||||
}
|
||||
|
||||
_requestMOCServer() {
|
||||
if (!this.spatialBtn.toggled || !this.on || this.browserClosed) {
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
MocServer.getAllHiPSesInsideView(this.aladin)
|
||||
.then((HiPSes) => {
|
||||
let HiPSIDs = HiPSes.map((x) => x.ID);
|
||||
self.params["spatial"] = HiPSIDs;
|
||||
|
||||
self._triggerFilteringCallback();
|
||||
})
|
||||
}
|
||||
|
||||
_triggerFilteringCallback() {
|
||||
let filterParams = {};
|
||||
|
||||
if (this.regimeBtn.toggled) {
|
||||
if (this.regimeBtn.checked) {
|
||||
filterParams['regime'] = this.params['regime']
|
||||
}
|
||||
|
||||
if (this.spatialBtn.toggled) {
|
||||
filterParams['spatial'] = this.params['spatial']
|
||||
}
|
||||
|
||||
if (this.resolutionBtn.toggled) {
|
||||
if (this.resolutionBtn.checked) {
|
||||
filterParams['resolution'] = this.params['resolution']
|
||||
}
|
||||
|
||||
@@ -232,21 +170,18 @@ export class HiPSFilterBox extends Box {
|
||||
}
|
||||
}
|
||||
|
||||
signalBrowserStatus(closed) {
|
||||
/*signalBrowserStatus(closed) {
|
||||
this.browserClosed = closed;
|
||||
|
||||
// open
|
||||
if (!closed) {
|
||||
this._requestMOCServer()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
enable(enable) {
|
||||
this.on = enable;
|
||||
|
||||
if (this.on)
|
||||
this._requestMOCServer();
|
||||
|
||||
this._triggerFilteringCallback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
|
||||
let colorSettingsContent = new Form({
|
||||
subInputs: [{
|
||||
label: 'colormap:',
|
||||
label: 'cmap:',
|
||||
type: 'select',
|
||||
name: 'cmap',
|
||||
value: 'native',
|
||||
@@ -295,13 +295,16 @@ import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
this.pixelSettingsContent.set('maxcut', +maxCut.toFixed(4))
|
||||
this.pixelSettingsContent.set('stretch', stretch)
|
||||
let fmtInput = this.pixelSettingsContent.getInput('fmt')
|
||||
|
||||
fmtInput.innerHTML = '';
|
||||
|
||||
for (const option of layer.getAvailableFormats()) {
|
||||
fmtInput.innerHTML += "<option>" + option + "</option>";
|
||||
if (layer.getAvailableFormats()) {
|
||||
|
||||
for (const option of layer.getAvailableFormats()) {
|
||||
fmtInput.innerHTML += "<option>" + option + "</option>";
|
||||
}
|
||||
fmtInput.value = layer.imgFormat;
|
||||
}
|
||||
fmtInput.value = layer.imgFormat;
|
||||
|
||||
|
||||
this.colorSettingsContent.set('cmap', colormap);
|
||||
this.colorSettingsContent.set('reverse', reversed);
|
||||
|
||||
@@ -43,7 +43,7 @@ import removeIconUrl from "../../../../assets/icons/remove.svg";
|
||||
import settingsIconUrl from "../../../../assets/icons/settings.svg";
|
||||
import searchIconImg from "../../../../assets/icons/search.svg";
|
||||
import downloadIconUrl from '../../../../assets/icons/download.svg';
|
||||
|
||||
import swapIcon from '../../../../assets/icons/swap.svg'
|
||||
import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
import { Icon } from "../Widgets/Icon.js";
|
||||
import { Box } from "../Widgets/Box.js";
|
||||
@@ -955,8 +955,7 @@ export class OverlayStackBox extends Box {
|
||||
|
||||
let deleteBtn = ActionButton.createSmallSizedIconBtn({
|
||||
icon: { url: removeIconUrl, monochrome: true },
|
||||
|
||||
disable: layer.layer === "base",
|
||||
//disable: layer.layer === "base",
|
||||
tooltip: { content: "Remove", position: { direction: "top" } },
|
||||
action(e) {
|
||||
self.aladin.removeImageLayer(layer.layer);
|
||||
@@ -965,6 +964,7 @@ export class OverlayStackBox extends Box {
|
||||
},
|
||||
});
|
||||
|
||||
let prevOpacity = null;
|
||||
let showBtn = ActionButton.createSmallSizedIconBtn({
|
||||
icon: {
|
||||
url: layer.getOpacity() === 0.0 ? hideIconUrl : showIconUrl,
|
||||
@@ -980,12 +980,15 @@ export class OverlayStackBox extends Box {
|
||||
|
||||
let opacity = layer.getOpacity();
|
||||
if (opacity === 0.0) {
|
||||
layer.setOpacity(1.0);
|
||||
let newOpacity = prevOpacity || 1.0;
|
||||
prevOpacity = null;
|
||||
layer.setOpacity(newOpacity);
|
||||
btn.update({
|
||||
icon: { monochrome: true, url: showIconUrl },
|
||||
tooltip: { content: "Hide" },
|
||||
});
|
||||
} else {
|
||||
prevOpacity = opacity;
|
||||
layer.setOpacity(0.0);
|
||||
btn.update({
|
||||
icon: { monochrome: true, url: hideIconUrl },
|
||||
@@ -1106,12 +1109,45 @@ export class OverlayStackBox extends Box {
|
||||
},
|
||||
});
|
||||
|
||||
self.layer2swap = null;
|
||||
let swapBtn = new ActionButton({
|
||||
size: "small",
|
||||
icon: {
|
||||
url: swapIcon,
|
||||
size: "small",
|
||||
monochrome: true,
|
||||
},
|
||||
tooltip: {
|
||||
content: "Swap 2 layers",
|
||||
position: { direction: "top" },
|
||||
},
|
||||
toggled: false,
|
||||
action: (_) => {
|
||||
let toggled = swapBtn.options.toggled;
|
||||
if (!toggled) {
|
||||
if (!self.layer2swap) {
|
||||
self.layer2swap = layer;
|
||||
} else {
|
||||
self.aladin.view.swapLayers(self.layer2swap.layer, layer.layer);
|
||||
}
|
||||
} else {
|
||||
if (self.layer2swap) {
|
||||
self.layer2swap = null;
|
||||
}
|
||||
}
|
||||
|
||||
swapBtn.update({
|
||||
toggled: !toggled,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
let btns = [showBtn, settingsBtn];
|
||||
|
||||
if (!(layer instanceof Image)) {
|
||||
btns.push(loadMOCBtn);
|
||||
}
|
||||
btns.push(deleteBtn);
|
||||
btns = btns.concat([swapBtn, deleteBtn]);
|
||||
|
||||
let item = Layout.horizontal({
|
||||
layout: [HiPSSelector, Layout.horizontal(btns)],
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright 2023 - UDS/CNRS
|
||||
// The Aladin Lite program is distributed under the terms
|
||||
// of the GNU General Public License version 3.
|
||||
//
|
||||
// This file is part of Aladin Lite.
|
||||
//
|
||||
// Aladin Lite is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 3 of the License.
|
||||
//
|
||||
// Aladin Lite is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// The GNU General Public License is available in COPYING file
|
||||
// along with Aladin Lite.
|
||||
//
|
||||
|
||||
import { ALEvent } from "../../events/ALEvent";
|
||||
|
||||
import { ActionButton } from "../Widgets/ActionButton";
|
||||
import mapIconUrl from '../../../../assets/icons/map.svg';
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
* File gui/ActionButton.js
|
||||
*
|
||||
* A context menu that shows when the user right clicks, or long touch on touch device
|
||||
*
|
||||
*
|
||||
* Author: Matthieu Baumann[CDS]
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
export class MainSurveyActionButton extends ActionButton {
|
||||
/**
|
||||
* UI responsible for displaying the viewport infos
|
||||
* @param {Aladin} aladin - The aladin instance.
|
||||
*/
|
||||
constructor(aladin, options) {
|
||||
super({
|
||||
...options,
|
||||
tooltip: {content: 'Survey name<br/>Click to change it!', position: { direction: 'bottom' }},
|
||||
iconURL: mapIconUrl,
|
||||
})
|
||||
|
||||
this.addClass('medium-sized-icon')
|
||||
|
||||
this._addListeners(aladin)
|
||||
}
|
||||
|
||||
_addListeners(aladin) {
|
||||
ALEvent.HIPS_LAYER_ADDED.listenedBy(aladin.aladinDiv, (e) => {
|
||||
const layer = e.detail.layer;
|
||||
if (layer.layer === 'base') {
|
||||
let name = (layer.properties && layer.properties.obsTitle) || layer.name;
|
||||
this.update({
|
||||
tooltip: {
|
||||
content: 'Survey: ' + name,
|
||||
position: {
|
||||
direction: 'left'
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ export class Dropdown extends Input {
|
||||
|
||||
super({
|
||||
type: 'text',
|
||||
autocomplete: {options: options.options},
|
||||
//autocomplete: {options: options.options},
|
||||
...options
|
||||
})
|
||||
this.el.classList.add('search')
|
||||
@@ -91,11 +91,11 @@ export class Dropdown extends Input {
|
||||
update(options) {
|
||||
let newOptions = {};
|
||||
|
||||
if (options && options.options) {
|
||||
/*if (options && options.options) {
|
||||
newOptions['autocomplete'] = {options: options.options};
|
||||
|
||||
delete options.options;
|
||||
}
|
||||
}*/
|
||||
|
||||
// add the other input text options
|
||||
newOptions = {...newOptions, ...options};
|
||||
|
||||
@@ -67,6 +67,47 @@ export class Layout extends DOMElement {
|
||||
this.appendContent(item)
|
||||
}
|
||||
}
|
||||
|
||||
if (options.draggable) {
|
||||
// retrieve the children and add the drag listeners
|
||||
let draggableFn = options.draggable;
|
||||
let firstSelected = null;
|
||||
|
||||
this.el.childNodes.forEach(div => {
|
||||
div.addEventListener("click", () => {
|
||||
// If nothing selected yet → select this one
|
||||
if (!firstSelected) {
|
||||
firstSelected = div;
|
||||
div.classList.add("aladin-item-selected");
|
||||
return;
|
||||
}
|
||||
|
||||
// If clicking the same one again → unselect
|
||||
if (firstSelected === div) {
|
||||
div.classList.remove("aladin-item-selected");
|
||||
firstSelected = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise: swap the two elements
|
||||
let a = firstSelected;
|
||||
let b = div;
|
||||
|
||||
let temp = document.createElement("div");
|
||||
a.parentNode.insertBefore(temp, a);
|
||||
b.parentNode.insertBefore(a, b);
|
||||
temp.parentNode.insertBefore(b, temp);
|
||||
temp.remove();
|
||||
|
||||
// Exec callback
|
||||
draggableFn(a, b)
|
||||
|
||||
// Clear selection
|
||||
a.classList.remove("aladin-item-selected");
|
||||
firstSelected = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// The tooltip has to be set once the element
|
||||
@@ -182,9 +223,5 @@ export class Layout extends DOMElement {
|
||||
if (this.options.position) {
|
||||
this.setPosition(this.options.position)
|
||||
}
|
||||
|
||||
//super._show()
|
||||
// attach to the DOM again
|
||||
//this.attachTo(this.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,11 +137,7 @@ export class Box extends DOMElement {
|
||||
|
||||
if (this.options.content) {
|
||||
let content = this.options.content
|
||||
//if (Array.isArray(content)) {
|
||||
this.appendContent(content);
|
||||
//} else {
|
||||
// this.appendContent(content);
|
||||
//}
|
||||
this.appendContent(content);
|
||||
}
|
||||
|
||||
if (this.options.position) {
|
||||
|
||||
@@ -74,12 +74,17 @@ export class Input extends DOMElement {
|
||||
this.el.type = this.type;
|
||||
|
||||
this.el.checked = this.options.checked;
|
||||
this.checked = this.options.checked;
|
||||
|
||||
// for checkbox widgets, we authorize calling the callback name click or change
|
||||
let action = this.options.click || this.options.change;
|
||||
if (action) {
|
||||
this.el.removeEventListener('click', this.action);
|
||||
this.action = action;
|
||||
this.action = (e) => {
|
||||
this.checked = this.el.checked;
|
||||
|
||||
action(e);
|
||||
};
|
||||
this.el.addEventListener('click', this.action);
|
||||
}
|
||||
} else if (this.type === "select") {
|
||||
@@ -374,6 +379,7 @@ export class Input extends DOMElement {
|
||||
set(value) {
|
||||
if (this.el.type === "checkbox") {
|
||||
this.el.checked = value;
|
||||
this.checked = value;
|
||||
} else {
|
||||
this.el.value = value;
|
||||
}
|
||||
|
||||
331
src/js/gui/Widgets/Tree.js
Normal file
331
src/js/gui/Widgets/Tree.js
Normal file
@@ -0,0 +1,331 @@
|
||||
// Copyright 2023 - UDS/CNRS
|
||||
// The Aladin Lite program is distributed under the terms
|
||||
// of the GNU General Public License version 3.
|
||||
//
|
||||
// This file is part of Aladin Lite.
|
||||
//
|
||||
// Aladin Lite is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 3 of the License.
|
||||
//
|
||||
// Aladin Lite is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// The GNU General Public License is available in COPYING file
|
||||
// along with Aladin Lite.
|
||||
//
|
||||
|
||||
import { DOMElement } from "./Widget";
|
||||
import { Icon } from "./Icon";
|
||||
import folderIconUrl from "../../../../assets/icons/folder.svg";
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
* File gui/Tree.js
|
||||
*
|
||||
* A tree
|
||||
*
|
||||
* Author: Matthieu Baumann[CDS]
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
export class Tree extends DOMElement {
|
||||
constructor(options, target, position = "beforeend") {
|
||||
let el = document.createElement("div");
|
||||
el.classList.add('aladin-tree');
|
||||
|
||||
super(el, options);
|
||||
|
||||
this.click = options && options.click;
|
||||
|
||||
let rootNode = options && options.root || {};
|
||||
this.params = null;
|
||||
this.filter = options && options.filter;
|
||||
this.label = options && options.label;
|
||||
|
||||
this._setRoot(rootNode);
|
||||
|
||||
this.attachTo(target, position);
|
||||
this._show();
|
||||
this.addClass('aladin-dark-theme')
|
||||
}
|
||||
|
||||
_setRoot(root) {
|
||||
if (root) {
|
||||
root.label = new Icon({
|
||||
size: "small",
|
||||
url: folderIconUrl,
|
||||
monochrome: true,
|
||||
cssStyle: {'display': 'inline-block'}
|
||||
}).element().outerHTML;
|
||||
}
|
||||
|
||||
this.root = root;
|
||||
this._createDOM(root);
|
||||
}
|
||||
|
||||
_createDOM(node) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.el.innerHTML = "";
|
||||
this.curNode = node;
|
||||
|
||||
// create the parent directory
|
||||
let curNode = this.curNode;
|
||||
|
||||
let directoryLinks = []
|
||||
|
||||
var levelsOfParenty = 0;
|
||||
|
||||
while (curNode) {
|
||||
let parentLinkEl = document.createElement('a');
|
||||
parentLinkEl.innerHTML = curNode.label;
|
||||
let curLevel = levelsOfParenty;
|
||||
parentLinkEl.addEventListener('click', () => {
|
||||
this.navigate(curLevel)
|
||||
})
|
||||
levelsOfParenty += 1;
|
||||
|
||||
parentLinkEl.classList.add("aladin-link");
|
||||
directoryLinks.push(parentLinkEl);
|
||||
|
||||
curNode = curNode.parent;
|
||||
}
|
||||
|
||||
directoryLinks.reverse()
|
||||
|
||||
let directoryListEl = document.createElement('div');
|
||||
directoryListEl.classList.add('aladin-directory-path');
|
||||
directoryListEl.style.display = "inline-block"
|
||||
|
||||
for (var link of directoryLinks) {
|
||||
directoryListEl.appendChild(link);
|
||||
|
||||
// root node
|
||||
let spanSplitEl = document.createElement('span')
|
||||
spanSplitEl.innerText = ' \/ '
|
||||
directoryListEl.appendChild(spanSplitEl)
|
||||
}
|
||||
|
||||
this.el.appendChild(directoryListEl)
|
||||
|
||||
let listElt = document.createElement('ul');
|
||||
|
||||
for (const label of Object.keys(node).sort()) {
|
||||
if (label !== 'parent' && label !== "label") {
|
||||
let elt = document.createElement('li');
|
||||
// points towards the parent node
|
||||
let child = node[label];
|
||||
let isLeaf = typeof child === "object" && 'ID' in child;
|
||||
if (isLeaf) {
|
||||
if(this.params && this.filter && !this.filter(child, this.params)) {
|
||||
elt.style.display = "none";
|
||||
} else {
|
||||
elt.style.display = "block";
|
||||
}
|
||||
|
||||
elt.innerHTML = this.label(child);
|
||||
} else {
|
||||
// we see a parent, we must determine:
|
||||
// * its color: he has at least 1 child inside the FoV => green
|
||||
// * the number of children matching the filter params
|
||||
let numFilteringMatching = this.numChildMatchingFilter(child, true);
|
||||
let numTotal = this.numChildMatchingFilter(child, false);
|
||||
|
||||
let name = label;
|
||||
elt.innerHTML = name + ` (${numFilteringMatching}/${numTotal})`
|
||||
|
||||
if (numFilteringMatching == 0) {
|
||||
elt.style.display = "none";
|
||||
} else {
|
||||
elt.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
elt.style.color = this.hasChildLocatedInFov(child) ? 'yellowgreen' : 'orange';
|
||||
|
||||
child.label = label;
|
||||
child.parent = node;
|
||||
|
||||
elt.for = label;
|
||||
elt.classList.add("aladin-link");
|
||||
|
||||
elt.addEventListener('click', (e) => {
|
||||
if (isLeaf) {
|
||||
this.click(child)
|
||||
} else {
|
||||
// not leaf
|
||||
this._createDOM(child);
|
||||
}
|
||||
})
|
||||
|
||||
listElt.appendChild(elt)
|
||||
}
|
||||
}
|
||||
|
||||
this.el.appendChild(listElt);
|
||||
}
|
||||
|
||||
setHierarchy(root) {
|
||||
this._setRoot(root)
|
||||
}
|
||||
|
||||
navigate(numOfLevels) {
|
||||
let curNode = this.curNode;
|
||||
while (curNode && curNode.parent && numOfLevels >= 1) {
|
||||
numOfLevels -= 1;
|
||||
curNode = curNode.parent;
|
||||
}
|
||||
|
||||
this._createDOM(curNode)
|
||||
}
|
||||
|
||||
highlightNodes(highlight) {
|
||||
this.highlight = highlight
|
||||
|
||||
let elts = this.el.querySelectorAll("li");
|
||||
let i = 0;
|
||||
|
||||
for (const label of Object.keys(this.curNode).sort()) {
|
||||
if (label !== 'parent' && label !== "label") {
|
||||
let elt = elts[i];
|
||||
i += 1;
|
||||
// points towards the parent node
|
||||
let child = this.curNode[label];
|
||||
let isLeaf = typeof child === "object" && 'ID' in child;
|
||||
if (isLeaf) {
|
||||
// Check if its ID is found in the view
|
||||
if (this.highlight) {
|
||||
elt.style.color = this.highlight.includes(child.ID) ? 'yellowgreen' : 'orange';
|
||||
}
|
||||
} else {
|
||||
// we see a parent, we must determine:
|
||||
// * its color: he has at least 1 child inside the FoV => green
|
||||
// * the number of children matching the filter params
|
||||
elt.style.color = this.hasChildLocatedInFov(child) ? 'yellowgreen' : 'orange';
|
||||
|
||||
// we see a parent, we must determine:
|
||||
// * its color: he has at least 1 child inside the FoV => green
|
||||
// * the number of children matching the filter params
|
||||
let numFilteringMatching = this.numChildMatchingFilter(child, true);
|
||||
let numTotal = this.numChildMatchingFilter(child, false);
|
||||
|
||||
let name = elt.innerText.split('(');
|
||||
elt.innerHTML = name[0] + ` (${numFilteringMatching}/${numTotal})`
|
||||
|
||||
if (numFilteringMatching == 0) {
|
||||
elt.style.display = "none";
|
||||
} else {
|
||||
elt.style.display = "block";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set params to null, undefined or {} to disable the filtering
|
||||
triggerFilter(params) {
|
||||
if (params && params.title) {
|
||||
params.title = params.title.toLowerCase()
|
||||
}
|
||||
|
||||
this.params = params;
|
||||
|
||||
let elts = this.el.querySelectorAll("li");
|
||||
let i = 0;
|
||||
|
||||
for (const label of Object.keys(this.curNode).sort()) {
|
||||
if (label !== 'parent' && label !== "label") {
|
||||
let elt = elts[i];
|
||||
i += 1;
|
||||
// points towards the parent node
|
||||
let child = this.curNode[label];
|
||||
let isLeaf = typeof child === "object" && 'ID' in child;
|
||||
if (isLeaf) {
|
||||
if(this.params && this.filter && !this.filter(child, this.params)) {
|
||||
elt.style.display = "none"
|
||||
} else {
|
||||
elt.style.display = "block"
|
||||
}
|
||||
} else {
|
||||
// we see a parent, we must determine:
|
||||
// * its color: he has at least 1 child inside the FoV => green
|
||||
// * the number of children matching the filter params
|
||||
let numFilteringMatching = this.numChildMatchingFilter(child, true);
|
||||
let numTotal = this.numChildMatchingFilter(child, false);
|
||||
|
||||
let name = elt.innerText.split('(');
|
||||
elt.innerHTML = name[0] + ` (${numFilteringMatching}/${numTotal})`
|
||||
if (numFilteringMatching == 0) {
|
||||
elt.style.display = "none";
|
||||
} else {
|
||||
elt.style.display = "block";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasChildLocatedInFov(node) {
|
||||
if (!this.highlight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof node !== "object") {
|
||||
return false;
|
||||
}
|
||||
|
||||
let isLeaf = typeof node === "object" && 'ID' in node;
|
||||
if (isLeaf) {
|
||||
if (this.highlight.includes(node.ID)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
for (const label of Object.keys(node).sort()) {
|
||||
if (label === "parent")
|
||||
continue;
|
||||
|
||||
let child = node[label];
|
||||
if (child && this.hasChildLocatedInFov(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
numChildMatchingFilter(node, filtering) {
|
||||
if (typeof node !== "object") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let isLeaf = typeof node === "object" && 'ID' in node;
|
||||
if (isLeaf) {
|
||||
if (!filtering || (this.params && this.filter && this.filter(node, this.params))) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
let num = 0;
|
||||
for (const label of Object.keys(node).sort()) {
|
||||
if (label === "parent")
|
||||
continue;
|
||||
|
||||
let child = node[label];
|
||||
|
||||
if (child) {
|
||||
num += this.numChildMatchingFilter(child, filtering);
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ export class SAMPConnector {
|
||||
let params = message["samp.params"];
|
||||
|
||||
const {url, name} = params;
|
||||
const image = aladin.createImageFITS(url, {name}, (e) => window.alert(e));
|
||||
const image = aladin.createImageFITS(url, {name}, undefined, (e) => window.alert(e));
|
||||
|
||||
aladin.setOverlayImageLayer(image, name);
|
||||
};
|
||||
@@ -92,6 +92,8 @@ export class SAMPConnector {
|
||||
let url = params['url'];
|
||||
let name = params['name'] || id;
|
||||
|
||||
console.log(id, url, name)
|
||||
|
||||
A.catalogFromURL(
|
||||
url,
|
||||
{name, onClick: 'showTable'},
|
||||
@@ -99,7 +101,7 @@ export class SAMPConnector {
|
||||
(catalog) => {
|
||||
aladin.addCatalog(catalog)
|
||||
},
|
||||
(e) => window.alert(e)
|
||||
(e) => window.alert(e),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user