Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

[SugarCube 2.13] Unable to use multiple radiobutton groups on the same passage?

I'm designing a passage a game with a passage that has a few customizable options. For reason of clarity and aesthetics alone I was opting to utilize the <radiobutton> macro as opposed to an anchor when I noticed what seemed to me to be odd behavior.

When using the radiobutton macro the first grouping will have the id assigned as expected, but the second does not. Instead of an ordering applied to the ID you'll receive a "Not a Number" designation to the ID.


Example:
<<nobr>>
<table>
	<tr>
		<td width="40%">
			Measurement system:
		</td>
		<td>
			<<if $imperial eq true>>
				<<radiobutton "$imperial" "true" checked>>
			<<else>>
				<<radiobutton "$imperial" "true">>
			<<endif>>
			
			<<if $imperial eq false>>
				<<radiobutton "$imperial" "false" checked>>
			<<else>>
				<<radiobutton "$imperial" "false">>
			<<endif>>
		</td>
	</tr>
	<tr>
		<td width="40%">
			Enable Cheats:
		</td>
		<td>
			<<if $cheatMode eq true>>
				<<radiobutton "$cheatMode" "true" checked>>
			<<else>>
				<<radiobutton "$cheatMode" "true">>
			<<endif>>
			
			<<if $cheatMode eq false>>
				<<radiobutton "$cheatMode" "false" checked>>
			<<else>>
				<<radiobutton "$cheatMode" "false">>
			<<endif>>
		</td>
	</tr>
</table>
<</nobr>>


Which results in:
<table>
	<tr>
		<td width="40%">Measurement system:</td>
		<td>
			<input id="radiobutton-imperial-0" name="radiobutton-imperial" type="radio" tabindex="0" class="macro-radiobutton">
			<input id="radiobutton-imperial-1" name="radiobutton-imperial" type="radio" tabindex="0" class="macro-radiobutton">
		</td>
	</tr>
	<tr>
		<td width="40%">Enable Cheats:</td>
 		<td>
			<input id="radiobutton-cheatmode-NaN" name="radiobutton-cheatmode" type="radio" tabindex="0" class="macro-radiobutton">
			<input id="radiobutton-cheatmode-NaN" name="radiobutton-cheatmode" type="radio" tabindex="0" class="macro-radiobutton">
		</td>
	</tr>
</table>

For the sake of curiosity I've swapped table rows around to see if the behavior was repeatable when sure enough whichever group of radiobuttons comes second is id'd with a Not a Number postfix.

Did I do something really dumb and implement the control incorrectly?

Comments

  • It appears you have found a bug in the SugarCube 2.x implementation of the <<radiobutton>> macro that does not exist in the SugarCube 1.x implementation.

    I strongly suggest you create a new issue on that story format's repository so that the developer knows about the problem you have found, and so you can track the fix and it's release.
  • Thank you for confirming that, Greyelf. I wasn't sure if I had somehow messed up on my implementation. So I was starting to go a little nuts.
  • I can confirm the issue. A quick check reveals that it's been broken since the v.2.3.0 release. Whoops. :sweat:

    A fix has already been committed its repository and will be in the next release.

    Beyond that, you have some issues with your code:
    1. All conditionals resolve to a boolean value. If a conditional (sub)expression consists of a variable which contains a boolean value, simply use the variable, there's no need to test it against the boolean literals. For example, for true values:
      → Code like this
      <<if $myVariable eq true>>
      
      → Should instead be like this
      <<if $myVariable>>
      
      And for false values:
      → Code like this
      <<if $myVariable eq false>>
      
      → Should instead be like this
      <<if not $myVariable>>
      
    2. You obviously seem to want $imperial and $cheatMode to contain boolean values, however, you're assigning them strings via the radiobuttons. In other words:
      "true"   ← String
      "false"  ← String
      true     ← Boolean
      false    ← Boolean
      
      Ergo:
      → Code like this
      <<radiobutton "$imperial" "true" checked>>
      
      → Should instead be like this
      <<radiobutton "$imperial" true checked>>
      
    3. Your <<if>> logic is redundant. For example:
      → Code like this
      <<if $imperial eq true>>
      	<<radiobutton "$imperial" "true" checked>>
      <<else>>
      	<<radiobutton "$imperial" "true">>
      <<endif>>
      			
      <<if $imperial eq false>>
      	<<radiobutton "$imperial" "false" checked>>
      <<else>>
      	<<radiobutton "$imperial" "false">>
      <<endif>>
      
      → Should instead be like this
      <<if $imperial>>
      	<<radiobutton "$imperial" true checked>>
      	<<radiobutton "$imperial" false>>
      <<else>>
      	<<radiobutton "$imperial" true>>
      	<<radiobutton "$imperial" false checked>>
      <<endif>>
      

    Here's a version of your example code containing all of the suggested fixes:
    <<nobr>>
    <table>
    	<tr>
    		<td width="40%">
    			Measurement system:
    		</td>
    		<td>
    			<<if $imperial>>
    				<<radiobutton "$imperial" true checked>>
    				<<radiobutton "$imperial" false>>
    			<<else>>
    				<<radiobutton "$imperial" true>>
    				<<radiobutton "$imperial" false checked>>
    			<<endif>>
    		</td>
    	</tr>
    	<tr>
    		<td width="40%">
    			Enable Cheats:
    		</td>
    		<td>
    			<<if $cheatMode>>
    				<<radiobutton "$cheatMode" true checked>>
    				<<radiobutton "$cheatMode" false>>
    			<<else>>
    				<<radiobutton "$cheatMode" true>>
    				<<radiobutton "$cheatMode" false checked>>
    			<<endif>>
    		</td>
    	</tr>
    </table>
    <</nobr>>
    

    PS: Considering what you're attempting to do with the above code, you may also want to have a look at the Setting API.
  • I can confirm the issue. A quick check reveals that it's been broken since the v.2.3.0 release. Whoops. :sweat:

    A fix has already been committed its repository and will be in the next release.

    Thank you for finding the problem and fixing it. I've been fumbling around from time to time, and I'm not always sure when it's something I'm not understanding or a legitimate bug. Glad that I wasn't at fault this time, but sorry it caused you more work.

    Beyond that, you have some issues with your code:
    1. All conditionals resolve to a boolean value. If a conditional (sub)expression consists of a variable which contains a boolean value, simply use the variable, there's no need to test it against the boolean literals. For example, for true values:
      → Code like this
      <<if $myVariable eq true>>
      
      → Should instead be like this
      <<if $myVariable>>
      

    Thank you for pointing that out. I've gone through and changed that throughout my passages.
    And for false values:
    → Code like this
    <<if $myVariable eq false>>
    
    → Should instead be like this
    <<if not $myVariable>>
    
    [*]You obviously seem to want $imperial and $cheatMode to contain boolean values, however, you're assigning them strings via the radiobuttons. In other words:
    "true"   ← String
    "false"  ← String
    true     ← Boolean
    false    ← Boolean
    

    This was something I was going back and forth testing at the time of posting the code. I wasn't sure if the radiobutton was accepting the boolean value or if a stringliteral was required. I had read somewhere that the second argument had to be encapsulated in quotations, which would make it a string, but now for the life of me I cannot find where it was I had read that.
    PS: Considering what you're attempting to do with the above code, you may also want to have a look at the Setting API.

    I was reading up on the settings api, but honestly I've been a bit foggy on how to use it and a little too afraid to ask. However, I wasn't quite sure how to utilize the API and have been unable to find any more concrete examples of its full implementation for an "options" passage. Instead I came across a fair number of games that implemented their settings panel in a similar way to what I was attempting.
  • You obviously seem to want $imperial and $cheatMode to contain boolean values, however, you're assigning them strings via the radiobuttons. In other words:
    "true"   ← String
    "false"  ← String
    true     ← Boolean
    false    ← Boolean
    
    This was something I was going back and forth testing at the time of posting the code. I wasn't sure if the radiobutton was accepting the boolean value or if a stringliteral was required. I had read somewhere that the second argument had to be encapsulated in quotations, which would make it a string, but now for the life of me I cannot find where it was I had read that.
    I couldn't say where you saw it, however, as a general rule, if it's a part of SugarCube's documentation at all, then you'll find it within its section of said documentation.

    In this instance, the need to pass the variable name, rather than its value, which necessitates quoting them, may be found in two places within the Macro Library document. Right at the top under the Macro Arguments section and also within <<radiobutton>>'s own entry—the latter simply tells you that you must do so, the former explains why. Only a very few macros require that and only with the specific argument their entries detail—normally, you do not quote variable names.

    As far as macro's acceptance of types. You may pass all primitive type literals to macros as-is. Reference type literals are not supported as macro arguments directly, so you have to use an intermediate variable or a backtick expression to pass the object in directly.

    I was reading up on the settings api, but honestly I've been a bit foggy on how to use it and a little too afraid to ask. However, I wasn't quite sure how to utilize the API and have been unable to find any more concrete examples of its full implementation for an "options" passage. Instead I came across a fair number of games that implemented their settings panel in a similar way to what I was attempting.
    It, generally, does require some comfort with JavaScript, so it's not for everyone I suppose.

    Use of the Setting API causes a new menu entry to appear, Settings, which opens a dialog for said settings. Within user code, access to the setting values is granted by the settings object.

    For example, to replicate the settings from your example could be as simple as the following: (goes in Story JavaScript)
    Setting.addToggle("imperial", {
    	label : "Use the old imperial measurement system?"
    });
    
    Setting.addToggle("cheatMode", {
    	label : "Enable cheats?"
    });
    
    Checking the settings within your code:
    → Measurements, combined
    <<if settings.imperial>>
    	…pounds…
    <<else>>
    	…kilograms…
    <</if>>
    
    → Measurements, individually: Imperial
    <<if settings.imperial>>
    	…pounds…
    <</if>>
    
    → Measurements, individually: SI/Metric
    <<if not settings.imperial>>
    	…kilograms…
    <</if>>
    
    You can probably figure out how to use settings.cheatMode from there.

    PEDANTRY: If the "imperial" setting is for US audiences, we don't actually use the old British Imperial system. Our system, US Customary, was based upon the pre-Imperial system that the British used at the time the US was a colony. The Imperial system was created by overhauling that system sometime after US independence. Basically, the US Customary and British Imperial systems are siblings, both children of the older British system. Further, while there are a great many similarities, there are also some significant differences as well.
  • As far as macro's acceptance of types. You may pass all primitive type literals to macros as-is. Reference type literals are not supported as macro arguments directly, so you have to use an intermediate variable or a backtick expression to pass the object in directly.

    Thank you for clearing that up.
    It, generally, does require some comfort with JavaScript, so it's not for everyone I suppose.

    Use of the Setting API causes a new menu entry to appear, Settings, which opens a dialog for said settings. Within user code, access to the setting values is granted by the settings object.

    For example, to replicate the settings from your example could be as simple as the following: (goes in Story JavaScript)

    This here was my real confusion on it. I wasn't sure if there was a special passage that needed to be created, where you made the api calls, etc. I just gave it a go and that's actually very nice.
    PEDANTRY: If the "imperial" setting is for US audiences, we don't actually use the old British Imperial system. Our system, US Customary, was based upon the pre-Imperial system that the British used at the time the US was a colony. The Imperial system was created by overhauling that system sometime after US independence. Basically, the US Customary and British Imperial systems are siblings, both children of the older British system. Further, while there are a great many similarities, there are also some significant differences as well.

    Oh geeze as if I couldn't appreciate you anymore here you go being pedantic about my haphazard naming of things. :D

    The "Imperial" setting is for US audiences. The biggest issue being cm/m vs in/ft being something easily conceptualized by American audiences members that aren't used to the metric system. Growing up I've always had it casually referred to as the Imperial system of measurements, or based there upon. As an American, this is honestly the first time I've ever heard of what we use as the US Customary measurement system and this strangely excites me a little to learn that.
Sign In or Register to comment.