Skip to content
Snippets Groups Projects
Commit fbb1b0fe authored by baletiballo's avatar baletiballo
Browse files

Moved scroll-Slot label assignment to SetScrollContent.js. Unity still sends the neccessary data

parent 512dcfb9
No related branches found
No related tags found
No related merge requests found
......@@ -12,6 +12,7 @@
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UIElements;
public class WebViewController : ScrollView
{
......@@ -35,9 +36,10 @@ private void OnWebViewComponentReady()
SwitchScrollUI.activeScrollData.HintAvailableEvent.AddListener(OnHintAvailable);
webViewComponent.tab.AddJSBinding("applyScroll", ApplyScrollHandler);
webViewComponent.tab.AddJSBinding("getHint", GetHintHandler);
// webViewComponent.tab.AddJSBinding("updateAssignments", UpdateAssignmentsHandler); // The browser can just ask the MMTServer directly
if (SwitchScrollUI.activeScrollData.Scroll is not null)
{
SetScrollContent(SwitchScrollUI.activeScrollData.Scroll);
SetScrollContent(SwitchScrollUI.activeScrollData.RenderedScroll);
}
RegisterBrowserEventhandlers();
}
......@@ -76,42 +78,23 @@ private void DeRegisterBrowserEventhandlers()
}
/// <summary>
/// sets or updates the content of the scroll container dom element
/// <para>
/// Hand the ScrollView the labels (and potentially assignments) of all facts, so it can render the scroll content. (And then tell it to do so)
/// </para><para>
/// More precisely: Put a stringified and Json serialized Dictionary
/// <see cref="OMS.uri"/> slotID -> (<see cref="string"/> label, <see cref="Fact.Id"/> factId) <br/>
/// into the "data-assignments" attribute of the "assignments" node
/// </para>
/// </summary>
/// <param name="scroll"></param>
private async void SetScrollContent(Scroll scroll)
{
// update scroll container content
DomNodeWrapper document = await webViewComponent.tab.Document;
DomNodeWrapper scrollContainer = await document.querySelectorAsync("#scrollContainer");
DomNodeWrapper scrollContainer = await document.querySelectorAsync("#scrollContainer");
var description = scroll.description;
if (Regex.IsMatch(description, ".*<scroll-description.*"))
{
// replace slot templates
description = Regex.Replace(description, "<scroll-slot([^>]*)>([^<]*)</scroll-slot>", match =>
{
var extraAttributes = match.Groups[1].Value;
var slotId = match.Groups[2].Value;
var assignment = SwitchScrollUI.activeScrollData.Assignments[slotId];
/** label of the assigned fact, or the slot label if nothing assigned */
var label = assignment.IsSet ? assignment.fact.GetLabel(StageStatic.stage.factState)
: scroll.requiredFacts.Find(fact => fact.@ref.uri == slotId).label;
/** id of the assigned fact. If nothing is assigned don't add the attribute */
var fact_id = assignment.IsSet ? $"data-fact-id='{assignment.fact.Id}'"
: "";
return $"<mi dropzone='copy' data-slot-id='{slotId}' {fact_id} {extraAttributes}>{label}</mi>";
});
// replace solution templates
description = Regex.Replace(description, "<scroll-solution([^>]*)>([^<]*)</scroll-solution>", match =>
{
var extraAttributes = match.Groups[1].Value;
var solutionId = match.Groups[2].Value;
var label = scroll.acquiredFacts.Find(fact => fact.@ref.uri == solutionId).label;
return $"<mi data-solution-id='{solutionId}' {extraAttributes}>{label}</mi>";
});
}
else
if (!Regex.IsMatch(description, ".*<scroll-description.*"))
{
// scroll is a legacy plain text scroll, generate html with slots for the required facts
var factSlots = SwitchScrollUI.activeScrollData.Assignments
......@@ -120,15 +103,67 @@ private async void SetScrollContent(Scroll scroll)
@$"<span class='legacySlot' dropzone='copy' data-slot-id='{pair.Key}' {(pair.Value.IsSet ? $"data-fact-id='{pair.Value.fact.Id}'" : "")}>
{(pair.Value.IsSet ?
pair.Value.fact.GetLabel(StageStatic.stage.factState) :
scroll.requiredFacts.Find(fact => fact.@ref.uri == pair.Key).label )}
scroll.requiredFacts.Find(fact => fact.@ref.uri == pair.Key).label)}
</span>");
description = $"<scroll-description><p>{scroll.description}</p><div id='legacySlots'>{String.Join("", factSlots)}</div></scroll-description>";
}
// display the scroll description
dropzones = null;
//else // Is done by JS. How to render the scroll is the scrolls buisness
//{
// // replace slot templates
// description = Regex.Replace(description, "<scroll-slot([^>]*)>([^<]*)</scroll-slot>", match =>
// {
// var extraAttributes = match.Groups[1].Value;
// var slotId = match.Groups[2].Value;
// var assignment = SwitchScrollUI.activeScrollData.Assignments[slotId];
// /** label of the assigned fact, or the slot label if nothing assigned */
// var label = assignment.IsSet ? assignment.fact.GetLabel(StageStatic.stage.factState)
// : scroll.requiredFacts.Find(fact => fact.@ref.uri == slotId).label;
// /** id of the assigned fact. If nothing is assigned don't add the attribute */
// var fact_id = assignment.IsSet ? $"data-fact-id='{assignment.fact.Id}'"
// : "";
// return $"<mi dropzone='copy' data-slot-id='{slotId}' {fact_id} {extraAttributes}>{label}</mi>";
// });
// // replace solution templates
// description = Regex.Replace(description, "<scroll-solution([^>]*)>([^<]*)</scroll-solution>", match =>
// {
// var extraAttributes = match.Groups[1].Value;
// var solutionId = match.Groups[2].Value;
// var label = scroll.acquiredFacts.Find(fact => fact.@ref.uri == solutionId).label;
// return $"<mi data-solution-id='{solutionId}' {extraAttributes}>{label}</mi>";
// });
//}
// Display the scroll description.
await scrollContainer.setOuterHtmlAsync($"<div id='scrollContainer'>{description}</div>");
DomNodeWrapper assignmentsNode = await document.querySelectorAsync("#assignments");
Dictionary<string, (string, string)> assignments = new();
foreach (MMTFact fact in scroll.requiredFacts)
{
string slotId = fact.@ref.uri;
ActiveScroll.SlotAssignment assignment = SwitchScrollUI.activeScrollData.Assignments[slotId];
if (assignment.IsSet)
{
assignments.Add(slotId, (assignment.fact.GetLabel(StageStatic.stage.factState), assignment.fact.Id));
}
else
{
assignments.Add(slotId, (fact.label, ""));
}
}
foreach (MMTFact fact in scroll.acquiredFacts)
{
assignments.Add(fact.@ref.uri, (fact.label, ""));
}
await assignmentsNode.setAttributeValue("data-assignments", JsonConvert.SerializeObject(assignments));
_ = webViewComponent.tab.Evaluate("RenderScroll()");
// Update the interactive components
dropzones = null;
RegisterBrowserEventhandlers();
}
......@@ -194,6 +229,43 @@ private void GetHintHandler(string url)
SwitchScrollUI.activeScrollData.ButtonClicked(new HintScrollButton(url));
}
/// <summary>
/// <para>
/// Hand the ScrollView the labels (and potentially assignments) of all facts, so it can render the scroll.
/// </para><para>
/// More precisely: Put a stringified and Json serialized Dictionary
/// <see cref="OMS.uri"/> slotID -> (<see cref="string"/> label, <see cref="Fact.Id"/> factId) <br/>
/// into the "data-assignments" attribute of the "assignments" node
/// </para>
/// </summary>
/// <param name="youHappyNowJS">Is ignored. JS bindings need to take a string argument, so here it is.</param>
[Obsolete("This data can be aquired directly from the MMTServer")]
private async void UpdateAssignmentsHandler(string youHappyNowJS = "")
{
DomNodeWrapper document = await webViewComponent.tab.Document;
DomNodeWrapper assignmentsNode = await document.querySelectorAsync("#assignments");
Scroll scroll = SwitchScrollUI.activeScrollData.RenderedScroll;
Dictionary<string, (string,string)> assignments = new();
foreach (var (slotId,assignment) in SwitchScrollUI.activeScrollData.Assignments)
{
string label = assignment.IsSet ? assignment.fact.GetLabel(StageStatic.stage.factState)
: scroll.requiredFacts.Find(fact => fact.@ref.uri == slotId).label;
/** id of the assigned fact. If nothing is assigned don't add the attribute */
string fact_id = assignment.IsSet ? assignment.fact.Id : "";
assignments.Add(slotId,(label,fact_id));
}
foreach(MMTFact fact in scroll.acquiredFacts)
{
string label = scroll.acquiredFacts.Find(f => fact.@ref.uri == f.@ref.uri).label;
Debug.Log(label);
Debug.Log(fact.label);
assignments.Add(fact.@ref.uri, (fact.label, ""));
}
await assignmentsNode.setAttributeValue("data-assignments", JsonConvert.SerializeObject(assignments));
}
public string[] GetFactAssignments()
{
return dropzones.Select(dropzone => dropzone.Node.attributes.GetValueOrDefault("data-fact-id", null)).ToArray();
......
......@@ -43,28 +43,28 @@
<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>
<mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem?A"></mi>
<mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem?B"></mi>
<mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem?C"></mi>
</math>
<span>right-angled at</span>
<math>
<!--<mi>&angrtvbd;</mi>--><!-- ⦝ -->
<scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC</scroll-slot>
<mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC"></mi>
</math>,<br />
<span>the opposite side has length</span>
<math>
<scroll-solution>http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA</scroll-solution>
<mi data-solution-id="http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA"></mi>
<mo>&equals;</mo>
<mrow>
<mi>tan</mi>
<!--<mo>&#8289;</mo>-->
<mo>(</mo>
<scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB</scroll-slot>
<mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB"></mi>
<mo>)</mo>
</mrow>
<mo>&#8290;</mo>
<scroll-slot>http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC</scroll-slot>
<mi data-slot-id="http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC"></mi>
</math>
<span>.</span>
<div>
......@@ -109,7 +109,6 @@
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'
......@@ -117,7 +116,6 @@
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'
......@@ -125,7 +123,6 @@
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'
......@@ -133,7 +130,6 @@
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'
......@@ -141,7 +137,6 @@
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'
......@@ -149,7 +144,6 @@
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'
......@@ -183,15 +177,10 @@
}
loadScript("./scroll_interaction/Drop_facts.js")
const container = document.getElementById('scrollContainer');
const tmp = document.createElement('div');
tmp.id='test'
tmp.innerText = 'test'
container.append(tmp);
loadScript("./scroll_interaction/SetScrollContent.js")
</script>
<data id="assignments" hidden data-assignments="">hi</data>
<data id="assignments" hidden data-assignments="{&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem?A&quot;:{&quot;Item1&quot;:&quot;(C)&quot;,&quot;Item2&quot;:&quot;http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact310&quot;},&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem?B&quot;:{&quot;Item1&quot;:&quot;(B)&quot;,&quot;Item2&quot;:&quot;http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact309&quot;},&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem?C&quot;:{&quot;Item1&quot;:&quot;C&quot;,&quot;Item2&quot;:&quot;&quot;},&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC&quot;:{&quot;Item1&quot;:&quot;⊾C&quot;,&quot;Item2&quot;:&quot;&quot;},&quot;http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC&quot;:{&quot;Item1&quot;:&quot;BC&quot;,&quot;Item2&quot;:&quot;&quot;},&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB&quot;:{&quot;Item1&quot;:&quot;∠ABC&quot;,&quot;Item2&quot;:&quot;&quot;},&quot;http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA&quot;:{&quot;Item1&quot;:&quot;CA&quot;,&quot;Item2&quot;:&quot;&quot;}}">hi</data>
<!--<script src="visualiseCursor.mjs" defer type="module"></script>-->
<!--<script>
......
function RenderScroll() {
const scrollContainer = document.querySelector("#scrollContainer");
const description = scrollContainer.textContent;
const assignments = JSON.parse(document.querySelector("#assignments").dataset.assignments)
console.log(assignments);
//everything that has a slotID is a scroll slot
scrollContainer.querySelectorAll("[data-slot-id]").forEach(element => {
//console.log(element);
let slotId = element.dataset.slotId;
let fact_assignment = assignments[slotId];
element.setAttribute("dropzone", "copy");
element.textContent = fact_assignment.Item1;
if (fact_assignment.Item2 != "") {
element.dataset.factId = fact_assignment.Item2;
}
});
//everything that has a solutionID is a scroll solution
scrollContainer.querySelectorAll("[data-solution-id]").forEach(element => {
element.textContent = assignments[element.dataset.solutionId].Item1;
})
console.log('Scroll rendered')
}
RenderScroll()
// if (Regex.IsMatch(description, ".*<scroll-description.*"))
// {
// // replace slot templates
// description = Regex.Replace(description, "<scroll-slot([^>]*)>([^<]*)</scroll-slot>", match =>
// {
// var extraAttributes = match.Groups[1].Value;
// var slotId = match.Groups[2].Value;
// var assignment = SwitchScrollUI.activeScrollData.Assignments[slotId];
// /** label of the assigned fact, or the slot label if nothing assigned */
// var label = assignment.IsSet ? assignment.fact.GetLabel(StageStatic.stage.factState)
// : scroll.requiredFacts.Find(fact => fact.@ref.uri == slotId).label;
// /** id of the assigned fact. If nothing is assigned don't add the attribute */
// var fact_id = assignment.IsSet ? $"data-fact-id='{assignment.fact.Id}'"
// : "";
// return $"<mi dropzone='copy' data-slot-id='{slotId}' {fact_id} {extraAttributes}>{label}</mi>";
// });
// // replace solution templates
// description = Regex.Replace(description, "<scroll-solution([^>]*)>([^<]*)</scroll-solution>", match =>
// {
// var extraAttributes = match.Groups[1].Value;
// var solutionId = match.Groups[2].Value;
// var label = scroll.acquiredFacts.Find(fact => fact.@ref.uri == solutionId).label;
// return $"<mi data-solution-id='{solutionId}' {extraAttributes}>{label}</mi>";
// });
// }
// else
// {
// // scroll is a legacy plain text scroll, generate html with slots for the required facts
// var factSlots = SwitchScrollUI.activeScrollData.Assignments
// .Where(pair => pair.Value.IsVisible)
// .Select(pair =>
// @$"<span class='legacySlot' dropzone='copy' data-slot-id='{pair.Key}' {(pair.Value.IsSet ? $"data-fact-id='{pair.Value.fact.Id}'" : "")}>
// {(pair.Value.IsSet ?
// pair.Value.fact.GetLabel(StageStatic.stage.factState) :
// scroll.requiredFacts.Find(fact => fact.@ref.uri == pair.Key).label )}
// </span>");
// description = $"<scroll-description><p>{scroll.description}</p><div id='legacySlots'>{String.Join("", factSlots)}</div></scroll-description>";
// }
\ No newline at end of file
fileFormatVersion: 2
guid: 215e6162e17215b4a9118b3db2f4944f
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment