RichardSocher commited on
Commit
f860042
·
verified ·
1 Parent(s): 1d2b7e9

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +728 -219
index.html CHANGED
@@ -43,12 +43,45 @@
43
  padding: 0 1rem;
44
  }
45
 
 
 
 
 
 
 
 
 
 
46
  .era-navigation {
47
  display: flex;
48
  justify-content: center;
49
- margin-bottom: 2rem;
50
  flex-wrap: wrap;
51
  gap: 0.5rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
 
54
  .era-button {
@@ -266,6 +299,124 @@
266
  color: #888;
267
  }
268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  footer {
270
  text-align: center;
271
  padding: 2rem 0;
@@ -293,6 +444,81 @@
293
  left: 0;
294
  transition: width 0.5s ease-in-out;
295
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  </style>
297
  </head>
298
  <body>
@@ -305,16 +531,24 @@
305
  </header>
306
 
307
  <div class="container">
308
- <div class="era-navigation">
309
- <button class="era-button era-ancient">Ancient</button>
310
- <button class="era-button era-classical">Classical</button>
311
- <button class="era-button era-medieval">Medieval</button>
312
- <button class="era-button era-industrial">Industrial</button>
313
- <button class="era-button era-modern">Modern</button>
314
- <button class="era-button era-future">Future</button>
 
 
 
 
 
 
 
 
315
  </div>
316
 
317
- <div class="tech-tree-container">
318
  <div class="era-labels">
319
  <div>4000 BCE</div>
320
  <div>500 BCE</div>
@@ -324,11 +558,12 @@
324
  <div>Future</div>
325
  </div>
326
  <div class="tech-tree" id="techTree">
327
- <!-- Connections will be added via JavaScript -->
328
  </div>
329
  </div>
330
  </div>
331
 
 
332
  <div class="node-popup" id="nodePopup">
333
  <span class="close-popup">&times;</span>
334
  <h3 id="popupTitle">Technology Name</h3>
@@ -337,6 +572,53 @@
337
  <div class="prerequisites" id="popupPrereqs">Prerequisites: None</div>
338
  </div>
339
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  <footer>
341
  <p>Explore the technological advancements that shaped human civilization</p>
342
  </footer>
@@ -344,189 +626,141 @@
344
  <script>
345
  document.addEventListener('DOMContentLoaded', function() {
346
  const techTree = document.getElementById('techTree');
 
347
  const nodePopup = document.getElementById('nodePopup');
348
  const closePopup = document.querySelector('.close-popup');
349
  const techPath = document.getElementById('techPath');
 
 
 
 
 
 
 
350
 
351
- // Technology data
352
- const techData = [
353
- // Ancient Era
354
- {
355
- id: 1,
356
- name: "Fire",
357
- era: "ancient",
358
- icon: "fas fa-fire",
359
- description: "Mastery of fire allowed for cooking, warmth, protection and became the foundation for later metallurgy and energy technologies.",
360
- x: 100,
361
- y: 100,
362
- prerequisites: []
363
- },
364
- {
365
- id: 2,
366
- name: "Wheel",
367
- era: "ancient",
368
- icon: "fas fa-wheel",
369
- description: "The invention of the wheel revolutionized transportation and mechanical applications, enabling carts, potter's wheels, and later complex machinery.",
370
- x: 300,
371
- y: 100,
372
- prerequisites: []
373
- },
374
- {
375
- id: 3,
376
- name: "Agriculture",
377
- era: "ancient",
378
- icon: "fas fa-seedling",
379
- description: "The domestication of plants led to settled communities, food surplus, and the development of complex societies and specialization.",
380
- x: 500,
381
- y: 100,
382
- prerequisites: [1] // Requires Fire
383
- },
384
-
385
- // Classical Era
386
- {
387
- id: 4,
388
- name: "Writing",
389
- era: "classical",
390
- icon: "fas fa-book",
391
- description: "The development of writing systems enabled permanent records, complex communication, and the accumulation of knowledge across generations.",
392
- x: 200,
393
- y: 220,
394
- prerequisites: [3] // Requires Agriculture
395
- },
396
- {
397
- id: 5,
398
- name: "Mathematics",
399
- era: "classical",
400
- icon: "fas fa-square-root-alt",
401
- description: "Abstract numerical systems allowed for calculations, engineering, astronomy, and became foundational for all future scientific progress.",
402
- x: 400,
403
- y: 220,
404
- prerequisites: [4] // Requires Writing
405
- },
406
- {
407
- id: 6,
408
- name: "Metalworking",
409
- era: "classical",
410
- icon: "fas fa-hammer",
411
- description: "Advanced techniques in smelting and forging enabled better tools, weapons, and the beginning of mechanical engineering principles.",
412
- x: 600,
413
- y: 220,
414
- prerequisites: [1] // Requires Fire
415
- },
416
-
417
- // Medieval Era
418
- {
419
- id: 7,
420
- name: "Printing Press",
421
- era: "medieval",
422
- icon: "fas fa-print",
423
- description: "Movable type printing revolutionized knowledge dissemination, making books affordable and enabling mass literacy and education.",
424
- x: 300,
425
- y: 340,
426
- prerequisites: [4] // Requires Writing
427
- },
428
- {
429
- id: 8,
430
- name: "Compass",
431
- era: "medieval",
432
- icon: "fas fa-compass",
433
- description: "Magnetic navigation enabled accurate long-distance sea travel, global exploration, and the connection of world civilizations.",
434
- x: 500,
435
- y: 340,
436
- prerequisites: [5, 6] // Requires Mathematics and Metalworking
437
- },
438
-
439
- // Industrial Era
440
- {
441
- id: 9,
442
- name: "Steam Engine",
443
- era: "industrial",
444
- icon: "fas fa-train",
445
- description: "The practical application of steam power drove the Industrial Revolution, transforming manufacturing and transportation.",
446
- x: 200,
447
- y: 460,
448
- prerequisites: [5, 6] // Requires Mathematics and Metalworking
449
- },
450
- {
451
- id: 10,
452
- name: "Electricity",
453
- era: "industrial",
454
- icon: "fas fa-bolt",
455
- description: "Harnessing electromagnetic energy revolutionized nearly every aspect of life from lighting to communication to manufacturing.",
456
- x: 400,
457
- y: 460,
458
- prerequisites: [5] // Requires Mathematics
459
- },
460
- {
461
- id: 11,
462
- name: "Telegraph",
463
- era: "industrial",
464
- icon: "fas fa-satellite-dish",
465
- description: "Electrical communication over distance shrank the world, enabling near-instant information transfer across continents.",
466
- x: 600,
467
- y: 460,
468
- prerequisites: [10] // Requires Electricity
469
- },
470
-
471
- // Modern Era
472
- {
473
- id: 12,
474
- name: "Automobile",
475
- era: "modern",
476
- icon: "fas fa-car",
477
- description: "Combustion-powered personal transportation reshaped cities, economies, and global mobility patterns.",
478
- x: 200,
479
- y: 580,
480
- prerequisites: [9, 10] // Requires Steam Engine and Electricity
481
- },
482
- {
483
- id: 13,
484
- name: "Aeroplane",
485
- era: "modern",
486
- icon: "fas fa-plane",
487
- description: "Powered flight revolutionized global travel, warfare, and connected the world in unprecedented ways.",
488
- x: 400,
489
- y: 580,
490
- prerequisites: [10, 11] // Requires Electricity and Telegraph
491
- },
492
- {
493
- id: 14,
494
- name: "Computers",
495
- era: "modern",
496
- icon: "fas fa-computer",
497
- description: "Digital computing machines automated complex calculations, information processing, and later became universal tools.",
498
- x: 600,
499
- y: 580,
500
- prerequisites: [5, 10] // Requires Mathematics and Electricity
501
- },
502
-
503
- // Future Era
504
- {
505
- id: 15,
506
- name: "Internet",
507
- era: "future",
508
- icon: "fas fa-network-wired",
509
- description: "Global digital communication network enabling instant access to information and connecting humanity like never before.",
510
- x: 400,
511
- y: 700,
512
- prerequisites: [13, 14] // Requires Aeroplane and Computers
513
- },
514
- {
515
- id: 16,
516
- name: "AI",
517
- era: "future",
518
- icon: "fas fa-robot",
519
- description: "Artificial intelligence systems capable of learning, pattern recognition, and performing tasks once requiring human intelligence.",
520
- x: 600,
521
- y: 700,
522
- prerequisites: [14] // Requires Computers
523
- }
524
  ];
525
 
526
- // Draw the technology nodes
527
- techData.forEach(tech => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
528
  const node = document.createElement('div');
529
- node.className = `tech-node ${tech.era}`;
530
  node.style.left = `${tech.x}px`;
531
  node.style.top = `${tech.y}px`;
532
  node.dataset.id = tech.id;
@@ -537,49 +771,135 @@
537
  </div>
538
  <div class="tech-name">${tech.name}</div>
539
  <div class="tech-era">${tech.era.charAt(0).toUpperCase() + tech.era.slice(1)}</div>
 
 
540
  `;
541
 
542
  // Add click event for popup
543
- node.addEventListener('click', () => {
544
- document.getElementById('popupTitle').textContent = tech.name;
545
- document.getElementById('popupEra').textContent =
546
- `${tech.era.charAt(0).toUpperCase() + tech.era.slice(1)} Era`;
547
- document.getElementById('popupDescription').textContent = tech.description;
548
-
549
- if (tech.prerequisites && tech.prerequisites.length) {
550
- const prereqNames = tech.prerequisites.map(id =>
551
- techData.find(t => t.id === id).name
552
- ).join(', ');
553
- document.getElementById('popupPrereqs').textContent =
554
- `Prerequisites: ${prereqNames}`;
555
- } else {
556
- document.getElementById('popupPrereqs').textContent =
557
- 'Prerequisites: None (starting technology)';
558
  }
559
 
560
- nodePopup.style.display = 'block';
561
 
562
  // Animate the tech path
563
  animateTechPath(tech.era);
564
  });
565
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
566
  techTree.appendChild(node);
567
- });
568
 
569
- // Draw connections between technologies
570
- techData.forEach(tech => {
571
- if (tech.prerequisites && tech.prerequisites.length) {
572
- tech.prerequisites.forEach(prereqId => {
573
- const prereqTech = techData.find(t => t.id === prereqId);
574
- if (prereqTech) {
575
- drawConnection(
576
- prereqTech.x + 50, prereqTech.y + 50, // source (center of circle)
577
- tech.x + 50, tech.y + 50 // target
578
- );
579
- }
580
- });
581
- }
582
- });
 
 
 
 
 
 
 
583
 
584
  // Function to draw a connection line between two points
585
  function drawConnection(x1, y1, x2, y2) {
@@ -602,6 +922,28 @@
602
  techTree.insertBefore(line, techTree.firstChild);
603
  }
604
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
605
  // Close popup when clicking the X
606
  closePopup.addEventListener('click', () => {
607
  nodePopup.style.display = 'none';
@@ -614,16 +956,138 @@
614
  }
615
  });
616
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
  // Era button functionality
618
  document.querySelectorAll('.era-button').forEach(button => {
619
  button.addEventListener('click', () => {
620
  const era = button.textContent.toLowerCase();
621
 
622
  // Simple animation - we could enhance this with smooth scrolling
623
- document.querySelector('.tech-tree-container').scrollTo({
624
  left: getScrollPositionForEra(era),
625
  behavior: 'smooth'
626
  });
 
 
627
  });
628
  });
629
 
@@ -645,9 +1109,54 @@
645
  techPath.style.width = `${width}%`;
646
  }
647
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
  // Initial load - set to ancient era
649
  animateTechPath('ancient');
 
 
 
 
 
 
 
 
 
 
 
 
 
650
  });
651
  </script>
652
- <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
653
  </html>
 
43
  padding: 0 1rem;
44
  }
45
 
46
+ .controls {
47
+ display: flex;
48
+ justify-content: space-between;
49
+ align-items: center;
50
+ margin-bottom: 2rem;
51
+ flex-wrap: wrap;
52
+ gap: 1rem;
53
+ }
54
+
55
  .era-navigation {
56
  display: flex;
57
  justify-content: center;
 
58
  flex-wrap: wrap;
59
  gap: 0.5rem;
60
+ flex-grow: 1;
61
+ }
62
+
63
+ .add-tech-btn {
64
+ padding: 0.8rem 1.5rem;
65
+ border: none;
66
+ border-radius: 30px;
67
+ font-weight: bold;
68
+ cursor: pointer;
69
+ transition: all 0.3s ease;
70
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
71
+ background-color: #9d4edd;
72
+ color: white;
73
+ font-size: 0.9rem;
74
+ text-transform: uppercase;
75
+ letter-spacing: 1px;
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 0.5rem;
79
+ }
80
+
81
+ .add-tech-btn:hover {
82
+ transform: translateY(-2px);
83
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
84
+ background-color: #7b2cbf;
85
  }
86
 
87
  .era-button {
 
299
  color: #888;
300
  }
301
 
302
+ .add-node-form {
303
+ position: fixed;
304
+ top: 50%;
305
+ left: 50%;
306
+ transform: translate(-50%, -50%);
307
+ background: white;
308
+ padding: 2rem;
309
+ border-radius: 12px;
310
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
311
+ z-index: 100;
312
+ max-width: 400px;
313
+ display: none;
314
+ }
315
+
316
+ .add-node-form h2 {
317
+ margin-bottom: 1.5rem;
318
+ color: #444;
319
+ }
320
+
321
+ .form-group {
322
+ margin-bottom: 1rem;
323
+ }
324
+
325
+ .form-group label {
326
+ display: block;
327
+ margin-bottom: 0.5rem;
328
+ font-weight: bold;
329
+ color: #555;
330
+ }
331
+
332
+ .form-group input,
333
+ .form-group select,
334
+ .form-group textarea {
335
+ width: 100%;
336
+ padding: 0.8rem;
337
+ border: 1px solid #ddd;
338
+ border-radius: 6px;
339
+ font-family: inherit;
340
+ }
341
+
342
+ .form-group textarea {
343
+ min-height: 100px;
344
+ resize: vertical;
345
+ }
346
+
347
+ .form-actions {
348
+ display: flex;
349
+ justify-content: flex-end;
350
+ gap: 0.8rem;
351
+ margin-top: 1.5rem;
352
+ }
353
+
354
+ .form-actions button {
355
+ padding: 0.8rem 1.5rem;
356
+ border: none;
357
+ border-radius: 6px;
358
+ cursor: pointer;
359
+ font-weight: bold;
360
+ }
361
+
362
+ .form-cancel {
363
+ background-color: #f0f0f0;
364
+ color: #555;
365
+ }
366
+
367
+ .form-submit {
368
+ background-color: #9d4edd;
369
+ color: white;
370
+ }
371
+
372
+ .checkbox-group {
373
+ margin-top: 0.5rem;
374
+ }
375
+
376
+ .checkbox-item {
377
+ display: flex;
378
+ align-items: center;
379
+ margin-bottom: 0.5rem;
380
+ }
381
+
382
+ .checkbox-item input {
383
+ width: auto;
384
+ margin-right: 0.5rem;
385
+ }
386
+
387
+ .icon-selector {
388
+ display: grid;
389
+ grid-template-columns: repeat(4, 1fr);
390
+ gap: 0.5rem;
391
+ margin-top: 0.5rem;
392
+ }
393
+
394
+ .icon-option {
395
+ display: flex;
396
+ flex-direction: column;
397
+ align-items: center;
398
+ padding: 0.5rem;
399
+ border: 1px solid #ddd;
400
+ border-radius: 4px;
401
+ cursor: pointer;
402
+ transition: all 0.2s;
403
+ }
404
+
405
+ .icon-option:hover {
406
+ border-color: #9d4edd;
407
+ background-color: #f9f0ff;
408
+ }
409
+
410
+ .icon-option.selected {
411
+ border-color: #9d4edd;
412
+ background-color: #f0d6ff;
413
+ }
414
+
415
+ .icon-option i {
416
+ font-size: 1.5rem;
417
+ margin-bottom: 0.3rem;
418
+ }
419
+
420
  footer {
421
  text-align: center;
422
  padding: 2rem 0;
 
444
  left: 0;
445
  transition: width 0.5s ease-in-out;
446
  }
447
+
448
+ /* Drag handle for nodes */
449
+ .drag-handle {
450
+ position: absolute;
451
+ top: -5px;
452
+ right: -5px;
453
+ width: 20px;
454
+ height: 20px;
455
+ background-color: rgba(255, 255, 255, 0.8);
456
+ border-radius: 50%;
457
+ border: 1px solid #ccc;
458
+ cursor: move;
459
+ display: none;
460
+ z-index: 30;
461
+ font-size: 0.7rem;
462
+ display: flex;
463
+ align-items: center;
464
+ justify-content: center;
465
+ color: #555;
466
+ }
467
+
468
+ .tech-node.editable .drag-handle {
469
+ display: flex;
470
+ }
471
+
472
+ .delete-node {
473
+ position: absolute;
474
+ top: -5px;
475
+ left: -5px;
476
+ width: 20px;
477
+ height: 20px;
478
+ background-color: #ff6b6b;
479
+ border-radius: 50%;
480
+ cursor: pointer;
481
+ display: none;
482
+ z-index: 30;
483
+ font-size: 0.7rem;
484
+ display: flex;
485
+ align-items: center;
486
+ justify-content: center;
487
+ color: white;
488
+ opacity: 0;
489
+ transition: opacity 0.2s;
490
+ }
491
+
492
+ .tech-node.editable:hover .delete-node {
493
+ opacity: 1;
494
+ }
495
+
496
+ .editable-mode {
497
+ border: 2px dashed #9d4edd;
498
+ }
499
+
500
+ .toggle-edit-mode {
501
+ padding: 0.8rem 1.5rem;
502
+ border: none;
503
+ border-radius: 30px;
504
+ font-weight: bold;
505
+ cursor: pointer;
506
+ transition: all 0.3s ease;
507
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
508
+ font-size: 0.9rem;
509
+ text-transform: uppercase;
510
+ letter-spacing: 1px;
511
+ background-color: #ff6b6b;
512
+ color: white;
513
+ }
514
+
515
+ .toggle-edit-mode:hover {
516
+ background-color: #ff5252;
517
+ }
518
+
519
+ .toggle-edit-mode.active {
520
+ background-color: #4CAF50;
521
+ }
522
  </style>
523
  </head>
524
  <body>
 
531
  </header>
532
 
533
  <div class="container">
534
+ <div class="controls">
535
+ <div class="era-navigation">
536
+ <button class="era-button era-ancient">Ancient</button>
537
+ <button class="era-button era-classical">Classical</button>
538
+ <button class="era-button era-medieval">Medieval</button>
539
+ <button class="era-button era-industrial">Industrial</button>
540
+ <button class="era-button era-modern">Modern</button>
541
+ <button class="era-button era-future">Future</button>
542
+ </div>
543
+ <button class="add-tech-btn" id="addTechBtn">
544
+ <i class="fas fa-plus"></i> Add Technology
545
+ </button>
546
+ <button class="toggle-edit-mode" id="toggleEditMode">
547
+ Edit Mode: OFF
548
+ </button>
549
  </div>
550
 
551
+ <div class="tech-tree-container" id="techTreeContainer">
552
  <div class="era-labels">
553
  <div>4000 BCE</div>
554
  <div>500 BCE</div>
 
558
  <div>Future</div>
559
  </div>
560
  <div class="tech-tree" id="techTree">
561
+ <!-- Connections and nodes will be added via JavaScript -->
562
  </div>
563
  </div>
564
  </div>
565
 
566
+ <!-- Technology Details Popup -->
567
  <div class="node-popup" id="nodePopup">
568
  <span class="close-popup">&times;</span>
569
  <h3 id="popupTitle">Technology Name</h3>
 
572
  <div class="prerequisites" id="popupPrereqs">Prerequisites: None</div>
573
  </div>
574
 
575
+ <!-- Add Technology Form -->
576
+ <div class="add-node-form" id="addNodeForm">
577
+ <h2>Add New Technology</h2>
578
+ <form id="techForm">
579
+ <div class="form-group">
580
+ <label for="techName">Technology Name</label>
581
+ <input type="text" id="techName" required placeholder="e.g., Quantum Computing">
582
+ </div>
583
+
584
+ <div class="form-group">
585
+ <label for="techEra">Era</label>
586
+ <select id="techEra" required>
587
+ <option value="ancient">Ancient</option>
588
+ <option value="classical">Classical</option>
589
+ <option value="medieval">Medieval</option>
590
+ <option value="industrial">Industrial</option>
591
+ <option value="modern">Modern</option>
592
+ <option value="future">Future</option>
593
+ </select>
594
+ </div>
595
+
596
+ <div class="form-group">
597
+ <label for="techIcon">Icon</label>
598
+ <div class="icon-selector" id="iconSelector">
599
+ <!-- Icons will be added via JavaScript -->
600
+ </div>
601
+ </div>
602
+
603
+ <div class="form-group">
604
+ <label for="techDescription">Description</label>
605
+ <textarea id="techDescription" required placeholder="Describe the technology and its significance..."></textarea>
606
+ </div>
607
+
608
+ <div class="form-group">
609
+ <label>Prerequisites</label>
610
+ <div class="checkbox-group" id="prerequisiteCheckboxes">
611
+ <!-- Checkboxes will be added via JavaScript -->
612
+ </div>
613
+ </div>
614
+
615
+ <div class="form-actions">
616
+ <button type="button" class="form-cancel" id="cancelForm">Cancel</button>
617
+ <button type="submit" class="form-submit">Add Technology</button>
618
+ </div>
619
+ </form>
620
+ </div>
621
+
622
  <footer>
623
  <p>Explore the technological advancements that shaped human civilization</p>
624
  </footer>
 
626
  <script>
627
  document.addEventListener('DOMContentLoaded', function() {
628
  const techTree = document.getElementById('techTree');
629
+ const techTreeContainer = document.getElementById('techTreeContainer');
630
  const nodePopup = document.getElementById('nodePopup');
631
  const closePopup = document.querySelector('.close-popup');
632
  const techPath = document.getElementById('techPath');
633
+ const addTechBtn = document.getElementById('addTechBtn');
634
+ const addNodeForm = document.getElementById('addNodeForm');
635
+ const techForm = document.getElementById('techForm');
636
+ const cancelForm = document.getElementById('cancelForm');
637
+ const iconSelector = document.getElementById('iconSelector');
638
+ const prerequisiteCheckboxes = document.getElementById('prerequisiteCheckboxes');
639
+ const toggleEditMode = document.getElementById('toggleEditMode');
640
 
641
+ let editMode = false;
642
+ let selectedIcon = 'fas fa-question';
643
+ let techData = [];
644
+ let nextId = 1;
645
+ let draggingNode = null;
646
+ let offsetX, offsetY;
647
+
648
+ // Common Font Awesome icons for technologies
649
+ const commonIcons = [
650
+ 'fas fa-fire', 'fas fa-wheel', 'fas fa-seedling', 'fas fa-book',
651
+ 'fas fa-square-root-alt', 'fas fa-hammer', 'fas fa-print',
652
+ 'fas fa-compass', 'fas fa-train', 'fas fa-bolt', 'fas fa-satellite-dish',
653
+ 'fas fa-car', 'fas fa-plane', 'fas fa-computer', 'fas fa-network-wired',
654
+ 'fas fa-robot', 'fas fa-atom', 'fas fa-dna', 'fas fa-rocket',
655
+ 'fas fa-microchip', 'fas fa-brain', 'fas fa-vr-cardboard',
656
+ 'fas fa-biohazard', 'fas fa-solar-panel', 'fas fa-wind', 'fas fa-eye'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
657
  ];
658
 
659
+ // Initialize with some default technologies
660
+ initializeTechData();
661
+
662
+ // Draw the initial technology tree
663
+ drawTechTree();
664
+
665
+ // Technology data initialization
666
+ function initializeTechData() {
667
+ techData = [
668
+ // Ancient Era
669
+ {
670
+ id: nextId++,
671
+ name: "Fire",
672
+ era: "ancient",
673
+ icon: "fas fa-fire",
674
+ description: "Mastery of fire allowed for cooking, warmth, protection and became the foundation for later metallurgy and energy technologies.",
675
+ x: 100,
676
+ y: 100,
677
+ prerequisites: []
678
+ },
679
+ {
680
+ id: nextId++,
681
+ name: "Wheel",
682
+ era: "ancient",
683
+ icon: "fas fa-wheel",
684
+ description: "The invention of the wheel revolutionized transportation and mechanical applications, enabling carts, potter's wheels, and later complex machinery.",
685
+ x: 300,
686
+ y: 100,
687
+ prerequisites: []
688
+ },
689
+ {
690
+ id: nextId++,
691
+ name: "Agriculture",
692
+ era: "ancient",
693
+ icon: "fas fa-seedling",
694
+ description: "The domestication of plants led to settled communities, food surplus, and the development of complex societies and specialization.",
695
+ x: 500,
696
+ y: 100,
697
+ prerequisites: [1] // Requires Fire
698
+ },
699
+
700
+ // Classical Era
701
+ {
702
+ id: nextId++,
703
+ name: "Writing",
704
+ era: "classical",
705
+ icon: "fas fa-book",
706
+ description: "The development of writing systems enabled permanent records, complex communication, and the accumulation of knowledge across generations.",
707
+ x: 200,
708
+ y: 220,
709
+ prerequisites: [3] // Requires Agriculture
710
+ },
711
+ {
712
+ id: nextId++,
713
+ name: "Mathematics",
714
+ era: "classical",
715
+ icon: "fas fa-square-root-alt",
716
+ description: "Abstract numerical systems allowed for calculations, engineering, astronomy, and became foundational for all future scientific progress.",
717
+ x: 400,
718
+ y: 220,
719
+ prerequisites: [4] // Requires Writing
720
+ },
721
+ {
722
+ id: nextId++,
723
+ name: "Metalworking",
724
+ era: "classical",
725
+ icon: "fas fa-hammer",
726
+ description: "Advanced techniques in smelting and forging enabled better tools, weapons, and the beginning of mechanical engineering principles.",
727
+ x: 600,
728
+ y: 220,
729
+ prerequisites: [1] // Requires Fire
730
+ }
731
+ ];
732
+ }
733
+
734
+ // Draw the entire technology tree
735
+ function drawTechTree() {
736
+ // Clear existing nodes and connections
737
+ techTree.innerHTML = '';
738
+
739
+ // Draw connections first (so nodes appear on top)
740
+ techData.forEach(tech => {
741
+ if (tech.prerequisites && tech.prerequisites.length) {
742
+ tech.prerequisites.forEach(prereqId => {
743
+ const prereqTech = techData.find(t => t.id === prereqId);
744
+ if (prereqTech) {
745
+ drawConnection(
746
+ prereqTech.x + 50, prereqTech.y + 50, // source (center of circle)
747
+ tech.x + 50, tech.y + 50 // target
748
+ );
749
+ }
750
+ });
751
+ }
752
+ });
753
+
754
+ // Draw the technology nodes
755
+ techData.forEach(tech => {
756
+ createTechNode(tech);
757
+ });
758
+ }
759
+
760
+ // Create a single technology node
761
+ function createTechNode(tech) {
762
  const node = document.createElement('div');
763
+ node.className = `tech-node ${tech.era} ${editMode ? 'editable' : ''}`;
764
  node.style.left = `${tech.x}px`;
765
  node.style.top = `${tech.y}px`;
766
  node.dataset.id = tech.id;
 
771
  </div>
772
  <div class="tech-name">${tech.name}</div>
773
  <div class="tech-era">${tech.era.charAt(0).toUpperCase() + tech.era.slice(1)}</div>
774
+ <div class="drag-handle">↔</div>
775
+ <div class="delete-node" title="Delete technology">×</div>
776
  `;
777
 
778
  // Add click event for popup
779
+ node.addEventListener('click', (e) => {
780
+ // If we're dragging or clicking on the drag handle, don't show the popup
781
+ if (draggingNode || e.target.classList.contains('drag-handle') || e.target.classList.contains('delete-node')) {
782
+ return;
 
 
 
 
 
 
 
 
 
 
 
783
  }
784
 
785
+ showTechPopup(tech);
786
 
787
  // Animate the tech path
788
  animateTechPath(tech.era);
789
  });
790
 
791
+ // Add delete functionality
792
+ const deleteBtn = node.querySelector('.delete-node');
793
+ deleteBtn.addEventListener('click', () => {
794
+ if (confirm(`Are you sure you want to delete "${tech.name}"? This cannot be undone.`)) {
795
+ // Remove this tech from any prerequisite lists
796
+ techData.forEach(t => {
797
+ if (t.prerequisites && t.prerequisites.includes(tech.id)) {
798
+ t.prerequisites = t.prerequisites.filter(id => id !== tech.id);
799
+ }
800
+ });
801
+
802
+ // Remove the tech
803
+ techData = techData.filter(t => t.id !== tech.id);
804
+
805
+ // Redraw the tree
806
+ drawTechTree();
807
+ }
808
+ });
809
+
810
+ // Dragging functionality
811
+ const dragHandle = node.querySelector('.drag-handle');
812
+
813
+ dragHandle.addEventListener('mousedown', startDrag);
814
+ node.addEventListener('mousedown', startDrag);
815
+
816
+ function startDrag(e) {
817
+ if (!editMode) return;
818
+
819
+ // Don't drag if clicking on the delete button
820
+ if (e.target.classList.contains('delete-node')) {
821
+ return;
822
+ }
823
+
824
+ e.preventDefault();
825
+ draggingNode = node;
826
+
827
+ // Calculate offset from mouse to node position
828
+ const rect = node.getBoundingClientRect();
829
+ offsetX = e.clientX - rect.left;
830
+ offsetY = e.clientY - rect.top;
831
+
832
+ // Set the node to absolute positioning (if not already)
833
+ node.style.position = 'absolute';
834
+
835
+ // Move the node to the front
836
+ node.style.zIndex = '1000';
837
+
838
+ document.addEventListener('mousemove', dragNode);
839
+ document.addEventListener('mouseup', stopDrag);
840
+ }
841
+
842
+ function dragNode(e) {
843
+ if (!draggingNode) return;
844
+
845
+ // Calculate new position
846
+ const containerRect = techTreeContainer.getBoundingClientRect();
847
+ let newX = e.clientX - containerRect.left - offsetX;
848
+ let newY = e.clientY - containerRect.top - offsetY;
849
+
850
+ // Constrain movement within container
851
+ newX = Math.max(0, Math.min(newX, techTreeContainer.scrollWidth - 100));
852
+ newY = Math.max(0, Math.min(newY, techTreeContainer.scrollHeight - 100));
853
+
854
+ // Update node position
855
+ node.style.left = `${newX}px`;
856
+ node.style.top = `${newY}px`;
857
+
858
+ // Update position in the tech data
859
+ const techId = parseInt(node.dataset.id);
860
+ const tech = techData.find(t => t.id === techId);
861
+ if (tech) {
862
+ tech.x = newX;
863
+ tech.y = newY;
864
+ }
865
+
866
+ // Redraw connections
867
+ redrawConnections();
868
+ }
869
+
870
+ function stopDrag() {
871
+ if (!draggingNode) return;
872
+
873
+ draggingNode.style.zIndex = '10';
874
+ draggingNode = null;
875
+ document.removeEventListener('mousemove', dragNode);
876
+ document.removeEventListener('mouseup', stopDrag);
877
+ }
878
+
879
  techTree.appendChild(node);
880
+ }
881
 
882
+ // Redraw just the connections (more efficient than redrawing the whole tree)
883
+ function redrawConnections() {
884
+ // Remove all connection elements
885
+ const connections = document.querySelectorAll('.connection');
886
+ connections.forEach(c => c.remove());
887
+
888
+ // Redraw all connections
889
+ techData.forEach(tech => {
890
+ if (tech.prerequisites && tech.prerequisites.length) {
891
+ tech.prerequisites.forEach(prereqId => {
892
+ const prereqTech = techData.find(t => t.id === prereqId);
893
+ if (prereqTech) {
894
+ drawConnection(
895
+ prereqTech.x + 50, prereqTech.y + 50,
896
+ tech.x + 50, tech.y + 50
897
+ );
898
+ }
899
+ });
900
+ }
901
+ });
902
+ }
903
 
904
  // Function to draw a connection line between two points
905
  function drawConnection(x1, y1, x2, y2) {
 
922
  techTree.insertBefore(line, techTree.firstChild);
923
  }
924
 
925
+ // Show technology details popup
926
+ function showTechPopup(tech) {
927
+ document.getElementById('popupTitle').textContent = tech.name;
928
+ document.getElementById('popupEra').textContent =
929
+ `${tech.era.charAt(0).toUpperCase() + tech.era.slice(1)} Era`;
930
+ document.getElementById('popupDescription').textContent = tech.description;
931
+
932
+ if (tech.prerequisites && tech.prerequisites.length) {
933
+ const prereqNames = tech.prerequisites.map(id => {
934
+ const prereq = techData.find(t => t.id === id);
935
+ return prereq ? prereq.name : 'Unknown Technology';
936
+ }).join(', ');
937
+ document.getElementById('popupPrereqs').textContent =
938
+ `Prerequisites: ${prereqNames}`;
939
+ } else {
940
+ document.getElementById('popupPrereqs').textContent =
941
+ 'Prerequisites: None (starting technology)';
942
+ }
943
+
944
+ nodePopup.style.display = 'block';
945
+ }
946
+
947
  // Close popup when clicking the X
948
  closePopup.addEventListener('click', () => {
949
  nodePopup.style.display = 'none';
 
956
  }
957
  });
958
 
959
+ // Show add technology form
960
+ addTechBtn.addEventListener('click', () => {
961
+ // Populate icon selector
962
+ iconSelector.innerHTML = '';
963
+ commonIcons.forEach(icon => {
964
+ const iconOption = document.createElement('div');
965
+ iconOption.className = `icon-option ${icon === selectedIcon ? 'selected' : ''}`;
966
+ iconOption.dataset.icon = icon;
967
+ iconOption.innerHTML = `<i class="${icon}"></i>`;
968
+
969
+ iconOption.addEventListener('click', () => {
970
+ selectedIcon = icon;
971
+ document.querySelectorAll('.icon-option').forEach(opt => {
972
+ opt.classList.remove('selected');
973
+ });
974
+ iconOption.classList.add('selected');
975
+ });
976
+
977
+ iconSelector.appendChild(iconOption);
978
+ });
979
+
980
+ // Populate prerequisite checkboxes
981
+ prerequisiteCheckboxes.innerHTML = '';
982
+ techData.forEach(tech => {
983
+ const checkboxItem = document.createElement('div');
984
+ checkboxItem.className = 'checkbox-item';
985
+
986
+ const checkbox = document.createElement('input');
987
+ checkbox.type = 'checkbox';
988
+ checkbox.id = `prereq-${tech.id}`;
989
+ checkbox.value = tech.id;
990
+
991
+ const label = document.createElement('label');
992
+ label.htmlFor = `prereq-${tech.id}`;
993
+ label.textContent = tech.name;
994
+
995
+ checkboxItem.appendChild(checkbox);
996
+ checkboxItem.appendChild(label);
997
+ prerequisiteCheckboxes.appendChild(checkboxItem);
998
+ });
999
+
1000
+ // Show the form
1001
+ addNodeForm.style.display = 'block';
1002
+ });
1003
+
1004
+ // Close add technology form
1005
+ cancelForm.addEventListener('click', () => {
1006
+ addNodeForm.style.display = 'none';
1007
+ techForm.reset();
1008
+ });
1009
+
1010
+ // Submit new technology
1011
+ techForm.addEventListener('submit', (e) => {
1012
+ e.preventDefault();
1013
+
1014
+ const name = document.getElementById('techName').value;
1015
+ const era = document.getElementById('techEra').value;
1016
+ const description = document.getElementById('techDescription').value;
1017
+
1018
+ // Get selected prerequisites
1019
+ const prerequisites = [];
1020
+ document.querySelectorAll('#prerequisiteCheckboxes input:checked').forEach(checkbox => {
1021
+ prerequisites.push(parseInt(checkbox.value));
1022
+ });
1023
+
1024
+ // Determine default position based on era
1025
+ let x, y;
1026
+ switch(era) {
1027
+ case 'ancient':
1028
+ x = 100 + (techData.filter(t => t.era === 'ancient').length * 200);
1029
+ y = 100;
1030
+ break;
1031
+ case 'classical':
1032
+ x = 200 + (techData.filter(t => t.era === 'classical').length * 200);
1033
+ y = 220;
1034
+ break;
1035
+ case 'medieval':
1036
+ x = 300 + (techData.filter(t => t.era === 'medieval').length * 200);
1037
+ y = 340;
1038
+ break;
1039
+ case 'industrial':
1040
+ x = 200 + (techData.filter(t => t.era === 'industrial').length * 200);
1041
+ y = 460;
1042
+ break;
1043
+ case 'modern':
1044
+ x = 200 + (techData.filter(t => t.era === 'modern').length * 200);
1045
+ y = 580;
1046
+ break;
1047
+ case 'future':
1048
+ x = 400 + (techData.filter(t => t.era === 'future').length * 200);
1049
+ y = 700;
1050
+ break;
1051
+ default:
1052
+ x = 100;
1053
+ y = 100;
1054
+ }
1055
+
1056
+ // Create the new tech
1057
+ const newTech = {
1058
+ id: nextId++,
1059
+ name,
1060
+ era,
1061
+ icon: selectedIcon,
1062
+ description,
1063
+ x,
1064
+ y,
1065
+ prerequisites
1066
+ };
1067
+
1068
+ // Add to our data
1069
+ techData.push(newTech);
1070
+
1071
+ // Redraw the tree
1072
+ drawTechTree();
1073
+
1074
+ // Close and reset the form
1075
+ addNodeForm.style.display = 'none';
1076
+ techForm.reset();
1077
+ });
1078
+
1079
  // Era button functionality
1080
  document.querySelectorAll('.era-button').forEach(button => {
1081
  button.addEventListener('click', () => {
1082
  const era = button.textContent.toLowerCase();
1083
 
1084
  // Simple animation - we could enhance this with smooth scrolling
1085
+ techTreeContainer.scrollTo({
1086
  left: getScrollPositionForEra(era),
1087
  behavior: 'smooth'
1088
  });
1089
+
1090
+ animateTechPath(era);
1091
  });
1092
  });
1093
 
 
1109
  techPath.style.width = `${width}%`;
1110
  }
1111
 
1112
+ // Toggle edit mode
1113
+ toggleEditMode.addEventListener('click', () => {
1114
+ editMode = !editMode;
1115
+
1116
+ if (editMode) {
1117
+ toggleEditMode.textContent = 'Edit Mode: ON';
1118
+ toggleEditMode.classList.add('active');
1119
+ techTreeContainer.classList.add('editable-mode');
1120
+
1121
+ // Show all drag handles and delete buttons
1122
+ document.querySelectorAll('.tech-node').forEach(node => {
1123
+ node.classList.add('editable');
1124
+ });
1125
+ } else {
1126
+ toggleEditMode.textContent = 'Edit Mode: OFF';
1127
+ toggleEditMode.classList.remove('active');
1128
+ techTreeContainer.classList.remove('editable-mode');
1129
+
1130
+ // Hide all drag handles and delete buttons
1131
+ document.querySelectorAll('.tech-node').forEach(node => {
1132
+ node.classList.remove('editable');
1133
+ });
1134
+
1135
+ // Stop any active dragging
1136
+ if (draggingNode) {
1137
+ draggingNode = null;
1138
+ document.removeEventListener('mousemove', dragNode);
1139
+ document.removeEventListener('mouseup', stopDrag);
1140
+ }
1141
+ }
1142
+ });
1143
+
1144
  // Initial load - set to ancient era
1145
  animateTechPath('ancient');
1146
+
1147
+ // Add mousemove and mouseup handlers for the document
1148
+ document.addEventListener('mousemove', (e) => {
1149
+ if (draggingNode) {
1150
+ dragNode(e);
1151
+ }
1152
+ });
1153
+
1154
+ document.addEventListener('mouseup', () => {
1155
+ if (draggingNode) {
1156
+ stopDrag();
1157
+ }
1158
+ });
1159
  });
1160
  </script>
1161
+ </body>
1162
  </html>