parent
b8f2d1324c
commit
326101ed36
|
|
@ -157,7 +157,7 @@
|
|||
const parent = node.parent.model.id === -1? 999:node.parent.model.id;
|
||||
nodeDataArray.push({
|
||||
key: node.model.id,
|
||||
text: `${node.model.rank===7?'🔗':''}${node.model.name.slice(0,15)}${node.model.name.length>=15?'...':''}`,
|
||||
text: `${node.model.rank===7?'🔗':''}${node.model.name.slice(0,50)}${node.model.name.length>=50?'...':''}`,
|
||||
lineIndex: node.model.lineIndex,
|
||||
noteLink: node.model.rank===7?node.model.link:'',
|
||||
});
|
||||
|
|
@ -174,9 +174,9 @@
|
|||
var oldnode = adorn.adornedPart;
|
||||
var olddata = oldnode.data;
|
||||
if(olddata.noteLink){
|
||||
window.parent.postMessage({type: "jumpNote", link: olddata.noteLink}, "*");
|
||||
window.parent.postMessage({type: "jumpNote", link: olddata.noteLink, id: olddata.key}, "*");
|
||||
}else{
|
||||
window.parent.postMessage({type: "jumpNode", lineIndex: olddata.lineIndex}, "*");
|
||||
window.parent.postMessage({type: "jumpNode", lineIndex: olddata.lineIndex, id: olddata.key}, "*");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@
|
|||
const parent = node.parent.model.id === -1? 999:node.parent.model.id;
|
||||
data.nodeDataArray.push({
|
||||
key: node.model.id,
|
||||
text: `${node.model.rank===7?'🔗':''}${node.model.name.slice(0,10)}${node.model.name.length>=10?'...':''}`,
|
||||
text: `${node.model.rank===7?'🔗':''}${node.model.name.slice(0,50)}${node.model.name.length>=50?'...':''}`,
|
||||
parent: parent,
|
||||
lineIndex: node.model.lineIndex,
|
||||
noteLink: node.model.rank===7?node.model.link:'',
|
||||
|
|
@ -264,9 +264,9 @@
|
|||
var oldnode = adorn.adornedPart;
|
||||
var olddata = oldnode.data;
|
||||
if(olddata.noteLink){
|
||||
window.parent.postMessage({type: "jumpNote", link: olddata.noteLink}, "*");
|
||||
window.parent.postMessage({type: "jumpNote", link: olddata.noteLink, id: olddata.key}, "*");
|
||||
}else{
|
||||
window.parent.postMessage({type: "jumpNode", lineIndex: olddata.lineIndex}, "*");
|
||||
window.parent.postMessage({type: "jumpNode", lineIndex: olddata.lineIndex, id: olddata.key}, "*");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,327 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<body>
|
||||
<script src="chrome://__addonRef__/content/lib/js/jquery.min.js"></script>
|
||||
<script src="chrome://__addonRef__/content/lib/js/dx.all.js"></script>
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
div {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.form {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.form > div {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#treeview {
|
||||
padding: 20px 0 0 20px;
|
||||
}
|
||||
|
||||
.drive-header {
|
||||
min-height: auto;
|
||||
padding: 0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.drive-panel {
|
||||
font-size: 115%;
|
||||
font-weight: bold;
|
||||
border-right: 1px solid rgba(165, 165, 165, 0.4);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.drive-panel:last-of-type {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
ul,
|
||||
li {
|
||||
display: list-item;
|
||||
}
|
||||
</style>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="chrome://__addonRef__/content/lib/css/dx.light.css"
|
||||
/>
|
||||
<div
|
||||
class="dx-viewport"
|
||||
id="outline-container"
|
||||
style="background-color: inherit; overflow: hidden"
|
||||
>
|
||||
<script id="code">
|
||||
function init() {
|
||||
window.addEventListener("message", handler, false);
|
||||
window.parent.postMessage({ type: "ready" }, "*");
|
||||
getData();
|
||||
}
|
||||
|
||||
function createTreeView(selector, items) {
|
||||
$(selector).dxTreeView({
|
||||
items,
|
||||
expandNodesRecursive: false,
|
||||
dataStructure: "plain",
|
||||
height: $("window").height() - 100,
|
||||
displayExpr: "name",
|
||||
noDataText: "Create a heading with '+'",
|
||||
onItemClick: (e) => {
|
||||
window.parent.postMessage(
|
||||
{ type: "jumpNode", lineIndex: e.itemData.lineIndex },
|
||||
"*"
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function createSortable(selector, driveName) {
|
||||
$(selector).dxSortable({
|
||||
filter: ".dx-treeview-item",
|
||||
group: "shared",
|
||||
data: driveName,
|
||||
allowDropInsideItem: true,
|
||||
allowReordering: true,
|
||||
onDragChange: (e) => {
|
||||
if (e.fromComponent === e.toComponent) {
|
||||
const $nodes = e.element.find(".dx-treeview-node");
|
||||
const isDragIntoChild =
|
||||
$nodes.eq(e.fromIndex).find($nodes.eq(e.toIndex)).length > 0;
|
||||
if (isDragIntoChild) {
|
||||
e.cancel = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
onDragEnd: (e) => {
|
||||
if (
|
||||
e.fromComponent === e.toComponent &&
|
||||
e.fromIndex === e.toIndex
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fromTreeView = getTreeView();
|
||||
const toTreeView = getTreeView();
|
||||
|
||||
const fromNode = findNode(fromTreeView, e.fromIndex);
|
||||
const toNode = findNode(toTreeView, calculateToIndex(e));
|
||||
|
||||
if (
|
||||
e.dropInsideItem &&
|
||||
toNode !== null &&
|
||||
// !toNode.itemData.isDirectory &&
|
||||
toNode.itemData.rank === 7
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fromTopVisibleNode = getTopVisibleNode(fromTreeView);
|
||||
const toTopVisibleNode = getTopVisibleNode(toTreeView);
|
||||
|
||||
const fromItems = fromTreeView.option("items");
|
||||
const toItems = toTreeView.option("items");
|
||||
moveNode(fromNode, toNode, fromItems, toItems, e.dropInsideItem);
|
||||
|
||||
fromTreeView.option("items", fromItems);
|
||||
toTreeView.option("items", toItems);
|
||||
fromTreeView.scrollToItem(fromTopVisibleNode);
|
||||
toTreeView.scrollToItem(toTopVisibleNode);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function getTreeView() {
|
||||
return $("#treeview").dxTreeView("instance");
|
||||
}
|
||||
|
||||
function calculateToIndex(e) {
|
||||
if (e.fromComponent !== e.toComponent || e.dropInsideItem) {
|
||||
return e.toIndex;
|
||||
}
|
||||
|
||||
return e.fromIndex >= e.toIndex ? e.toIndex : e.toIndex + 1;
|
||||
}
|
||||
|
||||
function findNode(treeView, index) {
|
||||
const nodeElement = treeView.element().find(".dx-treeview-node")[
|
||||
index
|
||||
];
|
||||
if (nodeElement) {
|
||||
return findNodeById(
|
||||
treeView.getNodes(),
|
||||
nodeElement.getAttribute("data-item-id")
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findNodeById(nodes, id) {
|
||||
for (let i = 0; i < nodes.length; i += 1) {
|
||||
if (nodes[i].itemData.id === id) {
|
||||
return nodes[i];
|
||||
}
|
||||
if (nodes[i].children) {
|
||||
const node = findNodeById(nodes[i].children, id);
|
||||
if (node != null) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function moveNode(
|
||||
fromNode,
|
||||
toNode,
|
||||
fromItems,
|
||||
toItems,
|
||||
isDropInsideItem
|
||||
) {
|
||||
const fromIndex = findIndex(fromItems, fromNode.itemData.id);
|
||||
fromItems.splice(fromIndex, 1);
|
||||
|
||||
const toIndex =
|
||||
toNode === null || isDropInsideItem
|
||||
? toItems.length
|
||||
: findIndex(toItems, toNode.itemData.id);
|
||||
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: "moveNode",
|
||||
fromID: parseInt(fromNode.itemData.id),
|
||||
toID: toNode
|
||||
? parseInt(toNode.itemData.id)
|
||||
: toItems[toItems.length - 1].itemData.id,
|
||||
type: toNode ? "before" : "after",
|
||||
},
|
||||
"*"
|
||||
);
|
||||
|
||||
toItems.splice(toIndex, 0, fromNode.itemData);
|
||||
|
||||
moveChildren(fromNode, fromItems, toItems);
|
||||
if (isDropInsideItem) {
|
||||
fromNode.itemData.parentId = toNode.itemData.id;
|
||||
} else {
|
||||
fromNode.itemData.parentId =
|
||||
toNode != null ? toNode.itemData.parentId : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function moveChildren(node, fromItems, toItems) {
|
||||
if (!node.itemData.isDirectory) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.children.forEach((child) => {
|
||||
if (child.itemData.isDirectory) {
|
||||
moveChildren(child, fromItems, toItems);
|
||||
}
|
||||
|
||||
const fromIndex = findIndex(fromItems, child.itemData.id);
|
||||
fromItems.splice(fromIndex, 1);
|
||||
toItems.splice(toItems.length, 0, child.itemData);
|
||||
});
|
||||
}
|
||||
|
||||
function findIndex(array, id) {
|
||||
const idsArray = array.map((elem) => elem.id);
|
||||
return idsArray.indexOf(id);
|
||||
}
|
||||
|
||||
function getTopVisibleNode(component) {
|
||||
const treeViewElement = component.element().get(0);
|
||||
const treeViewTopPosition =
|
||||
treeViewElement.getBoundingClientRect().top;
|
||||
const nodes = treeViewElement.querySelectorAll(".dx-treeview-node");
|
||||
for (let i = 0; i < nodes.length; i += 1) {
|
||||
const nodeTopPosition = nodes[i].getBoundingClientRect().top;
|
||||
if (nodeTopPosition >= treeViewTopPosition) {
|
||||
return nodes[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const noteIcon = `<svg t="1652008007954" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10521" width="18" height="18"><path d="M574.3 896H159.7c-17.6 0-31.9-14.3-31.9-32V160c0-17.7 14.3-32 31.9-32h382.7v160c0 35.3 28.6 64 63.8 64h159.5v192c0 17.7 14.3 32 31.9 32 17.6 0 31.9-14.3 31.9-32V270.2c0-8.5-3.3-16.6-9.3-22.6L647.4 73.4c-6-6-14.1-9.4-22.6-9.4h-497C92.6 64 64 92.7 64 128v768c0 35.3 28.6 64 63.8 64h446.5c17.6 0 31.9-14.3 31.9-32s-14.3-32-31.9-32zM638.1 288c-17.6 0-31.9-14.3-31.9-32V128l159.5 160H638.1z" p-id="10522"></path><path d="M418.8 673H225.5c-17.6 0-31.9 14.3-31.9 32s14.3 32 31.9 32h193.3c17.6 0 31.9-14.3 31.9-32s-14.3-32-31.9-32zM608.2 481H225.5c-17.6 0-31.9 14.3-31.9 32s14.3 32 31.9 32h382.7c17.6 0 31.9-14.3 31.9-32s-14.3-32-31.9-32zM225.5 353h191.4c17.6 0 31.9-14.3 31.9-32s-14.3-32-31.9-32H225.5c-17.6 0-31.9 14.3-31.9 32s14.3 32 31.9 32zM862.7 959.4c-23.6 0-47-8.8-64.8-26.6l-24.4-24.4c-12.5-12.5-12.5-32.8 0-45.3s32.7-12.5 45.1 0l24.4 24.4c11.3 11.4 30.7 10.4 43.2-2.1 12.5-12.5 13.4-31.9 2.1-43.3L749.2 702.6c-11.3-11.4-30.7-10.4-43.2 2.1-6.2 6.3-9.8 14.4-10 22.8-0.2 7.9 2.6 15.1 7.9 20.4 12.5 12.5 12.5 32.8 0 45.3s-32.7 12.5-45.1 0c-36.2-36.3-35.2-96.3 2.1-133.8 37.4-37.5 97.2-38.4 133.4-2.1l139.1 139.5c36.2 36.3 35.2 96.3-2.1 133.8-19 19.2-43.9 28.8-68.6 28.8z" p-id="10523"></path><path d="M696.3 883.1c-23.6 0-47-8.8-64.8-26.6l-139-139.6c-17.7-17.8-27.2-41.7-26.6-67.2 0.6-25 10.8-48.6 28.7-66.6 17.9-17.9 41.5-28.2 66.4-28.8 25.5-0.6 49.3 8.9 67 26.6l24.4 24.4c12.5 12.5 12.5 32.8 0 45.3s-32.7 12.5-45.1 0l-24.4-24.4c-5.3-5.3-12.5-8.1-20.4-7.9-8.4 0.2-16.5 3.8-22.8 10-6.2 6.3-9.8 14.4-10 22.8-0.2 7.9 2.6 15.1 7.9 20.4L676.7 811c11.3 11.4 30.7 10.4 43.2-2.1 12.5-12.5 13.4-31.9 2.1-43.3-12.5-12.5-12.5-32.8 0-45.3s32.7-12.5 45.1 0c36.2 36.3 35.3 96.3-2.1 133.8-19.1 19.3-44 29-68.7 29z" p-id="10524"></path></svg>`;
|
||||
|
||||
function getData() {
|
||||
window.parent.postMessage({ type: "getMindMapData" }, "*");
|
||||
}
|
||||
|
||||
function setData(nodes) {
|
||||
console.log(nodes);
|
||||
const treeData = [];
|
||||
nodes.map((node) => {
|
||||
treeData.push({
|
||||
id: String(node.model.id),
|
||||
name: node.model.name,
|
||||
rank: node.model.rank,
|
||||
icon: node.model.rank === 7 ? noteIcon : undefined,
|
||||
lineIndex: node.model.lineIndex,
|
||||
endIndex: node.model.endIndex,
|
||||
isDirectory: node.children.length > 0,
|
||||
expanded: true,
|
||||
parentId:
|
||||
node.model.rank > 1 ? String(node.parent.model.id) : undefined,
|
||||
});
|
||||
});
|
||||
$(() => {
|
||||
createTreeView("#treeview", treeData);
|
||||
createSortable("#treeview", "treeData");
|
||||
});
|
||||
}
|
||||
|
||||
function jumpNode(e, obj) {
|
||||
var adorn = obj.part;
|
||||
var oldnode = adorn.adornedPart;
|
||||
var olddata = oldnode.data;
|
||||
if (olddata.noteLink) {
|
||||
window.parent.postMessage(
|
||||
{ type: "jumpNote", link: olddata.noteLink },
|
||||
"*"
|
||||
);
|
||||
} else {
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: "jumpNode",
|
||||
lineIndex: olddata.lineIndex,
|
||||
id: parseInt(olddata.id),
|
||||
},
|
||||
"*"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function handler(e) {
|
||||
console.log(e);
|
||||
if (e.data.type === "setMindMapData") {
|
||||
setData(e.data.nodes);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
try {
|
||||
init();
|
||||
} catch (e) {
|
||||
window.parent.postMessage({ type: "error", event: e }, "*");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<div class="demo-container">
|
||||
<div class="form">
|
||||
<div class="drive-panel">
|
||||
<div id="treeview"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
<script src="chrome://__addonRef__/content/lib/js/go.js"></script>
|
||||
<script type="application/javascript">
|
||||
Zotero.Knowledge4Zotero.views.$ = $;
|
||||
Zotero.Knowledge4Zotero.views.go = go;
|
||||
</script>
|
||||
|
||||
<keyset>
|
||||
|
|
@ -32,15 +31,6 @@
|
|||
|
||||
<hbox flex="1">
|
||||
<vbox id="zotero-knowledge-outline" flex="1" width="330" minwidth="300" style="overflow: hidden;">
|
||||
<html:div class="dx-viewport" id="outline-container">
|
||||
<div class="demo-container">
|
||||
<div class="form">
|
||||
<div class="drive-panel">
|
||||
<div id="treeview"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</html:div>
|
||||
<html:div id="mindmap-container">
|
||||
<!-- Inser Here -->
|
||||
</html:div>
|
||||
|
|
|
|||
|
|
@ -1,39 +1,3 @@
|
|||
.form {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.form > div {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#treeview {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.drive-header {
|
||||
min-height: auto;
|
||||
padding: 0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.drive-panel {
|
||||
padding: 20px 0px 20px 10px;
|
||||
font-size: 115%;
|
||||
font-weight: bold;
|
||||
border-right: 1px solid rgba(165, 165, 165, 0.4);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.drive-panel:last-of-type {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
ul,
|
||||
li {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
|
@ -81,4 +45,4 @@ li {
|
|||
.tool-button:active {
|
||||
background: #b3b3b3;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,15 +69,19 @@ class AddonEvents extends AddonBase {
|
|||
}
|
||||
|
||||
public addEditorInstanceListener() {
|
||||
Zotero.Notes._registerEditorInstance = Zotero.Notes.registerEditorInstance;
|
||||
Zotero.Notes.registerEditorInstance = (instance: EditorInstance) => {
|
||||
Zotero.Notes._registerEditorInstance(instance);
|
||||
this.onEditorEvent(
|
||||
new EditorMessage("addNoteInstance", {
|
||||
editorInstance: instance,
|
||||
})
|
||||
);
|
||||
};
|
||||
if (!Zotero.Notes._knowledgeInit) {
|
||||
Zotero.Notes._knowledgeInit = true;
|
||||
Zotero.Notes._registerEditorInstance =
|
||||
Zotero.Notes.registerEditorInstance;
|
||||
Zotero.Notes.registerEditorInstance = (instance: EditorInstance) => {
|
||||
Zotero.Notes._registerEditorInstance(instance);
|
||||
this.onEditorEvent(
|
||||
new EditorMessage("addNoteInstance", {
|
||||
editorInstance: instance,
|
||||
})
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public async addEditorEventListener(
|
||||
|
|
@ -388,7 +392,6 @@ class AddonEvents extends AddonBase {
|
|||
type
|
||||
}
|
||||
*/
|
||||
// if(message.content.)
|
||||
Zotero.debug("Knowledge4Zotero: addToKnowledgeLine");
|
||||
Zotero.debug(message.content.event.target.id);
|
||||
const idSplit = message.content.event.target.id.split("-");
|
||||
|
|
@ -398,24 +401,22 @@ class AddonEvents extends AddonBase {
|
|||
lineIndex,
|
||||
message.content.editorInstance._item.id
|
||||
);
|
||||
} else if (message.type === "clickOutlineHeading") {
|
||||
} else if (message.type === "jumpNode") {
|
||||
/*
|
||||
message.content = {
|
||||
event: {itemData}
|
||||
params: {id, lineIndex}
|
||||
}
|
||||
*/
|
||||
let editorInstance =
|
||||
await this._Addon.knowledge.getWorkspaceEditorInstance();
|
||||
// Set node id
|
||||
this._Addon.knowledge.currentNodeID = parseInt(
|
||||
(message.content.event as any).itemData.id
|
||||
);
|
||||
this._Addon.knowledge.currentNodeID = parseInt(message.content.params.id);
|
||||
this._Addon.views.scrollToLine(
|
||||
editorInstance,
|
||||
// Scroll to 6 lines before the inserted line
|
||||
(message.content.event as any).itemData.lineIndex - 5
|
||||
// Scroll to 1 lines before the inserted line
|
||||
message.content.params.lineIndex - 1
|
||||
);
|
||||
} else if (message.type === "moveOutlineHeading") {
|
||||
} else if (message.type === "moveNode") {
|
||||
/*
|
||||
message.content = {
|
||||
params: {
|
||||
|
|
|
|||
155
src/knowledge.ts
155
src/knowledge.ts
|
|
@ -37,16 +37,11 @@ class Knowledge extends AddonBase {
|
|||
);
|
||||
this.workspaceWindow = win;
|
||||
await this.waitWorkspaceReady();
|
||||
win.addEventListener("resize", (e) => {
|
||||
this._Addon.views.setTreeViewSize();
|
||||
});
|
||||
this._Addon.views.bindTreeViewResize();
|
||||
this.setWorkspaceNote("main");
|
||||
this.currentLine = -1;
|
||||
this._Addon.views.initKnowledgeWindow(win);
|
||||
this._Addon.views.switchView(OutlineType.treeView);
|
||||
this._Addon.views.buildOutline();
|
||||
// this._Addon.views.buildMindMap();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,47 +131,69 @@ class Knowledge extends AddonBase {
|
|||
noteText.length - "</div>".length
|
||||
);
|
||||
}
|
||||
let noteLines: string[] = noteText.split("\n");
|
||||
let noteLines = noteText.split("\n").filter((e) => e);
|
||||
|
||||
const cacheStart = [/<ol>/g, /<ul>/g, /<li>/g, /<blockquote>/g, /<pre>/g];
|
||||
const cacheEnd = [
|
||||
/<\/ol>/g,
|
||||
/<\/ul>/g,
|
||||
/<\/li>/g,
|
||||
/<\/blockquote>/g,
|
||||
/<\/pre>/g,
|
||||
];
|
||||
let parsedLines: string[] = [];
|
||||
let appendLater: boolean = false;
|
||||
let cacheStartLine = false;
|
||||
let cachedLines: string = "";
|
||||
let tagStack = [];
|
||||
let toPush = [];
|
||||
let toRemove = 0;
|
||||
|
||||
let nextAppend = false;
|
||||
|
||||
const forceInline = ["table", "blockquote", "pre", "li"];
|
||||
const selfInline = ["ol", "ul"];
|
||||
|
||||
const parsedLines = [];
|
||||
for (let line of noteLines) {
|
||||
cacheStartLine = false;
|
||||
if (
|
||||
cachedLines ||
|
||||
cacheStart.filter((e) => {
|
||||
return line.search(e) !== -1;
|
||||
}).length > 0
|
||||
) {
|
||||
appendLater = true;
|
||||
cachedLines += `${cachedLines.length > 0 ? "\n" : ""}${line}`;
|
||||
cacheStartLine = true;
|
||||
}
|
||||
if (
|
||||
cacheEnd.filter((e) => {
|
||||
return line.search(e) !== -1;
|
||||
}).length > 0
|
||||
) {
|
||||
appendLater = false;
|
||||
// If already added to cache
|
||||
if (!cacheStartLine) {
|
||||
cachedLines += `\n${line}`;
|
||||
for (const tag of forceInline) {
|
||||
const startReg = `<${tag}>`;
|
||||
const endReg = `</${tag}>`;
|
||||
const startIdx = line.search(startReg);
|
||||
const endIdx = line.search(endReg);
|
||||
if (startIdx !== -1 && endIdx === -1) {
|
||||
toPush.push(tag);
|
||||
} else if (endIdx !== -1) {
|
||||
toRemove += 1;
|
||||
}
|
||||
line = cachedLines;
|
||||
cachedLines = "";
|
||||
}
|
||||
if (!appendLater) {
|
||||
|
||||
if (tagStack.filter((e) => forceInline.indexOf(e) !== -1).length === 0) {
|
||||
let nextLoop = false;
|
||||
for (const tag of selfInline) {
|
||||
const startReg = new RegExp(`<${tag}>`);
|
||||
const endReg = new RegExp(`</${tag}>`);
|
||||
const startIdx = line.search(startReg);
|
||||
const endIdx = line.search(endReg);
|
||||
if (startIdx !== -1 && endIdx === -1) {
|
||||
nextAppend = true;
|
||||
nextLoop = true;
|
||||
parsedLines.push(line);
|
||||
break;
|
||||
}
|
||||
if (endIdx !== -1) {
|
||||
parsedLines[parsedLines.length - 1] += `\n${line}`;
|
||||
nextLoop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nextLoop) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (tagStack.length === 0 && !nextAppend) {
|
||||
parsedLines.push(line);
|
||||
} else {
|
||||
parsedLines[parsedLines.length - 1] += `\n${line}`;
|
||||
nextAppend = false;
|
||||
}
|
||||
|
||||
if (toPush.length > 0) {
|
||||
tagStack = tagStack.concat(toPush);
|
||||
toPush = [];
|
||||
}
|
||||
while (toRemove > 0) {
|
||||
tagStack.pop();
|
||||
toRemove -= 1;
|
||||
}
|
||||
}
|
||||
return parsedLines;
|
||||
|
|
@ -255,11 +272,20 @@ class Knowledge extends AddonBase {
|
|||
return;
|
||||
}
|
||||
let noteLines = this.getLinesInNote(note);
|
||||
if (newLine) {
|
||||
noteLines.splice(lineIndex, 0, "<p> </p>", text);
|
||||
} else {
|
||||
noteLines.splice(lineIndex, 0, text);
|
||||
Zotero.debug(
|
||||
`insert to ${lineIndex}, it used to be ${noteLines[lineIndex]}`
|
||||
);
|
||||
// Force links not to appear in one line
|
||||
if (lineIndex > 0 && noteLines[lineIndex - 1].search(/<a href/g) !== -1) {
|
||||
text = `<p> </p>\n${text}`;
|
||||
}
|
||||
if (
|
||||
lineIndex < noteLines.length &&
|
||||
noteLines[lineIndex].search(/<a href/g)
|
||||
) {
|
||||
text = `${text}\n<p> </p>`;
|
||||
}
|
||||
noteLines.splice(lineIndex, 0, text);
|
||||
this.setLinesToNote(note, noteLines);
|
||||
}
|
||||
|
||||
|
|
@ -272,8 +298,8 @@ class Knowledge extends AddonBase {
|
|||
if (lineIndex < 0) {
|
||||
lineIndex =
|
||||
this.currentLine >= 0
|
||||
? this.currentLine + 2
|
||||
: this.getLinesInNote(note).length + 1;
|
||||
? this.currentLine
|
||||
: this.getLinesInNote(note).length;
|
||||
}
|
||||
// let parentNode = this.getLineParentInNote(note, lineIndex);
|
||||
// if (!parentNode) {
|
||||
|
|
@ -466,8 +492,7 @@ class Knowledge extends AddonBase {
|
|||
endIndex: -1,
|
||||
});
|
||||
let id = 0;
|
||||
let currentNode = root;
|
||||
let lastNode = undefined;
|
||||
let lastNode = root;
|
||||
let headerStartReg = new RegExp("<h[1-6]>");
|
||||
let headerStopReg = new RegExp("</h[1-6]>");
|
||||
for (let i in noteLines) {
|
||||
|
|
@ -488,23 +513,35 @@ class Knowledge extends AddonBase {
|
|||
link = link.slice(0, link.search(/"/g));
|
||||
}
|
||||
name = this.parseLineText(lineElement);
|
||||
while (currentNode.model.rank >= currentRank) {
|
||||
currentNode = currentNode.parent;
|
||||
|
||||
// Find parent node
|
||||
let parentNode = lastNode;
|
||||
while (parentNode.model.rank >= currentRank) {
|
||||
parentNode = parentNode.parent;
|
||||
}
|
||||
if (lastNode) {
|
||||
lastNode.model.endIndex = i;
|
||||
}
|
||||
lastNode = tree.parse({
|
||||
|
||||
const currentNode = tree.parse({
|
||||
id: id++,
|
||||
rank: currentRank,
|
||||
// @ts-ignore
|
||||
name: name,
|
||||
lineIndex: i,
|
||||
lineIndex: parseInt(i),
|
||||
endIndex: noteLines.length,
|
||||
link: link,
|
||||
});
|
||||
currentNode.addChild(lastNode);
|
||||
currentNode = lastNode;
|
||||
parentNode.addChild(currentNode);
|
||||
const currentIndex = parentNode.children.indexOf(currentNode);
|
||||
if (currentIndex > 0) {
|
||||
const previousNode = parentNode.children[currentIndex - 1];
|
||||
// Traverse the previous node tree and set the end index
|
||||
previousNode.walk((node) => {
|
||||
if (node.model.endIndex > parseInt(i)) {
|
||||
node.model.endIndex = parseInt(i);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
previousNode.model.endIndex = parseInt(i);
|
||||
}
|
||||
lastNode = currentNode;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
|
|
|
|||
294
src/views.ts
294
src/views.ts
|
|
@ -3,7 +3,6 @@ import { AddonBase, EditorMessage, OutlineType } from "./base";
|
|||
class AddonViews extends AddonBase {
|
||||
progressWindowIcon: object;
|
||||
editorIcon: object;
|
||||
$: any;
|
||||
currentOutline: OutlineType;
|
||||
_initIframe: any;
|
||||
|
||||
|
|
@ -23,7 +22,6 @@ class AddonViews extends AddonBase {
|
|||
export: `<svg t="1651322116327" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11894" width="24" height="24"><path d="M849.2 599v217H178.5V599c-0.7-23.7-20.1-42.7-44-42.7s-43.3 19-44 42.7v252.5c0 28.9 23.6 52.5 52.5 52.5h741.7c28.9 0 52.5-23.6 52.5-52.5V599c-0.7-23.7-20.1-42.7-44-42.7s-43.3 19-44 42.7z" p-id="11895"></path><path d="M482.7 135.4l-164 164c-17.1 17.1-17.1 45.1 0 62.2s45.1 17.1 62.2 0l85.7-85.7v314.8c0 26 21.3 47.2 47.2 47.2 26 0 47.2-21.3 47.2-47.2V276l85.7 85.7c17.1 17.1 45.1 17.1 62.2 0s17.1-45.1 0-62.2l-164-164c-17.1-17.2-45.1-17.2-62.2-0.1z" p-id="11896"></path></svg>`,
|
||||
close: `<svg t="1651331457107" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12754" width="24" height="24"><path d="M557.311759 513.248864l265.280473-263.904314c12.54369-12.480043 12.607338-32.704421 0.127295-45.248112-12.512727-12.576374-32.704421-12.607338-45.248112-0.127295L512.127295 467.904421 249.088241 204.063755c-12.447359-12.480043-32.704421-12.54369-45.248112-0.063647-12.512727 12.480043-12.54369 32.735385-0.063647 45.280796l262.975407 263.775299-265.151458 263.744335c-12.54369 12.480043-12.607338 32.704421-0.127295 45.248112 6.239161 6.271845 14.463432 9.440452 22.687703 9.440452 8.160624 0 16.319527-3.103239 22.560409-9.311437l265.216826-263.807983 265.440452 266.240344c6.239161 6.271845 14.432469 9.407768 22.65674 9.407768 8.191587 0 16.352211-3.135923 22.591372-9.34412 12.512727-12.480043 12.54369-32.704421 0.063647-45.248112L557.311759 513.248864z" p-id="12755"></path></svg>`,
|
||||
openWorkspaceCollectionView: `<svg t="1651317033804" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2432" width="100%" height="100%"><path d="M874.9 459.4c-18.8 0-34 15.2-34 34v355.7c0 18.6-15.5 33.7-34.5 33.7H181.5c-19 0-34.5-15.1-34.5-33.7V232.3c0-18.6 15.5-33.7 34.5-33.7H541c18.8 0 34-15.2 34-34s-15.2-34-34-34H181.5C125 130.6 79 176.2 79 232.3v616.8c0 56 46 101.7 102.5 101.7h624.9c56.5 0 102.5-45.6 102.5-101.7V493.4c0-18.8-15.2-34-34-34z" fill="#b6b6b6" p-id="2433"></path><path d="M885.5 82.7H657.1c-18.8 0-34 15.2-34 34s15.2 34 34 34h169.7L358.5 619.1c-13.3 13.3-13.3 34.8 0 48.1 6.6 6.6 15.3 10 24 10s17.4-3.3 24-10l470-470v169.7c0 18.8 15.2 34 34 34s34-15.2 34-34V141.5c0.1-32.4-26.4-58.8-59-58.8z" fill="#b6b6b6" p-id="2434"></path></svg>`,
|
||||
note: `<svg t="1652008007954" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10521" width="18" height="18"><path d="M574.3 896H159.7c-17.6 0-31.9-14.3-31.9-32V160c0-17.7 14.3-32 31.9-32h382.7v160c0 35.3 28.6 64 63.8 64h159.5v192c0 17.7 14.3 32 31.9 32 17.6 0 31.9-14.3 31.9-32V270.2c0-8.5-3.3-16.6-9.3-22.6L647.4 73.4c-6-6-14.1-9.4-22.6-9.4h-497C92.6 64 64 92.7 64 128v768c0 35.3 28.6 64 63.8 64h446.5c17.6 0 31.9-14.3 31.9-32s-14.3-32-31.9-32zM638.1 288c-17.6 0-31.9-14.3-31.9-32V128l159.5 160H638.1z" p-id="10522"></path><path d="M418.8 673H225.5c-17.6 0-31.9 14.3-31.9 32s14.3 32 31.9 32h193.3c17.6 0 31.9-14.3 31.9-32s-14.3-32-31.9-32zM608.2 481H225.5c-17.6 0-31.9 14.3-31.9 32s14.3 32 31.9 32h382.7c17.6 0 31.9-14.3 31.9-32s-14.3-32-31.9-32zM225.5 353h191.4c17.6 0 31.9-14.3 31.9-32s-14.3-32-31.9-32H225.5c-17.6 0-31.9 14.3-31.9 32s14.3 32 31.9 32zM862.7 959.4c-23.6 0-47-8.8-64.8-26.6l-24.4-24.4c-12.5-12.5-12.5-32.8 0-45.3s32.7-12.5 45.1 0l24.4 24.4c11.3 11.4 30.7 10.4 43.2-2.1 12.5-12.5 13.4-31.9 2.1-43.3L749.2 702.6c-11.3-11.4-30.7-10.4-43.2 2.1-6.2 6.3-9.8 14.4-10 22.8-0.2 7.9 2.6 15.1 7.9 20.4 12.5 12.5 12.5 32.8 0 45.3s-32.7 12.5-45.1 0c-36.2-36.3-35.2-96.3 2.1-133.8 37.4-37.5 97.2-38.4 133.4-2.1l139.1 139.5c36.2 36.3 35.2 96.3-2.1 133.8-19 19.2-43.9 28.8-68.6 28.8z" p-id="10523"></path><path d="M696.3 883.1c-23.6 0-47-8.8-64.8-26.6l-139-139.6c-17.7-17.8-27.2-41.7-26.6-67.2 0.6-25 10.8-48.6 28.7-66.6 17.9-17.9 41.5-28.2 66.4-28.8 25.5-0.6 49.3 8.9 67 26.6l24.4 24.4c12.5 12.5 12.5 32.8 0 45.3s-32.7 12.5-45.1 0l-24.4-24.4c-5.3-5.3-12.5-8.1-20.4-7.9-8.4 0.2-16.5 3.8-22.8 10-6.2 6.3-9.8 14.4-10 22.8-0.2 7.9 2.6 15.1 7.9 20.4L676.7 811c11.3 11.4 30.7 10.4 43.2-2.1 12.5-12.5 13.4-31.9 2.1-43.3-12.5-12.5-12.5-32.8 0-45.3s32.7-12.5 45.1 0c36.2 36.3 35.3 96.3-2.1 133.8-19.1 19.3-44 29-68.7 29z" p-id="10524"></path></svg>`,
|
||||
};
|
||||
this.currentOutline = OutlineType.treeView;
|
||||
this._initIframe = Zotero.Promise.defer();
|
||||
|
|
@ -490,18 +488,22 @@ class AddonViews extends AddonBase {
|
|||
new EditorMessage("openUserGuide", {})
|
||||
);
|
||||
});
|
||||
_window.addEventListener("resize", (e) => this.resizeOutline(_window));
|
||||
}
|
||||
|
||||
async messageHandler(e) {
|
||||
const _window = this._Addon.knowledge.getWorkspaceWindow();
|
||||
Zotero.debug(`Knowledge4Zotero: view message ${e.data.type}`);
|
||||
console.log(`Knowledge4Zotero: view message ${e.data.type}`);
|
||||
if (e.data.type === "ready") {
|
||||
this._initIframe.resolve();
|
||||
} else if (e.data.type === "getMindMapData") {
|
||||
this.updateMindMap();
|
||||
} else if (e.data.type === "jumpNode") {
|
||||
this.scrollToLine(
|
||||
await this._Addon.knowledge.getWorkspaceEditorInstance(),
|
||||
e.data.lineIndex
|
||||
this._Addon.events.onEditorEvent(
|
||||
new EditorMessage("jumpNode", {
|
||||
params: e.data,
|
||||
})
|
||||
);
|
||||
} else if (e.data.type === "jumpNote") {
|
||||
Zotero.debug(e.data);
|
||||
|
|
@ -510,6 +512,12 @@ class AddonViews extends AddonBase {
|
|||
params: await this._Addon.knowledge.getNoteFromLink(e.data.link),
|
||||
})
|
||||
);
|
||||
} else if (e.data.type === "moveNode") {
|
||||
this._Addon.events.onEditorEvent(
|
||||
new EditorMessage("moveNode", {
|
||||
params: e.data,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -522,36 +530,23 @@ class AddonViews extends AddonBase {
|
|||
}
|
||||
const _window = this._Addon.knowledge.getWorkspaceWindow();
|
||||
const mindmap = _window.document.getElementById("mindmap-container");
|
||||
const outline = _window.document.getElementById("outline-container");
|
||||
this.currentOutline = newType;
|
||||
if (this.currentOutline === OutlineType.treeView) {
|
||||
_window.document.getElementById("mindmapIframe").remove();
|
||||
mindmap.setAttribute("hidden", "hidden");
|
||||
outline.removeAttribute("hidden");
|
||||
} else if (this.currentOutline === OutlineType.mindMap) {
|
||||
const iframe = _window.document.createElement("iframe");
|
||||
iframe.setAttribute("id", "mindmapIframe");
|
||||
iframe.setAttribute(
|
||||
"src",
|
||||
"chrome://Knowledge4Zotero/content/mindMap.html"
|
||||
);
|
||||
outline.setAttribute("hidden", "hidden");
|
||||
mindmap.removeAttribute("hidden");
|
||||
mindmap.append(iframe);
|
||||
this.setTreeViewSize();
|
||||
} else if (this.currentOutline === OutlineType.bubbleMap) {
|
||||
_window.document.getElementById("mindmapIframe").remove();
|
||||
const iframe = _window.document.createElement("iframe");
|
||||
iframe.setAttribute("id", "mindmapIframe");
|
||||
iframe.setAttribute(
|
||||
"src",
|
||||
"chrome://Knowledge4Zotero/content/bubbleMap.html"
|
||||
);
|
||||
outline.setAttribute("hidden", "hidden");
|
||||
mindmap.removeAttribute("hidden");
|
||||
mindmap.append(iframe);
|
||||
this.setTreeViewSize();
|
||||
|
||||
const oldIframe = _window.document.getElementById("mindmapIframe");
|
||||
if (oldIframe) {
|
||||
oldIframe.remove();
|
||||
}
|
||||
this.currentOutline = newType;
|
||||
const srcList = [
|
||||
"",
|
||||
"chrome://Knowledge4Zotero/content/treeView.html",
|
||||
"chrome://Knowledge4Zotero/content/mindMap.html",
|
||||
"chrome://Knowledge4Zotero/content/bubbleMap.html",
|
||||
];
|
||||
const iframe = _window.document.createElement("iframe");
|
||||
iframe.setAttribute("id", "mindmapIframe");
|
||||
iframe.setAttribute("src", srcList[this.currentOutline]);
|
||||
mindmap.append(iframe);
|
||||
this.resizeOutline(_window);
|
||||
this.buildOutline(this._Addon.knowledge.getWorkspaceNote());
|
||||
}
|
||||
|
||||
|
|
@ -571,236 +566,23 @@ class AddonViews extends AddonBase {
|
|||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Outline Code Start
|
||||
*/
|
||||
|
||||
// TODO: change this
|
||||
async buildOutline(note: ZoteroItem) {
|
||||
Zotero.debug(this.currentOutline);
|
||||
if (this.currentOutline === OutlineType.treeView) {
|
||||
this._Addon.knowledge.currentNodeID = -1;
|
||||
let treeList = this._Addon.knowledge.getNoteTreeAsList(note, true, false);
|
||||
const treeData = [];
|
||||
treeList.map((node: TreeModel.Node<object>) => {
|
||||
treeData.push({
|
||||
id: String(node.model.id),
|
||||
name: node.model.name,
|
||||
rank: node.model.rank,
|
||||
icon: node.model.rank === 7 ? this.editorIcon["note"] : undefined,
|
||||
lineIndex: node.model.lineIndex,
|
||||
endIndex: node.model.endIndex,
|
||||
isDirectory: node.hasChildren(),
|
||||
expanded: true,
|
||||
parentId:
|
||||
node.model.rank > 1 ? String(node.parent.model.id) : undefined,
|
||||
});
|
||||
});
|
||||
this.$(() => {
|
||||
this.createTreeView("#treeview", treeData);
|
||||
this.createSortable("#treeview", "treeData");
|
||||
});
|
||||
} else {
|
||||
this.updateMindMap();
|
||||
}
|
||||
this.updateMindMap();
|
||||
}
|
||||
|
||||
createTreeView(selector, items) {
|
||||
// @ts-ignore
|
||||
this.$(selector).dxTreeView({
|
||||
items,
|
||||
expandNodesRecursive: false,
|
||||
dataStructure: "plain",
|
||||
height: this.$("window").height() - 100,
|
||||
displayExpr: "name",
|
||||
noDataText: "Create a heading with '+'",
|
||||
onItemClick: (e) => {
|
||||
this._Addon.events.onEditorEvent(
|
||||
new EditorMessage("clickOutlineHeading", {
|
||||
event: e,
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
bindTreeViewResize() {
|
||||
this.$("#zotero-knowledge-outline").on("resize", (e) => {
|
||||
this.setTreeViewSize();
|
||||
});
|
||||
}
|
||||
|
||||
setTreeViewSize() {
|
||||
this.$("#treeview").css({
|
||||
height: `${this.$("window").height() - 100}px`,
|
||||
width: `${this.$("#zotero-knowledge-outline").width() - 10}px`,
|
||||
});
|
||||
this.$("#mindmapIframe").css({
|
||||
height: `${this.$("window").height() - 58}px`,
|
||||
width: `${this.$("#zotero-knowledge-outline").width() - 10}px`,
|
||||
});
|
||||
}
|
||||
|
||||
createSortable(selector, driveName) {
|
||||
// @ts-ignore
|
||||
this.$(selector).dxSortable({
|
||||
filter: ".dx-treeview-item",
|
||||
group: "shared",
|
||||
data: driveName,
|
||||
allowDropInsideItem: true,
|
||||
allowReordering: true,
|
||||
onDragChange: (e) => {
|
||||
if (e.fromComponent === e.toComponent) {
|
||||
const $nodes = e.element.find(".dx-treeview-node");
|
||||
const isDragIntoChild =
|
||||
$nodes.eq(e.fromIndex).find($nodes.eq(e.toIndex)).length > 0;
|
||||
if (isDragIntoChild) {
|
||||
e.cancel = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
onDragEnd: (e) => {
|
||||
if (e.fromComponent === e.toComponent && e.fromIndex === e.toIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fromTreeView = this.getTreeView();
|
||||
const toTreeView = this.getTreeView();
|
||||
|
||||
const fromNode = this.findNode(fromTreeView, e.fromIndex);
|
||||
const toNode = this.findNode(toTreeView, this.calculateToIndex(e));
|
||||
|
||||
if (
|
||||
e.dropInsideItem &&
|
||||
toNode !== null &&
|
||||
!toNode.itemData.isDirectory
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fromTopVisibleNode = this.getTopVisibleNode(fromTreeView);
|
||||
const toTopVisibleNode = this.getTopVisibleNode(toTreeView);
|
||||
|
||||
const fromItems = fromTreeView.option("items");
|
||||
const toItems = toTreeView.option("items");
|
||||
this.moveNode(fromNode, toNode, fromItems, toItems, e.dropInsideItem);
|
||||
|
||||
fromTreeView.option("items", fromItems);
|
||||
toTreeView.option("items", toItems);
|
||||
fromTreeView.scrollToItem(fromTopVisibleNode);
|
||||
toTreeView.scrollToItem(toTopVisibleNode);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getTreeView() {
|
||||
// @ts-ignore
|
||||
return this.$("#treeview").dxTreeView("instance");
|
||||
}
|
||||
|
||||
calculateToIndex(e) {
|
||||
if (e.fromComponent !== e.toComponent || e.dropInsideItem) {
|
||||
return e.toIndex;
|
||||
}
|
||||
|
||||
return e.fromIndex >= e.toIndex ? e.toIndex : e.toIndex + 1;
|
||||
}
|
||||
|
||||
findNode(treeView, index) {
|
||||
const nodeElement = treeView.element().find(".dx-treeview-node")[index];
|
||||
if (nodeElement) {
|
||||
return this.findNodeById(
|
||||
treeView.getNodes(),
|
||||
nodeElement.getAttribute("data-item-id")
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
findNodeById(nodes, id) {
|
||||
for (let i = 0; i < nodes.length; i += 1) {
|
||||
if (nodes[i].itemData.id === id) {
|
||||
return nodes[i];
|
||||
}
|
||||
if (nodes[i].children) {
|
||||
const node = this.findNodeById(nodes[i].children, id);
|
||||
if (node != null) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
moveNode(fromNode, toNode, fromItems, toItems, isDropInsideItem) {
|
||||
const fromIndex = this.findIndex(fromItems, fromNode.itemData.id);
|
||||
fromItems.splice(fromIndex, 1);
|
||||
|
||||
const toIndex =
|
||||
toNode === null || isDropInsideItem
|
||||
? toItems.length
|
||||
: this.findIndex(toItems, toNode.itemData.id);
|
||||
|
||||
this._Addon.events.onEditorEvent(
|
||||
new EditorMessage("moveOutlineHeading", {
|
||||
params: {
|
||||
fromID: parseInt(fromNode.itemData.id),
|
||||
toID: toNode
|
||||
? parseInt(toNode.itemData.id)
|
||||
: toItems[toItems.length - 1].itemData.id,
|
||||
type: toNode ? "before" : "after",
|
||||
},
|
||||
})
|
||||
resizeOutline(_window: Window) {
|
||||
const iframe = _window.document.getElementById("mindmapIframe");
|
||||
const container = _window.document.getElementById(
|
||||
"zotero-knowledge-outline"
|
||||
);
|
||||
toItems.splice(toIndex, 0, fromNode.itemData);
|
||||
|
||||
this.moveChildren(fromNode, fromItems, toItems);
|
||||
if (isDropInsideItem) {
|
||||
fromNode.itemData.parentId = toNode.itemData.id;
|
||||
} else {
|
||||
fromNode.itemData.parentId =
|
||||
toNode != null ? toNode.itemData.parentId : undefined;
|
||||
if (iframe) {
|
||||
iframe.style.height = `${container.clientHeight - 60}px`;
|
||||
iframe.style.width = `${container.clientWidth - 10}px`;
|
||||
}
|
||||
}
|
||||
|
||||
moveChildren(node, fromItems, toItems) {
|
||||
if (!node.itemData.isDirectory) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.children.forEach((child) => {
|
||||
if (child.itemData.isDirectory) {
|
||||
this.moveChildren(child, fromItems, toItems);
|
||||
}
|
||||
|
||||
const fromIndex = this.findIndex(fromItems, child.itemData.id);
|
||||
fromItems.splice(fromIndex, 1);
|
||||
toItems.splice(toItems.length, 0, child.itemData);
|
||||
});
|
||||
}
|
||||
|
||||
findIndex(array, id) {
|
||||
const idsArray = array.map((elem) => elem.id);
|
||||
return idsArray.indexOf(id);
|
||||
}
|
||||
|
||||
getTopVisibleNode(component) {
|
||||
const treeViewElement = component.element().get(0);
|
||||
const treeViewTopPosition = treeViewElement.getBoundingClientRect().top;
|
||||
const nodes = treeViewElement.querySelectorAll(".dx-treeview-node");
|
||||
for (let i = 0; i < nodes.length; i += 1) {
|
||||
const nodeTopPosition = nodes[i].getBoundingClientRect().top;
|
||||
if (nodeTopPosition >= treeViewTopPosition) {
|
||||
return nodes[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Outline Code End
|
||||
*/
|
||||
|
||||
showProgressWindow(
|
||||
header: string,
|
||||
context: string,
|
||||
|
|
|
|||
Loading…
Reference in New Issue