Issue with Harlowe

Twine Version: 2.3.9

I was writing a shop menu in twine, and ran into this error message. I think it is a conflict between the (live:) macro and the (if:) macro.
TypeError: Cannot read property ‘blocked’ of undefined
TypeError: Cannot read property ‘blocked’ of undefined
at Object.unblock
at :21:7179
at HTMLElement.
at HTMLElement.dispatch

Any advice?

1 Like

We would need to see an example of the ‘shop menu’ code that is producing that error.

note: please use the comment field’s Preformatted Text toolbar option when you include code.

This is the code I had that created the error:

(live: .3s)[==You have $gold Gold left to buy items with. 

(if: $gold >= 50)[ (if: $bow is false)[(link-repeat:"Bow (50 gold)")[(set: $gold to $gold-50)(set: $bow to true)] ](else:)[(link-repeat:"Bow (50 gold)")[(alert:"Sorry, You already have a bow")] ]](else:)[ (link-repeat:"Bow (50 gold)")[(alert:"Sorry, It's too expensive")] ]

Note that the variables were set in a previous passage.

I suggest you restructure your purchase logic and the link to something like the following.
(untested)

(link-repeat: "Bow (50 gold)")[
	(if: $bow)[
		(alert: "Sorry, You already have a bow")
	]
	(else-if: $gold < 50)[
		(alert: "Sorry, It's too expensive")
	]
	(else:)[
		(set: $gold to it - 50)
		(set: $bow to true)
	]
]

note: It is unclear from your example what the purpose of the (live:) macro call is.

warning: Harlowe was changed so that it uses HTML based dialogs instead of the web-browser’s inbuilt ones for things like ‘alert’ and ‘prompt’. Calling dialogs within the Associated Hook of a (live:) macro can cause context issues because the dialog moves the current focus away from the area associated with the live macro to that associates with the dialog.

The (live:) macro is there in order to reload the page, so after buying one object, the gold value at the top will update, and the if statements will recheck the values, preventing someone from buying the bow over and over again. Also the code you provided created an error saying the calls weren’t written correctly. I adjusted it to this:

(if: $bow is true)[
       (link-repeat:"Bow (50 gold)")[
              (alert: "Sorry, You already have a bow")
              ] 
 ]
(else-if: $gold <= 50)[
        (link-repeat:"Bow (50 gold)")[
              (alert: "Sorry, It's too expensive"  
        ]
]
(else:)
[
         (link-repeat:"Bow (50 gold)")[
               (set: $gold to $gold - 50)(set: $bow to true)
         ]
]

I am still getting the error message. If there is another way to get the page to reload, without forcing the reader to do so, or by making additional passages, and links to them, I think that would solve the issue. If there isn’t, I will most likely have to remove the (alert:) macros and just have the text appear.

There are a couple of issues with the general concept of both your and my implements, and the main cause is the fact that the dialog related macros interferes with the current execution context.

If I change my original (untested) example to output the ‘alerts’ to the current page instead of using a dialog…

|status>[]
(link-repeat: "Bow (50 gold)")[{
	(if: $bow)[
		(replace: ?status)["Sorry, You already have a bow"]
	]
	(else-if: $gold < 50)[
		(replace: ?status)["Sorry, It's too expensive"]
	]
	(else:)[
		(set: $gold to it - 50)
		(set: $bow to true)
	]
}]

…then the (else:) macro’s Associated Hook doesn’t incorrectly get executed. Which is what is happening when a dialog is shown instead, and something similar is occurring when a dialog is called from within a (live:) macro’s Associated Hook.

One common method used to ‘update’ the contents of the ‘current’ Passage is to place the content that needs to be ‘updated’ within a ‘child’ Passage that you inject into the ‘current’ Passage when needed.
The following TWEE Notation based example demonstrates this technic, it consists of two Passages named Start and Show List.

:: Start
(set: $list to (a: "item"))

|list>[(display: "Show List")]

(link-repeat: "Add Item to List")[{
	(set: $list to it + (a: "item"))
	(replace: ?list)[(display: "Show List")]
}]

:: Show List
(for: each _item, ...$list)[{
	_item<br>
}]