mirror of
https://github.com/sotam0316/drawNET.git
synced 2026-04-25 03:58:37 +09:00
Initial commit: drawNET Alpha v1.0 - Professional Topology Designer with Full i18n and Performance Optimizations
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import { state } from '../state.js';
|
||||
|
||||
/**
|
||||
* initGlobalSearch - Initializes the canvas-wide search and highlight functionality
|
||||
*/
|
||||
export function initGlobalSearch() {
|
||||
const searchInput = document.getElementById('global-search');
|
||||
if (!searchInput) return;
|
||||
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const query = e.target.value.toLowerCase().trim();
|
||||
if (!state.graph) return;
|
||||
|
||||
const allNodes = state.graph.getNodes();
|
||||
|
||||
if (query === '') {
|
||||
allNodes.forEach(node => {
|
||||
node.attr('body/opacity', 1);
|
||||
node.attr('image/opacity', 1);
|
||||
node.attr('label/opacity', 1);
|
||||
node.removeTools();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
allNodes.forEach(node => {
|
||||
const data = node.getData() || {};
|
||||
const label = (node.attr('label/text') || '').toLowerCase();
|
||||
const id = node.id.toLowerCase();
|
||||
|
||||
// PM 전용 표준 속성 검색 대상 포함
|
||||
const searchFields = [
|
||||
id, label,
|
||||
(data.type || '').toLowerCase(),
|
||||
(data.ip || '').toLowerCase(),
|
||||
(data.model || '').toLowerCase(),
|
||||
(data.vendor || '').toLowerCase(),
|
||||
(data.asset_tag || '').toLowerCase(),
|
||||
(data.serial || '').toLowerCase(),
|
||||
(data.project || '').toLowerCase(),
|
||||
(data.tags || []).join(' ').toLowerCase()
|
||||
];
|
||||
|
||||
const isMatch = searchFields.some(field => field.includes(query));
|
||||
|
||||
if (isMatch) {
|
||||
node.attr('body/opacity', 1);
|
||||
node.attr('image/opacity', 1);
|
||||
node.attr('label/opacity', 1);
|
||||
|
||||
// 검색 강조 툴 추가
|
||||
node.addTools({
|
||||
name: 'boundary',
|
||||
args: {
|
||||
padding: 5,
|
||||
attrs: {
|
||||
fill: 'none',
|
||||
stroke: '#3b82f6',
|
||||
strokeWidth: 3,
|
||||
strokeDasharray: '0',
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
node.attr('body/opacity', 0.1);
|
||||
node.attr('image/opacity', 0.1);
|
||||
node.attr('label/opacity', 0.1);
|
||||
node.removeTools();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 엔터 키 입력 시 검색된 첫 번째 항목으로 포커싱
|
||||
searchInput.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
const query = e.target.value.toLowerCase().trim();
|
||||
if (!query || !state.graph) return;
|
||||
|
||||
const matches = state.graph.getNodes().filter(node => {
|
||||
const data = node.getData() || {};
|
||||
const label = (node.attr('label/text') || '').toLowerCase();
|
||||
const searchFields = [
|
||||
node.id.toLowerCase(), label,
|
||||
(data.ip || ''), (data.asset_tag || ''), (data.model || '')
|
||||
];
|
||||
return searchFields.some(f => f.toLowerCase().includes(query));
|
||||
});
|
||||
|
||||
if (matches.length > 0) {
|
||||
// 첫 번째 매치된 항목으로 줌인
|
||||
state.graph.zoomToCell(matches[0], {
|
||||
padding: 100,
|
||||
animation: { duration: 600 }
|
||||
});
|
||||
state.graph.select(matches[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user