tree.js
18526
src/test_compare.html
Normal file
3197
src/test_snip.js
Normal file
BIN
src/tree/icons/array.png
Normal file
After Width: | Height: | Size: 183 B |
BIN
src/tree/icons/binary.png
Normal file
After Width: | Height: | Size: 203 B |
BIN
src/tree/icons/boolean.png
Normal file
After Width: | Height: | Size: 351 B |
BIN
src/tree/icons/bprocess.png
Normal file
After Width: | Height: | Size: 179 B |
BIN
src/tree/icons/catalog.png
Normal file
After Width: | Height: | Size: 180 B |
BIN
src/tree/icons/close.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
src/tree/icons/close_hover.png
Normal file
After Width: | Height: | Size: 284 B |
BIN
src/tree/icons/date.png
Normal file
After Width: | Height: | Size: 198 B |
BIN
src/tree/icons/document.png
Normal file
After Width: | Height: | Size: 213 B |
BIN
src/tree/icons/empty.png
Normal file
After Width: | Height: | Size: 126 B |
BIN
src/tree/icons/enum.png
Normal file
After Width: | Height: | Size: 189 B |
BIN
src/tree/icons/int.png
Normal file
After Width: | Height: | Size: 272 B |
BIN
src/tree/icons/keyvalue.png
Normal file
After Width: | Height: | Size: 179 B |
BIN
src/tree/icons/null.png
Normal file
After Width: | Height: | Size: 201 B |
BIN
src/tree/icons/open.png
Normal file
After Width: | Height: | Size: 281 B |
BIN
src/tree/icons/open_hover.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
src/tree/icons/picture.png
Normal file
After Width: | Height: | Size: 231 B |
BIN
src/tree/icons/query.png
Normal file
After Width: | Height: | Size: 422 B |
BIN
src/tree/icons/storage.png
Normal file
After Width: | Height: | Size: 180 B |
BIN
src/tree/icons/string.png
Normal file
After Width: | Height: | Size: 248 B |
BIN
src/tree/icons/structure.png
Normal file
After Width: | Height: | Size: 180 B |
BIN
src/tree/icons/table.png
Normal file
After Width: | Height: | Size: 181 B |
BIN
src/tree/icons/tabular.png
Normal file
After Width: | Height: | Size: 201 B |
BIN
src/tree/icons/task.png
Normal file
After Width: | Height: | Size: 180 B |
BIN
src/tree/icons/text.png
Normal file
After Width: | Height: | Size: 434 B |
BIN
src/tree/icons/tree.png
Normal file
After Width: | Height: | Size: 191 B |
BIN
src/tree/icons/undefined.png
Normal file
After Width: | Height: | Size: 269 B |
BIN
src/tree/icons/uuid.png
Normal file
After Width: | Height: | Size: 175 B |
BIN
src/tree/loading.gif
Normal file
After Width: | Height: | Size: 1.8 KiB |
235
src/tree/tree.css
Normal file
@ -0,0 +1,235 @@
|
||||
#display {
|
||||
height: 0;
|
||||
display: none;
|
||||
font-family: "Courier new";
|
||||
}
|
||||
|
||||
#display.dark {
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
#display-header {
|
||||
position: relative;
|
||||
height: 22px;
|
||||
width: 100%;
|
||||
border-top: solid 1px #ddd;
|
||||
border-bottom: solid 1px #ddd;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#display.dark > #display-header {
|
||||
background-color: #1e1e1e;
|
||||
border-color: #000;
|
||||
}
|
||||
|
||||
#display-title {
|
||||
font-size: 12px;
|
||||
color: #161616;
|
||||
margin-left: 10px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#display.dark #display-title {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
#variables-display {
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#variables-display::-webkit-scrollbar {
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
#variables-display::-webkit-scrollbar-thumb {
|
||||
border-radius: 100px;
|
||||
background-color: #aaa;
|
||||
border: 4px solid rgba(0, 0, 0, 0);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
#variables-tree {
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
font-size: 10pt;
|
||||
overflow: auto;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#variables-tree details > summary {
|
||||
list-style: none;
|
||||
padding: 3px;
|
||||
margin: 2px 0;
|
||||
color: #720501;
|
||||
}
|
||||
|
||||
#display.dark #variables-tree details > summary {
|
||||
color: #c3602c;
|
||||
}
|
||||
|
||||
#variables-tree details > summary:hover {
|
||||
background-color: #b8d9ff;
|
||||
transition: all .1s
|
||||
}
|
||||
|
||||
#display.dark #variables-tree details > summary:hover {
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
#variables-tree details > summary::marker, #variables-tree details > summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#variables-tree summary::marker, #variables-tree summary::-webkit-details-marker {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
#variables-tree summary.final:before {
|
||||
background-image: url('./icons/empty.png');
|
||||
}
|
||||
|
||||
#variables-tree summary:before {
|
||||
content: '.';
|
||||
padding-left: 7px;
|
||||
background-image: url('./icons/close.png');
|
||||
background-repeat: no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: transparent;
|
||||
margin: 0 5px 0 5px;
|
||||
}
|
||||
|
||||
#variables-tree summary.final:hover:before {
|
||||
background-image: url('./icons/empty.png');
|
||||
}
|
||||
|
||||
#variables-tree summary:hover:before {
|
||||
background-image: url('./icons/close_hover.png');
|
||||
}
|
||||
|
||||
#variables-tree details > summary.loading:before {
|
||||
background-image: url("./loading.gif") !important;
|
||||
}
|
||||
|
||||
#variables-tree details[open] > summary:before {
|
||||
background-image: url('./icons/open.png');
|
||||
}
|
||||
|
||||
#variables-tree details[open] > summary:hover:before {
|
||||
background-image: url('./icons/open_hover.png');
|
||||
}
|
||||
|
||||
#variables-tree summary .icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#variables-tree summary:only-child::-webkit-details-marker {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
#variables-tree details details {
|
||||
margin-left: 20px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#variables-tree .label {
|
||||
font-size: 14pt;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#variables-tree a {
|
||||
color: #0000ee;
|
||||
text-decoration: none;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
#variables-tree a:hover, #variables-tree a:visited:hover {
|
||||
color: #ad0404;
|
||||
}
|
||||
|
||||
#variables-tree a:visited {
|
||||
color: #0000ee;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#display.dark #variables-tree a {
|
||||
color: #9acd32;
|
||||
}
|
||||
|
||||
#display.dark #variables-tree a:visited {
|
||||
color: #9acd32;
|
||||
}
|
||||
|
||||
#display.dark #variables-tree a:hover, #display.dark #variables-tree a:visited:hover {
|
||||
color: #ff2c2c;
|
||||
}
|
||||
|
||||
#variables-tree .value, .equal {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#variables-tree .value, .equal {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#display.dark #variables-tree .value {
|
||||
color: #b8d9ff;
|
||||
}
|
||||
|
||||
#display.dark #variables-tree .equal {
|
||||
color: #959595;
|
||||
}
|
||||
|
||||
#variables-tree .type {
|
||||
color: #959595;
|
||||
}
|
||||
|
||||
#variables-tree .type:before {
|
||||
content: '{';
|
||||
}
|
||||
|
||||
#variables-tree .type:after {
|
||||
content: '}';
|
||||
}
|
||||
|
||||
#display-close {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 3px;
|
||||
width: 15px;
|
||||
height: 20px;
|
||||
opacity: 0.3;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#display-close:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#display-close:before, #display-close:after {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
height: 12px;
|
||||
width: 2px;
|
||||
top: 2px;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.dark #display-close:before, .dark #display-close:after {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#display-close:before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
#display-close:after {
|
||||
transform: rotate(-45deg);
|
||||
}
|
114
src/tree/tree.html
Normal file
@ -0,0 +1,114 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Treeview</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||
<link href="./tree.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Variables tree</h1>
|
||||
<section>
|
||||
<div id="variables-tree"></div>
|
||||
</section>
|
||||
<script src="./tree.js"></script>
|
||||
<script type="text/javascript">
|
||||
let treeview = new Treeview("#variables-tree", null, "./icons/");
|
||||
let cat = {
|
||||
ПриходнаяНакладная: {
|
||||
label: "ПриходнаяНакладная",
|
||||
value: '<a href="#1">Приходная накладная 000-2398 от 22.08.2022 21:32:59</a>',
|
||||
type: "ДокументСсылка.ПриходнаяНакладаная",
|
||||
children: {
|
||||
"Номер": { label: "Код", value: "000-2398", type: "Число", icon: "int.png" },
|
||||
"Дата": { label: "Дата", value: "22.08.2022 21:32:59", type: "Дата", icon: "date.png" },
|
||||
"Организация": {
|
||||
label: "Организация",
|
||||
value: "Рога и копыта",
|
||||
type: "СправочникСсылка.Организации",
|
||||
children: {
|
||||
"Код": { label: "Код", value: "0000001", type: "Число", icon: "int.png" },
|
||||
"ИНН": { label: "ИНН", value: "771111111", type: "Строка", icon: "string.png" },
|
||||
"КПП": { label: "КПП", value: "770000001", type: "Строка", icon: "string.png" }
|
||||
}
|
||||
},
|
||||
"Контрагент": {
|
||||
label: "Контрагент",
|
||||
value: '<a href="#1">Иванов И.И."</a>',
|
||||
type: "СправочникСсылка.Контрагенты",
|
||||
children: {
|
||||
"Код": { label: "Код", value: "0000052", type: "Число" },
|
||||
"ИНН": { label: "ИНН", value: "781111111", type: "Строка" },
|
||||
"КПП": { label: "КПП", value: "780000001", type: "Строка" }
|
||||
}
|
||||
},
|
||||
"Товары": {
|
||||
label: "Товары",
|
||||
type: "ТабличнаяЧасть",
|
||||
children: {
|
||||
"Строка 0": {
|
||||
label: "Строка 0",
|
||||
type: "СтрокаТабличнойЧасти",
|
||||
children: {
|
||||
"НомерСтроки": { label: "НомерСтроки", value: "1", type: "Число" },
|
||||
"Товар": { label: "Товар", value: "Товар №1", type: "СправочникСсылка.Товары" },
|
||||
"Количество": { label: "Количество", value: "5", type: "Число" },
|
||||
"Цена": { label: "Цена", value: "100", type: "Число" },
|
||||
"Сумма": { label: "Сумма", value: "500", type: "Число" }
|
||||
}
|
||||
},
|
||||
"Строка 1": {
|
||||
label: "Строка 1",
|
||||
type: "СтрокаТабличнойЧасти",
|
||||
children: {
|
||||
"НомерСтроки": { label: "НомерСтроки", value: "2", type: "Число" },
|
||||
"Товар": { label: "Товар", value: "Товар №2", type: "СправочникСсылка.Товары" },
|
||||
"Количество": { label: "Количество", value: "3", type: "Число" },
|
||||
"Цена": { label: "Цена", value: "50", type: "Число" },
|
||||
"Сумма": { label: "Сумма", value: "150", type: "Число" }
|
||||
}
|
||||
},
|
||||
"Строка 2": {
|
||||
label: "Строка 2",
|
||||
type: "СтрокаТабличнойЧасти",
|
||||
children: {
|
||||
"НомерСтроки": { label: "НомерСтроки", value: "3", type: "Число" },
|
||||
"Товар": { label: "Товар", value: "Товар №3", type: "СправочникСсылка.Товары" },
|
||||
"Количество": { label: "Количество", value: "6", type: "Число" },
|
||||
"Цена": { label: "Цена", value: "90", type: "Число" },
|
||||
"Сумма": { label: "Сумма", value: "540", type: "Число" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
НачалоПериода: {
|
||||
label: "НачалоПериода",
|
||||
value: "01.08.2022 00:00:00",
|
||||
type: "Дата"
|
||||
},
|
||||
КоличествоТоваров: {
|
||||
label: "КоличествоТоваров",
|
||||
value: "14",
|
||||
type: "Число"
|
||||
},
|
||||
ТекущийПартнер: {
|
||||
label: "ТекущийПартнер",
|
||||
value: "",
|
||||
type: ""
|
||||
},
|
||||
Строка: {
|
||||
label: "Строка",
|
||||
value: "Это какое-то предложение",
|
||||
type: "Строка",
|
||||
icon: "string.png"
|
||||
},
|
||||
|
||||
};
|
||||
treeview.replaceData(cat);
|
||||
</script>
|
||||
</body>
|
100
src/tree/tree.js
Normal file
@ -0,0 +1,100 @@
|
||||
class Treeview {
|
||||
constructor(treeviewId, editor, imageBase) {
|
||||
this.treeviewId = treeviewId;
|
||||
this.editor = editor;
|
||||
this.selected = null;
|
||||
this.imageBase = imageBase;
|
||||
document.querySelector(this.treeviewId).addEventListener("click", (event) => {
|
||||
this.on("click", event);
|
||||
});
|
||||
document.querySelector(this.treeviewId)
|
||||
};
|
||||
on(eventName, eventData) {
|
||||
switch (eventName) {
|
||||
case "click": {
|
||||
if (eventData.target.tagName == 'A') {
|
||||
eventData.preventDefault();
|
||||
let element = eventData.target;
|
||||
if (this.editor) {
|
||||
this.editor.sendEvent("EVENT_ON_LINK_CLICK", { label: element.innerText, href: element.getAttribute('href') });
|
||||
}
|
||||
}
|
||||
else if (eventData.target.nodeName == 'SUMMARY' && !eventData.target.parentNode.hasAttribute("open")) {
|
||||
if (eventData.target.dataset.requested == "false" && !eventData.target.classList.contains('final')) {
|
||||
eventData.target.classList.add('loading');
|
||||
eventData.preventDefault();
|
||||
if (this.editor) {
|
||||
let request = {
|
||||
variableName: eventData.target.dataset.label,
|
||||
variableId: eventData.target.id,
|
||||
variablePath: eventData.target.dataset.path
|
||||
};
|
||||
this.editor.sendEvent("EVENT_GET_VARIABLE_DATA", request);
|
||||
}
|
||||
else {
|
||||
setTimeout(() => {
|
||||
eventData.target.dataset.requested = true;
|
||||
this.open(eventData.target.id);
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
appendData(data, targetId) {
|
||||
if (targetId != null) {
|
||||
let target = document.getElementById(targetId);
|
||||
target.parentNode.innerHTML += this.parseData(data)
|
||||
}
|
||||
else {
|
||||
let target = document.querySelector(this.treeviewId);
|
||||
target.innerHTML += this.parseData(data);
|
||||
}
|
||||
};
|
||||
replaceData(data, targetId) {
|
||||
if (targetId != null) {
|
||||
let target = document.getElementById(targetId);
|
||||
target.parentNode.outerHTML = this.parseData(data)
|
||||
target.dataset.requested = true;
|
||||
}
|
||||
else {
|
||||
let target = document.querySelector(this.treeviewId);
|
||||
target.innerHTML = this.parseData(data);
|
||||
}
|
||||
};
|
||||
parseData(data) {
|
||||
let me = this;
|
||||
let buf = Object.keys(data).map((key) =>
|
||||
`<details><summary id="${key}" data-label="${data[key].label}" data-requested="false" data-path="${data[key].path}" class="${data[key].class}">
|
||||
<img class="icon" src="${me.imageBase}${data[key].icon ? data[key].icon : data[key].children ? 'structure.png' : 'undefined.png'}"> </img>
|
||||
${data[key].label}<span class="equal"> = </span>
|
||||
${Object.keys(data[key]).map((subkey) => {
|
||||
return subkey == 'type' || subkey == 'value' ? `<span class="${subkey}">${data[key][subkey]}</span>` : ' '
|
||||
}).join(' ')}
|
||||
</summary>
|
||||
${data[key].children ? me.parseData(data[key].children) : ""}</details>`
|
||||
);
|
||||
return buf.join("\n")
|
||||
};
|
||||
open(id) {
|
||||
let node = document.getElementById(id);
|
||||
while (node.parentNode.nodeName == "DETAILS") {
|
||||
node.classList.remove('loading');
|
||||
node = node.parentNode;
|
||||
node.setAttribute("open", "true");
|
||||
}
|
||||
};
|
||||
close(id) {
|
||||
let node = document.getElementById(id).parentNode;
|
||||
node.removeAttribute("open");
|
||||
let detailNodes = node.querySelectorAll("DETAILS");
|
||||
console.log(detailNodes); detailNodes.forEach((node) => node.removeAttribute("open"));
|
||||
};
|
||||
select(id) {
|
||||
this.open(id);
|
||||
document.getElementById(id).focus();
|
||||
document.getElementById(id).click();
|
||||
}
|
||||
}
|