mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 17:51:24 +01:00
throttle work done on zoom
This commit is contained in:
parent
9df7b2f7a5
commit
e7b354e217
3 changed files with 278 additions and 162 deletions
46
main.js
46
main.js
|
|
@ -128,9 +128,23 @@ let color = d3.scaleSequential(d3.interpolateSpectral); // default color scheme
|
||||||
const lineGen = d3.line().curve(d3.curveBasis); // d3 line generator with default curve interpolation
|
const lineGen = d3.line().curve(d3.curveBasis); // d3 line generator with default curve interpolation
|
||||||
|
|
||||||
// d3 zoom behavior
|
// d3 zoom behavior
|
||||||
let scale = 1,
|
let scale = 1;
|
||||||
viewX = 0,
|
let viewX = 0;
|
||||||
viewY = 0;
|
let viewY = 0;
|
||||||
|
|
||||||
|
const zoomThrottled = throttle(doWorkOnZoom, 100);
|
||||||
|
function zoomed() {
|
||||||
|
const {k, x, y} = d3.event.transform;
|
||||||
|
|
||||||
|
const isScaleChanged = Boolean(scale - k);
|
||||||
|
const isPositionChanged = Boolean(viewX - x || viewY - y);
|
||||||
|
|
||||||
|
scale = k;
|
||||||
|
viewX = x;
|
||||||
|
viewY = y;
|
||||||
|
|
||||||
|
zoomThrottled(isScaleChanged, isPositionChanged);
|
||||||
|
}
|
||||||
const zoom = d3.zoom().scaleExtent([1, 20]).on("zoom", zoomed);
|
const zoom = d3.zoom().scaleExtent([1, 20]).on("zoom", zoomed);
|
||||||
|
|
||||||
// default options
|
// default options
|
||||||
|
|
@ -414,30 +428,24 @@ function showWelcomeMessage() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function zoomed() {
|
function doWorkOnZoom(isScaleChanged, isPositionChanged) {
|
||||||
const transform = d3.event.transform;
|
viewbox.attr("transform", `translate(${viewX} ${viewY}) scale(${scale})`);
|
||||||
const scaleDiff = scale - transform.k;
|
|
||||||
const positionDiff = (viewX - transform.x) | (viewY - transform.y);
|
|
||||||
if (!positionDiff && !scaleDiff) return;
|
|
||||||
|
|
||||||
scale = transform.k;
|
if (isPositionChanged) drawCoordinates();
|
||||||
viewX = transform.x;
|
|
||||||
viewY = transform.y;
|
|
||||||
viewbox.attr("transform", transform);
|
|
||||||
|
|
||||||
// update grid only if view position
|
if (isScaleChanged) {
|
||||||
if (positionDiff) drawCoordinates();
|
|
||||||
|
|
||||||
// rescale only if zoom is changed
|
|
||||||
if (scaleDiff) {
|
|
||||||
invokeActiveZooming();
|
invokeActiveZooming();
|
||||||
drawScaleBar();
|
drawScaleBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// zoom image converter overlay
|
// zoom image converter overlay
|
||||||
|
if (customization === 1) {
|
||||||
const canvas = document.getElementById("canvas");
|
const canvas = document.getElementById("canvas");
|
||||||
if (canvas && +canvas.style.opacity) {
|
if (!canvas || canvas.style.opacity === "0") return;
|
||||||
const img = document.getElementById("image");
|
|
||||||
|
const img = document.getElementById("imageToConvert");
|
||||||
|
if (!img) return;
|
||||||
|
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
ctx.setTransform(scale, 0, 0, scale, viewX, viewY);
|
ctx.setTransform(scale, 0, 0, scale, viewX, viewY);
|
||||||
|
|
|
||||||
|
|
@ -131,15 +131,8 @@ function editHeightmap() {
|
||||||
|
|
||||||
// Exit customization mode
|
// Exit customization mode
|
||||||
function finalizeHeightmap() {
|
function finalizeHeightmap() {
|
||||||
if (viewbox.select("#heights").selectAll("*").size() < 200) {
|
if (viewbox.select("#heights").selectAll("*").size() < 200) return tip("Insufficient land area! There should be at least 200 land cells to finalize the heightmap", null, "error");
|
||||||
tip("Insufficient land area! There should be at least 200 land cells to finalize the heightmap", null, "error");
|
if (document.getElementById("imageConverter").offsetParent) return tip("Please exit the Image Conversion mode first", null, "error");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.getElementById("imageConverter").offsetParent) {
|
|
||||||
tip("Please exit the Image Conversion mode first", null, "error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete window.edits; // remove global variable
|
delete window.edits; // remove global variable
|
||||||
redo.disabled = templateRedo.disabled = true;
|
redo.disabled = templateRedo.disabled = true;
|
||||||
|
|
@ -1103,6 +1096,10 @@ function editHeightmap() {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
|
img.id = "imageToConvert";
|
||||||
|
img.style.display = "none";
|
||||||
|
document.body.appendChild(img);
|
||||||
|
|
||||||
img.onload = function () {
|
img.onload = function () {
|
||||||
const ctx = document.getElementById("canvas").getContext("2d");
|
const ctx = document.getElementById("canvas").getContext("2d");
|
||||||
ctx.drawImage(img, 0, 0, graphWidth, graphHeight);
|
ctx.drawImage(img, 0, 0, graphWidth, graphHeight);
|
||||||
|
|
@ -1295,10 +1292,7 @@ function editHeightmap() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyConversion() {
|
function applyConversion() {
|
||||||
if (colorsAssigned.childElementCount < 3) {
|
if (colorsAssigned.childElementCount < 3) return tip("Please do the assignment first", false, "error");
|
||||||
tip("Please do the assignment first", false, "error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
viewbox
|
viewbox
|
||||||
.select("#heights")
|
.select("#heights")
|
||||||
|
|
@ -1324,6 +1318,9 @@ function editHeightmap() {
|
||||||
const canvas = document.getElementById("canvas");
|
const canvas = document.getElementById("canvas");
|
||||||
if (canvas) canvas.remove();
|
if (canvas) canvas.remove();
|
||||||
|
|
||||||
|
const image = document.getElementById("imageToConvert");
|
||||||
|
if (image) image.remove();
|
||||||
|
|
||||||
d3.select("#imageConverter").selectAll("div.color-div").remove();
|
d3.select("#imageConverter").selectAll("div.color-div").remove();
|
||||||
colorsAssigned.style.display = "none";
|
colorsAssigned.style.display = "none";
|
||||||
colorsUnassigned.style.display = "none";
|
colorsUnassigned.style.display = "none";
|
||||||
|
|
|
||||||
355
modules/utils.js
355
modules/utils.js
|
|
@ -11,11 +11,11 @@ function getBoundaryPoints(width, height, spacing) {
|
||||||
const numberY = Math.ceil(h / bSpacing) - 1;
|
const numberY = Math.ceil(h / bSpacing) - 1;
|
||||||
let points = [];
|
let points = [];
|
||||||
for (let i = 0.5; i < numberX; i++) {
|
for (let i = 0.5; i < numberX; i++) {
|
||||||
let x = Math.ceil(w * i / numberX + offset);
|
let x = Math.ceil((w * i) / numberX + offset);
|
||||||
points.push([x, offset], [x, h + offset]);
|
points.push([x, offset], [x, h + offset]);
|
||||||
}
|
}
|
||||||
for (let i = 0.5; i < numberY; i++) {
|
for (let i = 0.5; i < numberY; i++) {
|
||||||
let y = Math.ceil(h * i / numberY + offset);
|
let y = Math.ceil((h * i) / numberY + offset);
|
||||||
points.push([offset, y], [w + offset, y]);
|
points.push([offset, y], [w + offset, y]);
|
||||||
}
|
}
|
||||||
return points;
|
return points;
|
||||||
|
|
@ -24,7 +24,7 @@ function getBoundaryPoints(width, height, spacing) {
|
||||||
// get points on a regular square grid and jitter them a bit
|
// get points on a regular square grid and jitter them a bit
|
||||||
function getJitteredGrid(width, height, spacing) {
|
function getJitteredGrid(width, height, spacing) {
|
||||||
const radius = spacing / 2; // square radius
|
const radius = spacing / 2; // square radius
|
||||||
const jittering = radius * .9; // max deviation
|
const jittering = radius * 0.9; // max deviation
|
||||||
const jitter = () => Math.random() * 2 * jittering - jittering;
|
const jitter = () => Math.random() * 2 * jittering - jittering;
|
||||||
|
|
||||||
let points = [];
|
let points = [];
|
||||||
|
|
@ -40,7 +40,7 @@ function getJitteredGrid(width, height, spacing) {
|
||||||
|
|
||||||
// return cell index on a regular square grid
|
// return cell index on a regular square grid
|
||||||
function findGridCell(x, y) {
|
function findGridCell(x, y) {
|
||||||
return Math.floor(Math.min(y / grid.spacing, grid.cellsY -1)) * grid.cellsX + Math.floor(Math.min(x / grid.spacing, grid.cellsX-1));
|
return Math.floor(Math.min(y / grid.spacing, grid.cellsY - 1)) * grid.cellsX + Math.floor(Math.min(x / grid.spacing, grid.cellsX - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// return array of cell indexes in radius on a regular square grid
|
// return array of cell indexes in radius on a regular square grid
|
||||||
|
|
@ -55,14 +55,12 @@ function findGridAll(x, y, radius) {
|
||||||
while (r > 1) {
|
while (r > 1) {
|
||||||
let cycle = frontier.slice();
|
let cycle = frontier.slice();
|
||||||
frontier = [];
|
frontier = [];
|
||||||
cycle.forEach(function(s) {
|
cycle.forEach(function (s) {
|
||||||
|
c[s].forEach(function (e) {
|
||||||
c[s].forEach(function(e) {
|
|
||||||
if (found.indexOf(e) !== -1) return;
|
if (found.indexOf(e) !== -1) return;
|
||||||
found.push(e);
|
found.push(e);
|
||||||
frontier.push(e);
|
frontier.push(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
r--;
|
r--;
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +98,7 @@ function getGridPolygon(i) {
|
||||||
|
|
||||||
// mbostock's poissonDiscSampler
|
// mbostock's poissonDiscSampler
|
||||||
function* poissonDiscSampler(x0, y0, x1, y1, r, k = 3) {
|
function* poissonDiscSampler(x0, y0, x1, y1, r, k = 3) {
|
||||||
if (!(x1 >= x0) || !(y1 >= y0) || !(r > 0)) throw new Error;
|
if (!(x1 >= x0) || !(y1 >= y0) || !(r > 0)) throw new Error();
|
||||||
|
|
||||||
const width = x1 - x0;
|
const width = x1 - x0;
|
||||||
const height = y1 - y0;
|
const height = y1 - y0;
|
||||||
|
|
@ -113,8 +111,8 @@ function* poissonDiscSampler(x0, y0, x1, y1, r, k = 3) {
|
||||||
const queue = [];
|
const queue = [];
|
||||||
|
|
||||||
function far(x, y) {
|
function far(x, y) {
|
||||||
const i = x / cellSize | 0;
|
const i = (x / cellSize) | 0;
|
||||||
const j = y / cellSize | 0;
|
const j = (y / cellSize) | 0;
|
||||||
const i0 = Math.max(i - 2, 0);
|
const i0 = Math.max(i - 2, 0);
|
||||||
const j0 = Math.max(j - 2, 0);
|
const j0 = Math.max(j - 2, 0);
|
||||||
const i1 = Math.min(i + 3, gridWidth);
|
const i1 = Math.min(i + 3, gridWidth);
|
||||||
|
|
@ -134,14 +132,14 @@ function* poissonDiscSampler(x0, y0, x1, y1, r, k = 3) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function sample(x, y) {
|
function sample(x, y) {
|
||||||
queue.push(grid[gridWidth * (y / cellSize | 0) + (x / cellSize | 0)] = [x, y]);
|
queue.push((grid[gridWidth * ((y / cellSize) | 0) + ((x / cellSize) | 0)] = [x, y]));
|
||||||
return [x + x0, y + y0];
|
return [x + x0, y + y0];
|
||||||
}
|
}
|
||||||
|
|
||||||
yield sample(width / 2, height / 2);
|
yield sample(width / 2, height / 2);
|
||||||
|
|
||||||
pick: while (queue.length) {
|
pick: while (queue.length) {
|
||||||
const i = Math.random() * queue.length | 0;
|
const i = (Math.random() * queue.length) | 0;
|
||||||
const parent = queue[i];
|
const parent = queue[i];
|
||||||
|
|
||||||
for (let j = 0; j < k; ++j) {
|
for (let j = 0; j < k; ++j) {
|
||||||
|
|
@ -171,20 +169,19 @@ function isWater(i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert RGB color string to HEX without #
|
// convert RGB color string to HEX without #
|
||||||
function toHEX(rgb){
|
function toHEX(rgb) {
|
||||||
if (rgb.charAt(0) === "#") {return rgb;}
|
if (rgb.charAt(0) === "#") {
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
|
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
|
||||||
return (rgb && rgb.length === 4) ? "#" +
|
return rgb && rgb.length === 4 ? "#" + ("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[3], 10).toString(16)).slice(-2) : "";
|
||||||
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
|
|
||||||
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
|
|
||||||
("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return array of standard shuffled colors
|
// return array of standard shuffled colors
|
||||||
function getColors(number) {
|
function getColors(number) {
|
||||||
const c12 = ["#dababf","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#c6b9c1","#bc80bd","#ccebc5","#ffed6f","#8dd3c7","#eb8de7"];
|
const c12 = ["#dababf", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#c6b9c1", "#bc80bd", "#ccebc5", "#ffed6f", "#8dd3c7", "#eb8de7"];
|
||||||
const cRB = d3.scaleSequential(d3.interpolateRainbow);
|
const cRB = d3.scaleSequential(d3.interpolateRainbow);
|
||||||
const colors = d3.shuffle(d3.range(number).map(i => i < 12 ? c12[i] : d3.color(cRB((i-12)/(number-12))).hex()));
|
const colors = d3.shuffle(d3.range(number).map(i => (i < 12 ? c12[i] : d3.color(cRB((i - 12) / (number - 12))).hex())));
|
||||||
return colors;
|
return colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,30 +190,42 @@ function getRandomColor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// mix a color with a random color
|
// mix a color with a random color
|
||||||
function getMixedColor(color, mix = .2, bright = .3) {
|
function getMixedColor(color, mix = 0.2, bright = 0.3) {
|
||||||
const c = color && color[0] === "#" ? color : getRandomColor(); // if provided color is not hex (e.g. harching), generate random one
|
const c = color && color[0] === "#" ? color : getRandomColor(); // if provided color is not hex (e.g. harching), generate random one
|
||||||
return d3.color(d3.interpolate(c, getRandomColor())(mix)).brighter(bright).hex();
|
return d3.color(d3.interpolate(c, getRandomColor())(mix)).brighter(bright).hex();
|
||||||
}
|
}
|
||||||
|
|
||||||
// conver temperature from °C to other scales
|
// conver temperature from °C to other scales
|
||||||
function convertTemperature(c) {
|
function convertTemperature(c) {
|
||||||
switch(temperatureScale.value) {
|
switch (temperatureScale.value) {
|
||||||
case "°C": return c + "°C";
|
case "°C":
|
||||||
case "°F": return rn(c * 9 / 5 + 32) + "°F";
|
return c + "°C";
|
||||||
case "K": return rn(c + 273.15) + "K";
|
case "°F":
|
||||||
case "°R": return rn((c + 273.15) * 9 / 5) + "°R";
|
return rn((c * 9) / 5 + 32) + "°F";
|
||||||
case "°De": return rn((100 - c) * 3 / 2) + "°De";
|
case "K":
|
||||||
case "°N": return rn(c * 33 / 100) + "°N";
|
return rn(c + 273.15) + "K";
|
||||||
case "°Ré": return rn(c * 4 / 5) + "°Ré";
|
case "°R":
|
||||||
case "°Rø": return rn(c * 21 / 40 + 7.5) + "°Rø";
|
return rn(((c + 273.15) * 9) / 5) + "°R";
|
||||||
default: return c + "°C";
|
case "°De":
|
||||||
|
return rn(((100 - c) * 3) / 2) + "°De";
|
||||||
|
case "°N":
|
||||||
|
return rn((c * 33) / 100) + "°N";
|
||||||
|
case "°Ré":
|
||||||
|
return rn((c * 4) / 5) + "°Ré";
|
||||||
|
case "°Rø":
|
||||||
|
return rn((c * 21) / 40 + 7.5) + "°Rø";
|
||||||
|
default:
|
||||||
|
return c + "°C";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// random number in a range
|
// random number in a range
|
||||||
function rand(min, max) {
|
function rand(min, max) {
|
||||||
if (min === undefined && max === undefined) return Math.random();
|
if (min === undefined && max === undefined) return Math.random();
|
||||||
if (max === undefined) {max = min; min = 0;}
|
if (max === undefined) {
|
||||||
|
max = min;
|
||||||
|
min = 0;
|
||||||
|
}
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,7 +254,9 @@ function rn(v, d = 0) {
|
||||||
|
|
||||||
// round string to d decimals
|
// round string to d decimals
|
||||||
function round(s, d = 1) {
|
function round(s, d = 1) {
|
||||||
return s.replace(/[\d\.-][\d\.e-]*/g, function(n) {return rn(n, d);})
|
return s.replace(/[\d\.-][\d\.e-]*/g, function (n) {
|
||||||
|
return rn(n, d);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// corvent number to short string with SI postfix
|
// corvent number to short string with SI postfix
|
||||||
|
|
@ -279,36 +290,39 @@ function capitalize(string) {
|
||||||
|
|
||||||
// transform string to array [translateX,translateY,rotateDeg,rotateX,rotateY,scale]
|
// transform string to array [translateX,translateY,rotateDeg,rotateX,rotateY,scale]
|
||||||
function parseTransform(string) {
|
function parseTransform(string) {
|
||||||
if (!string) {return [0,0,0,0,0,1];}
|
if (!string) {
|
||||||
const a = string.replace(/[a-z()]/g, "").replace(/[ ]/g, ",").split(",");
|
return [0, 0, 0, 0, 0, 1];
|
||||||
|
}
|
||||||
|
const a = string
|
||||||
|
.replace(/[a-z()]/g, "")
|
||||||
|
.replace(/[ ]/g, ",")
|
||||||
|
.split(",");
|
||||||
return [a[0] || 0, a[1] || 0, a[2] || 0, a[3] || 0, a[4] || 0, a[5] || 1];
|
return [a[0] || 0, a[1] || 0, a[2] || 0, a[3] || 0, a[4] || 0, a[5] || 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// findAll d3.quandtree search from https://bl.ocks.org/lwthatcher/b41479725e0ff2277c7ac90df2de2b5e
|
// findAll d3.quandtree search from https://bl.ocks.org/lwthatcher/b41479725e0ff2277c7ac90df2de2b5e
|
||||||
void function addFindAll() {
|
void (function addFindAll() {
|
||||||
const Quad = function(node, x0, y0, x1, y1) {
|
const Quad = function (node, x0, y0, x1, y1) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.x0 = x0;
|
this.x0 = x0;
|
||||||
this.y0 = y0;
|
this.y0 = y0;
|
||||||
this.x1 = x1;
|
this.x1 = x1;
|
||||||
this.y1 = y1;
|
this.y1 = y1;
|
||||||
}
|
};
|
||||||
|
|
||||||
const tree_filter = function(x, y, radius) {
|
const tree_filter = function (x, y, radius) {
|
||||||
var t = {x, y, x0: this._x0, y0: this._y0, x3: this._x1, y3: this._y1, quads: [], node: this._root};
|
var t = {x, y, x0: this._x0, y0: this._y0, x3: this._x1, y3: this._y1, quads: [], node: this._root};
|
||||||
if (t.node) {t.quads.push(new Quad(t.node, t.x0, t.y0, t.x3, t.y3))};
|
if (t.node) {
|
||||||
|
t.quads.push(new Quad(t.node, t.x0, t.y0, t.x3, t.y3));
|
||||||
|
}
|
||||||
radiusSearchInit(t, radius);
|
radiusSearchInit(t, radius);
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
while (t.q = t.quads.pop()) {
|
while ((t.q = t.quads.pop())) {
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
// Stop searching if this quadrant can’t contain a closer node.
|
// Stop searching if this quadrant can’t contain a closer node.
|
||||||
if (!(t.node = t.q.node)
|
if (!(t.node = t.q.node) || (t.x1 = t.q.x0) > t.x3 || (t.y1 = t.q.y0) > t.y3 || (t.x2 = t.q.x1) < t.x0 || (t.y2 = t.q.y1) < t.y0) continue;
|
||||||
|| (t.x1 = t.q.x0) > t.x3
|
|
||||||
|| (t.y1 = t.q.y0) > t.y3
|
|
||||||
|| (t.x2 = t.q.x1) < t.x0
|
|
||||||
|| (t.y2 = t.q.y1) < t.y0) continue;
|
|
||||||
|
|
||||||
// Bisect the current quadrant.
|
// Bisect the current quadrant.
|
||||||
if (t.node.length) {
|
if (t.node.length) {
|
||||||
|
|
@ -316,15 +330,10 @@ void function addFindAll() {
|
||||||
var xm = (t.x1 + t.x2) / 2,
|
var xm = (t.x1 + t.x2) / 2,
|
||||||
ym = (t.y1 + t.y2) / 2;
|
ym = (t.y1 + t.y2) / 2;
|
||||||
|
|
||||||
t.quads.push(
|
t.quads.push(new Quad(t.node[3], xm, ym, t.x2, t.y2), new Quad(t.node[2], t.x1, ym, xm, t.y2), new Quad(t.node[1], xm, t.y1, t.x2, ym), new Quad(t.node[0], t.x1, t.y1, xm, ym));
|
||||||
new Quad(t.node[3], xm, ym, t.x2, t.y2),
|
|
||||||
new Quad(t.node[2], t.x1, ym, xm, t.y2),
|
|
||||||
new Quad(t.node[1], xm, t.y1, t.x2, ym),
|
|
||||||
new Quad(t.node[0], t.x1, t.y1, xm, ym)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Visit the closest quadrant first.
|
// Visit the closest quadrant first.
|
||||||
if (t.i = (y >= ym) << 1 | (x >= xm)) {
|
if ((t.i = ((y >= ym) << 1) | (x >= xm))) {
|
||||||
t.q = t.quads[t.quads.length - 1];
|
t.q = t.quads[t.quads.length - 1];
|
||||||
t.quads[t.quads.length - 1] = t.quads[t.quads.length - 1 - t.i];
|
t.quads[t.quads.length - 1] = t.quads[t.quads.length - 1 - t.i];
|
||||||
t.quads[t.quads.length - 1 - t.i] = t.q;
|
t.quads[t.quads.length - 1 - t.i] = t.q;
|
||||||
|
|
@ -340,23 +349,26 @@ void function addFindAll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t.result;
|
return t.result;
|
||||||
}
|
};
|
||||||
d3.quadtree.prototype.findAll = tree_filter;
|
d3.quadtree.prototype.findAll = tree_filter;
|
||||||
|
|
||||||
var radiusSearchInit = function(t, radius) {
|
var radiusSearchInit = function (t, radius) {
|
||||||
t.result = [];
|
t.result = [];
|
||||||
t.x0 = t.x - radius, t.y0 = t.y - radius;
|
(t.x0 = t.x - radius), (t.y0 = t.y - radius);
|
||||||
t.x3 = t.x + radius, t.y3 = t.y + radius;
|
(t.x3 = t.x + radius), (t.y3 = t.y + radius);
|
||||||
t.radius = radius * radius;
|
t.radius = radius * radius;
|
||||||
}
|
};
|
||||||
|
|
||||||
var radiusSearchVisit = function(t, d2) {
|
var radiusSearchVisit = function (t, d2) {
|
||||||
t.node.data.scanned = true;
|
t.node.data.scanned = true;
|
||||||
if (d2 < t.radius) {
|
if (d2 < t.radius) {
|
||||||
do {t.result.push(t.node.data); t.node.data.selected = true;} while (t.node = t.node.next);
|
do {
|
||||||
|
t.result.push(t.node.data);
|
||||||
|
t.node.data.selected = true;
|
||||||
|
} while ((t.node = t.node.next));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}()
|
})();
|
||||||
|
|
||||||
// get segment of any point on polyline
|
// get segment of any point on polyline
|
||||||
function getSegmentId(points, point, step = 10) {
|
function getSegmentId(points, point, step = 10) {
|
||||||
|
|
@ -366,23 +378,23 @@ function getSegmentId(points, point, step = 10) {
|
||||||
let minSegment = 1;
|
let minSegment = 1;
|
||||||
let minDist = Infinity;
|
let minDist = Infinity;
|
||||||
|
|
||||||
for (let i=0; i < points.length-1; i++) {
|
for (let i = 0; i < points.length - 1; i++) {
|
||||||
const p1 = points[i];
|
const p1 = points[i];
|
||||||
const p2 = points[i+1];
|
const p2 = points[i + 1];
|
||||||
|
|
||||||
const length = Math.sqrt(d2(p1, p2));
|
const length = Math.sqrt(d2(p1, p2));
|
||||||
const segments = Math.ceil(length / step);
|
const segments = Math.ceil(length / step);
|
||||||
const dx = (p2[0] - p1[0]) / segments;
|
const dx = (p2[0] - p1[0]) / segments;
|
||||||
const dy = (p2[1] - p1[1]) / segments;
|
const dy = (p2[1] - p1[1]) / segments;
|
||||||
|
|
||||||
for (let s=0; s < segments; s++) {
|
for (let s = 0; s < segments; s++) {
|
||||||
const x = p1[0] + s * dx;
|
const x = p1[0] + s * dx;
|
||||||
const y = p1[1] + s * dy;
|
const y = p1[1] + s * dy;
|
||||||
const dist2 = d2(point, [x, y]);
|
const dist2 = d2(point, [x, y]);
|
||||||
|
|
||||||
if (dist2 >= minDist) continue;
|
if (dist2 >= minDist) continue;
|
||||||
minDist = dist2;
|
minDist = dist2;
|
||||||
minSegment = i+1;
|
minSegment = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -418,7 +430,9 @@ function vowel(c) {
|
||||||
|
|
||||||
// remove vowels from the end of the string
|
// remove vowels from the end of the string
|
||||||
function trimVowels(string) {
|
function trimVowels(string) {
|
||||||
while (string.length > 3 && vowel(last(string))) {string = string.slice(0,-1);}
|
while (string.length > 3 && vowel(last(string))) {
|
||||||
|
string = string.slice(0, -1);
|
||||||
|
}
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -427,7 +441,7 @@ function getAdjective(string) {
|
||||||
// special cases for some suffixes
|
// special cases for some suffixes
|
||||||
if (string.length > 8 && string.slice(-6) === "orszag") return string.slice(0, -6);
|
if (string.length > 8 && string.slice(-6) === "orszag") return string.slice(0, -6);
|
||||||
if (string.length > 6 && string.slice(-4) === "stan") return string.slice(0, -4);
|
if (string.length > 6 && string.slice(-4) === "stan") return string.slice(0, -4);
|
||||||
if (P(.5) && string.slice(-4) === "land") return string + "ic";
|
if (P(0.5) && string.slice(-4) === "land") return string + "ic";
|
||||||
if (string.slice(-4) === " Guo") string = string.slice(0, -4);
|
if (string.slice(-4) === " Guo") string = string.slice(0, -4);
|
||||||
|
|
||||||
// don't change is name ends on suffix
|
// don't change is name ends on suffix
|
||||||
|
|
@ -436,16 +450,16 @@ function getAdjective(string) {
|
||||||
if (string.slice(-1) === "i") return string;
|
if (string.slice(-1) === "i") return string;
|
||||||
|
|
||||||
const end = string.slice(-1); // last letter of string
|
const end = string.slice(-1); // last letter of string
|
||||||
if (end === "a") return string += "n";
|
if (end === "a") return (string += "n");
|
||||||
if (end === "o") return string = trimVowels(string) + "an";
|
if (end === "o") return (string = trimVowels(string) + "an");
|
||||||
if (vowel(end) || end === "c") return string += "an"; // ceiuy
|
if (vowel(end) || end === "c") return (string += "an"); // ceiuy
|
||||||
if (end === "m" || end === "n") return string += "ese";
|
if (end === "m" || end === "n") return (string += "ese");
|
||||||
if (end === "q") return string += "i";
|
if (end === "q") return (string += "i");
|
||||||
return trimVowels(string) + "ian";
|
return trimVowels(string) + "ian";
|
||||||
}
|
}
|
||||||
|
|
||||||
// get ordinal out of integer: 1 => 1st
|
// get ordinal out of integer: 1 => 1st
|
||||||
const nth = n => n+(["st","nd","rd"][((n+90)%100-10)%10-1]||"th");
|
const nth = n => n + (["st", "nd", "rd"][((((n + 90) % 100) - 10) % 10) - 1] || "th");
|
||||||
|
|
||||||
// get two-letters code (abbreviation) from string
|
// get two-letters code (abbreviation) from string
|
||||||
function abbreviate(name, restricted = []) {
|
function abbreviate(name, restricted = []) {
|
||||||
|
|
@ -453,8 +467,8 @@ function abbreviate(name, restricted = []) {
|
||||||
const words = parsed.split(" ");
|
const words = parsed.split(" ");
|
||||||
const letters = words.join("");
|
const letters = words.join("");
|
||||||
|
|
||||||
let code = words.length === 2 ? words[0][0]+words[1][0] : letters.slice(0,2);
|
let code = words.length === 2 ? words[0][0] + words[1][0] : letters.slice(0, 2);
|
||||||
for (let i = 1; i < letters.length-1 && restricted.includes(code); i++) {
|
for (let i = 1; i < letters.length - 1 && restricted.includes(code); i++) {
|
||||||
code = letters[0] + letters[i].toUpperCase();
|
code = letters[0] + letters[i].toUpperCase();
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
|
|
@ -463,7 +477,7 @@ function abbreviate(name, restricted = []) {
|
||||||
// conjunct array: [A,B,C] => "A, B and C"
|
// conjunct array: [A,B,C] => "A, B and C"
|
||||||
function list(array) {
|
function list(array) {
|
||||||
if (!Intl.ListFormat) return array.join(", ");
|
if (!Intl.ListFormat) return array.join(", ");
|
||||||
const conjunction = new Intl.ListFormat(window.lang || "en", {style:"long", type:"conjunction"});
|
const conjunction = new Intl.ListFormat(window.lang || "en", {style: "long", type: "conjunction"});
|
||||||
return conjunction.format(array);
|
return conjunction.format(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -472,7 +486,10 @@ function splitInTwo(str) {
|
||||||
const half = str.length / 2;
|
const half = str.length / 2;
|
||||||
const ar = str.split(" ");
|
const ar = str.split(" ");
|
||||||
if (ar.length < 2) return ar; // only one word
|
if (ar.length < 2) return ar; // only one word
|
||||||
let first = "", last = "", middle = "", rest = "";
|
let first = "",
|
||||||
|
last = "",
|
||||||
|
middle = "",
|
||||||
|
rest = "";
|
||||||
|
|
||||||
ar.forEach((w, d) => {
|
ar.forEach((w, d) => {
|
||||||
if (d + 1 !== ar.length) w += " ";
|
if (d + 1 !== ar.length) w += " ";
|
||||||
|
|
@ -501,10 +518,10 @@ function ra(array) {
|
||||||
function rw(object) {
|
function rw(object) {
|
||||||
const array = [];
|
const array = [];
|
||||||
for (const key in object) {
|
for (const key in object) {
|
||||||
for (let i=0; i < object[key]; i++) {
|
for (let i = 0; i < object[key]; i++) {
|
||||||
array.push(key);
|
array.push(key);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
return array[Math.floor(Math.random() * array.length)];
|
return array[Math.floor(Math.random() * array.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -515,33 +532,55 @@ function lim(v) {
|
||||||
|
|
||||||
// get number from string in format "1-3" or "2" or "0.5"
|
// get number from string in format "1-3" or "2" or "0.5"
|
||||||
function getNumberInRange(r) {
|
function getNumberInRange(r) {
|
||||||
if (typeof r !== "string") {ERROR && console.error("The value should be a string", r); return 0;}
|
if (typeof r !== "string") {
|
||||||
|
ERROR && console.error("The value should be a string", r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!isNaN(+r)) return ~~r + +P(r - ~~r);
|
if (!isNaN(+r)) return ~~r + +P(r - ~~r);
|
||||||
const sign = r[0] === "-" ? -1 : 1;
|
const sign = r[0] === "-" ? -1 : 1;
|
||||||
if (isNaN(+r[0])) r = r.slice(1);
|
if (isNaN(+r[0])) r = r.slice(1);
|
||||||
const range = r.includes("-") ? r.split("-") : null;
|
const range = r.includes("-") ? r.split("-") : null;
|
||||||
if (!range) {ERROR && console.error("Cannot parse the number. Check the format", r); return 0;}
|
if (!range) {
|
||||||
|
ERROR && console.error("Cannot parse the number. Check the format", r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
const count = rand(range[0] * sign, +range[1]);
|
const count = rand(range[0] * sign, +range[1]);
|
||||||
if (isNaN(count) || count < 0) {ERROR && console.error("Cannot parse number. Check the format", r); return 0;}
|
if (isNaN(count) || count < 0) {
|
||||||
|
ERROR && console.error("Cannot parse number. Check the format", r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper function non-used for the generation
|
// helper function non-used for the generation
|
||||||
function drawCellsValue(data) {
|
function drawCellsValue(data) {
|
||||||
debug.selectAll("text").remove();
|
debug.selectAll("text").remove();
|
||||||
debug.selectAll("text").data(data).enter().append("text")
|
debug
|
||||||
.attr("x", (d,i) => pack.cells.p[i][0]).attr("y", (d,i) => pack.cells.p[i][1]).text(d => d);
|
.selectAll("text")
|
||||||
|
.data(data)
|
||||||
|
.enter()
|
||||||
|
.append("text")
|
||||||
|
.attr("x", (d, i) => pack.cells.p[i][0])
|
||||||
|
.attr("y", (d, i) => pack.cells.p[i][1])
|
||||||
|
.text(d => d);
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper function non-used for the generation
|
// helper function non-used for the generation
|
||||||
function drawPolygons(data) {
|
function drawPolygons(data) {
|
||||||
const max = d3.max(data), min = d3.min(data), scheme = getColorScheme();
|
const max = d3.max(data),
|
||||||
|
min = d3.min(data),
|
||||||
|
scheme = getColorScheme();
|
||||||
data = data.map(d => 1 - normalize(d, min, max));
|
data = data.map(d => 1 - normalize(d, min, max));
|
||||||
|
|
||||||
debug.selectAll("polygon").remove();
|
debug.selectAll("polygon").remove();
|
||||||
debug.selectAll("polygon").data(data).enter().append("polygon")
|
debug
|
||||||
.attr("points", (d,i) => getPackPolygon(i))
|
.selectAll("polygon")
|
||||||
.attr("fill", d => scheme(d)).attr("stroke", d => scheme(d));
|
.data(data)
|
||||||
|
.enter()
|
||||||
|
.append("polygon")
|
||||||
|
.attr("points", (d, i) => getPackPolygon(i))
|
||||||
|
.attr("fill", d => scheme(d))
|
||||||
|
.attr("stroke", d => scheme(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
// polyfill for composedPath
|
// polyfill for composedPath
|
||||||
|
|
@ -552,56 +591,86 @@ function getComposedPath(node) {
|
||||||
else if (node.defaultView) parent = node.defaultView;
|
else if (node.defaultView) parent = node.defaultView;
|
||||||
if (parent !== undefined) return [node].concat(getComposedPath(parent));
|
if (parent !== undefined) return [node].concat(getComposedPath(parent));
|
||||||
return [node];
|
return [node];
|
||||||
};
|
}
|
||||||
|
|
||||||
// polyfill for replaceAll
|
// polyfill for replaceAll
|
||||||
if (!String.prototype.replaceAll) {
|
if (!String.prototype.replaceAll) {
|
||||||
String.prototype.replaceAll = function(str, newStr){
|
String.prototype.replaceAll = function (str, newStr) {
|
||||||
if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') return this.replace(str, newStr);
|
if (Object.prototype.toString.call(str).toLowerCase() === "[object regexp]") return this.replace(str, newStr);
|
||||||
return this.replace(new RegExp(str, 'g'), newStr);
|
return this.replace(new RegExp(str, "g"), newStr);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// get next unused id
|
// get next unused id
|
||||||
function getNextId(core, i = 1) {
|
function getNextId(core, i = 1) {
|
||||||
while (document.getElementById(core+i)) i++;
|
while (document.getElementById(core + i)) i++;
|
||||||
return core + i;
|
return core + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
function debounce(f, ms) {
|
function debounce(func, ms) {
|
||||||
let isCooldown = false;
|
let isCooldown = false;
|
||||||
|
|
||||||
return function() {
|
return function () {
|
||||||
if (isCooldown) return;
|
if (isCooldown) return;
|
||||||
f.apply(this, arguments);
|
func.apply(this, arguments);
|
||||||
isCooldown = true;
|
isCooldown = true;
|
||||||
setTimeout(() => isCooldown = false, ms);
|
setTimeout(() => (isCooldown = false), ms);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function throttle(func, ms) {
|
||||||
|
let isThrottled = false;
|
||||||
|
let savedArgs;
|
||||||
|
let savedThis;
|
||||||
|
|
||||||
|
function wrapper() {
|
||||||
|
if (isThrottled) {
|
||||||
|
savedArgs = arguments;
|
||||||
|
savedThis = this;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
func.apply(this, arguments);
|
||||||
|
isThrottled = true;
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
isThrottled = false;
|
||||||
|
if (savedArgs) {
|
||||||
|
wrapper.apply(savedThis, savedArgs);
|
||||||
|
savedArgs = savedThis = null;
|
||||||
|
}
|
||||||
|
}, ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
// parse error to get the readable string in Chrome and Firefox
|
// parse error to get the readable string in Chrome and Firefox
|
||||||
function parseError(error) {
|
function parseError(error) {
|
||||||
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
const isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
|
||||||
const errorString = isFirefox ? error.toString() + " " + error.stack : error.stack;
|
const errorString = isFirefox ? error.toString() + " " + error.stack : error.stack;
|
||||||
const regex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
|
const regex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi;
|
||||||
const errorNoURL = errorString.replace(regex, url => '<i>' + last(url.split("/")) + '</i>');
|
const errorNoURL = errorString.replace(regex, url => "<i>" + last(url.split("/")) + "</i>");
|
||||||
const errorParsed = errorNoURL.replace(/at /ig, "<br> at ");
|
const errorParsed = errorNoURL.replace(/at /gi, "<br> at ");
|
||||||
return errorParsed;
|
return errorParsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// polyfills
|
// polyfills
|
||||||
if (Array.prototype.flat === undefined) {
|
if (Array.prototype.flat === undefined) {
|
||||||
Array.prototype.flat = function() {
|
Array.prototype.flat = function () {
|
||||||
return this.reduce((acc, val) => Array.isArray(val) ? acc.concat(val.flat()) : acc.concat(val), []);
|
return this.reduce((acc, val) => (Array.isArray(val) ? acc.concat(val.flat()) : acc.concat(val)), []);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if string is a valid for JSON parse
|
// check if string is a valid for JSON parse
|
||||||
JSON.isValid = str => {
|
JSON.isValid = str => {
|
||||||
try {JSON.parse(str);}
|
try {
|
||||||
catch(e) {return false;}
|
JSON.parse(str);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
};
|
||||||
|
|
||||||
function getBase64(url, callback) {
|
function getBase64(url, callback) {
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
@ -640,16 +709,16 @@ function wiki(page) {
|
||||||
|
|
||||||
// wrap URL into html a element
|
// wrap URL into html a element
|
||||||
function link(URL, description) {
|
function link(URL, description) {
|
||||||
return `<a href="${URL}" rel="noopener" target="_blank">${description}</a>`
|
return `<a href="${URL}" rel="noopener" target="_blank">${description}</a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCtrlClick(event) {
|
function isCtrlClick(event) {
|
||||||
// meta key is cmd key on MacOs
|
// meta key is cmd key on MacOs
|
||||||
return event.ctrlKey || event.metaKey;
|
return event.ctrlKey || event.metaKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateDate(from = 100, to = 1000) {
|
function generateDate(from = 100, to = 1000) {
|
||||||
return new Date(rand(from, to),rand(12),rand(31)).toLocaleDateString("en", {year:'numeric', month:'long', day:'numeric'});
|
return new Date(rand(from, to), rand(12), rand(31)).toLocaleDateString("en", {year: "numeric", month: "long", day: "numeric"});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getQGIScoordinates(x, y) {
|
function getQGIScoordinates(x, y) {
|
||||||
|
|
@ -659,15 +728,18 @@ function getQGIScoordinates(x, y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// prompt replacer (prompt does not work in Electron)
|
// prompt replacer (prompt does not work in Electron)
|
||||||
void function() {
|
void (function () {
|
||||||
const prompt = document.getElementById("prompt");
|
const prompt = document.getElementById("prompt");
|
||||||
const form = prompt.querySelector("#promptForm");
|
const form = prompt.querySelector("#promptForm");
|
||||||
|
|
||||||
window.prompt = function(promptText = "Please provide an input", options = {default:1, step:.01, min:0, max:100}, callback) {
|
window.prompt = function (promptText = "Please provide an input", options = {default: 1, step: 0.01, min: 0, max: 100}, callback) {
|
||||||
if (options.default === undefined) {ERROR && console.error("Prompt: options object does not have default value defined"); return;}
|
if (options.default === undefined) {
|
||||||
|
ERROR && console.error("Prompt: options object does not have default value defined");
|
||||||
|
return;
|
||||||
|
}
|
||||||
const input = prompt.querySelector("#promptInput");
|
const input = prompt.querySelector("#promptInput");
|
||||||
prompt.querySelector("#promptText").innerHTML = promptText;
|
prompt.querySelector("#promptText").innerHTML = promptText;
|
||||||
const type = typeof(options.default) === "number" ? "number" : "text";
|
const type = typeof options.default === "number" ? "number" : "text";
|
||||||
input.type = type;
|
input.type = type;
|
||||||
if (options.step !== undefined) input.step = options.step;
|
if (options.step !== undefined) input.step = options.step;
|
||||||
if (options.min !== undefined) input.min = options.min;
|
if (options.min !== undefined) input.min = options.min;
|
||||||
|
|
@ -676,17 +748,56 @@ void function() {
|
||||||
input.value = options.default;
|
input.value = options.default;
|
||||||
prompt.style.display = "block";
|
prompt.style.display = "block";
|
||||||
|
|
||||||
form.addEventListener("submit", event => {
|
form.addEventListener(
|
||||||
|
"submit",
|
||||||
|
event => {
|
||||||
prompt.style.display = "none";
|
prompt.style.display = "none";
|
||||||
const v = type === "number" ? +input.value : input.value;
|
const v = type === "number" ? +input.value : input.value;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (callback) callback(v);
|
if (callback) callback(v);
|
||||||
}, {once: true});
|
},
|
||||||
}
|
{once: true}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const cancel = prompt.querySelector("#promptCancel");
|
const cancel = prompt.querySelector("#promptCancel");
|
||||||
cancel.addEventListener("click", () => prompt.style.display = "none");
|
cancel.addEventListener("click", () => (prompt.style.display = "none"));
|
||||||
}()
|
})();
|
||||||
|
|
||||||
// indexedDB; ldb object
|
// indexedDB; ldb object
|
||||||
!function(){function e(t,o){return n?void(n.transaction("s").objectStore("s").get(t).onsuccess=function(e){var t=e.target.result&&e.target.result.v||null;o(t)}):void setTimeout(function(){e(t,o)},100)}var t=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB;if(!t)return void ERROR && console.error("indexedDB not supported");var n,o={k:"",v:""},r=t.open("d2",1);r.onsuccess=function(e){n=this.result},r.onerror=function(e){ERROR && console.error("indexedDB request error"),INFO && console.log(e)},r.onupgradeneeded=function(e){n=null;var t=e.target.result.createObjectStore("s",{keyPath:"k"});t.transaction.oncomplete=function(e){n=e.target.db}},window.ldb={get:e,set:function(e,t){o.k=e,o.v=t,n.transaction("s","readwrite").objectStore("s").put(o)}}}();
|
!(function () {
|
||||||
|
function e(t, o) {
|
||||||
|
return n
|
||||||
|
? void (n.transaction("s").objectStore("s").get(t).onsuccess = function (e) {
|
||||||
|
var t = (e.target.result && e.target.result.v) || null;
|
||||||
|
o(t);
|
||||||
|
})
|
||||||
|
: void setTimeout(function () {
|
||||||
|
e(t, o);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
var t = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
||||||
|
if (!t) return void ERROR && console.error("indexedDB not supported");
|
||||||
|
var n,
|
||||||
|
o = {k: "", v: ""},
|
||||||
|
r = t.open("d2", 1);
|
||||||
|
(r.onsuccess = function (e) {
|
||||||
|
n = this.result;
|
||||||
|
}),
|
||||||
|
(r.onerror = function (e) {
|
||||||
|
ERROR && console.error("indexedDB request error"), INFO && console.log(e);
|
||||||
|
}),
|
||||||
|
(r.onupgradeneeded = function (e) {
|
||||||
|
n = null;
|
||||||
|
var t = e.target.result.createObjectStore("s", {keyPath: "k"});
|
||||||
|
t.transaction.oncomplete = function (e) {
|
||||||
|
n = e.target.db;
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
(window.ldb = {
|
||||||
|
get: e,
|
||||||
|
set: function (e, t) {
|
||||||
|
(o.k = e), (o.v = t), n.transaction("s", "readwrite").objectStore("s").put(o);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue