Using the result of a list box selection

Twine Version: 2.5.1
Story Format: Sugarcube 2.36.1

What am I trying to do:

  1. put the result of a list box selection into a sugarcube variable
  2. use that variable to set the value of a <div>, and also as a selector from a JS Object

I have this code, based on an answer on how to access the value selected from a listbox:


<div id="pie"></div>

<<set _pieOptions = ["Choose one:", "blueberry", "cherry", "coconut cream"]>>\
What's your favorite pie?
<<listbox "$pie" autoselect>>
    <<optionsfrom _pieOptions>>
<</listbox>>

<<done>>
    <<run $('#listbox-pie').change(function () { 
        console.log('selected: ' + $(this).find('option:selected').text());
        state.active.variables.chosen_pie = state.active.variables.pie;
        console.log('chosen pie: ', state.active.variables.chosen_pie) })>>
    <<replace "#pie">><<print $chosen_pie>><</replace>>
<</done>>

Sure enough, the selected option is displayed via the console log; once as the value of

find.('option:selected').text()

and again as the value of

state.active.variables.chosen_pie

But the <div> is not updated.

I want to update the #pie div with the value of the chosen pie.

So

  1. I don’t really understand when <<done>> runs. It runs when the page has initially been rendered, but it seems to run when new options are selected from the list box. Where could I read about that behaviour? (and apologies it its in the docs - I couldn’t see it there, or didn’t understand what was there - more likely!)

  2. How can I get the <<replace>> macro to run, with the value of state.active.variables.chosen_pie (or ??equivalently??) $chosen_pie.

I hope I have provided enough info

with many thanks

<<done>> only runs once, immediately after the passage has been rendered. What’s running every time the listbox is changed is the event handler you defined inside the <<done>> macro. All you need to do is to is have that function also update the <div>.

<<done>>
    <<run $('#listbox-pie').change(function () { 
        console.log('selected: ' + $(this).find('option:selected').text());
        state.active.variables.chosen_pie = state.active.variables.pie;
        console.log('chosen pie: ', state.active.variables.chosen_pie);
        $("#pie").text(state.active.variables.chosen_pie);
    })>>
<</done>>

<<done>> executes once. You’re seeing the firing of change event, which occurs each time the listbox is changed.

It’s not working because the change event handler you’re attaching is asynchronous. The <<replace>> is executed once as part of the <<done>>. You need to place the <div#pie> update within the change event handler.

You’re also using old APIs, from SugarCube v1.

Example:

<div id="pie"></div>

<<set _pieOptions = ["Choose one:", "blueberry", "cherry", "coconut cream"]>>\
What's your favorite pie?
<<listbox "$chosen_pie" autoselect>>
	<<optionsfrom _pieOptions>>
<</listbox>>

<<done>>
	<<script>>
		$('#listbox-pie').on('change', function () {
			$('#pie').text(State.variables.chosen_pie);
		});
	<</script>>
<</done>>

That is crystal clear and I am very grateful for your help.
Yes - I see - the <> macro runs and “installs” the event handler on “#listbox-pie”.

Thank very much

This code

<<done>>
	<<script>>
		$('#listbox-pie').on('change', function () {
			$('#pie').text(State.variables.chosen_pie);
		});
	<</script>>
<</done>>

Doesn’t have the $(this).find('option:selected').text(). Should I expect to see the chosen value in $chosen-pie (the receiver var of the list box) without needing the $(this).find('option:selected').text() code?

thanks for your patience

Worked it out…

the list box id is #listbox-chosen-pie

Cheers again!