+1 vote
by (240 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.6k 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 (159k 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 (240 points)
Thanks! Works like a charm!
by (8.6k points)
Multiple div elements with the same id were asked for, so that's what my code delivers.
+1 vote
by (68.6k 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 (240 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

...