+1 vote
by (130 points)

I'm using widgets to create goto-buttons surrounded by divs.
However, I'd like to expand upon this widget to allow me to create several buttons in succession (to be wrapped around one div later on)
Though, I'm having issues using a for-loop to create the desired effect.


Functional single-argument widget

<<widget "dlink">>
	<div id="dlink" name="dlink" style="border: thin solid gray; border-radius: 15px;padding: 0px 2px;background: #231306;">
<<button $args[0]>><<goto $args[0]>><</button>></div>
<</widget>>

Non-functional multi-argument widget

<<widget "mdlink">>
	<<for _l to 0; _l lt $args.length; _l++>><div id="mdlink" name="mdlink" style="border: thin solid gray; border-radius: 15px;padding: 0px 2px;background: #231306;" ><<button $args[_l]>><<goto $args[_l]>><</button>></div><</for>>
<</widget>>

 

The full stacktrace for the error is:
 

Apologies! An error has occured. You may be able to continue, but some parts may not work properly.

Error: cannot execute macro <<goto>>: Story.has title parameter cannot be undefined.

Stack Trace:
Error: cannot execute macro <<goto>>: Story.has title parameter cannot be undefined.
   at Function.value (<anonymous>:5:6881)
   at HTMLButtonElement.<anonymous> (<anonymous>:6:19238)
   at <anonymous>:6:6866
   at HTMLButtonElement.<anonymous> (<anonymous>:6:7024)
   at HTMLButtonElement.<anonymous> (<anonymous>:3:21766)
   at HTMLButtonElement.dispatch (<anonymous>:26:10315)
   at HTMLButtonElement.q.handle (<anonymous>:26:8342)

 

2 Answers

–2 votes
by (8.5k points)
edited by

You need to "capture" the value of _l inside your loop for it to work.

<<widget "mdlink">>
	<<for _l to 0; _l lt $args.length; _l++>>
		<<capture _l>>
			<div id="mdlink" name="mdlink" style="border: thin solid gray; border-radius: 15px;padding: 0px 2px;background: #231306;" >
				<<button $args[_l]>><<goto $args[_l]>><</button>>
			</div>
		<</capture>>
	<</for>>
<</widget>>

Alternatively, generate the whole content all in one go using map/reduce and print it out.

<<widget "mdlink">>
	<<= $args
		.map(psg => '<div id="mdlink" name="mdlink" style="border: thin solid gray; border-radius: 15px;padding: 0px 2px;background: #231306;"><<button "' + psg + '">><<goto "' + psg + '">><</button>></div>')
		.join("")>>
<</widget>>

You can even filter out invalid passages at runtime.

<<widget "mdlink">>
	<<= $args
		.filter(Story.has)
		.map(psg => '<div id="mdlink" name="mdlink" style="border: thin solid gray; border-radius: 15px;padding: 0px 2px;background: #231306;"><<button "' + psg + '">><<goto "' + psg + '">><</button>></div>')
		.join("")>>
<</widget>>

 

by (153k points)
The ID of each element needs to be unique but your examples are trying to create multiple elements with the same ID of "mdlink".
by (130 points)
Thanks! Works like a charm!
by (8.5k points)
Multiple div elements with the same id were asked for, so that's what my code delivers.
+1 vote
by (64.2k points)
edited by

There's no real point in using <<goto>> here.  The <<button>> macro accepts a passageName argument, so just use that.

 

Single passage example:

<<widget "dlink">>
\<div id="dlink" name="dlink" style="border: thin solid gray; border-radius: 15px; padding: 0 2px; background: #231306;">
\<<button $args[0] $args[0]>><</button>>
\</div>
\<</widget>>

 

Multiple passage example:

<<widget "mdlink">>
\<<for _l to 0; _l lt $args.length; _l++>>
\<div id="mdlink" name="mdlink" style="border: thin solid gray; border-radius: 15px; padding: 0 2px; background: #231306;">
\<<button $args[_l] $args[_l]>><</button>>
\</div>
\<</for>>
\<</widget>>

WARNING: You're reusing IDs there.  IDs should be unique, so you'll probably want to address that.  As an example of that:

<<widget "mdlink">>
\<<for _l to 0; _l lt $args.length; _l++>>
\<<= '<div id="mdlink-' + _l + '" name="mdlink" style="border: thin solid gray; border-radius: 15px; padding: 0 2px; background: #231306;"><<button "' + $args[_l] + '" "' + $args[_l] + '">><</button>></div>'>>
\<</for>>
\<</widget>>

Because of the need to create a unique ID each loop iteration, you end up having to print the entire construct, which is a bit messy as you can see.  Still, it's what you should be doing.

Beyond that, I'd also suggest using a class, rather than the style attribute (especially for the multiple link version).  Otherwise, you're just being redundant.

by (130 points)

There's no real point in using <<goto>> here.  The <<button>> macro accepts a passageName argument, so just use that.

How could I have missed that surprise Thanks!

WARNING: You're reusing IDs there.  IDs should be unique, so you'll probably want to address that

 Thank you for the warning. I have incorporated your example into my code smiley

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.
...