From ff99a64adf57e70ad214176e8e896d14d8ae9879 Mon Sep 17 00:00:00 2001 From: smmercuri Date: Mon, 6 Nov 2023 15:34:00 +0000 Subject: [PATCH] add support for custom keys in question variables and fix linkage to input --- corsscripts/stacksortable.js | 16 ++++++++++++---- corsscripts/stacksortable.min.js | 5 +++-- stack/cas/castext2/blocks/parsons.block.php | 18 +++++++++++++----- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/corsscripts/stacksortable.js b/corsscripts/stacksortable.js index f3af6c6f31f..b1788dbb6f7 100644 --- a/corsscripts/stacksortable.js +++ b/corsscripts/stacksortable.js @@ -7,7 +7,7 @@ export const stack_sortable = class { - constructor(state, availableId, inputId = null, options = null) { + constructor(state, availableId, usedId, inputId = null, options = null) { this.state = state; this.inputId = inputId; if (inputId != null) { @@ -15,6 +15,8 @@ export const stack_sortable = class { }; this.availableId = availableId; this.available = document.getElementById(this.availableId); + this.usedId = usedId; + this.used = document.getElementById(this.usedId); // TODO : additional default options? this.defaultOptions = {animation: 50}; if (options == null) { @@ -34,9 +36,15 @@ export const stack_sortable = class { li.className = "list-group-item"; this.available.append(li); }; - if (this.inputId != null) { - this.input.value = JSON.stringify(this.state); - this.input.dispatchEvent(new Event("change")); + } + + generate_used(proofSteps) { + for (const key in this.state.used) { + let li = document.createElement("li"); + li.innerText = proofSteps[this.state.used[key]]; + li.setAttribute("data-id", this.state.used[key]); + li.className = "list-group-item"; + this.used.append(li); }; } diff --git a/corsscripts/stacksortable.min.js b/corsscripts/stacksortable.min.js index 0a2fa21afdf..68141404540 100644 --- a/corsscripts/stacksortable.min.js +++ b/corsscripts/stacksortable.min.js @@ -1,4 +1,5 @@ -export const stack_sortable=class{constructor(state,availableId,inputId=null,options=null){this.state=state;this.inputId=inputId;if(inputId!=null){this.input=document.getElementById(this.inputId);};this.availableId=availableId;this.available=document.getElementById(this.availableId);this.defaultOptions={animation:50};if(options==null){this.userOptions=this.defaultOptions;}else{this.userOptions=Object.assign(this.defaultOptions,options);};this.options=Object.assign(this.userOptions,{ghostClass:"list-group-item-info",group:"shared"});} -generate_available(proofSteps){for(const key in this.state.available){let li=document.createElement("li");li.innerText=proofSteps[this.state.available[key]];li.setAttribute("data-id",this.state.available[key]);li.className="list-group-item";this.available.append(li);};if(this.inputId!=null){this.input.value=JSON.stringify(this.state);this.input.dispatchEvent(new Event("change"));};} +export const stack_sortable=class{constructor(state,availableId,usedId,inputId=null,options=null){this.state=state;this.inputId=inputId;if(inputId!=null){this.input=document.getElementById(this.inputId);};this.availableId=availableId;this.available=document.getElementById(this.availableId);this.usedId=usedId;this.used=document.getElementById(this.usedId);this.defaultOptions={animation:50};if(options==null){this.userOptions=this.defaultOptions;}else{this.userOptions=Object.assign(this.defaultOptions,options);};this.options=Object.assign(this.userOptions,{ghostClass:"list-group-item-info",group:"shared"});} +generate_available(proofSteps){for(const key in this.state.available){let li=document.createElement("li");li.innerText=proofSteps[this.state.available[key]];li.setAttribute("data-id",this.state.available[key]);li.className="list-group-item";this.available.append(li);};} +generate_used(proofSteps){for(const key in this.state.used){let li=document.createElement("li");li.innerText=proofSteps[this.state.used[key]];li.setAttribute("data-id",this.state.used[key]);li.className="list-group-item";this.used.append(li);};} update_state(newUsed,newAvailable){var newState={used:[],available:[]};newState.used=newUsed.toArray();newState.available=newAvailable.toArray();if(this.inputId!=null){this.input.value=JSON.stringify(newState);this.input.dispatchEvent(new Event('change'));};this.state=newState;}};export default{stack_sortable}; \ No newline at end of file diff --git a/stack/cas/castext2/blocks/parsons.block.php b/stack/cas/castext2/blocks/parsons.block.php index 7c4a97a84f1..9c1cdf4d0fc 100644 --- a/stack/cas/castext2/blocks/parsons.block.php +++ b/stack/cas/castext2/blocks/parsons.block.php @@ -173,11 +173,11 @@ public function compile($format, $options): ? MP_Node { // parse steps and options separately if they exist $code = 'var userOpts;' . "\n"; - $code .= 'if (typeof proofSteps === "string") {proofSteps = JSON.parse(proofSteps);}' . "\n"; + $code .= 'if (typeof proofSteps === "string") {proofSteps = Object.fromEntries(new Map(Object.values(JSON.parse(proofSteps))));}' . "\n"; $code .= 'if (JSON.stringify(Object.keys(proofSteps)) === JSON.stringify([ "steps", "options" ])) {' . "\n"; $code .= 'userOpts = proofSteps["options"];' . "\n"; $code .= 'proofSteps = proofSteps["steps"];' . "\n"; - $code .= 'if (typeof proofSteps === "string") {proofSteps = JSON.parse(proofSteps);}' . "\n"; + $code .= 'if (typeof proofSteps === "string") {proofSteps = Object.fromEntries(new Map(Object.values(JSON.parse(proofSteps))));}' . "\n"; $code .= '}' . "\n"; // Link up to STACK inputs @@ -188,12 +188,20 @@ public function compile($format, $options): ? MP_Node { $code .= 'var id;' . "\n"; }; - // Generate initial state + // Generate state $code .= 'var state;' . "\n"; - $code .= 'state = {used: [], available: [...Object.keys(proofSteps)]};' . "\n"; + // If we already have a stored state in the statestringinput input, then we use this state + $code .= 'let stateStore = document.getElementById(id);' . "\n"; + $code .= 'if (stateStore.value && stateStore.value != ""){' . "\n"; + $code .= 'state = JSON.parse(stateStore.value);}' . "\n"; + + // otherwise we generate the initial state based on the contents of the block + $code .= 'else {' . "\n"; + $code .= 'state = {used: [], available: [...Object.keys(proofSteps)]};}' . "\n"; // Create the sortable objects by filling in the container div - $code .= 'const sortable = new stack_sortable(state, "availableList", id, userOpts);' . "\n"; + $code .= 'const sortable = new stack_sortable(state, "availableList", "usedList", id, userOpts);' . "\n"; + $code .= 'sortable.generate_used(proofSteps);' . "\n"; $code .= 'sortable.generate_available(proofSteps);' . "\n"; if (count($inputs) > 0) { $code .= 'MathJax.typesetPromise();' . "\n";