Update dev-tools.js
Browse files- dev-tools.js +0 -288
dev-tools.js
CHANGED
@@ -1731,294 +1731,6 @@ function refreshElementsPanel() {
|
|
1731 |
}
|
1732 |
}
|
1733 |
}
|
1734 |
-
// Elementsパネル作成
|
1735 |
-
function createElementsPanel() {
|
1736 |
-
const panel = document.createElement('div');
|
1737 |
-
panel.className = 'devtools-panel';
|
1738 |
-
panel.id = 'elements-panel';
|
1739 |
-
|
1740 |
-
const container = document.createElement('div');
|
1741 |
-
container.className = 'elements-container';
|
1742 |
-
|
1743 |
-
const tree = document.createElement('div');
|
1744 |
-
tree.className = 'dom-tree';
|
1745 |
-
tree.id = 'dom-tree';
|
1746 |
-
|
1747 |
-
const cssPanel = document.createElement('div');
|
1748 |
-
cssPanel.className = 'css-panel';
|
1749 |
-
cssPanel.id = 'css-panel';
|
1750 |
-
|
1751 |
-
container.appendChild(tree);
|
1752 |
-
container.appendChild(cssPanel);
|
1753 |
-
panel.appendChild(container);
|
1754 |
-
|
1755 |
-
// CSSパネル更新関数
|
1756 |
-
function updateCSSPanel(element) {
|
1757 |
-
const cssPanel = document.getElementById('css-panel');
|
1758 |
-
cssPanel.innerHTML = '';
|
1759 |
-
|
1760 |
-
if (!element) return;
|
1761 |
-
|
1762 |
-
if (element.style.length > 0) {
|
1763 |
-
const inlineRule = document.createElement('div');
|
1764 |
-
inlineRule.className = 'css-rule';
|
1765 |
-
|
1766 |
-
const selector = document.createElement('div');
|
1767 |
-
selector.className = 'css-selector';
|
1768 |
-
selector.textContent = 'インラインスタイル';
|
1769 |
-
inlineRule.appendChild(selector);
|
1770 |
-
|
1771 |
-
for (let i = 0; i < element.style.length; i++) {
|
1772 |
-
const propName = element.style[i];
|
1773 |
-
const propValue = element.style[propName];
|
1774 |
-
|
1775 |
-
const propDiv = document.createElement('div');
|
1776 |
-
propDiv.className = 'css-property';
|
1777 |
-
|
1778 |
-
const nameSpan = document.createElement('span');
|
1779 |
-
nameSpan.className = 'css-property-name editable';
|
1780 |
-
nameSpan.textContent = propName;
|
1781 |
-
nameSpan.onclick = () => editCSSProperty(element, propName, 'style');
|
1782 |
-
|
1783 |
-
const valueSpan = document.createElement('span');
|
1784 |
-
valueSpan.className = 'css-property-value editable';
|
1785 |
-
valueSpan.textContent = propValue;
|
1786 |
-
valueSpan.onclick = () => editCSSProperty(element, propName, 'style');
|
1787 |
-
|
1788 |
-
const toggleSpan = document.createElement('span');
|
1789 |
-
toggleSpan.className = 'css-toggle';
|
1790 |
-
toggleSpan.textContent = '×';
|
1791 |
-
toggleSpan.title = 'プロパティを無効化';
|
1792 |
-
toggleSpan.onclick = () => {
|
1793 |
-
element.style[propName] = '';
|
1794 |
-
updateCSSPanel(element);
|
1795 |
-
};
|
1796 |
-
|
1797 |
-
propDiv.appendChild(nameSpan);
|
1798 |
-
propDiv.appendChild(valueSpan);
|
1799 |
-
propDiv.appendChild(toggleSpan);
|
1800 |
-
inlineRule.appendChild(propDiv);
|
1801 |
-
}
|
1802 |
-
|
1803 |
-
cssPanel.appendChild(inlineRule);
|
1804 |
-
}
|
1805 |
-
|
1806 |
-
const computedStyles = window.getComputedStyle(element);
|
1807 |
-
const computedRule = document.createElement('div');
|
1808 |
-
computedRule.className = 'css-rule';
|
1809 |
-
|
1810 |
-
const computedSelector = document.createElement('div');
|
1811 |
-
computedSelector.className = 'css-selector';
|
1812 |
-
computedSelector.textContent = '計算されたスタイル';
|
1813 |
-
computedRule.appendChild(computedSelector);
|
1814 |
-
|
1815 |
-
const importantProps = [
|
1816 |
-
'display', 'position', 'width', 'height', 'margin', 'padding',
|
1817 |
-
'color', 'background', 'border', 'font', 'flex', 'grid'
|
1818 |
-
];
|
1819 |
-
|
1820 |
-
importantProps.forEach(prop => {
|
1821 |
-
const value = computedStyles[prop];
|
1822 |
-
|
1823 |
-
const propDiv = document.createElement('div');
|
1824 |
-
propDiv.className = 'css-property';
|
1825 |
-
|
1826 |
-
const nameSpan = document.createElement('span');
|
1827 |
-
nameSpan.className = 'css-property-name';
|
1828 |
-
nameSpan.textContent = prop;
|
1829 |
-
|
1830 |
-
const valueSpan = document.createElement('span');
|
1831 |
-
valueSpan.className = 'css-property-value';
|
1832 |
-
valueSpan.textContent = value;
|
1833 |
-
|
1834 |
-
propDiv.appendChild(nameSpan);
|
1835 |
-
propDiv.appendChild(valueSpan);
|
1836 |
-
computedRule.appendChild(propDiv);
|
1837 |
-
});
|
1838 |
-
|
1839 |
-
cssPanel.appendChild(computedRule);
|
1840 |
-
}
|
1841 |
-
|
1842 |
-
// DOMツリー構築
|
1843 |
-
function buildDOMTree(node, parentElement, depth = 0, isRoot = false) {
|
1844 |
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
1845 |
-
const element = document.createElement('div');
|
1846 |
-
element.className = 'dom-node';
|
1847 |
-
element.style.marginLeft = `${depth * 15}px`;
|
1848 |
-
element.dataset.elementId = node.id || Math.random().toString(36).substr(2, 9);
|
1849 |
-
|
1850 |
-
// 右クリックイベント
|
1851 |
-
element.oncontextmenu = (e) => {
|
1852 |
-
e.preventDefault();
|
1853 |
-
selectedElement = node;
|
1854 |
-
selectedDOMNode = element;
|
1855 |
-
|
1856 |
-
document.querySelectorAll('.dom-node').forEach(el => el.classList.remove('selected'));
|
1857 |
-
element.classList.add('selected');
|
1858 |
-
|
1859 |
-
// HTML要素にはコンテキストメニューを表示しない
|
1860 |
-
if (node !== document.documentElement) {
|
1861 |
-
contextMenu.style.display = 'block';
|
1862 |
-
contextMenu.style.left = `${e.pageX}px`;
|
1863 |
-
contextMenu.style.top = `${e.pageY}px`;
|
1864 |
-
}
|
1865 |
-
|
1866 |
-
updateCSSPanel(node);
|
1867 |
-
};
|
1868 |
-
|
1869 |
-
// 左クリックで選択
|
1870 |
-
element.onclick = (e) => {
|
1871 |
-
if (e.target.classList.contains('dom-toggle')) return;
|
1872 |
-
|
1873 |
-
e.stopPropagation();
|
1874 |
-
selectedElement = node;
|
1875 |
-
selectedDOMNode = element;
|
1876 |
-
|
1877 |
-
document.querySelectorAll('.dom-node').forEach(el => el.classList.remove('selected'));
|
1878 |
-
element.classList.add('selected');
|
1879 |
-
|
1880 |
-
updateCSSPanel(node);
|
1881 |
-
};
|
1882 |
-
|
1883 |
-
// 子要素がある場合はトグルボタンを追加
|
1884 |
-
const hasChildren = node.childNodes.length > 0 &&
|
1885 |
-
!(node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE && !node.childNodes[0].textContent.trim());
|
1886 |
-
|
1887 |
-
if (hasChildren) {
|
1888 |
-
const toggle = document.createElement('div');
|
1889 |
-
toggle.className = 'dom-toggle';
|
1890 |
-
toggle.onclick = (e) => {
|
1891 |
-
e.stopPropagation();
|
1892 |
-
const children = element.querySelector('.dom-children');
|
1893 |
-
if (children) {
|
1894 |
-
if (children.style.maxHeight === '0px') {
|
1895 |
-
children.style.maxHeight = children.scrollHeight + 'px';
|
1896 |
-
toggle.classList.remove('collapsed');
|
1897 |
-
} else {
|
1898 |
-
children.style.maxHeight = '0px';
|
1899 |
-
toggle.classList.add('collapsed');
|
1900 |
-
}
|
1901 |
-
}
|
1902 |
-
};
|
1903 |
-
element.appendChild(toggle);
|
1904 |
-
}
|
1905 |
-
|
1906 |
-
// タグ名(HTML要素は編集不可)
|
1907 |
-
const tag = document.createElement('span');
|
1908 |
-
tag.className = 'dom-tag';
|
1909 |
-
tag.textContent = `<${node.tagName.toLowerCase()}`;
|
1910 |
-
|
1911 |
-
if (node !== document.documentElement) {
|
1912 |
-
tag.classList.add('editable');
|
1913 |
-
tag.onclick = (e) => {
|
1914 |
-
e.stopPropagation();
|
1915 |
-
startInlineEdit(tag, node.tagName.toLowerCase(), (newValue) => {
|
1916 |
-
const newElement = document.createElement(newValue);
|
1917 |
-
Array.from(node.attributes).forEach(attr => {
|
1918 |
-
newElement.setAttribute(attr.name, attr.value);
|
1919 |
-
});
|
1920 |
-
newElement.innerHTML = node.innerHTML;
|
1921 |
-
node.parentNode.replaceChild(newElement, node);
|
1922 |
-
selectedElement = newElement;
|
1923 |
-
refreshElementsPanel();
|
1924 |
-
});
|
1925 |
-
};
|
1926 |
-
}
|
1927 |
-
|
1928 |
-
element.appendChild(tag);
|
1929 |
-
|
1930 |
-
// 属性(HTML要素は編集不可)
|
1931 |
-
Array.from(node.attributes).forEach(attr => {
|
1932 |
-
const attrSpan = document.createElement('span');
|
1933 |
-
attrSpan.className = 'dom-attr';
|
1934 |
-
attrSpan.textContent = ` ${attr.name}="${attr.value}"`;
|
1935 |
-
|
1936 |
-
if (node !== document.documentElement) {
|
1937 |
-
attrSpan.classList.add('editable');
|
1938 |
-
attrSpan.onclick = (e) => {
|
1939 |
-
e.stopPropagation();
|
1940 |
-
startInlineEdit(attrSpan, attr.value, (newValue) => {
|
1941 |
-
node.setAttribute(attr.name, newValue);
|
1942 |
-
refreshElementsPanel();
|
1943 |
-
});
|
1944 |
-
};
|
1945 |
-
}
|
1946 |
-
|
1947 |
-
element.appendChild(attrSpan);
|
1948 |
-
});
|
1949 |
-
|
1950 |
-
element.appendChild(document.createTextNode('>'));
|
1951 |
-
|
1952 |
-
if (hasChildren) {
|
1953 |
-
const childrenContainer = document.createElement('div');
|
1954 |
-
childrenContainer.className = 'dom-children';
|
1955 |
-
childrenContainer.style.maxHeight = isRoot ? 'none' : '0px';
|
1956 |
-
|
1957 |
-
node.childNodes.forEach(child => {
|
1958 |
-
buildDOMTree(child, childrenContainer, depth + 1);
|
1959 |
-
});
|
1960 |
-
|
1961 |
-
if (node.tagName.toLowerCase() !== 'br') {
|
1962 |
-
const closeTag = document.createElement('div');
|
1963 |
-
closeTag.style.marginLeft = `${depth * 15}px`;
|
1964 |
-
closeTag.innerHTML = `<span class="dom-tag"></${node.tagName.toLowerCase()}></span>`;
|
1965 |
-
childrenContainer.appendChild(closeTag);
|
1966 |
-
}
|
1967 |
-
|
1968 |
-
element.appendChild(childrenContainer);
|
1969 |
-
}
|
1970 |
-
|
1971 |
-
parentElement.appendChild(element);
|
1972 |
-
} else if (node.nodeType === Node.TEXT_NODE && node.textContent.trim()) {
|
1973 |
-
const text = document.createElement('div');
|
1974 |
-
text.style.marginLeft = `${depth * 15}px`;
|
1975 |
-
text.className = 'dom-text editable';
|
1976 |
-
text.textContent = `"${node.textContent.trim()}"`;
|
1977 |
-
text.onclick = (e) => {
|
1978 |
-
e.stopPropagation();
|
1979 |
-
startInlineEdit(text, node.textContent.trim(), (newValue) => {
|
1980 |
-
node.textContent = newValue;
|
1981 |
-
refreshElementsPanel();
|
1982 |
-
});
|
1983 |
-
};
|
1984 |
-
parentElement.appendChild(text);
|
1985 |
-
}
|
1986 |
-
}
|
1987 |
-
|
1988 |
-
// CSSプロパティ編集
|
1989 |
-
function editCSSProperty(element, propName, styleType) {
|
1990 |
-
let currentValue = '';
|
1991 |
-
|
1992 |
-
if (styleType === 'style') {
|
1993 |
-
currentValue = element.style[propName];
|
1994 |
-
}
|
1995 |
-
|
1996 |
-
const newValue = prompt(`${propName} の新しい値を入力`, currentValue);
|
1997 |
-
|
1998 |
-
if (newValue !== null) {
|
1999 |
-
if (styleType === 'style') {
|
2000 |
-
element.style[propName] = newValue;
|
2001 |
-
}
|
2002 |
-
|
2003 |
-
updateCSSPanel(element);
|
2004 |
-
refreshElementsPanel();
|
2005 |
-
}
|
2006 |
-
}
|
2007 |
-
|
2008 |
-
// DOM変更を監視
|
2009 |
-
observer.observe(document.documentElement, {
|
2010 |
-
childList: true,
|
2011 |
-
subtree: true,
|
2012 |
-
attributes: true,
|
2013 |
-
characterData: true
|
2014 |
-
});
|
2015 |
-
|
2016 |
-
setTimeout(() => {
|
2017 |
-
refreshElementsPanel();
|
2018 |
-
}, 0);
|
2019 |
-
|
2020 |
-
return panel;
|
2021 |
-
}
|
2022 |
|
2023 |
// 開発者ツール表示/非表示
|
2024 |
function toggleDevTools() {
|
|
|
1731 |
}
|
1732 |
}
|
1733 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1734 |
|
1735 |
// 開発者ツール表示/非表示
|
1736 |
function toggleDevTools() {
|