RichardSocher commited on
Commit
9dcc7bc
·
verified ·
1 Parent(s): d7bf09b

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +527 -281
index.html CHANGED
@@ -273,35 +273,54 @@
273
  position: fixed;
274
  top: 50%;
275
  left: 50%;
276
- transform: translate(-50%, -50%);
277
  background: white;
278
  padding: 2rem;
279
  border-radius: 12px;
280
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
281
  z-index: 100;
282
  max-width: 400px;
283
- display: none;
 
 
 
 
 
 
 
 
284
  }
285
 
286
  .node-popup h3 {
287
  margin-bottom: 0.5rem;
288
  color: #444;
 
289
  }
290
 
291
  .node-popup .era {
292
  font-size: 0.9rem;
293
  margin-bottom: 1rem;
294
  font-weight: bold;
 
 
 
 
 
295
  }
296
 
297
  .node-popup .description {
298
  margin-bottom: 1.5rem;
299
  line-height: 1.6;
 
300
  }
301
 
302
  .node-popup .prerequisites {
303
  font-size: 0.9rem;
304
  color: #666;
 
 
 
 
305
  }
306
 
307
  .close-popup {
@@ -311,66 +330,101 @@
311
  font-size: 1.5rem;
312
  cursor: pointer;
313
  color: #888;
 
 
 
 
 
 
314
  }
315
 
316
  .add-node-form {
317
  position: fixed;
318
  top: 50%;
319
  left: 50%;
320
- transform: translate(-50%, -50%);
321
  background: white;
322
- padding: 2rem;
323
  border-radius: 12px;
324
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
325
  z-index: 100;
326
- max-width: 400px;
327
- display: none;
 
 
 
 
 
 
 
 
 
 
 
328
  }
329
 
330
  .add-node-form h2 {
331
- margin-bottom: 1.5rem;
332
  color: #444;
 
 
 
333
  }
334
 
335
  .form-group {
336
- margin-bottom: 1rem;
337
  }
338
 
339
  .form-group label {
340
  display: block;
341
- margin-bottom: 0.5rem;
342
  font-weight: bold;
343
  color: #555;
 
344
  }
345
 
346
  .form-group input,
347
  .form-group select,
348
  .form-group textarea {
349
  width: 100%;
350
- padding: 0.8rem;
351
  border: 1px solid #ddd;
352
  border-radius: 6px;
353
  font-family: inherit;
 
 
 
 
 
 
 
 
 
 
354
  }
355
 
356
  .form-group textarea {
357
- min-height: 100px;
358
  resize: vertical;
359
  }
360
 
361
  .form-actions {
362
  display: flex;
363
  justify-content: flex-end;
364
- gap: 0.8rem;
365
- margin-top: 1.5rem;
 
 
366
  }
367
 
368
  .form-actions button {
369
- padding: 0.8rem 1.5rem;
370
  border: none;
371
  border-radius: 6px;
372
  cursor: pointer;
373
  font-weight: bold;
 
 
374
  }
375
 
376
  .form-cancel {
@@ -378,42 +432,71 @@
378
  color: #555;
379
  }
380
 
 
 
 
 
381
  .form-submit {
382
  background-color: #9d4edd;
383
  color: white;
384
  }
385
 
 
 
 
 
386
  .checkbox-group {
387
- margin-top: 0.5rem;
 
 
 
 
 
 
388
  }
389
 
390
  .checkbox-item {
391
  display: flex;
392
  align-items: center;
393
- margin-bottom: 0.5rem;
 
 
 
 
 
 
 
 
394
  }
395
 
396
  .checkbox-item input {
397
  width: auto;
398
- margin-right: 0.5rem;
 
399
  }
400
 
401
  .icon-selecter {
402
  display: grid;
403
  grid-template-columns: repeat(4, 1fr);
404
- gap: 0.5rem;
405
- margin-top: 0.5rem;
 
 
 
 
 
406
  }
407
 
408
  .icon-option {
409
  display: flex;
410
  flex-direction: column;
411
  align-items: center;
412
- padding: 0.5rem;
413
  border: 1px solid #ddd;
414
  border-radius: 4px;
415
  cursor: pointer;
416
  transition: all 0.2s;
 
417
  }
418
 
419
  .icon-option:hover {
@@ -427,8 +510,8 @@
427
  }
428
 
429
  .icon-option i {
430
- font-size: 1.5rem;
431
- margin-bottom: 0.3rem;
432
  }
433
 
434
  footer {
@@ -534,50 +617,100 @@
534
  .toggle-edit-mode.active {
535
  background-color: #4CAF50;
536
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
537
  </style>
538
  </head>
539
  <body>
540
  <header>
541
  <h1>Technology Evolution Tree</h1>
542
- <div class="subtitle">Visualizing humanity's technological progress</div>
543
  </header>
544
 
545
  <div class="container">
546
  <div class="controls">
547
- <button class="era-button era-ancient">Ancient</button>
548
- <button class="era-button era-classical">Classical</button>
549
- <button class="era-button era-medieval">Medieval</button>
550
- <button class="era-button era-industrial">Industrial</button>
551
- <button class="era-button era-modern">Modern</button>
552
- <button class="era-button era-future">Future</button>
553
- <button class="add-tech-btn" id="addTechBtn">
554
- <i class="fas fa-plus"></i> Add Technology
555
- </button>
556
- <button class="toggle-edit-mode" id="toggleEditMode">
557
- Edit Mode: OFF
558
- </button>
 
 
 
 
 
 
 
 
 
559
  </div>
560
 
561
  <div class="tech-tree-container" id="techTreeContainer">
562
- <div class="timeline-bar">
563
- <div class="tech-path" id="techPath"></div>
564
- </div>
565
- <div class="era-labels">
566
- <div>Ancient (4000 BCE)</div>
567
- <div>Classical (500 BCE)</div>
568
- <div>Medieval (500 CE)</div>
569
- <div>Industrial (1700 CE)</div>
570
- <div>Modern (1900 CE)</div>
571
- <div>Future</div>
572
- </div>
573
- <div class="era-line ancient-line"></div>
574
- <div class="era-line classical-line"></div>
575
- <div class="era-line medieval-line"></div>
576
- <div class="era-line industrial-line"></div>
577
- <div class="era-line modern-line"></div>
578
- <div class="era-line future-line"></div>
579
  <div class="tech-tree" id="techTree">
580
- <!-- Technology nodes and connections will be added via JavaScript -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
  </div>
582
  </div>
583
  </div>
@@ -614,7 +747,7 @@
614
 
615
  <div class="form-group">
616
  <label for="techIcon">Icon</label>
617
- <div class="icon-selector" id="iconSelector">
618
  <!-- Icons will be added via JavaScript -->
619
  </div>
620
  </div>
@@ -648,7 +781,7 @@
648
  const techTreeContainer = document.getElementById('techTreeContainer');
649
  const nodePopup = document.getElementById('nodePopup');
650
  const closePopup = document.querySelector('.close-popup');
651
- const techPath = document.getElementById('techPath');
652
  const addTechBtn = document.getElementById('addTechBtn');
653
  const addNodeForm = document.getElementById('addNodeForm');
654
  const techForm = document.getElementById('techForm');
@@ -657,14 +790,14 @@
657
  const prerequisiteCheckboxes = document.getElementById('prerequisiteCheckboxes');
658
  const toggleEditMode = document.getElementById('toggleEditMode');
659
 
660
- let editMode = false;
661
  let selectedIcon = 'fas fa-question';
662
  let techData = [];
663
  let nextId = 1;
664
  let draggingNode = null;
665
  let offsetX, offsetY;
 
666
 
667
- // Common Font Awesome icons for technologies
668
  const commonIcons = [
669
  'fas fa-fire', 'fas fa-wheel', 'fas fa-seedling', 'fas fa-book',
670
  'fas fa-square-root-alt', 'fas fa-hammer', 'fas fa-print',
@@ -672,10 +805,16 @@
672
  'fas fa-car', 'fas fa-plane', 'fas fa-computer', 'fas fa-network-wired',
673
  'fas fa-robot', 'fas fa-atom', 'fas fa-dna', 'fas fa-rocket',
674
  'fas fa-microchip', 'fas fa-brain', 'fas fa-vr-cardboard',
675
- 'fas fa-biohazard', 'fas fa-solar-panel', 'fas fa-wind', 'fas fa-eye'
 
 
 
 
 
 
676
  ];
677
 
678
- // Initialize with some default technologies
679
  initializeTechData();
680
 
681
  // Draw the initial technology tree
@@ -684,14 +823,14 @@
684
  // Technology data initialization
685
  function initializeTechData() {
686
  techData = [
687
- // Ancient Era (top: ~150px)
688
  {
689
  id: nextId++,
690
  name: "Fire",
691
  era: "ancient",
692
  icon: "fas fa-fire",
693
  description: "Mastery of fire allowed for cooking, warmth, protection and became the foundation for later metallurgy and energy technologies.",
694
- x: 200,
695
  y: 150,
696
  prerequisites: []
697
  },
@@ -701,7 +840,7 @@
701
  era: "ancient",
702
  icon: "fas fa-wheel",
703
  description: "The invention of the wheel revolutionized transportation and mechanical applications, enabling carts, potter's wheels, and later complex machinery.",
704
- x: 400,
705
  y: 150,
706
  prerequisites: []
707
  },
@@ -711,51 +850,71 @@
711
  era: "ancient",
712
  icon: "fas fa-seedling",
713
  description: "The domestication of plants led to settled communities, food surplus, and the development of complex societies and specialization.",
714
- x: 600,
715
  y: 150,
716
  prerequisites: [1] // Requires Fire
717
  },
718
-
719
- // Classical Era (top: ~450px)
720
  {
721
  id: nextId++,
722
  name: "Writing",
723
- era: "classical",
724
  icon: "fas fa-book",
725
- description: "The development of writing systems enabled permanent records, complex communication, and the accumulation of knowledge across generations.",
726
- x: 200,
727
- y: 450,
728
  prerequisites: [3] // Requires Agriculture
729
  },
 
 
730
  {
731
  id: nextId++,
732
  name: "Mathematics",
733
  era: "classical",
734
  icon: "fas fa-square-root-alt",
735
- description: "Abstract numerical systems allowed for calculations, engineering, astronomy, and became foundational for all future scientific progress.",
736
- x: 400,
737
  y: 450,
738
  prerequisites: [4] // Requires Writing
739
  },
 
 
 
 
 
 
 
 
 
 
740
  {
741
  id: nextId++,
742
  name: "Metalworking",
743
  era: "classical",
744
  icon: "fas fa-hammer",
745
- description: "Advanced techniques in smelting and forging enabled better tools, weapons, and the beginning of mechanical engineering principles.",
746
- x: 600,
747
  y: 450,
748
  prerequisites: [1] // Requires Fire
749
  },
 
 
 
 
 
 
 
 
 
 
750
 
751
- // Medieval Era (top: ~750px)
752
  {
753
  id: nextId++,
754
  name: "Printing",
755
  era: "medieval",
756
  icon: "fas fa-print",
757
- description: "The printing press revolutionized information distribution, making books more accessible and enabling widespread literacy and education.",
758
- x: 300,
759
  y: 750,
760
  prerequisites: [4] // Requires Writing
761
  },
@@ -764,66 +923,126 @@
764
  name: "Compass",
765
  era: "medieval",
766
  icon: "fas fa-compass",
767
- description: "The magnetic compass enabled reliable navigation at sea, facilitating exploration, trade, and the exchange of ideas across continents.",
 
 
 
 
 
 
 
 
 
 
768
  x: 500,
769
  y: 750,
770
- prerequisites: [6] // Requires Metalworking
 
 
 
 
 
 
 
 
 
 
771
  },
772
 
773
- // Industrial Era (top: ~1050px)
774
  {
775
  id: nextId++,
776
  name: "Steam Engine",
777
  era: "industrial",
778
  icon: "fas fa-train",
779
- description: "The steam engine powered the Industrial Revolution, mechanizing production and transportation on an unprecedented scale.",
780
- x: 300,
781
  y: 1050,
782
- prerequisites: [6] // Requires Metalworking
783
  },
784
  {
785
  id: nextId++,
786
  name: "Electricity",
787
  era: "industrial",
788
  icon: "fas fa-bolt",
789
- description: "Harnessing electricity transformed every aspect of life, from lighting and communication to industrial production and transportation.",
 
 
 
 
 
 
 
 
 
 
790
  x: 500,
791
  y: 1050,
792
- prerequisites: [9] // Requires Steam Engine
 
 
 
 
 
 
 
 
 
 
793
  },
794
 
795
- // Modern Era (top: ~1350px)
796
  {
797
  id: nextId++,
798
  name: "Computing",
799
  era: "modern",
800
  icon: "fas fa-computer",
801
- description: "Digital computing revolutionized information processing, leading to the Information Age and transforming nearly every aspect of modern life.",
 
 
 
 
 
 
 
 
 
 
802
  x: 300,
803
  y: 1350,
804
- prerequisites: [10] // Requires Electricity
 
 
 
 
 
 
 
 
 
 
805
  },
806
  {
807
  id: nextId++,
808
  name: "Internet",
809
  era: "modern",
810
  icon: "fas fa-network-wired",
811
- description: "The Internet created a globally interconnected digital network, revolutionizing communication, commerce, and access to information.",
812
- x: 500,
813
  y: 1350,
814
- prerequisites: [11] // Requires Computing
815
  },
816
 
817
- // Future Era (top: ~1650px)
818
  {
819
  id: nextId++,
820
  name: "AI",
821
  era: "future",
822
  icon: "fas fa-robot",
823
- description: "Artificial Intelligence promises to automate complex tasks, enhance human capabilities, and solve problems beyond human-scale processing.",
824
- x: 300,
825
  y: 1650,
826
- prerequisites: [11, 12] // Requires Computing and Internet
827
  },
828
  {
829
  id: nextId++,
@@ -831,19 +1050,29 @@
831
  era: "future",
832
  icon: "fas fa-atom",
833
  description: "Nuclear fusion could provide nearly limitless clean energy, solving humanity's energy needs while reducing environmental impact.",
 
 
 
 
 
 
 
 
 
 
834
  x: 500,
835
  y: 1650,
836
- prerequisites: [10] // Requires Electricity
837
  },
838
  {
839
  id: nextId++,
840
  name: "Space Colonization",
841
  era: "future",
842
  icon: "fas fa-rocket",
843
- description: "Establishing permanent human settlements beyond Earth would ensure the survival of our species and open new frontiers for exploration and resource utilization.",
844
  x: 700,
845
  y: 1650,
846
- prerequisites: [10, 14] // Requires Electricity and Fusion Power
847
  }
848
  ];
849
  }
@@ -853,6 +1082,25 @@
853
  // Clear existing nodes and connections
854
  techTree.innerHTML = '';
855
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
856
  // Draw connections first (so nodes appear on top)
857
  techData.forEach(tech => {
858
  if (tech.prerequisites && tech.prerequisites.length) {
@@ -877,7 +1125,7 @@
877
  // Create a single technology node
878
  function createTechNode(tech) {
879
  const node = document.createElement('div');
880
- node.className = `tech-node ${tech.era} ${editMode ? 'editable' : ''}`;
881
  node.style.left = `${tech.x}px`;
882
  node.style.top = `${tech.y}px`;
883
  node.dataset.id = tech.id;
@@ -889,49 +1137,22 @@
889
  <div class="tech-name">${tech.name}</div>
890
  <div class="tech-era">${tech.era.charAt(0).toUpperCase() + tech.era.slice(1)}</div>
891
  <div class="drag-handle">↔</div>
892
- <div class="delete-node" title="Delete technology">×</div>
893
  `;
894
 
895
- // Add click event for popup
896
  node.addEventListener('click', (e) => {
897
- // If we're dragging or clicking on the drag handle, don't show the popup
898
- if (draggingNode || e.target.classList.contains('drag-handle') || e.target.classList.contains('delete-node')) {
899
  return;
900
  }
901
 
902
  showTechPopup(tech);
903
-
904
- // Animate the tech path
905
  animateTechPath(tech.era);
906
  });
907
 
908
- // Add delete functionality
909
- const deleteBtn = node.querySelector('.delete-node');
910
- deleteBtn.addEventListener('click', () => {
911
- if (confirm(`Are you sure you want to delete "${tech.name}"? This cannot be undone.`)) {
912
- // Remove this tech from any prerequisite lists
913
- techData.forEach(t => {
914
- if (t.prerequisites && t.prerequisites.includes(tech.id)) {
915
- t.prerequisites = t.prerequisites.filter(id => id !== tech.id);
916
- }
917
- });
918
-
919
- // Remove the tech
920
- techData = techData.filter(t => t.id !== tech.id);
921
-
922
- // Redraw the tree
923
- drawTechTree();
924
- }
925
- });
926
-
927
- // Dragging functionality
928
- const dragHandle = node.querySelector('.drag-handle');
929
-
930
- dragHandle.addEventListener('mousedown', startDrag);
931
- node.addEventListener('mousedown', startDrag);
932
-
933
- function startDrag(e) {
934
- if (!editMode) return;
935
 
936
  // Don't drag if clicking on the delete button
937
  if (e.target.classList.contains('delete-node')) {
@@ -954,46 +1175,107 @@
954
 
955
  document.addEventListener('mousemove', dragNode);
956
  document.addEventListener('mouseup', stopDrag);
957
- }
958
 
959
- function dragNode(e) {
960
- if (!draggingNode) return;
961
-
962
- // Calculate new position
963
- const containerRect = techTreeContainer.getBoundingClientRect();
964
- let newX = e.clientX - containerRect.left - offsetX;
965
- let newY = e.clientY - containerRect.top - offsetY;
966
-
967
- // Constrain movement within container
968
- newX = Math.max(0, Math.min(newX, techTreeContainer.scrollWidth - 100));
969
- newY = Math.max(0, Math.min(newY, techTreeContainer.scrollHeight - 100));
970
-
971
- // Update node position
972
- node.style.left = `${newX}px`;
973
- node.style.top = `${newY}px`;
974
 
975
- // Update position in the tech data
976
- const techId = parseInt(node.dataset.id);
977
- const tech = techData.find(t => t.id === techId);
978
- if (tech) {
979
- tech.x = newX;
980
- tech.y = newY;
 
 
 
 
 
 
981
  }
982
-
983
- // Redraw connections
984
- redrawConnections();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
985
  }
 
 
 
 
 
 
986
 
987
- function stopDrag() {
988
- if (!draggingNode) return;
989
-
990
- draggingNode.style.zIndex = '10';
991
- draggingNode = null;
992
- document.removeEventListener('mousemove', dragNode);
993
- document.removeEventListener('mouseup', stopDrag);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
994
  }
995
 
996
- techTree.appendChild(node);
 
 
 
 
 
 
 
 
 
 
 
997
  }
998
 
999
  // Redraw just the connections (more efficient than redrawing the whole tree)
@@ -1018,29 +1300,15 @@
1018
  });
1019
  }
1020
 
1021
- // Function to draw a connection line between two points
1022
- function drawConnection(x1, y1, x2, y2) {
1023
- const line = document.createElement('div');
1024
- line.className = 'connection';
1025
-
1026
- // Calculate length and angle of the line
1027
- const length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
1028
- const angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
1029
-
1030
- // Style the line
1031
- line.style.width = `${length}px`;
1032
- line.style.left = `${x1}px`;
1033
- line.style.top = `${y1}px`;
1034
- line.style.transform = `rotate(${angle}deg)`;
1035
-
1036
- techTree.insertBefore(line, techTree.firstChild);
1037
- }
1038
-
1039
  // Show technology details popup
1040
  function showTechPopup(tech) {
1041
  document.getElementById('popupTitle').textContent = tech.name;
1042
- document.getElementById('popupEra').textContent =
1043
- `${tech.era.charAt(0).toUpperCase() + tech.era.slice(1)} Era`;
 
 
 
 
1044
  document.getElementById('popupDescription').textContent = tech.description;
1045
 
1046
  if (tech.prerequisites && tech.prerequisites.length) {
@@ -1055,18 +1323,19 @@
1055
  'Prerequisites: None (starting technology)';
1056
  }
1057
 
1058
- nodePopup.style.display = 'block';
 
1059
  }
1060
 
1061
  // Close popup when clicking the X
1062
  closePopup.addEventListener('click', () => {
1063
- nodePopup.style.display = 'none';
1064
  });
1065
 
1066
  // Close popup when clicking outside
1067
  window.addEventListener('click', (e) => {
1068
  if (e.target === nodePopup) {
1069
- nodePopup.style.display = 'none';
1070
  }
1071
  });
1072
 
@@ -1111,13 +1380,14 @@
1111
  prerequisiteCheckboxes.appendChild(checkboxItem);
1112
  });
1113
 
1114
- // Show the form
1115
- addNodeForm.style.display = 'block';
 
1116
  });
1117
 
1118
  // Close add technology form
1119
  cancelForm.addEventListener('click', () => {
1120
- addNodeForm.style.display = 'none';
1121
  techForm.reset();
1122
  });
1123
 
@@ -1137,34 +1407,25 @@
1137
 
1138
  // Determine default position based on era
1139
  let x, y;
1140
- switch(era) {
1141
- case 'ancient':
1142
- x = 200 + (techData.filter(t => t.era === 'ancient').length * 200);
1143
- y = 150;
1144
- break;
1145
- case 'classical':
1146
- x = 200 + (techData.filter(t => t.era === 'classical').length * 200);
1147
- y = 450;
1148
- break;
1149
- case 'medieval':
1150
- x = 200 + (techData.filter(t => t.era === 'medieval').length * 200);
1151
- y = 750;
1152
- break;
1153
- case 'industrial':
1154
- x = 200 + (techData.filter(t => t.era === 'industrial').length * 200);
1155
- y = 1050;
1156
- break;
1157
- case 'modern':
1158
- x = 200 + (techData.filter(t => t.era === 'modern').length * 200);
1159
- y = 1350;
1160
- break;
1161
- case 'future':
1162
- x = 200 + (techData.filter(t => t.era === 'future').length * 200);
1163
- y = 1650;
1164
- break;
1165
- default:
1166
- x = 200;
1167
- y = 150;
1168
  }
1169
 
1170
  // Create the new tech
@@ -1186,96 +1447,81 @@
1186
  drawTechTree();
1187
 
1188
  // Close and reset the form
1189
- addNodeForm.style.display = 'none';
1190
  techForm.reset();
 
 
 
 
 
 
1191
  });
1192
 
1193
- // Era button functionality
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1194
  document.querySelectorAll('.era-button').forEach(button => {
1195
  button.addEventListener('click', () => {
1196
  const era = button.textContent.toLowerCase();
1197
-
1198
- // Scroll to the appropriate era
1199
- let scrollTop;
1200
- switch(era) {
1201
- case 'ancient': scrollTop = 0; break;
1202
- case 'classical': scrollTop = 300; break;
1203
- case 'medieval': scrollTop = 600; break;
1204
- case 'industrial': scrollTop = 900; break;
1205
- case 'modern': scrollTop = 1200; break;
1206
- case 'future': scrollTop = 1500; break;
1207
- default: scrollTop = 0;
1208
- }
1209
-
1210
- techTreeContainer.scrollTo({
1211
- top: scrollTop,
1212
- behavior: 'smooth'
1213
- });
1214
-
1215
  animateTechPath(era);
1216
  });
1217
  });
1218
 
1219
- function animateTechPath(era) {
1220
- let height = 0;
 
1221
  switch(era) {
1222
- case 'ancient': height = 5; break;
1223
- case 'classical': height = 18; break;
1224
- case 'medieval': height = 32; break;
1225
- case 'industrial': height = 46; break;
1226
- case 'modern': height = 65; break;
1227
- case 'future': height = 100; break;
 
1228
  }
1229
- techPath.style.height = `${height}%`;
 
 
 
 
1230
  }
1231
 
1232
  // Toggle edit mode
1233
  toggleEditMode.addEventListener('click', () => {
1234
- editMode = !editMode;
1235
 
1236
- if (editMode) {
1237
- toggleEditMode.textContent = 'Edit Mode: ON';
1238
  toggleEditMode.classList.add('active');
 
1239
  techTreeContainer.classList.add('editable-mode');
1240
-
1241
- // Show all drag handles and delete buttons
1242
- document.querySelectorAll('.tech-node').forEach(node => {
1243
- node.classList.add('editable');
1244
- });
1245
  } else {
1246
- toggleEditMode.textContent = 'Edit Mode: OFF';
1247
  toggleEditMode.classList.remove('active');
 
1248
  techTreeContainer.classList.remove('editable-mode');
1249
-
1250
- // Hide all drag handles and delete buttons
1251
- document.querySelectorAll('.tech-node').forEach(node => {
1252
- node.classList.remove('editable');
1253
- });
1254
-
1255
- // Stop any active dragging
1256
- if (draggingNode) {
1257
- draggingNode = null;
1258
- document.removeEventListener('mousemove', dragNode);
1259
- document.removeEventListener('mouseup', stopDrag);
1260
- }
1261
  }
 
 
 
 
 
1262
  });
1263
 
1264
  // Initial load - set to ancient era
1265
  animateTechPath('ancient');
1266
-
1267
- // Add mousemove and mouseup handlers for the document
1268
- document.addEventListener('mousemove', (e) => {
1269
- if (draggingNode) {
1270
- dragNode(e);
1271
- }
1272
- });
1273
-
1274
- document.addEventListener('mouseup', () => {
1275
- if (draggingNode) {
1276
- stopDrag();
1277
- }
1278
- });
1279
  });
1280
  </script>
1281
  </body>
 
273
  position: fixed;
274
  top: 50%;
275
  left: 50%;
276
+ transform: translate(-50%, -50%) scale(0.9);
277
  background: white;
278
  padding: 2rem;
279
  border-radius: 12px;
280
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
281
  z-index: 100;
282
  max-width: 400px;
283
+ opacity: 0;
284
+ pointer-events: none;
285
+ transition: all 0.3s ease;
286
+ }
287
+
288
+ .node-popup.active {
289
+ transform: translate(-50%, -50%) scale(1);
290
+ opacity: 1;
291
+ pointer-events: auto;
292
  }
293
 
294
  .node-popup h3 {
295
  margin-bottom: 0.5rem;
296
  color: #444;
297
+ font-size: 1.5rem;
298
  }
299
 
300
  .node-popup .era {
301
  font-size: 0.9rem;
302
  margin-bottom: 1rem;
303
  font-weight: bold;
304
+ padding: 0.3rem 0.8rem;
305
+ background-color: #f0f0f0;
306
+ display: inline-block;
307
+ border-radius: 20px;
308
+ color: #555;
309
  }
310
 
311
  .node-popup .description {
312
  margin-bottom: 1.5rem;
313
  line-height: 1.6;
314
+ color: #555;
315
  }
316
 
317
  .node-popup .prerequisites {
318
  font-size: 0.9rem;
319
  color: #666;
320
+ padding: 0.8rem;
321
+ background-color: #f8f8f8;
322
+ border-radius: 6px;
323
+ border-left: 3px solid #9d4edd;
324
  }
325
 
326
  .close-popup {
 
330
  font-size: 1.5rem;
331
  cursor: pointer;
332
  color: #888;
333
+ transition: all 0.2s;
334
+ }
335
+
336
+ .close-popup:hover {
337
+ color: #333;
338
+ transform: rotate(90deg);
339
  }
340
 
341
  .add-node-form {
342
  position: fixed;
343
  top: 50%;
344
  left: 50%;
345
+ transform: translate(-50%, -50%) scale(0.9);
346
  background: white;
347
+ padding: 1rem;
348
  border-radius: 12px;
349
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
350
  z-index: 100;
351
+ width: 90%;
352
+ max-height: 80vh;
353
+ overflow-y: auto;
354
+ max-width: 320px;
355
+ opacity: 0;
356
+ pointer-events: none;
357
+ transition: all 0.3s ease;
358
+ }
359
+
360
+ .add-node-form.active {
361
+ transform: translate(-50%, -50%) scale(1);
362
+ opacity: 1;
363
+ pointer-events: auto;
364
  }
365
 
366
  .add-node-form h2 {
367
+ margin-bottom: 0.8rem;
368
  color: #444;
369
+ font-size: 1.1rem;
370
+ padding-bottom: 0.5rem;
371
+ border-bottom: 1px solid #eee;
372
  }
373
 
374
  .form-group {
375
+ margin-bottom: 0.6rem;
376
  }
377
 
378
  .form-group label {
379
  display: block;
380
+ margin-bottom: 0.2rem;
381
  font-weight: bold;
382
  color: #555;
383
+ font-size: 0.8rem;
384
  }
385
 
386
  .form-group input,
387
  .form-group select,
388
  .form-group textarea {
389
  width: 100%;
390
+ padding: 0.5rem;
391
  border: 1px solid #ddd;
392
  border-radius: 6px;
393
  font-family: inherit;
394
+ font-size: 0.8rem;
395
+ transition: all 0.2s;
396
+ }
397
+
398
+ .form-group input:focus,
399
+ .form-group select:focus,
400
+ .form-group textarea:focus {
401
+ border-color: #9d4edd;
402
+ outline: none;
403
+ box-shadow: 0 0 0 3px rgba(157, 78, 221, 0.2);
404
  }
405
 
406
  .form-group textarea {
407
+ min-height: 60px;
408
  resize: vertical;
409
  }
410
 
411
  .form-actions {
412
  display: flex;
413
  justify-content: flex-end;
414
+ gap: 0.6rem;
415
+ margin-top: 0.8rem;
416
+ padding-top: 0.8rem;
417
+ border-top: 1px solid #eee;
418
  }
419
 
420
  .form-actions button {
421
+ padding: 0.5rem 1rem;
422
  border: none;
423
  border-radius: 6px;
424
  cursor: pointer;
425
  font-weight: bold;
426
+ font-size: 0.8rem;
427
+ transition: all 0.2s;
428
  }
429
 
430
  .form-cancel {
 
432
  color: #555;
433
  }
434
 
435
+ .form-cancel:hover {
436
+ background-color: #e0e0e0;
437
+ }
438
+
439
  .form-submit {
440
  background-color: #9d4edd;
441
  color: white;
442
  }
443
 
444
+ .form-submit:hover {
445
+ background-color: #7b2cbf;
446
+ }
447
+
448
  .checkbox-group {
449
+ margin-top: 0.3rem;
450
+ max-height: 100px;
451
+ overflow-y: auto;
452
+ border: 1px solid #eee;
453
+ padding: 0.3rem;
454
+ border-radius: 4px;
455
+ font-size: 0.75rem;
456
  }
457
 
458
  .checkbox-item {
459
  display: flex;
460
  align-items: center;
461
+ margin-bottom: 0.2rem;
462
+ font-size: 0.75rem;
463
+ padding: 0.2rem;
464
+ border-radius: 3px;
465
+ transition: all 0.2s;
466
+ }
467
+
468
+ .checkbox-item:hover {
469
+ background-color: #f5f5f5;
470
  }
471
 
472
  .checkbox-item input {
473
  width: auto;
474
+ margin-right: 0.3rem;
475
+ accent-color: #9d4edd;
476
  }
477
 
478
  .icon-selecter {
479
  display: grid;
480
  grid-template-columns: repeat(4, 1fr);
481
+ gap: 0.3rem;
482
+ margin-top: 0.3rem;
483
+ max-height: 120px;
484
+ overflow-y: auto;
485
+ padding: 0.3rem;
486
+ border: 1px solid #eee;
487
+ border-radius: 4px;
488
  }
489
 
490
  .icon-option {
491
  display: flex;
492
  flex-direction: column;
493
  align-items: center;
494
+ padding: 0.3rem;
495
  border: 1px solid #ddd;
496
  border-radius: 4px;
497
  cursor: pointer;
498
  transition: all 0.2s;
499
+ font-size: 0.7rem;
500
  }
501
 
502
  .icon-option:hover {
 
510
  }
511
 
512
  .icon-option i {
513
+ font-size: 1rem;
514
+ margin-bottom: 0.1rem;
515
  }
516
 
517
  footer {
 
617
  .toggle-edit-mode.active {
618
  background-color: #4CAF50;
619
  }
620
+
621
+ /* Additional styling for the controls section */
622
+ .controls-section {
623
+ background-color: white;
624
+ padding: 1rem;
625
+ border-radius: 8px;
626
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
627
+ margin-bottom: 1rem;
628
+ }
629
+
630
+ .controls-title {
631
+ font-size: 0.9rem;
632
+ font-weight: bold;
633
+ color: #555;
634
+ margin-bottom: 0.5rem;
635
+ display: flex;
636
+ align-items: center;
637
+ gap: 0.5rem;
638
+ }
639
+
640
+ .controls-title i {
641
+ font-size: 1rem;
642
+ }
643
+
644
+ /* Animation for new nodes */
645
+ @keyframes nodeAppear {
646
+ 0% {
647
+ transform: scale(0.5) rotate(0deg);
648
+ opacity: 0;
649
+ }
650
+ 100% {
651
+ transform: scale(1) rotate(0deg);
652
+ opacity: 1;
653
+ }
654
+ }
655
+
656
+ .new-node {
657
+ animation: nodeAppear 0.3s ease-out forwards;
658
+ }
659
  </style>
660
  </head>
661
  <body>
662
  <header>
663
  <h1>Technology Evolution Tree</h1>
664
+ <div class="subtitle">Explore the progression of human innovation through history</div>
665
  </header>
666
 
667
  <div class="container">
668
  <div class="controls">
669
+ <div class="controls-section">
670
+ <div class="controls-title"><i class="fas fa-clock"></i> Era Navigation</div>
671
+ <div class="era-navigation">
672
+ <button class="era-button era-ancient">Ancient</button>
673
+ <button class="era-button era-classical">Classical</button>
674
+ <button class="era-button era-medieval">Medieval</button>
675
+ <button class="era-button era-industrial">Industrial</button>
676
+ <button class="era-button era-modern">Modern</button>
677
+ <button class="era-button era-future">Future</button>
678
+ </div>
679
+ </div>
680
+
681
+ <div class="controls-section">
682
+ <div class="controls-title"><i class="fas fa-cog"></i> Controls</div>
683
+ <button class="add-tech-btn" id="addTechBtn">
684
+ <i class="fas fa-plus"></i> Add Technology
685
+ </button>
686
+ <button class="toggle-edit-mode" id="toggleEditMode">
687
+ <i class="fas fa-edit"></i> Toggle Edit Mode
688
+ </button>
689
+ </div>
690
  </div>
691
 
692
  <div class="tech-tree-container" id="techTreeContainer">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
693
  <div class="tech-tree" id="techTree">
694
+ <!-- Era dividers -->
695
+ <div class="era-line ancient-line"></div>
696
+ <div class="era-line classical-line"></div>
697
+ <div class="era-line medieval-line"></div>
698
+ <div class="era-line industrial-line"></div>
699
+ <div class="era-line modern-line"></div>
700
+ <div class="era-line future-line"></div>
701
+
702
+ <div class="era-labels">
703
+ <div>Ancient</div>
704
+ <div>Classical</div>
705
+ <div>Medieval</div>
706
+ <div>Industrial</div>
707
+ <div>Modern</div>
708
+ <div>Future</div>
709
+ </div>
710
+
711
+ <div class="timeline-bar">
712
+ <div class="tech-path"></div>
713
+ </div>
714
  </div>
715
  </div>
716
  </div>
 
747
 
748
  <div class="form-group">
749
  <label for="techIcon">Icon</label>
750
+ <div class="icon-selecter" id="iconSelector">
751
  <!-- Icons will be added via JavaScript -->
752
  </div>
753
  </div>
 
781
  const techTreeContainer = document.getElementById('techTreeContainer');
782
  const nodePopup = document.getElementById('nodePopup');
783
  const closePopup = document.querySelector('.close-popup');
784
+ const techPath = document.querySelector('.tech-path');
785
  const addTechBtn = document.getElementById('addTechBtn');
786
  const addNodeForm = document.getElementById('addNodeForm');
787
  const techForm = document.getElementById('techForm');
 
790
  const prerequisiteCheckboxes = document.getElementById('prerequisiteCheckboxes');
791
  const toggleEditMode = document.getElementById('toggleEditMode');
792
 
 
793
  let selectedIcon = 'fas fa-question';
794
  let techData = [];
795
  let nextId = 1;
796
  let draggingNode = null;
797
  let offsetX, offsetY;
798
+ let isEditMode = false;
799
 
800
+ // Extended list of Font Awesome icons for technologies
801
  const commonIcons = [
802
  'fas fa-fire', 'fas fa-wheel', 'fas fa-seedling', 'fas fa-book',
803
  'fas fa-square-root-alt', 'fas fa-hammer', 'fas fa-print',
 
805
  'fas fa-car', 'fas fa-plane', 'fas fa-computer', 'fas fa-network-wired',
806
  'fas fa-robot', 'fas fa-atom', 'fas fa-dna', 'fas fa-rocket',
807
  'fas fa-microchip', 'fas fa-brain', 'fas fa-vr-cardboard',
808
+ 'fas fa-biohazard', 'fas fa-solar-panel', 'fas fa-wind', 'fas fa-eye',
809
+ 'fas fa-bullseye', 'fas fa-tools', 'fas fa-flask', 'fas fa-microscope',
810
+ 'fas fa-disease', 'fas fa-virus', 'fas fa-dove', 'fas fa-globe',
811
+ 'fas fa-magnet', 'fas fa-lightbulb', 'fas fa-broadcast-tower',
812
+ 'fas fa-satellite', 'fas fa-shield-alt', 'fas fa-cogs', 'fas fa-brain',
813
+ 'fas fa-fan', 'fas fa-chart-line', 'fas fa-industry', 'fas fa-city',
814
+ 'fas fa-battery-full', 'fas fa-cloud', 'fas fa-database'
815
  ];
816
 
817
+ // Initialize with robust technology data
818
  initializeTechData();
819
 
820
  // Draw the initial technology tree
 
823
  // Technology data initialization
824
  function initializeTechData() {
825
  techData = [
826
+ // Ancient Era (4000 BCE - 500 BCE)
827
  {
828
  id: nextId++,
829
  name: "Fire",
830
  era: "ancient",
831
  icon: "fas fa-fire",
832
  description: "Mastery of fire allowed for cooking, warmth, protection and became the foundation for later metallurgy and energy technologies.",
833
+ x: 100,
834
  y: 150,
835
  prerequisites: []
836
  },
 
840
  era: "ancient",
841
  icon: "fas fa-wheel",
842
  description: "The invention of the wheel revolutionized transportation and mechanical applications, enabling carts, potter's wheels, and later complex machinery.",
843
+ x: 300,
844
  y: 150,
845
  prerequisites: []
846
  },
 
850
  era: "ancient",
851
  icon: "fas fa-seedling",
852
  description: "The domestication of plants led to settled communities, food surplus, and the development of complex societies and specialization.",
853
+ x: 500,
854
  y: 150,
855
  prerequisites: [1] // Requires Fire
856
  },
 
 
857
  {
858
  id: nextId++,
859
  name: "Writing",
860
+ era: "ancient",
861
  icon: "fas fa-book",
862
+ description: "Early writing systems like cuneiform and hieroglyphics emerged for record keeping, enabling complex administration and knowledge transmission.",
863
+ x: 700,
864
+ y: 150,
865
  prerequisites: [3] // Requires Agriculture
866
  },
867
+
868
+ // Classical Era (500 BCE - 500 CE)
869
  {
870
  id: nextId++,
871
  name: "Mathematics",
872
  era: "classical",
873
  icon: "fas fa-square-root-alt",
874
+ description: "Systematic development of mathematics including geometry, algebra, and number theory that became foundational for all sciences.",
875
+ x: 100,
876
  y: 450,
877
  prerequisites: [4] // Requires Writing
878
  },
879
+ {
880
+ id: nextId++,
881
+ name: "Architecture",
882
+ era: "classical",
883
+ icon: "fas fa-archway",
884
+ description: "Advanced techniques in construction enabled monumental buildings like temples, aqueducts and coliseums using arches, domes and concrete.",
885
+ x: 300,
886
+ y: 450,
887
+ prerequisites: [5] // Requires Mathematics
888
+ },
889
  {
890
  id: nextId++,
891
  name: "Metalworking",
892
  era: "classical",
893
  icon: "fas fa-hammer",
894
+ description: "Advanced techniques in smelting and forging enabled better tools, weapons, armor and the beginning of mechanical engineering.",
895
+ x: 500,
896
  y: 450,
897
  prerequisites: [1] // Requires Fire
898
  },
899
+ {
900
+ id: nextId++,
901
+ name: "Currency",
902
+ era: "classical",
903
+ icon: "fas fa-coins",
904
+ description: "Standardized coinage systems enabled complex trade networks and economic systems beyond simple barter.",
905
+ x: 700,
906
+ y: 450,
907
+ prerequisites: [4, 3] // Requires Writing, Agriculture
908
+ },
909
 
910
+ // Medieval Era (500 CE - 1500 CE)
911
  {
912
  id: nextId++,
913
  name: "Printing",
914
  era: "medieval",
915
  icon: "fas fa-print",
916
+ description: "Movable type printing enabled mass production of books, spreading literacy and enabling the Renaissance and scientific revolution.",
917
+ x: 100,
918
  y: 750,
919
  prerequisites: [4] // Requires Writing
920
  },
 
923
  name: "Compass",
924
  era: "medieval",
925
  icon: "fas fa-compass",
926
+ description: "The magnetic compass enabled reliable navigation at sea, facilitating global exploration, trade and cultural exchange.",
927
+ x: 300,
928
+ y: 750,
929
+ prerequisites: [7] // Requires Metalworking
930
+ },
931
+ {
932
+ id: nextId++,
933
+ name: "Gunpowder",
934
+ era: "medieval",
935
+ icon: "fas fa-bomb",
936
+ description: "Revolutionized warfare and mining, leading to new military strategies and eventually industrial explosives.",
937
  x: 500,
938
  y: 750,
939
+ prerequisites: [7] // Requires Metalworking
940
+ },
941
+ {
942
+ id: nextId++,
943
+ name: "Mechanical Clock",
944
+ era: "medieval",
945
+ icon: "fas fa-clock",
946
+ description: "Accurate timekeeping enabled better navigation, scheduling of economic activities, and scientific measurements.",
947
+ x: 700,
948
+ y: 750,
949
+ prerequisites: [7] // Requires Metalworking
950
  },
951
 
952
+ // Industrial Era (1500 CE - 1900 CE)
953
  {
954
  id: nextId++,
955
  name: "Steam Engine",
956
  era: "industrial",
957
  icon: "fas fa-train",
958
+ description: "Powered the Industrial Revolution, transforming transportation, manufacturing and energy production.",
959
+ x: 100,
960
  y: 1050,
961
+ prerequisites: [7] // Requires Metalworking
962
  },
963
  {
964
  id: nextId++,
965
  name: "Electricity",
966
  era: "industrial",
967
  icon: "fas fa-bolt",
968
+ description: "Harnessing electricity transformed every aspect of life from lighting and communication to industrial production.",
969
+ x: 300,
970
+ y: 1050,
971
+ prerequisites: [13] // Requires Steam Engine
972
+ },
973
+ {
974
+ id: nextId++,
975
+ name: "Telegraph",
976
+ era: "industrial",
977
+ icon: "fas fa-broadcast-tower",
978
+ description: "First rapid long-distance communication system that shrank the world and transformed business, news and diplomacy.",
979
  x: 500,
980
  y: 1050,
981
+ prerequisites: [14] // Requires Electricity
982
+ },
983
+ {
984
+ id: nextId++,
985
+ name: "Vaccination",
986
+ era: "industrial",
987
+ icon: "fas fa-syringe",
988
+ description: "Scientific immunization methods dramatically reduced mortality from infectious diseases, increasing global population health.",
989
+ x: 700,
990
+ y: 1050,
991
+ prerequisites: []
992
  },
993
 
994
+ // Modern Era (1900 CE - 2000 CE)
995
  {
996
  id: nextId++,
997
  name: "Computing",
998
  era: "modern",
999
  icon: "fas fa-computer",
1000
+ description: "Digital computing revolutionized information processing, leading to the Information Age and transforming society.",
1001
+ x: 100,
1002
+ y: 1350,
1003
+ prerequisites: [14] // Requires Electricity
1004
+ },
1005
+ {
1006
+ id: nextId++,
1007
+ name: "Automobile",
1008
+ era: "modern",
1009
+ icon: "fas fa-car",
1010
+ description: "Mass production of affordable personal vehicles transformed transportation, urban design and modern lifestyles.",
1011
  x: 300,
1012
  y: 1350,
1013
+ prerequisites: [13, 14] // Requires Steam Engine, Electricity
1014
+ },
1015
+ {
1016
+ id: nextId++,
1017
+ name: "Aviation",
1018
+ era: "modern",
1019
+ icon: "fas fa-plane",
1020
+ description: "Powered flight revolutionized global transportation, warfare and connected the world more tightly than ever before.",
1021
+ x: 500,
1022
+ y: 1350,
1023
+ prerequisites: [13, 14] // Requires Steam Engine, Electricity
1024
  },
1025
  {
1026
  id: nextId++,
1027
  name: "Internet",
1028
  era: "modern",
1029
  icon: "fas fa-network-wired",
1030
+ description: "Global digital network revolutionized communication, commerce, education and access to information.",
1031
+ x: 700,
1032
  y: 1350,
1033
+ prerequisites: [17] // Requires Computing
1034
  },
1035
 
1036
+ // Future Era (2000 CE - beyond)
1037
  {
1038
  id: nextId++,
1039
  name: "AI",
1040
  era: "future",
1041
  icon: "fas fa-robot",
1042
+ description: "Artificial Intelligence promises to automate complex tasks, enhance human capabilities and solve problems beyond human-scale processing.",
1043
+ x: 100,
1044
  y: 1650,
1045
+ prerequisites: [17, 20] // Requires Computing, Internet
1046
  },
1047
  {
1048
  id: nextId++,
 
1050
  era: "future",
1051
  icon: "fas fa-atom",
1052
  description: "Nuclear fusion could provide nearly limitless clean energy, solving humanity's energy needs while reducing environmental impact.",
1053
+ x: 300,
1054
+ y: 1650,
1055
+ prerequisites: [14, 17] // Requires Electricity, Computing
1056
+ },
1057
+ {
1058
+ id: nextId++,
1059
+ name: "Quantum Computing",
1060
+ era: "future",
1061
+ icon: "fas fa-brain",
1062
+ description: "Harnesses quantum mechanics to perform calculations impossible for classical computers, revolutionizing cryptography, simulation and optimization.",
1063
  x: 500,
1064
  y: 1650,
1065
+ prerequisites: [17] // Requires Computing
1066
  },
1067
  {
1068
  id: nextId++,
1069
  name: "Space Colonization",
1070
  era: "future",
1071
  icon: "fas fa-rocket",
1072
+ description: "Establishing permanent human settlements beyond Earth would ensure species survival and open new frontiers for exploration and resources.",
1073
  x: 700,
1074
  y: 1650,
1075
+ prerequisites: [14, 22] // Requires Electricity, Fusion Power
1076
  }
1077
  ];
1078
  }
 
1082
  // Clear existing nodes and connections
1083
  techTree.innerHTML = '';
1084
 
1085
+ // Add back the era dividers and labels
1086
+ techTree.innerHTML += `
1087
+ <div class="era-line ancient-line"></div>
1088
+ <div class="era-line classical-line"></div>
1089
+ <div class="era-line medieval-line"></div>
1090
+ <div class="era-line industrial-line"></div>
1091
+ <div class="era-line modern-line"></div>
1092
+ <div class="era-line future-line"></div>
1093
+
1094
+ <div class="era-labels">
1095
+ <div style="top: 150px;">Ancient</div>
1096
+ <div style="top: 450px;">Classical</div>
1097
+ <div style="top: 750px;">Medieval</div>
1098
+ <div style="top: 1050px;">Industrial</div>
1099
+ <div style="top: 1350px;">Modern</div>
1100
+ <div style="top: 1650px;">Future</div>
1101
+ </div>
1102
+ `;
1103
+
1104
  // Draw connections first (so nodes appear on top)
1105
  techData.forEach(tech => {
1106
  if (tech.prerequisites && tech.prerequisites.length) {
 
1125
  // Create a single technology node
1126
  function createTechNode(tech) {
1127
  const node = document.createElement('div');
1128
+ node.className = `tech-node ${tech.era}`;
1129
  node.style.left = `${tech.x}px`;
1130
  node.style.top = `${tech.y}px`;
1131
  node.dataset.id = tech.id;
 
1137
  <div class="tech-name">${tech.name}</div>
1138
  <div class="tech-era">${tech.era.charAt(0).toUpperCase() + tech.era.slice(1)}</div>
1139
  <div class="drag-handle">↔</div>
1140
+ <div class="delete-node">×</div>
1141
  `;
1142
 
 
1143
  node.addEventListener('click', (e) => {
1144
+ // Don't show popup if in edit mode or clicking on the delete button
1145
+ if (isEditMode || e.target.classList.contains('delete-node') || e.target.classList.contains('drag-handle')) {
1146
  return;
1147
  }
1148
 
1149
  showTechPopup(tech);
 
 
1150
  animateTechPath(tech.era);
1151
  });
1152
 
1153
+ // Dragging functionality (only in edit mode)
1154
+ node.addEventListener('mousedown', (e) => {
1155
+ if (!isEditMode) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1156
 
1157
  // Don't drag if clicking on the delete button
1158
  if (e.target.classList.contains('delete-node')) {
 
1175
 
1176
  document.addEventListener('mousemove', dragNode);
1177
  document.addEventListener('mouseup', stopDrag);
1178
+ });
1179
 
1180
+ // Delete functionality (only in edit mode)
1181
+ const deleteBtn = node.querySelector('.delete-node');
1182
+ deleteBtn.addEventListener('click', (e) => {
1183
+ if (!isEditMode) return;
 
 
 
 
 
 
 
 
 
 
 
1184
 
1185
+ e.stopPropagation();
1186
+ if (confirm(`Delete "${tech.name}"?`)) {
1187
+ // Remove this tech from prerequisites of other techs
1188
+ techData.forEach(t => {
1189
+ t.prerequisites = t.prerequisites.filter(id => id !== tech.id);
1190
+ });
1191
+
1192
+ // Remove the tech
1193
+ techData = techData.filter(t => t.id !== tech.id);
1194
+
1195
+ // Reddraw the tree
1196
+ drawTechTree();
1197
  }
1198
+ });
1199
+
1200
+ // Show/hide edit controls based on mode
1201
+ updateNodeEditControls(node);
1202
+
1203
+ techTree.appendChild(node);
1204
+ return node;
1205
+ }
1206
+
1207
+ // Update node edit controls based on current mode
1208
+ function updateNodeEditControls(node) {
1209
+ const dragHandle = node.querySelector('.drag-handle');
1210
+ const deleteBtn = node.querySelector('.delete-node');
1211
+
1212
+ if (isEditMode) {
1213
+ node.classList.add('editable');
1214
+ dragHandle.style.display = 'flex';
1215
+ deleteBtn.style.display = 'flex';
1216
+ } else {
1217
+ node.classList.remove('editable');
1218
+ dragHandle.style.display = 'none';
1219
+ deleteBtn.style.display = 'none';
1220
  }
1221
+ }
1222
+
1223
+ // Function to draw a connection line between two points
1224
+ function drawConnection(x1, y1, x2, y2) {
1225
+ const line = document.createElement('div');
1226
+ line.className = 'connection';
1227
 
1228
+ // Calculate length and angle of the line
1229
+ const length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
1230
+ const angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
1231
+
1232
+ // Style the line
1233
+ line.style.width = `${length}px`;
1234
+ line.style.left = `${x1}px`;
1235
+ line.style.top = `${y1}px`;
1236
+ line.style.transform = `rotate(${angle}deg)`;
1237
+
1238
+ techTree.appendChild(line);
1239
+ return line;
1240
+ }
1241
+
1242
+ // Drag node handler
1243
+ function dragNode(e) {
1244
+ if (!draggingNode) return;
1245
+
1246
+ // Calculate new position
1247
+ const containerRect = techTreeContainer.getBoundingClientRect();
1248
+ let newX = e.clientX - containerRect.left - offsetX;
1249
+ let newY = e.clientY - containerRect.top - offsetY;
1250
+
1251
+ // Constrain movement within container
1252
+ newX = Math.max(0, Math.min(newX, techTreeContainer.scrollWidth - 100));
1253
+ newY = Math.max(0, Math.min(newY, techTreeContainer.scrollHeight - 100));
1254
+
1255
+ // Update node position
1256
+ draggingNode.style.left = `${newX}px`;
1257
+ draggingNode.style.top = `${newY}px`;
1258
+
1259
+ // Update position in the tech data
1260
+ const techId = parseInt(draggingNode.dataset.id);
1261
+ const tech = techData.find(t => t.id === techId);
1262
+ if (tech) {
1263
+ tech.x = newX;
1264
+ tech.y = newY;
1265
  }
1266
 
1267
+ // Redraw connections
1268
+ redrawConnections();
1269
+ }
1270
+
1271
+ // Stop dragging handler
1272
+ function stopDrag() {
1273
+ if (!draggingNode) return;
1274
+
1275
+ draggingNode.style.zIndex = '10';
1276
+ draggingNode = null;
1277
+ document.removeEventListener('mousemove', dragNode);
1278
+ document.removeEventListener('mouseup', stopDrag);
1279
  }
1280
 
1281
  // Redraw just the connections (more efficient than redrawing the whole tree)
 
1300
  });
1301
  }
1302
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1303
  // Show technology details popup
1304
  function showTechPopup(tech) {
1305
  document.getElementById('popupTitle').textContent = tech.name;
1306
+
1307
+ // Format era with appropriate color
1308
+ const eraElement = document.getElementById('popupEra');
1309
+ eraElement.textContent = `${tech.era.charAt(0).toUpperCase() + tech.era.slice(1)} Era`;
1310
+ eraElement.className = `era ${tech.era}`;
1311
+
1312
  document.getElementById('popupDescription').textContent = tech.description;
1313
 
1314
  if (tech.prerequisites && tech.prerequisites.length) {
 
1323
  'Prerequisites: None (starting technology)';
1324
  }
1325
 
1326
+ // Show the popup with animation
1327
+ nodePopup.classList.add('active');
1328
  }
1329
 
1330
  // Close popup when clicking the X
1331
  closePopup.addEventListener('click', () => {
1332
+ nodePopup.classList.remove('active');
1333
  });
1334
 
1335
  // Close popup when clicking outside
1336
  window.addEventListener('click', (e) => {
1337
  if (e.target === nodePopup) {
1338
+ nodePopup.classList.remove('active');
1339
  }
1340
  });
1341
 
 
1380
  prerequisiteCheckboxes.appendChild(checkboxItem);
1381
  });
1382
 
1383
+ // Show the form with animation
1384
+ addNodeForm.classList.add('active');
1385
+ techForm.reset();
1386
  });
1387
 
1388
  // Close add technology form
1389
  cancelForm.addEventListener('click', () => {
1390
+ addNodeForm.classList.remove('active');
1391
  techForm.reset();
1392
  });
1393
 
 
1407
 
1408
  // Determine default position based on era
1409
  let x, y;
1410
+ const eraTechs = techData.filter(t => t.era === era);
1411
+
1412
+ if (eraTechs.length > 0) {
1413
+ // Position new node near others of the same era
1414
+ const lastTech = eraTechs[eraTechs.length - 1];
1415
+ x = lastTech.x + 200;
1416
+ y = lastTech.y;
1417
+ } else {
1418
+ // First tech of this era - position appropriately
1419
+ switch(era) {
1420
+ case 'ancient': y = 150; break;
1421
+ case 'classical': y = 450; break;
1422
+ case 'medieval': y = 750; break;
1423
+ case 'industrial': y = 1050; break;
1424
+ case 'modern': y = 1350; break;
1425
+ case 'future': y = 1650; break;
1426
+ default: y = 150;
1427
+ }
1428
+ x = 100;
 
 
 
 
 
 
 
 
 
1429
  }
1430
 
1431
  // Create the new tech
 
1447
  drawTechTree();
1448
 
1449
  // Close and reset the form
1450
+ addNodeForm.classList.remove('active');
1451
  techForm.reset();
1452
+
1453
+ // Scroll to show the new node
1454
+ techTreeContainer.scrollTo({
1455
+ top: y - 100,
1456
+ behavior: 'smooth'
1457
+ });
1458
  });
1459
 
1460
+ // Animate the timeline path to show current era
1461
+ function animateTechPath(era) {
1462
+ let height = 0;
1463
+ switch(era) {
1464
+ case 'ancient': height = 7; break;
1465
+ case 'classical': height = 20; break;
1466
+ case 'medieval': height = 35; break;
1467
+ case 'industrial': height = 50; break;
1468
+ case 'modern': height = 70; break;
1469
+ case 'future': height = 100; break;
1470
+ }
1471
+ techPath.style.height = `${height}%`;
1472
+ }
1473
+
1474
+ // Era navigation buttons
1475
  document.querySelectorAll('.era-button').forEach(button => {
1476
  button.addEventListener('click', () => {
1477
  const era = button.textContent.toLowerCase();
1478
+ scrollToEra(era);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1479
  animateTechPath(era);
1480
  });
1481
  });
1482
 
1483
+ // Scroll to specific era
1484
+ function scrollToEra(era) {
1485
+ let scrollTop;
1486
  switch(era) {
1487
+ case 'ancient': scrollTop = 0; break;
1488
+ case 'classical': scrollTop = 300; break;
1489
+ case 'medieval': scrollTop = 600; break;
1490
+ case 'industrial': scrollTop = 900; break;
1491
+ case 'modern': scrollTop = 1200; break;
1492
+ case 'future': scrollTop = 1500; break;
1493
+ default: scrollTop = 0;
1494
  }
1495
+
1496
+ techTreeContainer.scrollTo({
1497
+ top: scrollTop,
1498
+ behavior: 'smooth'
1499
+ });
1500
  }
1501
 
1502
  // Toggle edit mode
1503
  toggleEditMode.addEventListener('click', () => {
1504
+ isEditMode = !isEditMode;
1505
 
1506
+ // Update button appearance
1507
+ if (isEditMode) {
1508
  toggleEditMode.classList.add('active');
1509
+ toggleEditMode.innerHTML = '<i class="fas fa-check"></i> Edit Mode ON';
1510
  techTreeContainer.classList.add('editable-mode');
 
 
 
 
 
1511
  } else {
 
1512
  toggleEditMode.classList.remove('active');
1513
+ toggleEditMode.innerHTML = '<i class="fas fa-edit"></i> Toggle Edit Mode';
1514
  techTreeContainer.classList.remove('editable-mode');
 
 
 
 
 
 
 
 
 
 
 
 
1515
  }
1516
+
1517
+ // Update all nodes
1518
+ document.querySelectorAll('.tech-node').forEach(node => {
1519
+ updateNodeEditControls(node);
1520
+ });
1521
  });
1522
 
1523
  // Initial load - set to ancient era
1524
  animateTechPath('ancient');
 
 
 
 
 
 
 
 
 
 
 
 
 
1525
  });
1526
  </script>
1527
  </body>