first commit

This commit is contained in:
Matthieu Baumann
2024-05-02 18:11:00 +02:00
committed by Matthieu Baumann
parent 2981e634d2
commit 22db1baac7
18 changed files with 1554 additions and 751 deletions

View File

@@ -2,7 +2,7 @@
"homepage": "https://aladin.u-strasbg.fr/",
"name": "aladin-lite",
"type": "module",
"version": "3.4.0-beta",
"version": "3.4.1-beta",
"description": "An astronomical HiPS visualizer in the browser",
"author": "Thomas Boch and Matthieu Baumann",
"license": "GPL-3",

View File

@@ -353,16 +353,15 @@ canvas {
.aladin-btn.aladin-dark-theme.toggled {
border-color: greenyellow;
}
.aladin-btn.aladin-dark-theme:hover, .aladin-input-select.aladin-dark-theme:hover {
border-color: red;
}
.aladin-btn.disabled {
cursor: not-allowed;
filter: brightness(70%);
}
.aladin-btn:not(.disabled):hover {
filter: brightness(105%);
}
.aladin-btn.svg-icon {
background-repeat: no-repeat;
background-position:center center;
@@ -417,6 +416,10 @@ canvas {
height: 1.7rem;
}
.aladin-input-text.aladin-dark-theme:focus {
border-color: dodgerblue;
}
.aladin-input-text.aladin-dark-theme.search {
width: 15rem;
text-shadow: 0px 0px 2px #000;
@@ -436,14 +439,20 @@ canvas {
line-height: 1.2rem;
}
.aladin-input-text.search.aladin-unknownObject {
.aladin-input-text.search.aladin-not-valid {
-webkit-box-shadow:inset 0px 0px 0px 1px #f00;
-moz-box-shadow:inset 0px 0px 0px 1px #f00;
box-shadow:inset 0px 0px 0px 1px #f00;
}
.aladin-input-text.aladin-dark-theme.aladin-not-valid {
border: 1px solid red;
}
.aladin-input-text.aladin-dark-theme.aladin-valid {
border: 1px solid yellowgreen;
}
.aladin-cancelBtn {
background-color: #ca4242;
border-color: #bd3935;
@@ -1096,10 +1105,11 @@ canvas {
height: 1.7rem;
}
/*
.aladin-input-text.aladin-dark-theme.search.aladin-HiPS-search {
width: 100%;
}
}*/
.aladin-stack-box {
width: 17rem;

View File

@@ -106,13 +106,13 @@ A.aladin = function (divSelector, options) {
* @function
* @name A.imageHiPS
* @memberof A
* @param {string} id - Mandatory unique identifier for the survey.
* @param {string} url - Can be an `url` that refers to a HiPS.
* @param {string} id - Can be an `url` that refers to a HiPS.
* Or it can be a "CDS ID" pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}.
* @param {ImageHiPSOptions} [options] - Options describing the survey
* @returns {ImageHiPS} - A HiPS image object
*/
A.imageHiPS = function (id, url, options) {
A.imageHiPS = function (id, options) {
let url = id;
return Aladin.createImageSurvey(
id,
options && options.name,

File diff suppressed because it is too large Load Diff

View File

@@ -33,13 +33,13 @@ export let HiPSCache = (function () {
HiPSCache.append = function (key, image) {
HiPSCache.cache[key] = image;
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(document.body);
ALEvent.HIPS_CACHE_UPDATED.dispatchedTo(document.body);
};
HiPSCache.delete = function (key) {
delete HiPSCache.cache[key];
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(document.body);
ALEvent.HIPS_CACHE_UPDATED.dispatchedTo(document.body);
};
HiPSCache.get = function (key) {

View File

@@ -88,13 +88,6 @@ export let ImageFITS = (function () {
}
ImageFITS.prototype._saveInCache = function () {
/*ImageHiPS.cache[this.id] = this;
// Tell that the HiPS List has been updated
if (this.view) {
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(this.view.aladin.aladinDiv);
}*/
HiPSCache.append(this.id, this);
};

View File

@@ -181,7 +181,6 @@ export let ImageHiPS = (function () {
this.id = id;
this.name = (options && options.name) || undefined;
this.subtype = "survey";
this.url = url;
this.maxOrder = options.maxOrder;
this.minOrder = options.minOrder || 0;
@@ -296,12 +295,8 @@ export let ImageHiPS = (function () {
}
})
.catch((e) => {
//alert(e);
console.error(self);
console.error(e);
// the survey has been added so we remove it from the stack
//self.view.removeImageLayer(self.layer)
//throw e;
});
}
@@ -490,21 +485,6 @@ export let ImageHiPS = (function () {
// append new important infos from the properties queried
...surveyOpt,
});
/*ImageHiPS.cache[self.id] = {
// Erase by the cache already put values which is considered
// as the ground truth
...ImageHiPS.cache[self.id],
// append new important infos from the properties queried
...surveyOpt,
}*/
//console.log('new CACHE', ImageHiPS.cache, self.id, surveyOpt, ImageHiPS.cache[self.id], ImageHiPS.cache["CSIRO/P/RACS/mid/I"])
// Tell that the HiPS List has been updated
/*if (this.view) {
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(this.view.aladin.aladinDiv);
}*/
};
/**

View File

@@ -51,19 +51,46 @@ export class MocServer {
expr: "dataproduct_type=image",
get: "record",
fmt: "json",
fields: "ID,hips_creator,hips_copyright,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",
//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",
};
this._allHiPSes = Utils.loadFromUrls(MocServer.MIRRORS_HTTPS, {
data: params,
dataType: 'json'
dataType: 'json',
desc: 'MOCServer query to get all the HiPS metadata'
})
}
return this._allHiPSes;
}
static getAllHiPSesInsideView(aladin) {
let params = {
//expr: "dataproduct_type=image||dataproduct_type=cube",
expr: "dataproduct_type=image",
get: "record",
fmt: "json",
fields: "ID",
};
try {
const corners = aladin.getFoVCorners();
let stc = 'Polygon '
for (var radec of corners) {
stc += radec[0] + ' ' + radec[1] + ' ';
}
params['stc'] = stc;
} catch (e) {}
return Utils.loadFromUrls(MocServer.MIRRORS_HTTPS, {
data: params,
dataType: 'json',
desc: 'MOCServer: Retrieve HiPS inside FoV'
})
}
static getHiPSesFromIDs(ids) {
const params = {
//expr: "dataproduct_type=image||dataproduct_type=cube",

View File

@@ -265,7 +265,7 @@ Utils.loadFromUrls = function (urls, options) {
const mode = options && options.mode || 'cors';
const contentType = options && options.contentType || undefined;
const dataType = (options && options.dataType) || 'text';
const desc = options && options.desc;
// A controller that can abort the query when a timeout is reached
const controller = new AbortController()
@@ -289,7 +289,9 @@ Utils.loadFromUrls = function (urls, options) {
cache: 'default',
// Abort the request when a timeout exceeded
signal: controller.signal,
dataType
dataType,
// message description
desc
}
if (contentType) {

View File

@@ -1742,7 +1742,7 @@ export let View = (function () {
if (this.overlayLayers.length === 0) {
this.empty = true;
} else if (this.selectedLayer === layer) {
// If the layer removed was selected then we select the base layer
// If the layer removed was selected then we select the last layer
this.selectLayer(this.overlayLayers[this.overlayLayers.length - 1]);
}

View File

@@ -53,7 +53,7 @@ export class ALEvent {
static HIPS_LAYER_RENAMED = new ALEvent("AL:HiPSLayer.renamed");
static HIPS_LAYER_SWAP = new ALEvent("AL:HiPSLayer.swap");
static HIPS_LIST_UPDATED = new ALEvent("AL:HiPSList.updated");
static HIPS_CACHE_UPDATED = new ALEvent("AL:HiPSCache.updated");
static HIPS_LAYER_CHANGED = new ALEvent("AL:HiPSLayer.changed");

View File

@@ -0,0 +1,273 @@
// Copyright 2013 - 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 { MocServer } from "../../MocServer.js";
import { Box } from "../Widgets/Box.js";
import { Dropdown } from "../Input/Dropdown.js";
import filterOnUrl from "../../../../assets/icons/filter-on.svg";
import filterOffUrl from "../../../../assets/icons/filter-off.svg";
import { Input } from "../Widgets/Input.js";
import { TogglerActionButton } from "../Button/Toggler.js";
import { Layout } from "../Layout.js";
import { HiPSFilterBox } from "./HiPSFilterBox.js";
import { ActionButton } from "../Widgets/ActionButton.js";
import addIconUrl from "../../../../assets/icons/plus.svg";
/******************************************************************************
* Aladin Lite project
*
* File gui/HiPSBrowserBox.js
*
*
* Author: Matthieu Baumann[CDS]
*
*****************************************************************************/
export class HiPSBrowserBox extends Box {
static HiPSList = {};
constructor(aladin, options) {
let self;
MocServer.getAllHiPSes().then((HiPSes) => {
// Fill the HiPSList from the MOCServer
HiPSes.forEach((h) => {
HiPSBrowserBox.HiPSList[h.ID] = h;
});
// Initialize the autocompletion without any filtering
self._filterHiPSList({})
});
let searchDropdown = new Dropdown(aladin, {
name: "HiPS browser",
placeholder: "HiPS name, URL or ID",
tooltip: {
content: 'Type an url, CDS ID or a name to search for a HiPS'
},
actions: {
change(e) {
const value = e.target.value;
/*if (!key) {
self.update({value: prevKey, title: prevKey});
return;
}*/
let image;
// A user can put an url
try {
image = new URL(value).href;
} catch (e) {
// Or he can select a HiPS from the list given
const hips = HiPSBrowserBox.HiPSList[value];
if (hips) {
image = hips.id || hips.url || undefined;
} else {
// Finally if not found, interpret the input text value as the HiPS (e.g. ID)
image = value;
}
}
self.el.blur();
if (image) {
self.image = image;
//prevKey = image;
// set the layer to the new value
//aladin.setOverlayImageLayer(image, layer.layer);
}
},
},
});
let filterEnabler = Input.checkbox({
name: "filter-enabler",
checked: false,
tooltip: {
content: "Filter off",
},
click(e) {
let on = e.target.checked;
self.filterBox.enable(on);
if (!on) {
// if the filter has been disabled we also need to update
// the autocompletion list of the search dropdown
// We give no filter params
self._filterHiPSList({});
}
filterBtn.update({
icon: {
url: on ? filterOnUrl : filterOffUrl,
monochrome: true,
},
});
filterEnabler.update({
tooltip: {
content: on
? "Filtering on"
: "Filtering off",
},
checked: on,
});
},
});
let filterBtn = new TogglerActionButton({
icon: {
url: filterOffUrl,
monochrome: true,
},
size: "small",
tooltip: {
content: "Want to filter HiPS surveys by criteria ?",
position: { direction: "top" },
},
toggled: false,
actionOn: (e) => {
self.filterBox._show({
position: {
nextTo: filterBtn,
direction: "right",
aladin,
},
});
},
actionOff: (e) => {
self.filterBox._hide();
},
});
let addBtn = new ActionButton({
icon: {
url: addIconUrl,
size: "small",
monochrome: true,
},
tooltip: {
content: "Add the HiPS",
position: { direction: "top" },
},
action(e) {
aladin.addNewImageLayer("sdfff");
}
});
super(
{
close: true,
header: {
title: "HiPS browser",
},
content: new Layout([
Layout.horizontal(["Filter:", filterEnabler, filterBtn]),
"Browse:",
searchDropdown,
addBtn,
]),
...options,
},
aladin.aladinDiv
);
this.filterBox = new HiPSFilterBox(aladin, {
callback: (params) => {
self._filterHiPSList(params);
},
})
this.filterBox._hide();
this.searchDropdown = searchDropdown;
this.filterBtn = filterBtn;
this.aladin = aladin;
self = this;
this.filterCallback = (HiPS, params) => {
if (!HiPS.obs_regime || (
params.regime &&
HiPS.obs_regime &&
params.regime.toLowerCase() !==
HiPS.obs_regime.toLowerCase()
)) {
return false;
}
if (Array.isArray(params.spatial) && HiPS.ID && !(params.spatial.includes(HiPS.ID))) {
return false;
}
if (!HiPS.hips_tile_width || !HiPS.hips_order)
return false;
if (params.resolution) {
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 method is executed only if the filter is enabled
_filterHiPSList(params) {
let self = this;
let HiPSIDs = [];
for (var key in HiPSBrowserBox.HiPSList) {
let HiPS = HiPSBrowserBox.HiPSList[key];
// apply filtering
if (
self.filterCallback &&
self.filterCallback(HiPS, params)
) {
// search with the name or id
HiPSIDs.push(HiPS.obs_title);
}
}
self.searchDropdown.update({ options: HiPSIDs });
}
_hide() {
if (this.filterBox)
this.filterBox.signalBrowserStatus(true)
if (this.filterBtn && this.filterBtn.toggled) {
this.filterBtn.toggle();
}
super._hide()
}
_show(options) {
if (this.filterBox)
this.filterBox.signalBrowserStatus(false)
super._show(options)
}
}

View File

@@ -0,0 +1,235 @@
// Copyright 2013 - 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 { Box } from "../Widgets/Box.js";
import { Input } from "../Widgets/Input.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";
/******************************************************************************
* Aladin Lite project
*
* File gui/HiPSBrowserBox.js
*
*
* Author: Matthieu Baumann[CDS]
*
*****************************************************************************/
export class HiPSFilterBox extends Box {
constructor(aladin, options) {
let self;
let regimeBtn = new TogglerActionButton({
content: 'Optical',
toggled: true,
actionOn: () => {
self._triggerFilteringCallback();
},
actionOff: () => {
self._triggerFilteringCallback();
}
});
let spatialBtn = new TogglerActionButton({
content: 'Spatial',
toggled: false,
actionOn: () => {
self._triggerFilteringCallback();
},
actionOff: () => {
self._triggerFilteringCallback();
}
});
let resolutionBtn = new TogglerActionButton({
content: '<=1°',
toggled: false,
actionOn: () => {
self._triggerFilteringCallback();
},
actionOff: () => {
self._triggerFilteringCallback();
}
});
super(
{
header: {
title: 'HiPS Filter'
},
close: false,
content: new Layout([
'Filters:',
new Layout([regimeBtn, spatialBtn, resolutionBtn]),
'Parameters:',
new Form({
subInputs: [
{
type: "group",
subInputs: [
{
label: "Regime:",
name: "regime",
value: "Optical",
type: 'select',
options: [
"Optical",
"UV",
"Radio",
"Infrared",
"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" },
},
},
{
label: "Angular res/px:",
name: "res",
value: "1°",
type: 'text',
classList: ['aladin-valid'],
autocomplete: 'off',
actions: {
input: (e) => {
e.target.classList.remove('aladin-not-valid');
e.target.classList.remove('aladin-valid');
let value = e.target.value;
let resolution = new Angle();
if (resolution.parse(value)) {
// The angle has been parsed
console.log(resolution.degrees())
self.params["resolution"] = resolution.degrees();
e.target.classList.add('aladin-valid');
resolutionBtn.update({content: '<=' + value});
self._triggerFilteringCallback();
} else {
e.target.classList.add('aladin-not-valid');
}
},
change: (e) => {
e.preventDefault();
e.stopPropagation();
}
}
},
],
},
],
}),
])
},
aladin.aladinDiv
);
self = this;
this.browserClosed = false;
this.callback = options.callback;
this.regimeBtn = regimeBtn;
this.spatialBtn = spatialBtn;
this.resolutionBtn = resolutionBtn;
this.params = {
regime: "Optical",
spatial: 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) {
filterParams['regime'] = this.params['regime']
}
if (this.spatialBtn.toggled) {
filterParams['spatial'] = this.params['spatial']
}
if (this.resolutionBtn.toggled) {
filterParams['resolution'] = this.params['resolution']
}
if (this.on && this.callback) {
this.callback(filterParams);
}
}
signalBrowserStatus(closed) {
this.browserClosed = closed;
// open
if (!closed) {
this._requestMOCServer()
}
}
enable(enable) {
this.on = enable;
this._triggerFilteringCallback();
}
}

View File

@@ -41,18 +41,17 @@ import addIconUrl from "../../../../assets/icons/plus.svg";
import hideIconUrl from "../../../../assets/icons/hide.svg";
import removeIconUrl from "../../../../assets/icons/remove.svg";
import settingsIconUrl from "../../../../assets/icons/settings.svg";
import filterOnUrl from "../../../../assets/icons/filter-on.svg";
import filterOffUrl from "../../../../assets/icons/filter-off.svg";
import searchIconImg from "../../../../assets/icons/search.svg";
import { TogglerActionButton } from "../Button/Toggler.js";
import { Icon } from "../Widgets/Icon.js";
import { ImageHiPS } from "../../ImageHiPS.js";
import { Box } from "../Widgets/Box.js";
import { CtxMenuActionButtonOpener } from "../Button/CtxMenuOpener.js";
import { Input } from "../Widgets/Input.js";
import { ImageFITS } from "../../ImageFITS.js";
import { HiPSCache } from "../../DefaultHiPSCache.js";
import { HiPSBrowserBox } from "./HiPSBrowserBox.js";
export class OverlayStackBox extends Box {
/*static previewImagesUrl = {
@@ -138,24 +137,6 @@ export class OverlayStackBox extends Box {
this.aladin = aladin;
this.filterHiPSOn = false;
this.filterCallback = (HiPS) => {
if (!HiPS.regime) {
return false;
}
if (
this.filterParams.regime &&
HiPS.regime &&
this.filterParams.regime.toLowerCase() !==
HiPS.regime.toLowerCase()
) {
return false;
}
return true;
};
this.mode = "stack";
this._addListeners();
@@ -526,10 +507,10 @@ export class OverlayStackBox extends Box {
{
label: {
icon: {
url: searchIconUrl,
url: addIconUrl,
monochrome: true,
tooltip: {
content: "From our database...",
content: "Add a new layer",
position: { direction: "right" },
},
cssStyle: {
@@ -544,23 +525,50 @@ export class OverlayStackBox extends Box {
/*self._hide();
self.hipsSelectorBox = new HiPSSelectorBox(self.aladin);
// attach a callback
self.hipsSelectorBox.attach(
(HiPSId) => {
let name = Utils.uuidv4()
self.aladin.setOverlayImageLayer(HiPSId, name)
self.hipsSelectorBox = new HiPSSelectorBox(self.aladin);
// attach a callback
self.hipsSelectorBox.attach(
(HiPSId) => {
let name = Utils.uuidv4()
self.aladin.setOverlayImageLayer(HiPSId, name)
self.show();
}
);
self.show();
}
);
self.hipsSelectorBox._show({
position: self.position,
});*/
self.hipsSelectorBox._show({
position: self.position,
});*/
self.aladin.addNewImageLayer();
},
},
{
label: {
icon: {
url: searchIconUrl,
monochrome: true,
tooltip: {
content: "From our database...",
position: { direction: "right" },
},
cssStyle: {
cursor: "help",
},
},
content: "Browse HiPS",
},
action: (e) => {
e.stopPropagation();
e.preventDefault();
if (!self.hipsBrowser)
self.hipsBrowser = new HiPSBrowserBox(aladin);
self.hipsBrowser._show({position: {
anchor: 'center center'
}});
},
},
ContextMenu.fileLoaderItem({
label: "FITS image file",
accept: ".fits",
@@ -595,97 +603,6 @@ export class OverlayStackBox extends Box {
this.aladin
);
this.filterParams = {
regime: "Optical",
};
this.filterBox = new Box(
{
close: false,
content: [
Input.select({
name: "regime",
value: "Optical",
options: [
"Optical",
"UV",
"Radio",
"Infrared",
"X-ray",
"Gamma-ray",
],
change() {
self.filterParams["regime"] = this.value;
if (self.filterHiPSOn) {
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(
self.aladin.aladinDiv
);
}
},
tooltip: {
content: "Observation regime",
position: { direction: "right" },
},
}),
],
},
self.aladin.aladinDiv
);
this.filterBox._hide();
this.filterEnabler = Input.checkbox({
name: "filter-enabler",
checked: this.filterHiPSOn,
tooltip: {
content: self.filterHiPSOn ? "Filtering on" : "Filtering off",
},
click(e) {
self.filterHiPSOn = e.target.checked;
self.filterBtn.update({
icon: {
url: self.filterHiPSOn ? filterOnUrl : filterOffUrl,
monochrome: true,
},
});
self.filterEnabler.update({
tooltip: {
content: self.filterHiPSOn
? "Filtering on"
: "Filtering off",
},
checked: self.filterHiPSOn,
});
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(self.aladin.aladinDiv);
},
});
this.filterBtn = new TogglerActionButton({
icon: {
url: this.filterHiPSOn ? filterOnUrl : filterOffUrl,
monochrome: true,
},
size: "small",
tooltip: {
content: "Want to filter HiPS surveys by criteria ?",
position: { direction: "top" },
},
toggled: false,
actionOn: (e) => {
self.filterBox._show({
position: {
nextTo: self.filterBtn,
direction: "right",
aladin: self.aladin,
},
});
},
actionOff: (e) => {
self.filterBox._hide();
},
});
this.update({ content: this.createLayout() });
}
@@ -784,13 +701,11 @@ export class OverlayStackBox extends Box {
updateOverlayList();
// Add a listener for HiPS list changes
ALEvent.HIPS_LIST_UPDATED.listenedBy(document.body, () => {
ALEvent.HIPS_CACHE_UPDATED.listenedBy(document.body, () => {
self.cachedHiPS = {};
for (var key in HiPSCache.cache) {
let HiPS = HiPSCache.cache[key];
self.cachedHiPS[HiPS.name] = HiPS;
}
@@ -803,33 +718,6 @@ export class OverlayStackBox extends Box {
hips.HiPSSelector.update({options});
}
});
/*ALEvent.HIPS_LIST_UPDATED.listenedBy(this.aladin.aladinDiv, () => {
// Recompute the autocompletion as the cache has changed
HiPSSearch.HiPSList = {};
for (var key in ImageHiPS.cache) {
let HiPS = ImageHiPS.cache[key];
// apply filtering
if (
!self.filterHiPSOn ||
(self.filterHiPSOn && !self.filterCallback) ||
(self.filterHiPSOn &&
self.filterCallback &&
self.filterCallback(HiPS))
) {
// search with the name or id
HiPSSearch.HiPSList[HiPS.name] = HiPS;
}
}
let keys = Object.keys(HiPSSearch.HiPSList);
// Change the autocomplete of all the search input text
for (var key in this.HiPSui) {
let hips = this.HiPSui[key];
hips.searchInput.setAutocompletionList(keys);
}
});*/
}
_hide() {
@@ -841,12 +729,12 @@ export class OverlayStackBox extends Box {
}
}
if (this.catBox) {
this.catBox._hide();
if (this.hipsBrowser) {
this.hipsBrowser._hide();
}
if (this.filterBtn && this.filterBtn.toggled) {
this.filterBtn.toggle();
if (this.catBox) {
this.catBox._hide();
}
if (this.addOverlayBtn) this.addOverlayBtn.hideMenu();
@@ -984,7 +872,7 @@ export class OverlayStackBox extends Box {
_createSurveysList() {
let self = this;
const layers = Array.from(self.aladin.getImageOverlays())
const layers = Array.from(self.aladin.getStackLayers())
.reverse()
.map((name) => {
let overlay = self.aladin.getOverlayImageLayer(name);
@@ -1103,8 +991,8 @@ export class OverlayStackBox extends Box {
);
return found !== undefined;
})(),
action: (e, btn) => {
if (!btn.options.toggled) {
action: (e) => {
if (!loadMOCBtn.options.toggled) {
// load the moc
let moc = A.MOCFromURL(
layer.url + "/Moc.fits",
@@ -1123,7 +1011,7 @@ export class OverlayStackBox extends Box {
});
}
btn.update({
loadMOCBtn.update({
toggled: true,
tooltip: {
content: "Remove coverage",
@@ -1149,7 +1037,7 @@ export class OverlayStackBox extends Box {
});
}
btn.update({
loadMOCBtn.update({
toggled: false,
tooltip: {
content: "Add coverage",

View File

@@ -0,0 +1,107 @@
// Copyright 2013 - 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 { Box } from "../Widgets/Box.js";
import { Layout } from "../Layout.js";
import { ActionButton } from "../Widgets/ActionButton.js";
import { ALEvent } from "../../events/ALEvent.js";
import { Icon } from "../Widgets/Icon.js";
import infoIconUrl from '../../../../assets/icons/info.svg';
/******************************************************************************
* Aladin Lite project
*
* File gui/HiPSSelector.js
*
*
* Author: Thomas Boch, Matthieu Baumann[CDS]
*
*****************************************************************************/
// Copyright 2013 - 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.
//
/******************************************************************************
* Aladin Lite project
*
* File Location.js
*
* Author: Thomas Boch[CDS]
*
*****************************************************************************/
import { Input } from "../Widgets/Input.js";
export class Dropdown extends Input {
// constructor
constructor(aladin, options) {
let self;
aladin.view.catalogCanvas.addEventListener('click', (e) => {
self.el.blur();
});
options.options = options.options || [];
super({
type: 'text',
autocomplete: {options: options.options},
...options
})
//this.el.classList.add('search')
self = this;
this._addListeners(aladin);
}
update(options) {
let newOptions = {};
if (options && options.options) {
newOptions['autocomplete'] = {options: options.options};
delete options.options;
}
// add the other input text options
newOptions = {...newOptions, ...options};
super.update(newOptions)
}
_addListeners(aladin) {
}
};

View File

@@ -76,7 +76,7 @@ export class Location extends DOMElement {
keydown: (e) => {
e.stopPropagation();
field.removeClass('aladin-unknownObject'); // remove red border
field.removeClass('aladin-not-valid'); // remove red border
if (e.key === 'Enter') {
field.el.blur();
@@ -90,7 +90,7 @@ export class Location extends DOMElement {
object,
{
error: function () {
field.addClass('aladin-unknownObject');
field.addClass('aladin-not-valid');
field.update({placeholder: object + ' not found...'})
field.set('');
field.el.focus();
@@ -220,7 +220,7 @@ export class Location extends DOMElement {
else {
self.field.set(coo.format('d/'))
}
self.field.removeClass('aladin-unknownObject');
self.field.removeClass('aladin-not-valid');
self.field.element().style.color = options.isViewCenter ? aladin.getReticle().getColor() : 'white';
//self.field.el.blur()

View File

@@ -53,6 +53,9 @@ Exemple of layout object
export class Form extends DOMElement {
constructor(options, target, position = "beforeend") {
let el = document.createElement('form');
el.onsubmit = (e) => {
e.preventDefault();
};
el.className = "aladin-form";
super(el, options);

View File

@@ -2,10 +2,13 @@
// Class Coo
//=================================
import { Format } from "./coo";
/**
* Constructor
* @param angle angle (precision in degrees)
* @param prec precision
* Creates an angle of the Aladin interactive sky atlas.
* @class
* @constructs Angle
* @param {number} angle - precision in degrees
* @param {number} prec - precision
* (8: 1/1000th sec, 7: 1/100th sec, 6: 1/10th sec, 5: sec, 4: 1/10th min, 3: min, 2: 1/10th deg, 1: deg
*/
export let Angle = function(angle, prec) {
@@ -43,28 +46,66 @@ Angle.prototype = {
return Format.toDecimal(fov, this.prec) + suffix;
},
/**
* @memberof Angle
*
* @param {string} str - A string in the form [<deg>°<minutes>'<seconds>"]. [hms] form is not supported
* @returns {boolean} - Whether the string has been successfully parsed
*/
parse: function(str) {
// check for degrees
let idxUnit;
idxUnit = str.indexOf('°');
if (idxUnit > 0) {
this.angle = +str.substring(0, idxUnit)
return true;
let idx = str.indexOf('°');
let angleDeg = NaN;
if (idx > 0) {
const deg = parseFloat(str.substring(0, idx));
if (!Number.isFinite(deg)) {
return false
}
angleDeg = deg;
str = str.substring(idx + 1)
}
idxUnit = str.indexOf('\'');
if (idxUnit > 0) {
this.angle = (+str.substring(0, idxUnit)) / 60.0
return true;
idx = str.indexOf('\'');
if (idx > 0) {
const minutes = parseFloat(str.substring(0, idx))
if (!Number.isFinite(minutes)) {
return false
}
if (!Number.isFinite(angleDeg)) {
angleDeg = 0;
}
angleDeg += minutes / 60.0
str = str.substring(idx + 1);
}
idxUnit = str.indexOf('"');
if (idxUnit > 0) {
this.angle = (+str.substring(0, idxUnit)) / 3600.0
return true;
idx = str.indexOf('"');
if (idx > 0) {
const seconds = parseFloat(str.substring(0, idx))
if (!Number.isFinite(seconds)) {
return false;
}
if (!Number.isFinite(angleDeg)) {
angleDeg = 0;
}
angleDeg += seconds / 3600.0
}
return false
if (Number.isFinite(angleDeg)) {
this.angle = angleDeg;
return true;
} else {
return false
}
},
degrees: function() {