Update dev-tools.js
Browse files- dev-tools.js +95 -104
dev-tools.js
CHANGED
@@ -231,6 +231,7 @@
|
|
231 |
let selectedElement = null;
|
232 |
let selectedDOMNode = null;
|
233 |
|
|
|
234 |
// 開発者ツールのUI構築
|
235 |
function createDevTools() {
|
236 |
const container = document.createElement('div');
|
@@ -454,7 +455,81 @@
|
|
454 |
|
455 |
return panel;
|
456 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
457 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
458 |
// Elementsパネルの作成
|
459 |
function createElementsPanel() {
|
460 |
const panel = document.createElement('div');
|
@@ -476,86 +551,6 @@
|
|
476 |
container.appendChild(cssPanel);
|
477 |
panel.appendChild(container);
|
478 |
|
479 |
-
// DOMツリーを構築
|
480 |
-
function buildDOMTree(node, parentElement, depth = 0) {
|
481 |
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
482 |
-
const element = document.createElement('div');
|
483 |
-
element.className = 'dom-node';
|
484 |
-
element.style.marginLeft = `${depth * 15}px`;
|
485 |
-
element.dataset.elementId = node.id || Math.random().toString(36).substr(2, 9);
|
486 |
-
|
487 |
-
// 右クリックイベント
|
488 |
-
element.oncontextmenu = (e) => {
|
489 |
-
e.preventDefault();
|
490 |
-
selectedElement = node;
|
491 |
-
selectedDOMNode = element;
|
492 |
-
|
493 |
-
// 選択状態を更新
|
494 |
-
document.querySelectorAll('.dom-node').forEach(el => el.classList.remove('selected'));
|
495 |
-
element.classList.add('selected');
|
496 |
-
|
497 |
-
// コンテキストメニュー表示
|
498 |
-
contextMenu.style.display = 'block';
|
499 |
-
contextMenu.style.left = `${e.pageX}px`;
|
500 |
-
contextMenu.style.top = `${e.pageY}px`;
|
501 |
-
|
502 |
-
// CSSパネルを更新
|
503 |
-
updateCSSPanel(node);
|
504 |
-
};
|
505 |
-
|
506 |
-
// クリックで選択
|
507 |
-
element.onclick = (e) => {
|
508 |
-
e.stopPropagation();
|
509 |
-
selectedElement = node;
|
510 |
-
selectedDOMNode = element;
|
511 |
-
|
512 |
-
document.querySelectorAll('.dom-node').forEach(el => el.classList.remove('selected'));
|
513 |
-
element.classList.add('selected');
|
514 |
-
|
515 |
-
updateCSSPanel(node);
|
516 |
-
};
|
517 |
-
|
518 |
-
// タグ名
|
519 |
-
const tag = document.createElement('span');
|
520 |
-
tag.className = 'dom-tag';
|
521 |
-
tag.textContent = `<${node.tagName.toLowerCase()}`;
|
522 |
-
element.appendChild(tag);
|
523 |
-
|
524 |
-
// 属性
|
525 |
-
Array.from(node.attributes).forEach(attr => {
|
526 |
-
const attrSpan = document.createElement('span');
|
527 |
-
attrSpan.className = 'dom-attr';
|
528 |
-
attrSpan.textContent = ` ${attr.name}="${attr.value}"`;
|
529 |
-
element.appendChild(attrSpan);
|
530 |
-
});
|
531 |
-
|
532 |
-
element.appendChild(document.createTextNode('>'));
|
533 |
-
|
534 |
-
// 子要素
|
535 |
-
if (node.childNodes.length > 0) {
|
536 |
-
node.childNodes.forEach(child => {
|
537 |
-
buildDOMTree(child, element, depth + 1);
|
538 |
-
});
|
539 |
-
}
|
540 |
-
|
541 |
-
// 閉じタグ
|
542 |
-
if (node.childNodes.length > 0 || node.tagName.toLowerCase() !== 'br') {
|
543 |
-
const closeTag = document.createElement('div');
|
544 |
-
closeTag.style.marginLeft = `${depth * 15}px`;
|
545 |
-
closeTag.innerHTML = `<span class="dom-tag"></${node.tagName.toLowerCase()}></span>`;
|
546 |
-
element.appendChild(closeTag);
|
547 |
-
}
|
548 |
-
|
549 |
-
parentElement.appendChild(element);
|
550 |
-
} else if (node.nodeType === Node.TEXT_NODE && node.textContent.trim()) {
|
551 |
-
const text = document.createElement('div');
|
552 |
-
text.style.marginLeft = `${depth * 15}px`;
|
553 |
-
text.style.color = '#e0e0e0';
|
554 |
-
text.textContent = `"${node.textContent.trim()}"`;
|
555 |
-
parentElement.appendChild(text);
|
556 |
-
}
|
557 |
-
}
|
558 |
-
|
559 |
// CSSパネルを更新
|
560 |
function updateCSSPanel(element) {
|
561 |
const cssPanel = document.getElementById('css-panel');
|
@@ -674,44 +669,40 @@
|
|
674 |
return panel;
|
675 |
}
|
676 |
|
677 |
-
|
678 |
-
function refreshElementsPanel() {
|
679 |
let tree = document.getElementById('dom-tree');
|
680 |
|
681 |
-
// ツリー要素が存在しない場合は作成
|
682 |
if (!tree) {
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
}
|
692 |
}
|
|
|
693 |
}
|
694 |
|
695 |
-
// ツリー要素がまだない場合は処理を中止
|
696 |
if (!tree) return;
|
697 |
|
698 |
tree.innerHTML = '';
|
699 |
buildDOMTree(document.documentElement, tree);
|
700 |
|
701 |
if (selectedElement) {
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
}
|
711 |
}
|
|
|
712 |
}
|
713 |
-
}
|
714 |
-
|
715 |
// Storageパネルの作成
|
716 |
function createStoragePanel() {
|
717 |
const panel = document.createElement('div');
|
|
|
231 |
let selectedElement = null;
|
232 |
let selectedDOMNode = null;
|
233 |
|
234 |
+
// 開発者ツールのUI構築
|
235 |
// 開発者ツールのUI構築
|
236 |
function createDevTools() {
|
237 |
const container = document.createElement('div');
|
|
|
455 |
|
456 |
return panel;
|
457 |
}
|
458 |
+
function buildDOMTree(node, parentElement, depth = 0) {
|
459 |
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
460 |
+
const element = document.createElement('div');
|
461 |
+
element.className = 'dom-node';
|
462 |
+
element.style.marginLeft = `${depth * 15}px`;
|
463 |
+
element.dataset.elementId = node.id || Math.random().toString(36).substr(2, 9);
|
464 |
+
|
465 |
+
// 右クリックイベント
|
466 |
+
element.oncontextmenu = (e) => {
|
467 |
+
e.preventDefault();
|
468 |
+
selectedElement = node;
|
469 |
+
selectedDOMNode = element;
|
470 |
+
|
471 |
+
document.querySelectorAll('.dom-node').forEach(el => el.classList.remove('selected'));
|
472 |
+
element.classList.add('selected');
|
473 |
+
|
474 |
+
contextMenu.style.display = 'block';
|
475 |
+
contextMenu.style.left = `${e.pageX}px`;
|
476 |
+
contextMenu.style.top = `${e.pageY}px`;
|
477 |
+
|
478 |
+
updateCSSPanel(node);
|
479 |
+
};
|
480 |
+
|
481 |
+
// クリックで選択
|
482 |
+
element.onclick = (e) => {
|
483 |
+
e.stopPropagation();
|
484 |
+
selectedElement = node;
|
485 |
+
selectedDOMNode = element;
|
486 |
+
|
487 |
+
document.querySelectorAll('.dom-node').forEach(el => el.classList.remove('selected'));
|
488 |
+
element.classList.add('selected');
|
489 |
+
|
490 |
+
updateCSSPanel(node);
|
491 |
+
};
|
492 |
+
|
493 |
+
// タグ名
|
494 |
+
const tag = document.createElement('span');
|
495 |
+
tag.className = 'dom-tag';
|
496 |
+
tag.textContent = `<${node.tagName.toLowerCase()}`;
|
497 |
+
element.appendChild(tag);
|
498 |
+
|
499 |
+
// 属性
|
500 |
+
Array.from(node.attributes).forEach(attr => {
|
501 |
+
const attrSpan = document.createElement('span');
|
502 |
+
attrSpan.className = 'dom-attr';
|
503 |
+
attrSpan.textContent = ` ${attr.name}="${attr.value}"`;
|
504 |
+
element.appendChild(attrSpan);
|
505 |
+
});
|
506 |
+
|
507 |
+
element.appendChild(document.createTextNode('>'));
|
508 |
|
509 |
+
// 子要素
|
510 |
+
if (node.childNodes.length > 0) {
|
511 |
+
node.childNodes.forEach(child => {
|
512 |
+
buildDOMTree(child, element, depth + 1);
|
513 |
+
});
|
514 |
+
}
|
515 |
+
|
516 |
+
// 閉じタグ
|
517 |
+
if (node.childNodes.length > 0 || node.tagName.toLowerCase() !== 'br') {
|
518 |
+
const closeTag = document.createElement('div');
|
519 |
+
closeTag.style.marginLeft = `${depth * 15}px`;
|
520 |
+
closeTag.innerHTML = `<span class="dom-tag"></${node.tagName.toLowerCase()}></span>`;
|
521 |
+
element.appendChild(closeTag);
|
522 |
+
}
|
523 |
+
|
524 |
+
parentElement.appendChild(element);
|
525 |
+
} else if (node.nodeType === Node.TEXT_NODE && node.textContent.trim()) {
|
526 |
+
const text = document.createElement('div');
|
527 |
+
text.style.marginLeft = `${depth * 15}px`;
|
528 |
+
text.style.color = '#e0e0e0';
|
529 |
+
text.textContent = `"${node.textContent.trim()}"`;
|
530 |
+
parentElement.appendChild(text);
|
531 |
+
}
|
532 |
+
}
|
533 |
// Elementsパネルの作成
|
534 |
function createElementsPanel() {
|
535 |
const panel = document.createElement('div');
|
|
|
551 |
container.appendChild(cssPanel);
|
552 |
panel.appendChild(container);
|
553 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
554 |
// CSSパネルを更新
|
555 |
function updateCSSPanel(element) {
|
556 |
const cssPanel = document.getElementById('css-panel');
|
|
|
669 |
return panel;
|
670 |
}
|
671 |
|
672 |
+
function refreshElementsPanel() {
|
|
|
673 |
let tree = document.getElementById('dom-tree');
|
674 |
|
|
|
675 |
if (!tree) {
|
676 |
+
const panel = document.getElementById('elements-panel');
|
677 |
+
if (panel) {
|
678 |
+
const container = panel.querySelector('.elements-container');
|
679 |
+
if (container) {
|
680 |
+
tree = document.createElement('div');
|
681 |
+
tree.className = 'dom-tree';
|
682 |
+
tree.id = 'dom-tree';
|
683 |
+
container.insertBefore(tree, container.querySelector('.css-panel'));
|
|
|
684 |
}
|
685 |
+
}
|
686 |
}
|
687 |
|
|
|
688 |
if (!tree) return;
|
689 |
|
690 |
tree.innerHTML = '';
|
691 |
buildDOMTree(document.documentElement, tree);
|
692 |
|
693 |
if (selectedElement) {
|
694 |
+
const elementId = selectedElement.id || Array.from(selectedElement.attributes)
|
695 |
+
.find(attr => attr.name.startsWith('data-element-id'))?.value;
|
696 |
+
|
697 |
+
if (elementId) {
|
698 |
+
const node = document.querySelector(`[data-element-id="${elementId}"]`);
|
699 |
+
if (node) {
|
700 |
+
node.classList.add('selected');
|
701 |
+
updateCSSPanel(selectedElement);
|
|
|
702 |
}
|
703 |
+
}
|
704 |
}
|
705 |
+
}
|
|
|
706 |
// Storageパネルの作成
|
707 |
function createStoragePanel() {
|
708 |
const panel = document.createElement('div');
|