@cquiroz/aladin-lite
Version:
AladinLite module
279 lines (238 loc) • 8.26 kB
JavaScript
// 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 Utils
*
* Author: Thomas Boch[CDS]
*
*****************************************************************************/
var Utils = {};
var JSONP_PROXY = "https://alasky.unistra.fr/cgi/JSONProxy";
Utils.cssScale = undefined; // adding relMouseCoords to HTMLCanvasElement prototype (see http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element )
function relMouseCoords(event) {
if (event.offsetX) {
return {
x: event.offsetX,
y: event.offsetY
};
} else {
if (!Utils.cssScale) {
var st = window.getComputedStyle(document.body, null);
var tr = st.getPropertyValue("-webkit-transform") || st.getPropertyValue("-moz-transform") || st.getPropertyValue("-ms-transform") || st.getPropertyValue("-o-transform") || st.getPropertyValue("transform");
var matrixRegex = /matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/;
var matches = tr.match(matrixRegex);
if (matches) {
Utils.cssScale = parseFloat(matches[1]);
} else {
Utils.cssScale = 1;
}
}
var e = event; // http://www.jacklmoore.com/notes/mouse-position/
var target = e.target || e.srcElement;
var style = target.currentStyle || window.getComputedStyle(target, null);
var borderLeftWidth = parseInt(style['borderLeftWidth'], 10);
var borderTopWidth = parseInt(style['borderTopWidth'], 10);
var rect = target.getBoundingClientRect();
var clientX = e.clientX;
var clientY = e.clientY;
if (e.clientX === undefined) {
clientX = e.changedTouches[0].clientX;
clientY = e.changedTouches[0].clientY;
}
var offsetX = clientX - borderLeftWidth - rect.left;
var offsetY = clientY - borderTopWidth - rect.top;
return {
x: parseInt(offsetX / Utils.cssScale),
y: parseInt(offsetY / Utils.cssScale)
};
}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;
/* source: http://stackoverflow.com/a/1830844 */
Utils.isNumber = function (n) {
return !isNaN(parseFloat(n)) && isFinite(n);
};
Utils.isInt = function (n) {
return Utils.isNumber(n) && Math.floor(n) === n;
};
/* a debounce function, used to prevent multiple calls to the same function if less than delay milliseconds have passed */
Utils.debounce = function (fn, delay) {
var timer = null;
return function () {
var context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
};
};
/* return a throttled function, to rate limit the number of calls (by default, one call every 250 milliseconds) */
Utils.throttle = function (fn, threshhold, scope) {
threshhold || (threshhold = 250);
var last, deferTimer;
return function () {
var context = scope || this;
var now = +new Date(),
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
};
};
/* A LRU cache, inspired by https://gist.github.com/devinus/409353#file-gistfile1-js */
// TODO : utiliser le LRU cache pour les tuiles images
Utils.LRUCache = function (maxsize) {
this._keys = [];
this._items = {};
this._expires = {};
this._size = 0;
this._maxsize = maxsize || 1024;
};
Utils.LRUCache.prototype = {
set: function set(key, value) {
var keys = this._keys,
items = this._items,
expires = this._expires,
size = this._size,
maxsize = this._maxsize;
if (size >= maxsize) {
// remove oldest element when no more room
keys.sort(function (a, b) {
if (expires[a] > expires[b]) return -1;
if (expires[a] < expires[b]) return 1;
return 0;
});
size--;
delete expires[keys[size]];
delete items[keys[size]];
}
keys[size] = key;
items[key] = value;
expires[key] = Date.now();
size++;
this._keys = keys;
this._items = items;
this._expires = expires;
this._size = size;
},
get: function get(key) {
var item = this._items[key];
if (item) this._expires[key] = Date.now();
return item;
},
keys: function keys() {
return this._keys;
}
}; ////////////////////////////////////////////////////////////////////////////:
/**
Make an AJAX call, given a list of potential mirrors
First successful call will result in options.onSuccess being called back
If all calls fail, onFailure is called back at the end
This method assumes the URL are CORS-compatible, no proxy will be used
*/
Utils.loadFromMirrors = function (urls, options) {
var data = options && options.data || null;
var dataType = options && options.dataType || null;
var onSuccess = options && options.onSuccess || null;
var onFailure = options && options.onFailure || null;
if (urls.length === 0) {
typeof onFailure === 'function' && onFailure();
} else {
var ajaxOptions = {
url: urls[0],
data: data
};
if (dataType) {
ajaxOptions.dataType = dataType;
}
var url = new URL(ajaxOptions.url);
url.search = new URLSearchParams(ajaxOptions.data);
fetch(url).then(res => {
var type = res.headers.get('content-type');
if (type.includes("application/json")) return res.json();else if (type.includes("text/html")) return res.text();
}).then(data => {
typeof onSuccess === 'function' && onSuccess(data);
}).catch(err => {
console.log(err);
Utils.loadFromMirrors(urls.slice(1), options);
});
}
}; // return the jquery ajax object configured with the requested parameters
// by default, we use the proxy (safer, as we don't know if the remote server supports CORS)
Utils.getAjaxObject = function (url, method, dataType, useProxy) {
if (useProxy !== false) {
useProxy = true;
}
var JsonProxy = JSONP_PROXY;
var urlToRequest = "";
if (useProxy === true) {
urlToRequest = JsonProxy + '?url=' + encodeURIComponent(url);
} else {
urlToRequest = url;
}
method = method || 'GET';
dataType = dataType || null;
return fetch(urlToRequest, {
method: method
});
}; // return true if script is executed in a HTTPS context
// return false otherwise
Utils.isHttpsContext = function () {
return window.location.protocol === 'https:';
}; // generate an absolute URL from a relative URL
// example: getAbsoluteURL('foo/bar/toto') return http://cds.unistra.fr/AL/foo/bar/toto if executed from page http://cds.unistra.fr/AL/
Utils.getAbsoluteURL = function (url) {
var a = document.createElement('a');
a.href = url;
return a.href;
}; // generate a valid v4 UUID
Utils.uuidv4 = function () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0,
v = c === 'x' ? r : r & 0x3 | 0x8;
return v.toString(16);
});
};
Utils.radecToPolar = function (t, s) {
return {
theta: Math.PI / 2 - s / 180 * Math.PI,
phi: t / 180 * Math.PI
};
};
Utils.polarToRadec = function (t, s) {
return {
ra: 180 * s / Math.PI,
dec: 180 * (Math.PI / 2 - t) / Math.PI
};
};
Utils.castToInt = function (t) {
return t > 0 ? Math.floor(t) : Math.ceil(t);
};
export default Utils;