+2 votes
asked by (1.1k points)
retagged by

I'm attempting to auto-create tables in harlowe.

If my story goes to according to plan, I'll end up with a number of tables for various reasons (stores, displaying stats, etc). To make it easier, I thought I'd make a function passage to create the tables as needed.

It seems, though, the html statements are buried under other classes by harlowe, rendering them invisible/nonfunction. (in a browser, the screen is blank in the table's area).


(set: $w3table_all_opts_op to ("<div class=w3-container><table class=w3-table-all>"))
(set: $w3table_close to ("</table></div>"))
(set: $heroStatAdjTableHead to (array: "Stat Name" , "Current" , "Increase" , "Decrease" , "Save"))
(set: $heroStatAdjTableRows to (array: "open" , "header" , "brains" , "brawn" , "agility" , "spirit" , "vigor" , "close"))

(for: each _tablerow, ...$heroStatAdjTableRows)[
	(if: _tablerow is "open")[$w3table_all_opts_op<!--open table-->]
	(else-if: _tablerow is "header")[<!--one tr and th's for each head--><tr>(for: each _tablehead, ...$heroStatAdjTableHead)[<th>_tablehead</th>]</tr>]
	(else-if: _tablerow is "close")[<!--closes table-->(print: $w3table_close)]
	(else:)[<!-- one tr and other table td's --><tr>(for: each _tabledef, _tablerow)[<td>_tablerow</td>]</tr>]

inspector output

Also, if I try to create the table html elements normally, then use a for: macro to write the elements, they "escape" from the table.

Is there a way to classify or style the html so it will display in the game?


(I also tried using the column/table markdown, but the markdown wasn't recognized as output from the macros.)


1 Answer

+2 votes
answered by (132k points)
selected by
Best answer

NOTE: the parenthesis around the String values of your first two (set:) macro calls are not needed, and should be removed.

The main issue you will run into with Harlowe is that most macro calls result in at least one custom HTML elements being added to the generated output, and because these custom elements are not valid elements of structures like a HTML table then the web-browser has to guess what to do with them, and these guesses generally result in output you don't want.

eg, the dynamic table section of the following Passage content.

(set: $list to (array: "AAAA", "BBBB", "CCCC"))

(for: each _item, ...$list)[
	<tr><th>(print: _item)</th></tr>

.... is trying to generate a HTML element structure like the following, which the web-browser will reject.

		<tw-expression type="macro" name="for"></tw-expression>
				<tw-expression type="macro" name="print">AAAA</tw-expression>
				<tw-expression type="macro" name="print">BBBB</tw-expression>
				<tw-expression type="macro" name="print">CCCC</tw-expression>


One way to get around this issue is to build the structure as a String and then inject it's value into the location on the page you want the table to appear in.

(set: $list to (array: "AAAA", "BBBB", "CCCC"))

(set: $dummy to "<table>")
(for: each _item, ...$list)[
	(set: $dummy to it + "<tr><th>")
	(set: $dummy to it + _item)
	(set: $dummy to it + "</th></tr>")
(set: $dummy to it + "</table>")
(replace: ?output)[$dummy]

... you may wonder why I placed the building code within a named hook, this is so I can use CSS like the follow (within Story Stylesheet) to hide all the unwanted visual output generated by the formatting of that code.

tw-hook[name="workarea"] {
	display: none;


commented by (1.1k points)
edited by

Thanks for the great info, GreyElf! Using the hook and building the table into a variable really helped out--I hadn't thought of either!

Thanks to ge, I was able to build the following successfully. image link

<!-- built from grayelf example -->
(set: $tableDiv to "<div class=w3-container w3-responsive>")
(set: $tableClass to "<table class=w3-table w3-border w3-round-xlarge" + "&quot;" + " style=" + "&quot;" + "width:75%;" + "&quot;")
(set: $listHead to (array: "AAAA", "BBBB", "CCCC" , "DDDD", "EEEE"))
(set: $listBodyRows to (array: "Alpha" , "Beta" , "Delta" , "Gamma" ))
(set: $listBodyCols to (array: "EEE" , "FFF" , "GGG" , "HHH" ))
{(font: "Underdog")[]<ge-output|
(set: $dummy to $tableDiv)
(set: $dummy to $tableClass)
(set: $dummy to it + "<tr>")
(for: each _head, ...$listHead)[
	(set: $dummy to it + "<th>")
	(set: $dummy to it + _head)
	(set: $dummy to it + "</th>")
(set: $dummy to it + "</tr>")
(for: each _datarowstart, ...$listBodyRows)[
<!-- this is the first column of the body and the start of each data row-->
	(set: $dummy to it + "<tr>")
	(set: $dummy to it + "<td>")
	(set: $dummy to it + _datarowstart)
	(set: $dummy to it + "</td>")
	<!-- the rest of the data cells for the row-->
		(for: each _datacells, ...$listBodyCols)[
			(set: $dummy to it + "<td>")
			(set: $dummy to it + _datacells)
			(set: $dummy to it + "</td>")
	<!-- closes the row -->
	(set: $dummy to it + "</tr>")
(set: $dummy to it + "</table></div>")
(replace: ?ge-output)[$dummy]

(note: the extra ()s in my original question were left over from my attempts to get the quotes in my usual <table> class and styles to pass through. I tried graves, extra quotes, etc with little success. Now I'm quoting &quot;)


commented by (1.1k points)

PS: apparently the tw-hook CSS disables the debugging overlay in test mode. It may be unintentional, but it is awesome! A bit of testing shows it appears to be interacting with something else in my story stylesheet--not sure what yet. It disables the window in this story, but not another with a "clean" story stylesheet.

Scratch that, it seems the

tw-debugger {
	display: none;

in my stylesheet decided to work this morning--it's been in there a few days (the debugger covers the right panel where I put some links) and I'm not sure why it decided to start working. Tested it on some other stories and it worked, so not sure if it's genuine or my version of twine/harlowe. (twine 2.1.3 harlowe 2.0.1)

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.