RobinsAIWorld commited on
Commit
2345497
·
verified ·
1 Parent(s): d1b354f

🐳 10/02 - 14:04 - It's not syncing right to left, and not in resal-time letter by letter--so the changes in the left get overwritten and lost

Browse files
Files changed (1) hide show
  1. script.js +82 -38
script.js CHANGED
@@ -43,6 +43,12 @@ document.addEventListener('DOMContentLoaded', function() {
43
  let historyIndex = -1;
44
  const MAX_HISTORY = 50;
45
 
 
 
 
 
 
 
46
  // Track all editable fields for TAB navigation
47
  let editableFields = [];
48
  let currentFieldIndex = -1;
@@ -460,18 +466,23 @@ document.addEventListener('DOMContentLoaded', function() {
460
  // Save on blur or Enter
461
  const saveEdit = () => {
462
  const newValue = input.value.trim();
463
- input.parentNode.replaceChild(span, span);
464
 
465
  if (type === 'key') {
466
  // Rename the key
467
- if (newValue !== key) {
468
  renameKey(parentKey, key, newValue);
 
 
 
469
  }
470
  } else {
471
  // Update the value
472
  const parsedValue = parseValue(newValue);
473
  if (JSON.stringify(parsedValue) !== JSON.stringify(currentValue)) {
474
  updateValue(parentKey, key, parsedValue);
 
 
 
475
  }
476
  }
477
  };
@@ -536,10 +547,12 @@ document.addEventListener('DOMContentLoaded', function() {
536
  // Update a value
537
  function updateValue(parentKey, key, newValue) {
538
  if (parentKey === 'root') {
539
- jsonData[key] = newValue;
 
 
540
  } else {
541
  const parent = findElementByKey(jsonData, parentKey);
542
- if (parent && typeof parent === 'object') {
543
  parent[key] = newValue;
544
  }
545
  }
@@ -570,21 +583,31 @@ document.addEventListener('DOMContentLoaded', function() {
570
  // Insert a new field after the current one
571
  function insertNewField(currentFieldData) {
572
  const { key, parentKey } = currentFieldData;
 
 
 
 
 
 
 
573
 
574
  if (parentKey === 'root') {
575
  const keys = Object.keys(jsonData);
576
  const index = keys.indexOf(key);
577
- const newKey = 'newField';
578
-
579
  const newData = {};
580
- keys.forEach((k, i) => {
581
- newData[k] = jsonData[k];
582
- if (i === index) {
583
- newData[newKey] = '';
584
- }
585
- });
586
  if (index === -1 || index === keys.length - 1) {
 
 
587
  newData[newKey] = '';
 
 
 
 
 
 
 
 
588
  }
589
 
590
  jsonData = newData;
@@ -593,21 +616,27 @@ document.addEventListener('DOMContentLoaded', function() {
593
  if (parent && typeof parent === 'object' && !Array.isArray(parent)) {
594
  const keys = Object.keys(parent);
595
  const index = keys.indexOf(key);
596
- const newKey = 'newField';
597
-
598
  const newData = {};
599
- keys.forEach((k, i) => {
600
- newData[k] = parent[k];
601
- if (i === index) {
602
- newData[newKey] = '';
603
- }
604
- });
605
  if (index === -1 || index === keys.length - 1) {
 
 
606
  newData[newKey] = '';
 
 
 
 
 
 
 
 
607
  }
608
 
609
  Object.keys(parent).forEach(k => delete parent[k]);
610
  Object.assign(parent, newData);
 
 
 
611
  }
612
  }
613
 
@@ -650,14 +679,17 @@ document.addEventListener('DOMContentLoaded', function() {
650
  return null;
651
  }
652
 
653
- // Update JSON output
654
  function updateOutput() {
655
  if (isApplyingChanges) return;
 
 
656
  try {
657
  const jsonString = JSON.stringify(jsonData, null, 2);
658
  jsonOutput.value = jsonString;
659
  jsonOutput.style.borderColor = '#10b981';
660
  validationStatus.innerHTML = '<i class="fas fa-check-circle text-green-500"></i><span class="text-green-600">Valid JSON</span>';
 
661
  } catch (e) {
662
  jsonOutput.style.borderColor = '#ef4444';
663
  validationStatus.innerHTML = '<i class="fas fa-exclamation-circle text-red-500"></i><span class="text-red-600">Invalid JSON</span>';
@@ -665,7 +697,7 @@ document.addEventListener('DOMContentLoaded', function() {
665
  }
666
 
667
  // Apply changes from code editor to visual editor
668
- function applyCodeChanges() {
669
  if (!jsonOutput.value.trim()) return false;
670
  try {
671
  const newData = JSON.parse(jsonOutput.value);
@@ -675,22 +707,44 @@ document.addEventListener('DOMContentLoaded', function() {
675
  updateOutput();
676
  saveToHistory();
677
  isApplyingChanges = false;
678
- showNotification('Changes applied successfully!');
 
 
 
679
  return true;
680
  } catch (e) {
681
- showNotification('Invalid JSON: ' + e.message);
682
  jsonOutput.style.borderColor = '#ef4444';
683
  validationStatus.innerHTML = '<i class="fas fa-exclamation-circle text-red-500"></i><span class="text-red-600">Invalid JSON</span>';
684
  return false;
685
  }
686
  }
687
 
688
- // Real-time validation of code editor
689
  jsonOutput.addEventListener('input', () => {
 
 
 
690
  try {
691
  JSON.parse(jsonOutput.value);
692
  jsonOutput.style.borderColor = '#10b981';
693
  validationStatus.innerHTML = '<i class="fas fa-check-circle text-green-500"></i><span class="text-green-600">Valid JSON</span>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
694
  } catch (e) {
695
  jsonOutput.style.borderColor = '#ef4444';
696
  validationStatus.innerHTML = '<i class="fas fa-exclamation-circle text-red-500"></i><span class="text-red-600">Invalid JSON</span>';
@@ -698,27 +752,17 @@ document.addEventListener('DOMContentLoaded', function() {
698
  });
699
 
700
  // Apply button click
701
- applyCodeBtn.addEventListener('click', applyCodeChanges);
702
 
703
  // Auto-apply on Ctrl+Enter or Cmd+Enter
704
  jsonOutput.addEventListener('keydown', (e) => {
705
  if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
706
  e.preventDefault();
707
- applyCodeChanges();
 
708
  }
709
  });
710
 
711
- // Auto-apply on blur (when clicking away)
712
- jsonOutput.addEventListener('blur', () => {
713
- const autoSaveStatus = document.getElementById('autoSaveStatus');
714
- if (applyCodeChanges()) {
715
- autoSaveStatus.classList.remove('hidden');
716
- setTimeout(() => {
717
- autoSaveStatus.classList.add('hidden');
718
- }, 2000);
719
- }
720
- }, true);
721
-
722
  // Paste in JSON output pane
723
  jsonOutput.addEventListener('paste', (e) => {
724
  e.preventDefault();
 
43
  let historyIndex = -1;
44
  const MAX_HISTORY = 50;
45
 
46
+ // Track editor states to prevent data loss
47
+ let leftEditorModified = false;
48
+ let rightEditorModified = false;
49
+ let rightEditorLastModified = 0;
50
+ let autoApplyTimeout = null;
51
+
52
  // Track all editable fields for TAB navigation
53
  let editableFields = [];
54
  let currentFieldIndex = -1;
 
466
  // Save on blur or Enter
467
  const saveEdit = () => {
468
  const newValue = input.value.trim();
 
469
 
470
  if (type === 'key') {
471
  // Rename the key
472
+ if (newValue !== key && newValue !== '') {
473
  renameKey(parentKey, key, newValue);
474
+ } else {
475
+ // Just restore the span without saving
476
+ input.parentNode.replaceChild(span, input);
477
  }
478
  } else {
479
  // Update the value
480
  const parsedValue = parseValue(newValue);
481
  if (JSON.stringify(parsedValue) !== JSON.stringify(currentValue)) {
482
  updateValue(parentKey, key, parsedValue);
483
+ } else {
484
+ // Just restore the span without saving
485
+ input.parentNode.replaceChild(span, input);
486
  }
487
  }
488
  };
 
547
  // Update a value
548
  function updateValue(parentKey, key, newValue) {
549
  if (parentKey === 'root') {
550
+ if (jsonData[key] !== undefined) {
551
+ jsonData[key] = newValue;
552
+ }
553
  } else {
554
  const parent = findElementByKey(jsonData, parentKey);
555
+ if (parent && typeof parent === 'object' && parent[key] !== undefined) {
556
  parent[key] = newValue;
557
  }
558
  }
 
583
  // Insert a new field after the current one
584
  function insertNewField(currentFieldData) {
585
  const { key, parentKey } = currentFieldData;
586
+ let fieldCounter = 1;
587
+ let newKey = 'newField';
588
+
589
+ // Generate unique key name
590
+ while (getValue(parentKey, newKey) !== undefined) {
591
+ newKey = `newField${fieldCounter++}`;
592
+ }
593
 
594
  if (parentKey === 'root') {
595
  const keys = Object.keys(jsonData);
596
  const index = keys.indexOf(key);
 
 
597
  const newData = {};
598
+
 
 
 
 
 
599
  if (index === -1 || index === keys.length - 1) {
600
+ // Append at the end
601
+ Object.assign(newData, jsonData);
602
  newData[newKey] = '';
603
+ } else {
604
+ // Insert after current
605
+ keys.forEach((k, i) => {
606
+ newData[k] = jsonData[k];
607
+ if (i === index) {
608
+ newData[newKey] = '';
609
+ }
610
+ });
611
  }
612
 
613
  jsonData = newData;
 
616
  if (parent && typeof parent === 'object' && !Array.isArray(parent)) {
617
  const keys = Object.keys(parent);
618
  const index = keys.indexOf(key);
 
 
619
  const newData = {};
620
+
 
 
 
 
 
621
  if (index === -1 || index === keys.length - 1) {
622
+ // Append at the end
623
+ Object.assign(newData, parent);
624
  newData[newKey] = '';
625
+ } else {
626
+ // Insert after current
627
+ keys.forEach((k, i) => {
628
+ newData[k] = parent[k];
629
+ if (i === index) {
630
+ newData[newKey] = '';
631
+ }
632
+ });
633
  }
634
 
635
  Object.keys(parent).forEach(k => delete parent[k]);
636
  Object.assign(parent, newData);
637
+ } else if (parent && Array.isArray(parent)) {
638
+ // For arrays, push new empty string
639
+ parent.push('');
640
  }
641
  }
642
 
 
679
  return null;
680
  }
681
 
682
+ // Update JSON output (left → right sync)
683
  function updateOutput() {
684
  if (isApplyingChanges) return;
685
+ leftEditorModified = true;
686
+ leftEditorLastModified = Date.now();
687
  try {
688
  const jsonString = JSON.stringify(jsonData, null, 2);
689
  jsonOutput.value = jsonString;
690
  jsonOutput.style.borderColor = '#10b981';
691
  validationStatus.innerHTML = '<i class="fas fa-check-circle text-green-500"></i><span class="text-green-600">Valid JSON</span>';
692
+ rightEditorModified = false;
693
  } catch (e) {
694
  jsonOutput.style.borderColor = '#ef4444';
695
  validationStatus.innerHTML = '<i class="fas fa-exclamation-circle text-red-500"></i><span class="text-red-600">Invalid JSON</span>';
 
697
  }
698
 
699
  // Apply changes from code editor to visual editor
700
+ function applyCodeChanges(showMsg = true) {
701
  if (!jsonOutput.value.trim()) return false;
702
  try {
703
  const newData = JSON.parse(jsonOutput.value);
 
707
  updateOutput();
708
  saveToHistory();
709
  isApplyingChanges = false;
710
+ rightEditorModified = false;
711
+ if (showMsg) {
712
+ showNotification('Changes applied successfully!');
713
+ }
714
  return true;
715
  } catch (e) {
 
716
  jsonOutput.style.borderColor = '#ef4444';
717
  validationStatus.innerHTML = '<i class="fas fa-exclamation-circle text-red-500"></i><span class="text-red-600">Invalid JSON</span>';
718
  return false;
719
  }
720
  }
721
 
722
+ // Real-time validation and debounced auto-apply
723
  jsonOutput.addEventListener('input', () => {
724
+ rightEditorModified = true;
725
+ rightEditorLastModified = Date.now();
726
+
727
  try {
728
  JSON.parse(jsonOutput.value);
729
  jsonOutput.style.borderColor = '#10b981';
730
  validationStatus.innerHTML = '<i class="fas fa-check-circle text-green-500"></i><span class="text-green-600">Valid JSON</span>';
731
+
732
+ // Clear previous timeout
733
+ if (autoApplyTimeout) {
734
+ clearTimeout(autoApplyTimeout);
735
+ }
736
+
737
+ // Set debounced auto-apply (1.5 seconds after user stops typing)
738
+ autoApplyTimeout = setTimeout(() => {
739
+ // Only auto-apply if left editor hasn't been modified recently
740
+ const timeSinceLeftModified = Date.now() - (leftEditorLastModified || 0);
741
+ if (!leftEditorModified || timeSinceLeftModified > 2000) {
742
+ if (applyCodeChanges(false)) {
743
+ showSavedIndicator();
744
+ }
745
+ }
746
+ }, 1500);
747
+
748
  } catch (e) {
749
  jsonOutput.style.borderColor = '#ef4444';
750
  validationStatus.innerHTML = '<i class="fas fa-exclamation-circle text-red-500"></i><span class="text-red-600">Invalid JSON</span>';
 
752
  });
753
 
754
  // Apply button click
755
+ applyCodeBtn.addEventListener('click', () => applyCodeChanges(true));
756
 
757
  // Auto-apply on Ctrl+Enter or Cmd+Enter
758
  jsonOutput.addEventListener('keydown', (e) => {
759
  if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
760
  e.preventDefault();
761
+ e.stopPropagation();
762
+ applyCodeChanges(true);
763
  }
764
  });
765
 
 
 
 
 
 
 
 
 
 
 
 
766
  // Paste in JSON output pane
767
  jsonOutput.addEventListener('paste', (e) => {
768
  e.preventDefault();