Design suggestion from AI. Not very useable
This commit is contained in:
@@ -1,51 +1,190 @@
|
||||
{% extends "base.html" %}
|
||||
{% load mptt_tags %}
|
||||
{% block title %}Referenz: {{ referenz.Path }}{% endblock %}
|
||||
{% block breadcrumb_items %}
|
||||
<li class="breadcrumb-item"><a href="/referenzen/">Referenzen</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ referenz.Path }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1><a href="../{{ referenz.ParentID }}">⭡</a>{{ referenz.Path }}</h1>
|
||||
{% if referenz.erklaerung %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center bg-secondary text-light">
|
||||
<h3 class="h5 m-0">Beschreibung</h3>
|
||||
{% if referenz.url %}
|
||||
<span class="badge bg-light text-black">
|
||||
<a href="{{ referenz.url }}">Link</a>
|
||||
</span>{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="card-body p-2">
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<!-- Referenz Header -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<h1 class="h3 mb-2">🔗 {{ referenz.Path }}</h1>
|
||||
{% if referenz.ParentID %}
|
||||
<small class="opacity-75">
|
||||
<a href="/referenzen/{{ referenz.ParentID }}/" class="text-white">
|
||||
← Zurück zu übergeordneter Referenz
|
||||
</a>
|
||||
</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if referenz.url %}
|
||||
<a href="{{ referenz.url }}" class="btn btn-light btn-sm" target="_blank">
|
||||
🔗 Externer Link
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if referenz.erklaerung %}
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">📖 Beschreibung</h5>
|
||||
{% for typ, html in referenz.erklaerung %}
|
||||
{% if html %}<div>{{ html|safe }}</div>{% endif %}{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center bg-secondary text-light">
|
||||
<h3 class="h5 m-0">Referenzierte Vorgaben</h3>
|
||||
{% if html %}
|
||||
<div class="content-section">{{ html|safe }}</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="card-body p-2">
|
||||
{% recursetree referenz.children %}
|
||||
{% if not node == referenz %}
|
||||
{#<a href="../{{node.id}}">#}
|
||||
{{ node.Path }}
|
||||
{#</a>#}
|
||||
{% else %}
|
||||
{{ node.Path }}
|
||||
{% endif %}
|
||||
<br>
|
||||
{% if node.referenziertvon %}
|
||||
<ul>
|
||||
<!-- Referenzierte Vorgaben -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="h5 mb-0">📝 Referenzierte Vorgaben</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% recursetree referenz.children %}
|
||||
{% if not node == referenz %}
|
||||
<div class="mb-3 p-3 border rounded">
|
||||
<h6 class="mb-2">{{ node.Path }}</h6>
|
||||
{% if node.referenziertvon %}
|
||||
<div class="ms-3">
|
||||
<small class="text-muted">Referenziert von:</small>
|
||||
<ul class="list-unstyled mb-0">
|
||||
{% for ref in node.referenziertvon %}
|
||||
<li class="mb-1">
|
||||
<a href="/dokumente/{{ ref.dokument.nummer }}/#{{ref.Vorgabennummer}}"
|
||||
class="text-decoration-none">
|
||||
<span class="badge bg-secondary me-2">{{ ref.Vorgabennummer }}</span>
|
||||
{{ ref.titel }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if node.referenziertvon %}
|
||||
<div class="ms-3 mb-3">
|
||||
<small class="text-muted">Referenziert von:</small>
|
||||
<ul class="list-unstyled mb-0">
|
||||
{% for ref in node.referenziertvon %}
|
||||
<li><a href="{% url 'standard_detail' nummer=ref.dokument.nummer %}#{{ref.Vorgabennummer}}">{{ref}}</a></li>
|
||||
<li class="mb-1">
|
||||
<a href="/dokumente/{{ ref.dokument.nummer }}/#{{ref.Vorgabennummer}}"
|
||||
class="text-decoration-none">
|
||||
<span class="badge bg-secondary me-2">{{ ref.Vorgabennummer }}</span>
|
||||
{{ ref.titel }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<br>
|
||||
{% endif %}
|
||||
{% if not node.is_leaf_node %}
|
||||
{{ children }}
|
||||
{% endif %}
|
||||
{% endrecursetree %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not node.is_leaf_node %}
|
||||
<div class="ms-3">
|
||||
{{ children }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endrecursetree %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="col-lg-4">
|
||||
<!-- Quick Actions -->
|
||||
<div class="card mb-4 sticky-top" style="top: 1rem;">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">⚡ Aktionen</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-grid gap-2">
|
||||
{% if referenz.ParentID %}
|
||||
<a href="/referenzen/{{ referenz.ParentID }}/" class="btn btn-outline btn-sm">
|
||||
← Zurück
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="/referenzen/" class="btn btn-outline btn-sm">
|
||||
🌳 Zur Baumansicht
|
||||
</a>
|
||||
{% if referenz.url %}
|
||||
<a href="{{ referenz.url }}" class="btn btn-outline btn-sm" target="_blank">
|
||||
🔗 Externer Link
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistics -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">📊 Informationen</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<small class="text-muted">Referenz-ID</small>
|
||||
<p class="mb-0 fw-bold">{{ referenz.id }}</p>
|
||||
</div>
|
||||
{% if referenz.ParentID %}
|
||||
<div class="mb-3">
|
||||
<small class="text-muted">Übergeordnete Referenz</small>
|
||||
<p class="mb-0">
|
||||
<a href="/referenzen/{{ referenz.ParentID }}/" class="text-decoration-none">
|
||||
ID: {{ referenz.ParentID }}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="mb-3">
|
||||
<small class="text-muted">Anzahl Unterelemente</small>
|
||||
<p class="mb-0 fw-bold">{{ referenz.get_children.count }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Help -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">💡 Hinweise</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="small mb-0">
|
||||
<li>Diese Seite zeigt Details zur ausgewählten Referenz</li>
|
||||
<li>Verknüpfte Vorgaben sind direkt verlinkt</li>
|
||||
<li>Nutzen Sie die Baumansicht für die Übersicht</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.content-section {
|
||||
line-height: 1.6;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.content-section h1, .content-section h2, .content-section h3 {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.border {
|
||||
border-color: var(--border-color) !important;
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
@@ -1,21 +1,466 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Referenzen{% endblock %}
|
||||
{% block breadcrumb_items %}
|
||||
<li class="breadcrumb-item active" aria-current="page">Referenzen</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Referenzen</h1>
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<!-- Header -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h1 class="h3 mb-0">🔗 Referenzbaum</h1>
|
||||
<div class="d-flex gap-2">
|
||||
<button class="btn btn-outline btn-sm" onclick="expandAll()">
|
||||
➕ Alle ausklappen
|
||||
</button>
|
||||
<button class="btn btn-outline btn-sm" onclick="collapseAll()">
|
||||
➖ Alle einklappen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted mb-0">
|
||||
Hier finden Sie alle Referenzen und Querverbindungen zwischen den Standards und Vorgaben.
|
||||
Klicken Sie auf die Pfeile um den Baum zu navigieren.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% load mptt_tags %}
|
||||
<ul class="tree">
|
||||
{% recursetree referenzen %}
|
||||
<li>
|
||||
<a href="{{node.id}}">{{ node.name_nummer }}{% if node.name_text %} ({{node.name_text}}){% endif %}</a>
|
||||
{% if not node.is_leaf_node %}
|
||||
<ul class="children">
|
||||
<!-- Search and Filter -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-8">
|
||||
<label for="tree-search" class="form-label">🔍 Referenzen durchsuchen</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
id="tree-search"
|
||||
placeholder="Suchbegriff eingeben..."
|
||||
onkeyup="filterTree()">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="tree-filter" class="form-label">🏷️ Filter</label>
|
||||
<select class="form-select" id="tree-filter" onchange="filterTree()">
|
||||
<option value="">Alle anzeigen</option>
|
||||
<option value="has-children">Mit Unterelementen</option>
|
||||
<option value="leaf-only">Nur Endpunkte</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Interactive Tree -->
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% load mptt_tags %}
|
||||
<div id="tree-container">
|
||||
<ul class="tree-root">
|
||||
{% recursetree referenzen %}
|
||||
<li class="tree-node" data-node-id="{{ node.id }}" data-node-text="{{ node.name_text|default:'' }} {{ node.name_nummer|default:'' }}">
|
||||
<div class="tree-node-content" onclick="toggleNode(this)">
|
||||
{% if not node.is_leaf_node %}
|
||||
<span class="tree-toggle">▼</span>
|
||||
{% else %}
|
||||
<span class="tree-toggle-placeholder"></span>
|
||||
{% endif %}
|
||||
|
||||
<a href="{{ node.id }}" class="tree-link">
|
||||
{% if node.name_nummer %}
|
||||
<span class="tree-number">{{ node.name_nummer }}</span>
|
||||
{% endif %}
|
||||
{% if node.name_text %}
|
||||
<span class="tree-text">{{ node.name_text }}</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
<div class="tree-node-meta">
|
||||
{% if not node.is_leaf_node %}
|
||||
<span class="badge bg-info">{{ node.get_children.count }} Unterelemente</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">Endpunkt</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if not node.is_leaf_node %}
|
||||
<ul class="tree-children">
|
||||
{{ children }}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endrecursetree %}
|
||||
</ul>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endrecursetree %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% if not referenzen %}
|
||||
<div class="text-center py-5">
|
||||
<span style="font-size: 3rem;">🔗</span>
|
||||
<h4 class="text-muted mt-3">Keine Referenzen gefunden</h4>
|
||||
<p class="text-muted">Es wurden keine Referenzen in der Datenbank gefunden.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="col-lg-4">
|
||||
<!-- Statistics -->
|
||||
<div class="card mb-4 sticky-top" style="top: 1rem;">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">📊 Statistiken</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row text-center mb-3">
|
||||
<div class="col-6">
|
||||
<h4 class="text-primary mb-1">{{ referenzen|length }}</h4>
|
||||
<small class="text-muted">Gesamt</small>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h4 class="text-success mb-1">
|
||||
{% for node in referenzen %}
|
||||
{% if node.is_leaf_node %}
|
||||
{% if forloop.first %}1{% else %}{{ forloop.counter }}{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</h4>
|
||||
<small class="text-muted">Endpunkte</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-top pt-3">
|
||||
<h6 class="text-muted mb-2">Baumtiefe</h6>
|
||||
<div class="progress" style="height: 8px;">
|
||||
<div class="progress-bar bg-primary" style="width: 75%"></div>
|
||||
</div>
|
||||
<small class="text-muted">Maximale Tiefe: 4 Ebenen</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Navigation -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">🧭 Navigation</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-grid gap-2">
|
||||
<button class="btn btn-outline btn-sm" onclick="scrollToTop()">
|
||||
⬆️ Zum Anfang
|
||||
</button>
|
||||
<button class="btn btn-outline btn-sm" onclick="findNextMatch()">
|
||||
⬇️ Nächster Treffer
|
||||
</button>
|
||||
<button class="btn btn-outline btn-sm" onclick="resetFilters()">
|
||||
🔄 Filter zurücksetzen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Help -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">💡 Hinweise</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="small mb-0">
|
||||
<li>Klicken Sie auf ▼/▶ um Knoten ein-/auszuklappen</li>
|
||||
<li>Nutzen Sie die Suche um gezielt zu filtern</li>
|
||||
<li>Referenznummern sind hervorgehoben</li>
|
||||
<li>Endpunkte haben keine Unterelemente</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Tree Styles */
|
||||
.tree-root {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tree-node {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.tree-node-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.tree-node-content:hover {
|
||||
background-color: var(--bg-secondary);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.tree-toggle {
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.tree-toggle-placeholder {
|
||||
width: 20px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.tree-link {
|
||||
text-decoration: none;
|
||||
color: var(--text-primary);
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.tree-link:hover {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.tree-number {
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 600;
|
||||
color: var(--primary-color);
|
||||
background-color: var(--bg-secondary);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.tree-text {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tree-node-meta {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.tree-children {
|
||||
list-style: none;
|
||||
padding-left: 28px;
|
||||
margin: 2px 0 0 0;
|
||||
border-left: 2px solid var(--border-color);
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.tree-children .tree-node {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tree-children .tree-node::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -30px;
|
||||
top: 20px;
|
||||
width: 20px;
|
||||
height: 1px;
|
||||
background-color: var(--border-color);
|
||||
}
|
||||
|
||||
/* Collapsed state */
|
||||
.tree-children.collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tree-node.collapsed .tree-toggle {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
/* Highlighted search results */
|
||||
.tree-node.highlighted > .tree-node-content {
|
||||
background-color: var(--warning-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.tree-node.highlighted .tree-number {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.tree-children {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.tree-node-meta {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tree-number {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
let currentMatchIndex = -1;
|
||||
let matches = [];
|
||||
|
||||
function toggleNode(element) {
|
||||
const node = element.parentElement;
|
||||
const children = node.querySelector(':scope > .tree-children');
|
||||
const toggle = element.querySelector('.tree-toggle');
|
||||
|
||||
if (children) {
|
||||
children.classList.toggle('collapsed');
|
||||
node.classList.toggle('collapsed');
|
||||
|
||||
if (toggle) {
|
||||
toggle.textContent = children.classList.contains('collapsed') ? '▶' : '▼';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function expandAll() {
|
||||
const children = document.querySelectorAll('.tree-children');
|
||||
const nodes = document.querySelectorAll('.tree-node');
|
||||
const toggles = document.querySelectorAll('.tree-toggle');
|
||||
|
||||
children.forEach(child => child.classList.remove('collapsed'));
|
||||
nodes.forEach(node => node.classList.remove('collapsed'));
|
||||
toggles.forEach(toggle => {
|
||||
if (toggle.textContent === '▶') {
|
||||
toggle.textContent = '▼';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function collapseAll() {
|
||||
const children = document.querySelectorAll('.tree-children');
|
||||
const nodes = document.querySelectorAll('.tree-node');
|
||||
const toggles = document.querySelectorAll('.tree-toggle');
|
||||
|
||||
children.forEach(child => child.classList.add('collapsed'));
|
||||
nodes.forEach(node => node.classList.add('collapsed'));
|
||||
toggles.forEach(toggle => {
|
||||
if (toggle.textContent === '▼') {
|
||||
toggle.textContent = '▶';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function filterTree() {
|
||||
const searchTerm = document.getElementById('tree-search').value.toLowerCase();
|
||||
const filterType = document.getElementById('tree-filter').value;
|
||||
const nodes = document.querySelectorAll('.tree-node');
|
||||
|
||||
matches = [];
|
||||
currentMatchIndex = -1;
|
||||
|
||||
nodes.forEach(node => {
|
||||
const nodeText = node.dataset.nodeText.toLowerCase();
|
||||
const hasChildren = node.querySelector(':scope > .tree-children') !== null;
|
||||
const isLeaf = !hasChildren;
|
||||
|
||||
let showNode = true;
|
||||
|
||||
// Apply search filter
|
||||
if (searchTerm && !nodeText.includes(searchTerm)) {
|
||||
showNode = false;
|
||||
}
|
||||
|
||||
// Apply type filter
|
||||
if (filterType === 'has-children' && !hasChildren) {
|
||||
showNode = false;
|
||||
} else if (filterType === 'leaf-only' && !isLeaf) {
|
||||
showNode = false;
|
||||
}
|
||||
|
||||
// Show/hide node
|
||||
node.style.display = showNode ? 'block' : 'none';
|
||||
|
||||
// Highlight search matches
|
||||
if (searchTerm && nodeText.includes(searchTerm)) {
|
||||
node.classList.add('highlighted');
|
||||
matches.push(node);
|
||||
} else {
|
||||
node.classList.remove('highlighted');
|
||||
}
|
||||
|
||||
// Auto-expand parent nodes of matches
|
||||
if (searchTerm && nodeText.includes(searchTerm)) {
|
||||
let parent = node.parentElement;
|
||||
while (parent && parent.classList.contains('tree-children')) {
|
||||
parent.classList.remove('collapsed');
|
||||
parent.parentElement.classList.remove('collapsed');
|
||||
const toggle = parent.parentElement.querySelector('.tree-toggle');
|
||||
if (toggle) toggle.textContent = '▼';
|
||||
parent = parent.parentElement.parentElement;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function findNextMatch() {
|
||||
if (matches.length === 0) return;
|
||||
|
||||
currentMatchIndex = (currentMatchIndex + 1) % matches.length;
|
||||
const match = matches[currentMatchIndex];
|
||||
|
||||
// Scroll to match
|
||||
match.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
|
||||
// Highlight temporarily
|
||||
match.style.backgroundColor = 'var(--accent-color)';
|
||||
setTimeout(() => {
|
||||
match.style.backgroundColor = '';
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function scrollToTop() {
|
||||
document.getElementById('tree-container').scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
document.getElementById('tree-search').value = '';
|
||||
document.getElementById('tree-filter').value = '';
|
||||
filterTree();
|
||||
expandAll();
|
||||
}
|
||||
|
||||
// Initialize on page load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Add keyboard shortcuts
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
switch(e.key) {
|
||||
case 'f':
|
||||
e.preventDefault();
|
||||
document.getElementById('tree-search').focus();
|
||||
break;
|
||||
case 'e':
|
||||
e.preventDefault();
|
||||
expandAll();
|
||||
break;
|
||||
case 'w':
|
||||
e.preventDefault();
|
||||
collapseAll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user