mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-12 07:40:26 -08:00
first commit
This commit is contained in:
committed by
Matthieu Baumann
parent
2981e634d2
commit
22db1baac7
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
1286
src/js/Aladin.js
1286
src/js/Aladin.js
File diff suppressed because it is too large
Load Diff
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}*/
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
273
src/js/gui/Box/HiPSBrowserBox.js
Normal file
273
src/js/gui/Box/HiPSBrowserBox.js
Normal 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)
|
||||
}
|
||||
}
|
||||
235
src/js/gui/Box/HiPSFilterBox.js
Normal file
235
src/js/gui/Box/HiPSFilterBox.js
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
107
src/js/gui/Input/Dropdown.js
Normal file
107
src/js/gui/Input/Dropdown.js
Normal 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) {
|
||||
}
|
||||
};
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user