Identical code works with <script> but not with <<script>>

Twine Version: Sugarcube 2.36.1

Hey I plan to use two sugarcube variable in an if condition. Consequently, I have to use <<script>>. The problem, however, is that the code (without me even inserting the sugarcube value) breaks.

Working code:

<button type="submit" class="checkout-button" id="checkout-button" name="checkout-button">submit</button>

let disableButton = true; // Change this value to false, and the button will be clickable
let fancyButton = document.getElementById('checkout-button');

if (10 < 20) {
  console.log('Condition checked: DP is less than requiredDP');
  disableButton = true; 
} else {
  console.log('Condition checked: DP is greater than or equal to requiredDP');
  disableButton = false; 

if (disableButton) fancyButton.classList.add('disable');

However, the moment I turn the <script> into <<script>> I get this error

Error: <<script>>: bad evaluation: Cannot set properties of null (setting 'disabled')


What are you trying to do with this code?
Because if your plan is to disable the button depending on a condition, you may want to take a look at this custom macro (you can disable an element with a conditional expression)

Also SugarCube has a button macro

The code inside the <<script>> tag runs before the passage is rendered. This means that fancyButton is null, since the button didn’t exist on the page when document.getElementById was called. You can wrap the code inside a <<done>> macro to ensure that the code runs after the passage is rendered.

That said, I second Manon’s suggestion to check out the custom macro.


I have a variable $DP and $requiredDP. I want the button to become unclickable and change its style when $DP<$requiredDP.


.checkout-button.disable {
  background: #999;
  color: #555;
  cursor: not-allowed;

Thanks! That helps a lot. Does that mean that <script> is run after passage render and <<script>> is run before the passage is rendered?

I will check out the custom macro, it looks like it is what I am looking for!

Just a general question I have: Is the only way to add a class to a <<button>> through a <div> or a <span>?

The custom macro I linked above allows just that that:

<<disable $DP < $requiredDP>>/*your button code*/<</disable>>

And then:

button:disabled {
 your css

Thank you so much for the quick reply!

1 Like

I have a macro for adding attributes to any generated HTML element, including buttons: <<attr>> (link)

There’s even a shortcut version <<class>> for adding a class.

<<class "myClass">><<button "Button Text">><</button>><</class>>

Regarding the initial question, I remember being confused by this. Someone was telling me how to format display text with CSS and think Sugarcube macros normally use double pointy braces <<>> and CSS or JS under certain circumstances only use one so there are causes to switch between? <>

(Not looking for an answer, just pointing out that there may be a different levels in the code which changes brace format between Sugarcube and HTML+other things…)

SugarCube doesn’t grantee when the contents of a HTML <script> element will be executed during the processing of the Passage’s content, just that it will be executed.

eg. Passage content is processed from left to right starting with the first line and continuing downwards until all content has been processed. Any HTML elements generated by that processing are added to a buffer until the entire content has been processed, at which point the HTML in that buffer is injected into the Documentation Object Model (DOM) of the web-page. This delay in updating the DOM is why JavaScript that searches the DOM for elements created by the Passage will likely fail, unless the execution of that JavaScript is delayed somehow, like using the <<done>> macro.