0 votes
by (130 points)

Hello Everyone,

I've been having a little issue with one of my widgets that displays a store interface based on a list of items with different types. 

The issue seems to be specific to these two sections:

<<set _targetSpan = "#store" + $args[0][_i].itemType>>
			<<if _owned == true>>
			<<append _targetSpan>>
				$args[0][_i].itemName &emsp;
			<</append>>
			<<elseif _owned == false>>
				<<append _targetSpan>>
					<span class="thumbnail">
					<<link [img[$args[0][_i].src][passage()]]>>
				<<if $player.money gte $args[0][_i].price>>
					<<set $inventoryList.push($args[0][_i])>>
					<<set $player.money -= $args[0][_i].price>>
				<<set _passageName = passage()>>	
				<<goto  _passageName>>
				<</if>>
				<</link>>
				</span>
				<<if $player.money lt $args[0][_i].price>>
				<<print "You don't have enough money to buy that">>
				<<else>>
				<<print "$args[0][_i].price $">>
				&emsp;
				<</if>>
			<</append>>
			<</if>>

This part of the widget Works great as long as the individual spans are already named and created.

ex: <span id="storeshirts"></span>

My goal was to create these spans dynamically by using:

<<widget "createStoreSpans">>
<<for _i = 0; _i < $args[0].length; _i++>>
	<<capture _i>>
		<<set _storeName = $args[0]>>
		<<set $targetSpan = 'store' +_storeName[_i].itemType>>
		<<append ".store">> <span id=$targetSpan></span>
		<</append>>
	<</capture>>
<</for>>
<</widget>>

A div with class store is already on the page. 

Testing by printing "$targetSpan" shows the correct id but the previous widget doesnt seem to detect these. 

Any ideas what's causing this issue? Thx in advance.

ps. both of these are encased in click macros so I don't think this is an issue of the elements not loading in.

p.p.s if needed I'll provide the full code for the first widget(as ugly as it is).

 

2 Answers

+1 vote
by (64.2k points)

You cannot simply dump variables into HTML markup.  Try using the evaluation attribute directive.  For example:

<span @id="$targetSpan"></span>

Though, you probably want to use a temporary variable there.

PS: You don't currently need the <<capture>> in second widget as there's no asynchronous code in it.

by (130 points)
I must have missed that while looking through the docs. Thanks for the quick answer TheMadExile. Your answers are always helpfull.
0 votes
by (154k points)

Assumptions: You don't include an example of the Array you are passing to your <<createStoreSpans>> and "unnamed" widgets or the values of your other variables, so I will use the following to test your code.

:: StoryInit
<<set $items to [
	{
		itemName: "A-IN",
		itemType: "A-IT",
		price: 10,
		src: "A-src"
	},
	{
		itemName: "B-IN",
		itemType: "B-IT",
		price: 5,
		src: "B-src"
	}
]>>
<<set $player to {money: 100}>>
<<set  $inventoryList to []>>

:: Start
@@.store;@@

<<link "createStoreSpans">>
	<<createStoreSpans $items>>
<</link>>

<<link "unnamed">>
	<<unnamed $items>>
<</link>>


There are a couple of issues with your <<createStoreSpans>> widget, the main one being that as written the current value of the $targetSpan variable will not be injected into the ID attribute of span elements. If you use your web-browser's Web Developer Tools to Inspect the generated span elements added to you page you will see they all look like the following example.

<span id="$targetSpan"></span>

The following is a modified version of this widget that should achieve the outcome that you want, it uses HTML Attribute markup to inject the value of a variable. It also includes some simple argument checking.

<<widget "createStoreSpans">>
	<<if $args.length > 0 and Array.isArray($args[0])>>
		<<for _item range $args[0]>>
			<<set _id = 'store' + _item.itemType>>
			<<append ".store">> <span @id="_id"></span><br><</append>>
		<</for>>
	<</if>>
<</widget>>


There are a number of potentual issues with your "unnamed" widget:

1. You are using == true and == false to check the current value of a Boolean variable, the correct way to do this is as follows

<<if _owned>>The owned temporary variable equals true.<</if>>
<<if not _owned>>The owned temporary variable equals false.<</if>>
<<if ! _owned>>The owned temporary variable equals false.<</if>>

2. You are using an <<if>> and <<elseif>> macro combination to check for both of the two possible states of a Boolean variable, the correct way to do this is to use an <<if>> and <<else>> macro combination.

<<if _owned>>The owned temporary variable equals true.\
<<else>>The owned temporary variable equals false.\
<</if>>

3. (implied by the code) You are using the index based version of the <<for>> macro when the range based version would seem to suit your needs better.

<<for _item range $args[0]>>
	<<set _targetSpan = "#store" + _item.itemType>>
	...
<</for>>


I believe the following version of your original "unnamed" widget should achieve the results you want.

<<widget "unnamed">>
	<<if $args.length > 0 and Array.isArray($args[0])>>
		<<for _item range $args[0]>>
			<<set _targetSpan = "#store" + _item.itemType>>
			<<if _owned>>
				<<append _targetSpan>>
					\_item.itemName &emsp;
				<</append>>
			<<else>>
				<<append _targetSpan>>
					\<span class="thumbnail">
						\<<capture _item>>
							\<<link `_item.src`>>
								<<if $player.money gte _item.price>>
									<<set $inventoryList.push(_item)>>
									<<set $player.money -= _item.price>>
									<<set _passageName = passage()>>
									<<goto  _passageName>>
								<</if>>
							<</link>>
						<</capture>>
					\</span>
					\<<if $player.money lt _item.price>>
						\<<print "You don't have enough money to buy that">>
					\<<else>>
						\<<print "_item.price $">>
						\&emsp;
					\<</if>>
				\<</append>>
			<</if>>
		<</for>>
	<</if>>
<</widget>>


 

by (130 points)

Hello Greyelf, firstly thank you for the extensive reply, I really do appreciate it.

All of your assumptions are correct. As you and madexile noted the problem with my createStore widget was solved with the  evaluation attribute directive.

As for my other widget I'll be implementing the changes you suggested as they all seem to help clean up the code(I am curious as to the difference between == true and if _owned).

Thank you both once again.

Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.
...