added repulsion
This commit is contained in:
parent
8e5fcbeefa
commit
e0ba73702d
386
graph.js
386
graph.js
|
@ -8,24 +8,18 @@ import victor from "https://cdn.skypack.dev/victor@1.1.0";
|
||||||
class graph {
|
class graph {
|
||||||
// Оболочка (instanceof HTMLElement)
|
// Оболочка (instanceof HTMLElement)
|
||||||
#shell = document.getElementById("graph");
|
#shell = document.getElementById("graph");
|
||||||
|
|
||||||
// Оболочка (instanceof HTMLElement)
|
|
||||||
get shell() {
|
get shell() {
|
||||||
return this.#shell;
|
return this.#shell;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Реестр узлов
|
// Реестр узлов
|
||||||
#nodes = new Set();
|
#nodes = new Set();
|
||||||
|
|
||||||
// Реестр узлов
|
|
||||||
get nodes() {
|
get nodes() {
|
||||||
return this.#nodes;
|
return this.#nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Реестр соединений
|
// Реестр соединений
|
||||||
#connections = new Set();
|
#connections = new Set();
|
||||||
|
|
||||||
// Реестр соединений
|
|
||||||
get connections() {
|
get connections() {
|
||||||
return this.#connections;
|
return this.#connections;
|
||||||
}
|
}
|
||||||
|
@ -34,79 +28,70 @@ class graph {
|
||||||
#node = class node {
|
#node = class node {
|
||||||
// Реестр входящих соединений
|
// Реестр входящих соединений
|
||||||
#inputs = new Set();
|
#inputs = new Set();
|
||||||
|
|
||||||
// Реестр входящих соединений
|
|
||||||
get inputs() {
|
get inputs() {
|
||||||
return this.#inputs;
|
return this.#inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Реестр исходящих соединений
|
// Реестр исходящих соединений
|
||||||
#outputs = new Set();
|
#outputs = new Set();
|
||||||
|
|
||||||
// Реестр исходящих соединений
|
|
||||||
get outputs() {
|
get outputs() {
|
||||||
return this.#outputs;
|
return this.#outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Оператор
|
// Оператор
|
||||||
#operator;
|
#operator;
|
||||||
|
|
||||||
// Оператор
|
|
||||||
get operator() {
|
get operator() {
|
||||||
return this.#operator;
|
return this.#operator;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTML-элемент
|
// HTML-элемент
|
||||||
#element;
|
#element;
|
||||||
|
|
||||||
// HTML-элемент
|
|
||||||
get element() {
|
get element() {
|
||||||
return this.#element;
|
return this.#element;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Наблюдатель
|
// Наблюдатель
|
||||||
#observer = null;
|
#observer = null;
|
||||||
|
|
||||||
// Наблюдатель
|
|
||||||
get observer() {
|
get observer() {
|
||||||
return this.#observer;
|
return this.#observer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Реестр запрещённых к изменению параметров
|
// Реестр запрещённых к изменению параметров
|
||||||
#block = new Set(["events"]);
|
#block = new Set(["events"]);
|
||||||
|
|
||||||
// Реестр запрещённых к изменению параметров
|
|
||||||
get block() {
|
get block() {
|
||||||
return this.#block;
|
return this.#block;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Параметры генерации
|
// Диаметр узла
|
||||||
#diameter = 100;
|
#diameter = 100;
|
||||||
#increase = 5;
|
|
||||||
|
|
||||||
// Параметры генерации
|
|
||||||
get diameter() {
|
get diameter() {
|
||||||
return this.#diameter;
|
return this.#diameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Степень увеличения диаметра
|
||||||
|
#increase = 0;
|
||||||
get increase() {
|
get increase() {
|
||||||
return this.#increase;
|
return this.#increase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Величина степени увеличения диаметра
|
||||||
|
#addition = 12;
|
||||||
|
get addition() {
|
||||||
|
return this.#addition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обработка событий
|
||||||
|
actions = {
|
||||||
|
collision: true,
|
||||||
|
repulsion: true
|
||||||
|
};
|
||||||
|
|
||||||
constructor(operator, data) {
|
constructor(operator, data) {
|
||||||
// Инициализация оболочки
|
// Инициализация HTML-элемента узла
|
||||||
const article = document.createElement("article");
|
const a = document.createElement("a");
|
||||||
article.id = operator.nodes.size;
|
a.id = operator.nodes.size;
|
||||||
article.classList.add("node", "unselectable");
|
a.classList.add("node", "unselectable");
|
||||||
article.style.top =
|
if (typeof data.href === "string") a.href = data.href;
|
||||||
operator.shell.offsetHeight / 2 -
|
|
||||||
this.#diameter / 2 +
|
|
||||||
(0.5 - Math.random()) * 500 +
|
|
||||||
"px";
|
|
||||||
article.style.left =
|
|
||||||
operator.shell.offsetWidth / 2 -
|
|
||||||
this.#diameter / 2 +
|
|
||||||
(0.5 - Math.random()) * 500 +
|
|
||||||
"px";
|
|
||||||
|
|
||||||
if (typeof data.title === "string") {
|
if (typeof data.title === "string") {
|
||||||
// Найден заголовок узла
|
// Найден заголовок узла
|
||||||
|
@ -116,27 +101,43 @@ class graph {
|
||||||
title.innerText = data.title;
|
title.innerText = data.title;
|
||||||
|
|
||||||
// Запись в оболочку
|
// Запись в оболочку
|
||||||
article.appendChild(title);
|
a.appendChild(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
operator.shell.appendChild(a);
|
||||||
|
|
||||||
// Запись в свойство
|
// Запись в свойство
|
||||||
this.#element = article;
|
this.#element = a;
|
||||||
|
|
||||||
// Запись в свойство
|
// Запись в свойство
|
||||||
this.#operator = operator;
|
this.#operator = operator;
|
||||||
|
|
||||||
// Запись в документ
|
|
||||||
operator.shell.appendChild(article);
|
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
|
// Перемещение
|
||||||
|
this.move(
|
||||||
|
operator.shell.offsetWidth / 2 -
|
||||||
|
this.#diameter / 2 +
|
||||||
|
(0.5 - Math.random()) * 500,
|
||||||
|
operator.shell.offsetHeight / 2 -
|
||||||
|
this.#diameter / 2 +
|
||||||
|
(0.5 - Math.random()) * 500,
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
init(increase = 0) {
|
init(increase = 0) {
|
||||||
// Изменение диаметра
|
// Запись в свойство
|
||||||
if (increase !== 0) this.#diameter += this.#increase * increase;
|
this.#increase = increase;
|
||||||
|
|
||||||
// Инициализация размера элемента
|
// Инициализация диаметра
|
||||||
|
if (this.#increase !== 0)
|
||||||
|
this.#diameter += this.#addition ** this.#increase;
|
||||||
|
|
||||||
|
// Инициализация размера HTML-элемента
|
||||||
this.element.style.width = this.element.style.height =
|
this.element.style.width = this.element.style.height =
|
||||||
this.#diameter + "px";
|
this.#diameter + "px";
|
||||||
|
|
||||||
|
@ -147,6 +148,8 @@ class graph {
|
||||||
this.#observer = new MutationObserver(function (mutations) {
|
this.#observer = new MutationObserver(function (mutations) {
|
||||||
for (const mutation of mutations) {
|
for (const mutation of mutations) {
|
||||||
if (mutation.type === "attributes") {
|
if (mutation.type === "attributes") {
|
||||||
|
// Перехвачено изменение аттрибута
|
||||||
|
|
||||||
// Запись параметра в инстанцию бегущей строки
|
// Запись параметра в инстанцию бегущей строки
|
||||||
_this.configure(mutation.attributeName);
|
_this.configure(mutation.attributeName);
|
||||||
}
|
}
|
||||||
|
@ -160,6 +163,191 @@ class graph {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
move(x, y, collision = true, repulsion = false) {
|
||||||
|
// Запись отступов
|
||||||
|
this.element.style.left = x + "px";
|
||||||
|
this.element.style.top = y + "px";
|
||||||
|
|
||||||
|
// Запись аттрибутов с координатами
|
||||||
|
this.element.setAttribute("data-graph-x", x);
|
||||||
|
this.element.setAttribute("data-graph-y", y);
|
||||||
|
|
||||||
|
// Синхронизация местоположения исходящих и входящих соединений
|
||||||
|
for (const connection of this.outputs) connection.sync(this);
|
||||||
|
|
||||||
|
// Синхронизация местоположения входящих соединений
|
||||||
|
for (const connection of this.inputs) connection.sync(this);
|
||||||
|
|
||||||
|
// Обработка столкновений
|
||||||
|
if (collision) this.collision(this.operator.nodes);
|
||||||
|
|
||||||
|
// Обработка отталкивания
|
||||||
|
if (repulsion) this.repulsion(this.operator.nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
collision(nodes) {
|
||||||
|
// Инициализация буфера реестра узлов
|
||||||
|
const registry = new Set(nodes);
|
||||||
|
|
||||||
|
// Удаление текущего узла из буфера
|
||||||
|
registry.delete(this);
|
||||||
|
|
||||||
|
// Обработка коллизии
|
||||||
|
for (const node of registry) {
|
||||||
|
// Перебор узлов в реестре
|
||||||
|
|
||||||
|
// Инициализация вектора между узлами
|
||||||
|
let between;
|
||||||
|
|
||||||
|
// Инициализация ускорения
|
||||||
|
let increase = 0;
|
||||||
|
|
||||||
|
// Инициализация максимального количества итераций
|
||||||
|
let iterations = 300;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Произошла коллизия (границы кругов перекрылись)
|
||||||
|
|
||||||
|
// Инициализация универсального буфера
|
||||||
|
let buffer;
|
||||||
|
|
||||||
|
// Инициализация координат целевого узла
|
||||||
|
let x1 =
|
||||||
|
(isNaN((buffer = parseInt(node.element.style.left))) ? 0 : buffer) +
|
||||||
|
node.element.offsetWidth / 2;
|
||||||
|
let y1 =
|
||||||
|
(isNaN((buffer = parseInt(node.element.style.top))) ? 0 : buffer) +
|
||||||
|
node.element.offsetHeight / 2;
|
||||||
|
|
||||||
|
// Инициализация координат обрабатываемого узла
|
||||||
|
let x2 =
|
||||||
|
(isNaN((buffer = parseInt(this.element.style.left))) ? 0 : buffer) +
|
||||||
|
this.element.offsetWidth / 2;
|
||||||
|
let y2 =
|
||||||
|
(isNaN((buffer = parseInt(this.element.style.top))) ? 0 : buffer) +
|
||||||
|
this.element.offsetHeight / 2;
|
||||||
|
|
||||||
|
// Реинициализация вектора между узлами
|
||||||
|
between = new victor(x1 - x2, y1 - y2);
|
||||||
|
|
||||||
|
// Проверка на столкновение узлов
|
||||||
|
if (
|
||||||
|
!node.actions.collision ||
|
||||||
|
between.length() > node.diameter / 2 + this.diameter / 2 ||
|
||||||
|
--iterations <= 0
|
||||||
|
)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Инициализация координат вектора (узла с которым произошло столкновение)
|
||||||
|
let vector = new victor(x1, y1)
|
||||||
|
.add(new victor(between.x, between.y).norm().unfloat())
|
||||||
|
.subtract(
|
||||||
|
new victor(
|
||||||
|
node.element.offsetWidth / 2,
|
||||||
|
node.element.offsetHeight / 2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Перемещение узла с которым произошло столкновение
|
||||||
|
if (node.actions.collision) node.move(vector.x, vector.y, true, true);
|
||||||
|
|
||||||
|
// Проверка на столкновение узлов
|
||||||
|
} while (
|
||||||
|
node.actions.collision &&
|
||||||
|
between.length() <= node.diameter / 2 + this.diameter / 2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repulsion(nodes) {
|
||||||
|
// Инициализация буфера реестра узлов
|
||||||
|
const registry = new Set(nodes);
|
||||||
|
|
||||||
|
// Удаление текущего узла из буфера
|
||||||
|
registry.delete(this);
|
||||||
|
|
||||||
|
// Инициализация ссылки на ядро
|
||||||
|
const _this = this;
|
||||||
|
|
||||||
|
// Обработка отталкивания
|
||||||
|
for (const node of registry) {
|
||||||
|
// Перебор узлов в буфере реестра
|
||||||
|
|
||||||
|
// Инициализация вектора между узлами
|
||||||
|
let between;
|
||||||
|
|
||||||
|
// Минимальная дистанция между узлами
|
||||||
|
const distance = 100;
|
||||||
|
|
||||||
|
// Инициализация максимального количества итераций
|
||||||
|
let iterations = 300;
|
||||||
|
|
||||||
|
function move() {
|
||||||
|
// Инициализация универсального буфера
|
||||||
|
let buffer;
|
||||||
|
|
||||||
|
// Инициализация координат целевого узла
|
||||||
|
let x1 =
|
||||||
|
(isNaN((buffer = parseInt(node.element.style.left))) ? 0 : buffer) +
|
||||||
|
node.element.offsetWidth / 2;
|
||||||
|
let y1 =
|
||||||
|
(isNaN((buffer = parseInt(node.element.style.top))) ? 0 : buffer) +
|
||||||
|
node.element.offsetHeight / 2;
|
||||||
|
|
||||||
|
// Инициализация координат обрабатываемого узла
|
||||||
|
let x2 =
|
||||||
|
(isNaN((buffer = parseInt(_this.element.style.left)))
|
||||||
|
? 0
|
||||||
|
: buffer) +
|
||||||
|
_this.element.offsetWidth / 2;
|
||||||
|
let y2 =
|
||||||
|
(isNaN((buffer = parseInt(_this.element.style.top))) ? 0 : buffer) +
|
||||||
|
_this.element.offsetHeight / 2;
|
||||||
|
|
||||||
|
// Реинициализация вектора между узлами
|
||||||
|
between = new victor(x1 - x2, y1 - y2);
|
||||||
|
|
||||||
|
// Проверка на столкновение узлов
|
||||||
|
if (
|
||||||
|
!node.actions.repulsion ||
|
||||||
|
between.length() >
|
||||||
|
node.diameter / 2 +
|
||||||
|
_this.diameter / 2 +
|
||||||
|
distance +
|
||||||
|
(_this.diameter / 4) ** _this.increase ||
|
||||||
|
--iterations <= 0
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Инициализация координат вектора (узла с которым произошло столкновение)
|
||||||
|
let vector = new victor(x1, y1)
|
||||||
|
.add(new victor(between.x, between.y).norm().unfloat())
|
||||||
|
.subtract(
|
||||||
|
new victor(
|
||||||
|
node.element.offsetWidth / 2,
|
||||||
|
node.element.offsetHeight / 2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Перемещение узла с которым произошло столкновение
|
||||||
|
if (node.actions.repulsion) node.move(vector.x, vector.y, true, true);
|
||||||
|
|
||||||
|
// Проверка расстояния
|
||||||
|
if (
|
||||||
|
node.actions.repulsion &&
|
||||||
|
between.length() <=
|
||||||
|
node.diameter / 2 +
|
||||||
|
_this.diameter / 2 +
|
||||||
|
distance +
|
||||||
|
(_this.diameter / 4) ** (_this.increase ** _this.increase)
|
||||||
|
)
|
||||||
|
setTimeout(move, between.length() / 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.actions.repulsion) move();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
configure(attribute) {
|
configure(attribute) {
|
||||||
// Инициализация названия параметра
|
// Инициализация названия параметра
|
||||||
const parameter = (/^data-graph-(\w+)$/.exec(attribute) ?? [, null])[1];
|
const parameter = (/^data-graph-(\w+)$/.exec(attribute) ?? [, null])[1];
|
||||||
|
@ -195,91 +383,6 @@ class graph {
|
||||||
: buffer;
|
: buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
move(x, y) {
|
|
||||||
// Запись отступов
|
|
||||||
this.element.style.left = x + "px";
|
|
||||||
this.element.style.top = y + "px";
|
|
||||||
|
|
||||||
// Запись аттрибутов с координатами
|
|
||||||
this.element.setAttribute("data-graph-x", x);
|
|
||||||
this.element.setAttribute("data-graph-y", y);
|
|
||||||
|
|
||||||
// Перемещение исходящих соединений до узла
|
|
||||||
for (const connection of this.outputs) connection.move(this);
|
|
||||||
|
|
||||||
// Перемещение входящих соединений до узла
|
|
||||||
for (const connection of this.inputs) connection.move(this);
|
|
||||||
|
|
||||||
// Обработка столкновений
|
|
||||||
this.collision(this.operator.nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
collision(nodes) {
|
|
||||||
// Инициализация буфера реестра узлов
|
|
||||||
const buffer = new Set(nodes);
|
|
||||||
|
|
||||||
// Удаление текущего узла из буфера
|
|
||||||
buffer.delete(this);
|
|
||||||
|
|
||||||
// Удаление текущего узла из буфера
|
|
||||||
buffer.delete(this);
|
|
||||||
|
|
||||||
// Обработка коллизии
|
|
||||||
for (const node of buffer) {
|
|
||||||
// Перебор узлов в реестре
|
|
||||||
|
|
||||||
// Инициализация вектора между узлами
|
|
||||||
let between;
|
|
||||||
|
|
||||||
// Инициализация ускорения
|
|
||||||
let increase = 0;
|
|
||||||
|
|
||||||
// Инициализация количества итераций
|
|
||||||
let iterations = 300;
|
|
||||||
|
|
||||||
do {
|
|
||||||
// Произошла коллизия (границы кругов перекрылись)
|
|
||||||
|
|
||||||
// Инициализация координат целевого узла
|
|
||||||
let x1 = parseInt(node.element.style.left);
|
|
||||||
x1 = (isNaN(x1) ? 0 : x1) + node.element.offsetWidth / 2;
|
|
||||||
let y1 = parseInt(node.element.style.top);
|
|
||||||
y1 = (isNaN(y1) ? 0 : y1) + node.element.offsetHeight / 2;
|
|
||||||
|
|
||||||
// Инициализация координат обрабатываемого узла
|
|
||||||
let x2 = parseInt(this.element.style.left);
|
|
||||||
x2 = (isNaN(x2) ? 0 : x2) + this.element.offsetWidth / 2;
|
|
||||||
let y2 = parseInt(this.element.style.top);
|
|
||||||
y2 = (isNaN(y2) ? 0 : y2) + this.element.offsetHeight / 2;
|
|
||||||
|
|
||||||
// Реинициализация вектора между узлами
|
|
||||||
between = new victor(x1 - x2, y1 - y2);
|
|
||||||
|
|
||||||
// Проверка на столкновение узлов
|
|
||||||
if (
|
|
||||||
between.length() > node.diameter / 2 + this.diameter / 2 ||
|
|
||||||
--iterations === 0
|
|
||||||
)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Инициализация координат вектора (узла с которым произошло столкновение)
|
|
||||||
let vector = new victor(x1, y1)
|
|
||||||
.add(new victor(between.x, between.y).norm().unfloat())
|
|
||||||
.subtract(
|
|
||||||
new victor(
|
|
||||||
node.element.offsetWidth / 2,
|
|
||||||
node.element.offsetHeight / 2
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Перемещение узла с которым произошло столкновение
|
|
||||||
node.move(vector.x, vector.y);
|
|
||||||
} while (between.length() <= node.diameter / 2 + this.diameter / 2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -381,26 +484,27 @@ class graph {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Переместить
|
* Синхронизировать местоположение со связанным узлом
|
||||||
*
|
*
|
||||||
* @param {node} node Инстанция узла (связанного с соединением)
|
* @param {node} node Инстанция узла (связанного с соединением)
|
||||||
*/
|
*/
|
||||||
move(node) {
|
sync(node) {
|
||||||
// Инициализация названий аттрибутов
|
// Инициализация названий аттрибутов
|
||||||
let x, y;
|
let x = "x",
|
||||||
|
y = "y";
|
||||||
|
|
||||||
if (node === this.from) {
|
if (node === this.from) {
|
||||||
// Исходящее соединение
|
// Исходящее соединение
|
||||||
|
|
||||||
// Запись названий аттрибутов
|
// Запись названий аттрибутов
|
||||||
x = "x1";
|
x += 1;
|
||||||
y = "y1";
|
y += 1;
|
||||||
} else if (node === this.to) {
|
} else if (node === this.to) {
|
||||||
// Входящее соединение
|
// Входящее соединение
|
||||||
|
|
||||||
// Запись названий аттрибутов
|
// Запись названий аттрибутов
|
||||||
x = "x2";
|
x += 2;
|
||||||
y = "y2";
|
y += 2;
|
||||||
} else return;
|
} else return;
|
||||||
|
|
||||||
// Инициализация универсального буфера
|
// Инициализация универсального буфера
|
||||||
|
@ -513,12 +617,17 @@ class graph {
|
||||||
|
|
||||||
// Инициализация функции переноса узла
|
// Инициализация функции переноса узла
|
||||||
function move(onmousemove) {
|
function move(onmousemove) {
|
||||||
|
// Запись обработки столкновений и отталкивания
|
||||||
|
node.actions.collision = node.actions.repulsion = false;
|
||||||
|
|
||||||
// Перемещение
|
// Перемещение
|
||||||
node.move(
|
node.move(
|
||||||
onmousemove.pageX -
|
onmousemove.pageX -
|
||||||
(onmousedown.pageX - n.left + s.left + pageXOffset),
|
(onmousedown.pageX - n.left + s.left + pageXOffset),
|
||||||
onmousemove.pageY -
|
onmousemove.pageY -
|
||||||
(onmousedown.pageY - n.top + s.top + pageYOffset)
|
(onmousedown.pageY - n.top + s.top + pageYOffset),
|
||||||
|
true,
|
||||||
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,6 +641,9 @@ class graph {
|
||||||
document.onmousemove = null;
|
document.onmousemove = null;
|
||||||
node.element.onmouseup = null;
|
node.element.onmouseup = null;
|
||||||
|
|
||||||
|
// Запись обработки столкновений и отталкивания
|
||||||
|
node.actions.collision = node.actions.repulsion = true;
|
||||||
|
|
||||||
// Позиционирование вместе остальными узлами
|
// Позиционирование вместе остальными узлами
|
||||||
node.element.style.zIndex = 500;
|
node.element.style.zIndex = 500;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue