diff --git a/Assets/StreamingAssets/StreamToDataPath_withHandler/scrollView.html b/Assets/StreamingAssets/StreamToDataPath_withHandler/scrollView.html
index ab6b51d09ba0a7870fe249084b5e2405751c2fda..fdbda223d648b86a920c896deeb72e30c8bfbc5e 100644
--- a/Assets/StreamingAssets/StreamToDataPath_withHandler/scrollView.html
+++ b/Assets/StreamingAssets/StreamToDataPath_withHandler/scrollView.html
@@ -1,4 +1,5 @@
 <!DOCTYPE html>
+<html>
 <head>
   <meta charset="utf-8">
   <title>Scroll View</title>
@@ -38,254 +39,160 @@
 <body>
   <div id="scrollContainer">
     <div>No scroll selected</div>
-    <math>
-      <mi>E</mi>
-      <mo>=</mo>
-      <mfenced>
-      <mtable>
-        <mtr>
-          <mtd>
-            <mi dropzone="copy" data-allowed-types="PointFact,AngleFact" data-slot-id="http://mathhub.info/FrameIT/frameworld?Example?A">a</mi>
-          </mtd>
-          <mtd>
-              <mi dropzone="copy" data-slot-id="http://mathhub.info/FrameIT/frameworld?Example?B">b</mi>
-          </mtd>
-          <mtd>
-            <mn>0</mn>
-          </mtd>
-        </mtr>
-        <mtr>
-          <mtd>
-            <mn>0</mn>
-          </mtd>
-          <mtd>
-            <mn>1</mn>
-          </mtd>
-          <mtd>
-            <mn>0</mn>
-          </mtd>
-        </mtr>
-        <mtr>
-          <mtd>
-            <mn>0</mn>
-          </mtd>
-          <mtd>
-            <mn>0</mn>
-          </mtd>
-          <mtd>
-            <mn>1</mn>
-          </mtd>
-        </mtr>
-      </mtable>
-    </math>
+    <scroll-description title='OppositeLenScroll' alt='Given a triangle △A B C right-angled at ⊾C, the opposite side has length CA = tan(angleB) ⋅ BC.'>
+      <span>Given a triangle</span>
+      <math>
+          <mi>&xutri;<!-- △ --></mi>
+          <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem?A</scroll-slot>
+          <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem?B</scroll-slot>
+          <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem?C</scroll-slot>
+      </math>
+      <span>right-angled at</span>
+      <math>
+          <!--<mi>&angrtvbd;</mi>--><!-- ⦝ -->
+          <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC</scroll-slot>
+      </math>,<br />
+      <span>the opposite side has length</span>
+      <math>
+          <scroll-solution>http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA</scroll-solution>
+          <mo>&equals;</mo>
+          <mrow>
+              <mi>tan</mi>
+              <!--<mo>&#8289;</mo>-->
+              <mo>(</mo>
+              <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB</scroll-slot>
+              <mo>)</mo>
+          </mrow>
+          <mo>&#8290;</mo>
+          <scroll-slot>http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC</scroll-slot>
+      </math>
+      <span>.</span>
+      <div>
+          <svg
+          width='50mm'
+          height='45mm'
+          viewBox='35 0 90 70'
+          version='1.1'
+          id='triangle'
+          xmlns='http://www.w3.org/2000/svg'
+          xmlns:svg='http://www.w3.org/2000/svg'>
+          <g id='shape'>
+              <path
+                  style='fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1'
+                  d='M 42.871972,64.67128 H 84.290656 V 7.6297578 Z'
+                  id='triangle' />
+              <path
+                  id='angleABC'
+                  style='fill:none;stroke:#000000;stroke-width:0.265;stroke-dasharray:none;stroke-opacity:1'
+                  d='m 46.024276,60.304806 a 5.3589964,5.3589964 0 0 1 2.252109,4.366474 h -5.358996 z' />
+              <g
+                  id='angleBCA'>
+                  <path
+                      style='fill:none;stroke:#000000;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1'
+                      id='rightAngle'
+                      d='m 78.972396,64.665062 a 5.3308268,5.3308268 0 0 1 5.330827,-5.330827 v 5.330827 z' />
+                  <circle
+                      style='fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1'
+                      id='rightAngleDot'
+                      cx='82.081886'
+                      cy='62.813831'
+                      r='0.32113415' />
+              </g>
+          </g>
+          <g
+              id='labels'
+              style='font-size:4.23333px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583'
+          >
+              <text
+                  xml:space='preserve'
+                  x='39.242592'
+                  y='67.117035'
+                  id='pointB'
+                  style='fill:#0000ff'
+                  dropzone='copy'
+                  data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?B'>${lverb B}</text>
+              <text
+                  xml:space='preserve'
+                  x='85.100548'
+                  y='68.080437'
+                  id='pointC'
+                  style='fill:#0000ff'
+                  dropzone='copy'
+                  data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?C'>${lverb C}</text>
+              <text
+                  xml:space='preserve'
+                  x='84.650963'
+                  y='6.551136'
+                  id='pointA'
+                  style='fill:#0000ff'
+                  dropzone='copy'
+                  data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?A'>${lverb A}</text>
+              <text
+                  xml:space='preserve'
+                  x='48.234348'
+                  y='62.492699'
+                  id='angleAtB'
+                  style='fill:#ffcc00'
+                  dropzone='copy'
+                  data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB'>${lverb angleB}</text>
+              <text
+                  xml:space='preserve'
+                  x='71.548683'
+                  y='60.951256'
+                  id='rightAngleAtC'
+                  style='fill:#ffcc00'
+                  dropzone='copy'
+                  data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC'>${lverb rightAngleC}</text>
+              <text
+                  xml:space='preserve'
+                  x='59.409813'
+                  y='68.273117'
+                  id='distanceBC'
+                  style='fill:#008000'
+                  dropzone='copy'
+                  data-slot-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC'>${lverb distanceBC}</text>
+              <text
+                  xml:space='preserve'
+                  x='84.972092'
+                  y='35.260529'
+                  id='solutionCA'
+                  style='fill:#008000'
+                  data-solution-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA'>${lverb deducedLineCA}</text>
+          </g>
+          </svg>
+      </div>
+  </scroll-description>
   </div>
   <button type="button" title="Apply the scroll" onclick="applyScroll('')">Apply</button><br>
   <p>You can right click on yellow slots to get a hint.</p>
-</body>
-  <script>
-    /**
-   * @typedef Point
-   * @type {object}
-   * @property {number} x
-   * @property {number} y
-   * @property {number} z
-   */
-  
-  /**
-   * @property {Point} point
-   * @property {Point} normal
-   * @property {string} s_type
-   * @property {string} label
-   * @property {string|null} _CustomLabel
-   * @property {boolean} hasCustomLabel
-   * @property {number} labelId
-   */
-  
-  class Fact {
-      /** @property {string} id Fact id */
-      id = ""
-      /** @property {string} s_type Fact type */
-      s_type = ""
-      /** @property {string} label used in unity */
-      label = ""
-      /** @property {string | null} _CustomLabel Custom label */
-      _CustomLabel = null
-      /** @property {boolean} hasCustomLabel */
-      hasCustomLabel = false
-      /** @property {number} labelId */
-      labelId = 0
-  }
-  
-  class Point {
-      /** @property {number} x */
-      x = 0
-      /** @property {number} y */
-      y = 0
-      /** @property {number} z */
-      z = 0
-  }
-  /**
-  s_type: PointFact,
-  label: A,
-  _CustomLabel: null,
-  hasCustomLabel: false,
-  labelId: 0,
-  point: {x: -1.66086578, y: -0.00494432449, z: -2.17682648},
-  normal: {x: 0, y: 1, z: 0}
-   */
-  class PointFact extends Fact {
-      s_type = "PointFact";
-      /** @property {Point} point */
-      point = new Point()
-      /** @property {Point} normal */
-      normal = new Point()
-  }
-  
-  /**
-   * pid1: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact252,
-  pid2: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact254,
-  pid3: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact256,
-  s_type: AngleFact,
-  label: ∠BDF,
-  _CustomLabel: null,
-  is_right_angle: false,
-  hasCustomLabel: false,
-  labelId: 0
-   */
-  class AngleFact extends Fact {
-      s_type = "AngleFact";
-      pid1 = "";
-      pid2 = "";
-      pid3 = "";
-      is_right_angle = false;
-  }
-  
-  /**
-   * s_type: LineFact,
-  pid1: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact255,
-  pid2: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact256,
-  dir: [object Object],
-  label: [EF],
-  _CustomLabel: null,
-  hasCustomLabel: false,
-  labelId: 0
-   */
-  class LineFact extends Fact {
-      s_type = "LineFact";
-      pid1 = "";
-      pid2 = "";
-      dir = new Point();
-  }
-  
-  /**
-   * s_type: RayFact,
-  pid1: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact256,
-  pid2: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact252,
-  dir: [object Object],
-  label: FB,
-  _CustomLabel: null,
-  hasCustomLabel: false,
-  labelId: 0
-   */
-  class RayFact extends Fact {
-      s_type = "RayFact";
-      pid1 = "";
-      pid2 = "";
-      dir = new Point();
-  }
-  
-  
-  
-  /** @param {DragEvent} event  */
-  function dropHandler(event) {
-    event.preventDefault()
-    console.log("dropHandler", event)
 
-    const data = event.dataTransfer.getData("application/json")
-    //const data = event.dataTransfer.getData("text/plain")
-    console.log(`Dropped data: '${event.dataTransfer.types}'`, event.dataTransfer.types)
-
-    /** @type {Fact} */
-    const fact = JSON.parse(data)
-    console.warn(`Dropped Fact '${fact.label}':`, fact)
-
-    /** @type {HTMLElement} */
-    const element = event.target
-
-    if (element.hasAttribute("data-allowed-types")) {
-      //const allowedTypesStr = element.dataset["allowed-types"]
-      const allowedTypesStr = element.getAttribute("data-allowed-types")
-      const allowedTypes = allowedTypesStr.split(",")
-
-      if (!allowedTypes.includes(fact.s_type)) {
-        console.warn(`The drop target data-type '${fact.s_type}' is not a member of the allowed types '${allowedTypesStr}'`)
-        return
-      }
+  <script>  
+    /** 
+     * Load all .js files for interactive scrolls. (So we can use e.g. Typescript)
+     * 
+     * This is no more dangerous than having this file in the streaming assets. 
+     * Any malicious code could just be written in here as well ¯\_(ツ)_/¯. 
+    */
+    function loadScript(url)
+    {    
+        const head = document.getElementsByTagName('head')[0];
+        const script = document.createElement('script');
+        script.type = 'text/javascript';
+        script.src = url;
+        head.appendChild(script);
     }
 
-    element.innerHTML = fact.label
-    element.fact = fact
-    element.dataset.factId = fact.id
-  }
+    loadScript("./scroll_interaction/Drop_facts.js")
 
-  /** @param {MouseEvent} event  */
-  function clickHandler(event) {
-    event.preventDefault()
-    console.log("clickHandler")
-    console.log("clickHandler", event)
-    switch (event.button) {
-      case 0:
-        console.log("Left button clicked")
-        event.target.fact = null
-        event.target.dataset.factId = null
-        break
-      case 1:
-        console.log("Middle button clicked")
-        break
-      case 2:
-        console.log("Right button clicked")
-        getHint(event.target.dataset.slotId)
-        break
-      default:
-        console.log("Unknown button clicked")
-    }
-  }
+    const container = document.getElementById('scrollContainer');
+    const tmp = document.createElement('div');
+    tmp.id='test'
+    tmp.innerText = 'test'
+    container.append(tmp);
 
-  /*
-  * register the drag event listeners
-  */
-  //document.addEventListener("dragstart", ev => printHandler(ev, "DragStartEvent"))
-  //document.addEventListener("dragenter", ev => printHandler(ev, "DragEnterEvent"))
-  //document.addEventListener("drag", ev => printHandler(ev, "DragEvent"))
-  document.addEventListener("dragover", ev => ev.preventDefault())
-  //document.addEventListener("dragover", ev => printPreventDefaultHandler(ev, "DragOverEvent"))
-  //document.addEventListener("dragleave", ev => printHandler(ev, "DragLeaveEvent"))
-  //document.addEventListener("dragend", ev => printHandler(ev, "DragEndEvent"))
-  
-  // select all dropzones and add drop event listeners
-  //let dropZones = document.querySelectorAll('[dropzone="copy"]')
-  //dropZones.forEach( dropZone => dropZone.addEventListener("drop", ev => dropHandler(ev, "DropEvent")) )
-  
-  /** select all dropzones and add drop event listeners */
-  function addDropZoneEventListeners() {
-    console.log("addDropZoneEventListeners")
-    document.querySelectorAll('[dropzone="copy"]')
-      .forEach( dropZone => {
-        dropZone.removeEventListener("drop", dropHandler)
-        dropZone.removeEventListener("click", clickHandler)
-        dropZone.removeEventListener("contextmenu", clickHandler)
-        //dropZone.addEventListener("dragover", ev => ev.preventDefault())
-        dropZone.addEventListener("drop", dropHandler)
-        dropZone.addEventListener("click", clickHandler)
-        dropZone.addEventListener("contextmenu", clickHandler)
-      })
-  }
-  //addDropZoneEventListeners()
   </script>
-
-
-
-
+  <data id="assignments" hidden data-assignments="">hi</data>
+  
   <!--<script src="visualiseCursor.mjs" defer type="module"></script>-->
   <!--<script>
   /* mouse and pointer event handling */
@@ -312,4 +219,5 @@
   document.addEventListener("mouseout", followCursor);
   document.addEventListener("pointerout", followCursor);
   </script>-->
+</body>
 </html>
diff --git a/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction.meta b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction.meta
new file mode 100644
index 0000000000000000000000000000000000000000..bc705e5d67b18259958df6e53290fe1488dd0cca
--- /dev/null
+++ b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c135f4fc25ecfc745a294bbcae38777f
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/Drop_facts.js b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/Drop_facts.js
new file mode 100644
index 0000000000000000000000000000000000000000..d74a0862a545a2c3d94287f7bd1fc18a92a01827
--- /dev/null
+++ b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/Drop_facts.js
@@ -0,0 +1,204 @@
+/**
+ * @typedef Point
+ * @type {object}
+ * @property {number} x
+ * @property {number} y
+ * @property {number} z
+ */
+
+/**
+ * @property {Point} point
+ * @property {Point} normal
+ * @property {string} s_type
+ * @property {string} label
+ * @property {string|null} _CustomLabel
+ * @property {boolean} hasCustomLabel
+ * @property {number} labelId
+ */
+
+var assignment;
+
+class Fact {
+    /** @property {string} id Fact id */
+    id = ""
+    /** @property {string} s_type Fact type */
+    s_type = ""
+    /** @property {string} label used in unity */
+    label = ""
+    /** @property {string | null} _CustomLabel Custom label */
+    _CustomLabel = null
+    /** @property {boolean} hasCustomLabel */
+    hasCustomLabel = false
+    /** @property {number} labelId */
+    labelId = 0
+}
+
+class Point {
+    /** @property {number} x */
+    x = 0
+    /** @property {number} y */
+    y = 0
+    /** @property {number} z */
+    z = 0
+}
+/**
+s_type: PointFact,
+label: A,
+_CustomLabel: null,
+hasCustomLabel: false,
+labelId: 0,
+point: {x: -1.66086578, y: -0.00494432449, z: -2.17682648},
+normal: {x: 0, y: 1, z: 0}
+*/
+class PointFact extends Fact {
+    s_type = "PointFact";
+    /** @property {Point} point */
+    point = new Point()
+    /** @property {Point} normal */
+    normal = new Point()
+}
+
+/**
+ * pid1: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact252,
+pid2: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact254,
+pid3: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact256,
+s_type: AngleFact,
+label: ∠BDF,
+_CustomLabel: null,
+is_right_angle: false,
+hasCustomLabel: false,
+labelId: 0
+*/
+class AngleFact extends Fact {
+    s_type = "AngleFact";
+    pid1 = "";
+    pid2 = "";
+    pid3 = "";
+    is_right_angle = false;
+}
+
+/**
+ * s_type: LineFact,
+pid1: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact255,
+pid2: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact256,
+dir: [object Object],
+label: [EF],
+_CustomLabel: null,
+hasCustomLabel: false,
+labelId: 0
+*/
+class LineFact extends Fact {
+    s_type = "LineFact";
+    pid1 = "";
+    pid2 = "";
+    dir = new Point();
+}
+
+/**
+ * s_type: RayFact,
+pid1: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact256,
+pid2: http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact252,
+dir: [object Object],
+label: FB,
+_CustomLabel: null,
+hasCustomLabel: false,
+labelId: 0
+*/
+class RayFact extends Fact {
+    s_type = "RayFact";
+    pid1 = "";
+    pid2 = "";
+    dir = new Point();
+}
+
+
+
+/** @param {DragEvent} event  */
+function dropHandler(event) {
+    event.preventDefault()
+    console.log("dropHandler", event)
+
+    const data = event.dataTransfer.getData("application/json")
+    //const data = event.dataTransfer.getData("text/plain")
+    console.log(`Dropped data: '${event.dataTransfer.types}'`, event.dataTransfer.types)
+
+    /** @type {Fact} */
+    const fact = JSON.parse(data)
+    console.warn(`Dropped Fact '${fact.label}':`, fact)
+
+    /** @type {HTMLElement} */
+    const element = event.target
+
+    if (element.hasAttribute("data-allowed-types")) {
+    //const allowedTypesStr = element.dataset["allowed-types"]
+    const allowedTypesStr = element.getAttribute("data-allowed-types")
+    const allowedTypes = allowedTypesStr.split(",")
+
+    if (!allowedTypes.includes(fact.s_type)) {
+        console.warn(`The drop target data-type '${fact.s_type}' is not a member of the allowed types '${allowedTypesStr}'`)
+        return
+    }
+    }
+
+    element.innerHTML = fact.label
+    element.fact = fact
+    element.dataset.factId = fact.id
+}
+
+/** @param {MouseEvent} event  */
+function clickHandler(event) {
+    event.preventDefault()
+    console.log("clickHandler")
+    console.log("clickHandler", event)
+    switch (event.button) {
+    case 0:
+        console.log("Left button clicked")
+        event.target.fact = null
+        event.target.dataset.factId = null
+        break
+    case 1:
+        console.log("Middle button clicked")
+        break
+    case 2:
+        console.log("Right button clicked")
+        getHint(event.target.dataset.slotId)
+        break
+    default:
+        console.log("Unknown button clicked")
+    }
+}
+
+/*
+* register the drag event listeners
+*/
+//document.addEventListener("dragstart", ev => printHandler(ev, "DragStartEvent"))
+//document.addEventListener("dragenter", ev => printHandler(ev, "DragEnterEvent"))
+//document.addEventListener("drag", ev => printHandler(ev, "DragEvent"))
+document.addEventListener("dragover", ev => ev.preventDefault())
+//document.addEventListener("dragover", ev => printPreventDefaultHandler(ev, "DragOverEvent"))
+//document.addEventListener("dragleave", ev => printHandler(ev, "DragLeaveEvent"))
+//document.addEventListener("dragend", ev => printHandler(ev, "DragEndEvent"))
+
+// select all dropzones and add drop event listeners
+//let dropZones = document.querySelectorAll('[dropzone="copy"]')
+//dropZones.forEach( dropZone => dropZone.addEventListener("drop", ev => dropHandler(ev, "DropEvent")) )
+
+/** select all dropzones and add drop event listeners */
+function addDropZoneEventListeners() {
+    console.log("addDropZoneEventListeners")
+    document.querySelectorAll('[dropzone="copy"]')
+    .forEach( dropZone => {
+        dropZone.removeEventListener("drop", dropHandler)
+        dropZone.removeEventListener("click", clickHandler)
+        dropZone.removeEventListener("contextmenu", clickHandler)
+        //dropZone.addEventListener("dragover", ev => ev.preventDefault())
+        dropZone.addEventListener("drop", dropHandler)
+        dropZone.addEventListener("click", clickHandler)
+        dropZone.addEventListener("contextmenu", clickHandler)
+    })
+}
+//addDropZoneEventListeners()
+
+console.log("worked")
+const test = document.getElementById('test');
+test.innerText += ' successful'
diff --git a/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/Drop_facts.js.meta b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/Drop_facts.js.meta
new file mode 100644
index 0000000000000000000000000000000000000000..a98621e25b5e9222e2c1e3eb7062f07299840cc4
--- /dev/null
+++ b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/Drop_facts.js.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 817c254809af43848b2648523bd2fa70
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: