soiz1 commited on
Commit
f687325
·
verified ·
1 Parent(s): af1c1d6

Update dev-tools.js

Browse files
Files changed (1) hide show
  1. dev-tools.js +96 -77
dev-tools.js CHANGED
@@ -618,11 +618,20 @@
618
  if (!selectedElement) return;
619
 
620
  switch (action) {
621
- case 'edit-html':
622
- startInlineEdit(selectedDOMNode, selectedElement.outerHTML, (newValue) => {
623
- selectedElement.outerHTML = newValue;
624
- refreshElementsPanel();
625
- });
 
 
 
 
 
 
 
 
 
626
  break;
627
  case 'add-attribute':
628
  const attrName = prompt('属性名を入力');
@@ -676,7 +685,7 @@
676
  }
677
 
678
  // インライン編集関数
679
- function startInlineEdit(element, initialValue, callback) {
680
  if (activeEditElement) return;
681
 
682
  const originalValue = element.textContent;
@@ -695,46 +704,51 @@
695
  input.select();
696
 
697
  activeEditElement = {
698
- element: element,
699
- input: input,
700
- callback: callback
701
  };
702
 
703
  const clickOutsideHandler = (e) => {
704
- if (!input.contains(e.target)) {
705
- finishInlineEdit();
706
- }
707
  };
708
 
709
  input.addEventListener('keydown', (e) => {
710
- if (e.key === 'Enter') {
711
- finishInlineEdit();
712
- } else if (e.key === 'Escape') {
713
- cancelInlineEdit();
714
- }
715
  });
716
 
717
  setTimeout(() => {
718
- document.addEventListener('click', clickOutsideHandler);
719
  }, 0);
720
 
721
  function finishInlineEdit() {
722
- if (input.value !== originalValue && callback) {
723
- callback(input.value);
724
- }
725
- cleanup();
 
 
 
 
 
726
  }
727
 
728
  function cancelInlineEdit() {
729
- cleanup();
730
  }
731
 
732
  function cleanup() {
733
- document.removeEventListener('click', clickOutsideHandler);
734
- input.remove();
735
- activeEditElement = null;
736
  }
737
- }
738
 
739
  // Consoleパネル作成
740
  function createConsolePanel() {
@@ -918,69 +932,74 @@
918
  }
919
 
920
  // DOMツリー構築
921
- function buildDOMTree(node, parentElement, depth = 0) {
922
- if (node.nodeType === Node.ELEMENT_NODE) {
923
  const element = document.createElement('div');
924
  element.className = 'dom-node';
925
  element.style.marginLeft = `${depth * 15}px`;
926
  element.dataset.elementId = node.id || Math.random().toString(36).substr(2, 9);
927
 
 
928
  element.oncontextmenu = (e) => {
929
- e.preventDefault();
930
- selectedElement = node;
931
- selectedDOMNode = element;
932
-
933
- document.querySelectorAll('.dom-node').forEach(el => el.classList.remove('selected'));
934
- element.classList.add('selected');
935
-
936
- contextMenu.style.display = 'block';
937
- contextMenu.style.left = `${e.pageX}px`;
938
- contextMenu.style.top = `${e.pageY}px`;
939
-
940
- updateCSSPanel(node);
941
- };
942
-
943
- element.onclick = (e) => {
944
- e.stopPropagation();
945
- selectedElement = node;
946
- selectedDOMNode = element;
947
-
948
- document.querySelectorAll('.dom-node').forEach(el => el.classList.remove('selected'));
949
- element.classList.add('selected');
950
-
951
- updateCSSPanel(node);
952
  };
953
 
 
954
  const tag = document.createElement('span');
955
- tag.className = 'dom-tag editable';
956
  tag.textContent = `<${node.tagName.toLowerCase()}`;
957
- tag.onclick = (e) => {
958
- e.stopPropagation();
959
- startInlineEdit(tag, node.tagName.toLowerCase(), (newValue) => {
960
- const newElement = document.createElement(newValue);
961
- Array.from(node.attributes).forEach(attr => {
962
- newElement.setAttribute(attr.name, attr.value);
963
- });
964
- newElement.innerHTML = node.innerHTML;
965
- node.parentNode.replaceChild(newElement, node);
966
- selectedElement = newElement;
967
- refreshElementsPanel();
968
- });
969
- };
 
 
 
 
 
970
  element.appendChild(tag);
971
 
 
972
  Array.from(node.attributes).forEach(attr => {
973
- const attrSpan = document.createElement('span');
974
- attrSpan.className = 'dom-attr editable';
975
- attrSpan.textContent = ` ${attr.name}="${attr.value}"`;
976
- attrSpan.onclick = (e) => {
977
- e.stopPropagation();
978
- startInlineEdit(attrSpan, attr.value, (newValue) => {
979
- node.setAttribute(attr.name, newValue);
980
- refreshElementsPanel();
981
- });
982
- };
983
- element.appendChild(attrSpan);
 
 
 
 
 
984
  });
985
 
986
  element.appendChild(document.createTextNode('>'));
 
618
  if (!selectedElement) return;
619
 
620
  switch (action) {
621
+ case 'edit-html':
622
+ // document.documentElement(html要素)は編集不可
623
+ if (selectedElement === document.documentElement) {
624
+ alert('ルートHTML要素は直接編集できません');
625
+ return;
626
+ }
627
+ startInlineEdit(selectedDOMNode, selectedElement.outerHTML, (newValue) => {
628
+ try {
629
+ selectedElement.outerHTML = newValue;
630
+ refreshElementsPanel();
631
+ } catch (e) {
632
+ alert('この要素は編集できません: ' + e.message);
633
+ }
634
+ });
635
  break;
636
  case 'add-attribute':
637
  const attrName = prompt('属性名を入力');
 
685
  }
686
 
687
  // インライン編集関数
688
+ function startInlineEdit(element, initialValue, callback) {
689
  if (activeEditElement) return;
690
 
691
  const originalValue = element.textContent;
 
704
  input.select();
705
 
706
  activeEditElement = {
707
+ element: element,
708
+ input: input,
709
+ callback: callback
710
  };
711
 
712
  const clickOutsideHandler = (e) => {
713
+ if (!input.contains(e.target)) {
714
+ finishInlineEdit();
715
+ }
716
  };
717
 
718
  input.addEventListener('keydown', (e) => {
719
+ if (e.key === 'Enter') {
720
+ finishInlineEdit();
721
+ } else if (e.key === 'Escape') {
722
+ cancelInlineEdit();
723
+ }
724
  });
725
 
726
  setTimeout(() => {
727
+ document.addEventListener('click', clickOutsideHandler);
728
  }, 0);
729
 
730
  function finishInlineEdit() {
731
+ try {
732
+ if (input.value !== originalValue && callback) {
733
+ callback(input.value);
734
+ }
735
+ } catch (e) {
736
+ alert('編集に失敗しました: ' + e.message);
737
+ } finally {
738
+ cleanup();
739
+ }
740
  }
741
 
742
  function cancelInlineEdit() {
743
+ cleanup();
744
  }
745
 
746
  function cleanup() {
747
+ document.removeEventListener('click', clickOutsideHandler);
748
+ input.remove();
749
+ activeEditElement = null;
750
  }
751
+ }
752
 
753
  // Consoleパネル作成
754
  function createConsolePanel() {
 
932
  }
933
 
934
  // DOMツリー構築
935
+ function buildDOMTree(node, parentElement, depth = 0) {
936
+ if (node.nodeType === Node.ELEMENT_NODE) {
937
  const element = document.createElement('div');
938
  element.className = 'dom-node';
939
  element.style.marginLeft = `${depth * 15}px`;
940
  element.dataset.elementId = node.id || Math.random().toString(36).substr(2, 9);
941
 
942
+ // 右クリックイベント
943
  element.oncontextmenu = (e) => {
944
+ e.preventDefault();
945
+ selectedElement = node;
946
+ selectedDOMNode = element;
947
+
948
+ document.querySelectorAll('.dom-node').forEach(el => el.classList.remove('selected'));
949
+ element.classList.add('selected');
950
+
951
+ // HTML要素にはコンテキストメニューを表示しない
952
+ if (node !== document.documentElement) {
953
+ contextMenu.style.display = 'block';
954
+ contextMenu.style.left = `${e.pageX}px`;
955
+ contextMenu.style.top = `${e.pageY}px`;
956
+ }
957
+
958
+ updateCSSPanel(node);
 
 
 
 
 
 
 
 
959
  };
960
 
961
+ // タグ名(HTML要素は編集不可)
962
  const tag = document.createElement('span');
963
+ tag.className = 'dom-tag';
964
  tag.textContent = `<${node.tagName.toLowerCase()}`;
965
+
966
+ if (node !== document.documentElement) {
967
+ tag.classList.add('editable');
968
+ tag.onclick = (e) => {
969
+ e.stopPropagation();
970
+ startInlineEdit(tag, node.tagName.toLowerCase(), (newValue) => {
971
+ const newElement = document.createElement(newValue);
972
+ Array.from(node.attributes).forEach(attr => {
973
+ newElement.setAttribute(attr.name, attr.value);
974
+ });
975
+ newElement.innerHTML = node.innerHTML;
976
+ node.parentNode.replaceChild(newElement, node);
977
+ selectedElement = newElement;
978
+ refreshElementsPanel();
979
+ });
980
+ };
981
+ }
982
+
983
  element.appendChild(tag);
984
 
985
+ // 属性(HTML要素は編集不可)
986
  Array.from(node.attributes).forEach(attr => {
987
+ const attrSpan = document.createElement('span');
988
+ attrSpan.className = 'dom-attr';
989
+ attrSpan.textContent = ` ${attr.name}="${attr.value}"`;
990
+
991
+ if (node !== document.documentElement) {
992
+ attrSpan.classList.add('editable');
993
+ attrSpan.onclick = (e) => {
994
+ e.stopPropagation();
995
+ startInlineEdit(attrSpan, attr.value, (newValue) => {
996
+ node.setAttribute(attr.name, newValue);
997
+ refreshElementsPanel();
998
+ });
999
+ };
1000
+ }
1001
+
1002
+ element.appendChild(attrSpan);
1003
  });
1004
 
1005
  element.appendChild(document.createTextNode('>'));