File size: 5,597 Bytes
a389a28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
document.addEventListener('DOMContentLoaded', function() {
    // Initialize GOV.UK Frontend
    window.GOVUKFrontend.initAll();

    // Taxonomy Explorer implementation
    class TaxonomyExplorer {
        constructor(containerId) {
            this.container = document.getElementById(containerId);
            this.data = null;
            this.hierarchy = null;
            this.currentNode = null;
            this.searchTerm = '';
            this.stats = { l1: 0, l2: 0, l3: 0 };
            
            this.init();
        }

        async init() {
            // Load taxonomy data
            await this.loadData();
            
            // Initialize visualization
            this.initVisualization();
            
            // Render controls
            this.renderControls();
        }

        async loadData() {
            // In a real implementation, this would load from an API
            // For now we'll use the static data structure
            this.data = this.parseMarkdown(markdownData);
            this.hierarchy = d3.hierarchy(this.data);
            this.calculateStats();
        }

        parseMarkdown(markdown) {
            // Improved parsing logic from original code
            // ... (keep existing parsing logic)
        }

        calculateStats() {
            // Calculate stats for the taxonomy
            // ... (keep existing stats logic)
        }

        initVisualization() {
            // Set up D3 visualization with improved GOV.UK styling
            const width = this.container.clientWidth;
            const height = this.container.clientHeight;

            this.svg = d3.select(this.container)
                .append('svg')
                .attr('width', width)
                .attr('height', height)
                .style('font-family', '"GDS Transport", Arial, sans-serif');

            this.g = this.svg.append('g');

            // Add zoom behavior
            this.zoom = d3.zoom()
                .scaleExtent([0.1, 2])
                .on('zoom', (event) => this.g.attr('transform', event.transform));
            
            this.svg.call(this.zoom);

            // Set up tree layout
            this.tree = d3.tree()
                .size([width - 200, height - 200])
                .separation((a, b) => a.parent === b.parent ? 1.5 : 2);

            // Initial render
            this.updateVisualization();
        }

        updateVisualization() {
            // Update the visualization based on current state
            const treeData = this.tree(this.hierarchy);
            const nodes = treeData.descendants();
            const links = treeData.links();

            // Normalize positions
            nodes.forEach(d => d.y = d.depth * 180);

            // Update nodes and links
            // ... (keep existing update logic with GOV.UK styling)
        }

        renderControls() {
            // Create control panel
            const controls = this.container.insertBefore(
                document.createElement('div'),
                this.container.firstChild
            );
            controls.className = 'taxonomy-controls';

            // Add search input
            const searchDiv = document.createElement('div');
            searchDiv.className = 'taxonomy-search';
            searchDiv.innerHTML = `
                <div class="govuk-form-group">
                    <label class="govuk-label" for="taxonomy-search">Search taxonomy</label>
                    <input class="govuk-input" id="taxonomy-search" type="text" placeholder="Search...">
                </div>
            `;
            controls.appendChild(searchDiv);

            // Add stats display
            const statsDiv = document.createElement('div');
            statsDiv.className = 'taxonomy-stats';
            statsDiv.innerHTML = `
                <div class="taxonomy-stat">
                    <div class="taxonomy-stat-value" id="stat-l1">${this.stats.l1}</div>
                    <div class="taxonomy-stat-label">L1 Categories</div>
                </div>
                <div class="taxonomy-stat">
                    <div class="taxonomy-stat-value" id="stat-l2">${this.stats.l2}</div>
                    <div class="taxonomy-stat-label">L2 Subcategories</div>
                </div>
                <div class="taxonomy-stat">
                    <div class="taxonomy-stat-value" id="stat-l3">${this.stats.l3}</div>
                    <div class="taxonomy-stat-label">L3 Topics</div>
                </div>
            `;
            controls.appendChild(statsDiv);

            // Add event listeners
            document.getElementById('taxonomy-search').addEventListener('input', (e) => {
                this.searchTerm = e.target.value.toLowerCase();
                this.highlightMatches();
            });
        }

        highlightMatches() {
            // Highlight nodes matching search term
            this.svg.selectAll('.node')
                .classed('node-highlighted', (d) => {
                    if (!this.searchTerm) return false;
                    const nameMatch = d.data.name.toLowerCase().includes(this.searchTerm);
                    const slugMatch = d.data.slug && d.data.slug.toLowerCase().includes(this.searchTerm);
                    return nameMatch || slugMatch;
                });
        }

        showDetails(node) {
            // Show details panel for selected node
            // ... (keep existing details panel logic with GOV.UK styling)
        }
    }

    // Initialize the explorer
    new TaxonomyExplorer('taxonomy-explorer');
});