Twine Version: 2.3.5
Story Format: SugarCube 2.30.0
I really like the functionality of the <<actions>> macro, but I don’t like the fact that it defaults to an unordered list. I want to use <<actions>> for dialogue with NPCs, and a list just doesn’t fit with my style.
So, I hacked the <ul> and <li> elements in my stylesheet, like so:
Unfortunately you only state what you don’t want, and not what HTML element structure you do want. This makes it difficult to supply an example of a custom macro that solves your issue.
Essentially, I just want to remove the bullets (both the disc and margin). I can see from the code that the <ul> and <li> elements are hardcoded into the macro.
I’ve created a custom CSS class “dialogue” that effectively styles it the way I want, but it will be a hassle to add html divs every time I want to use it. To create a custom macro <<dialogue>> that does what I want, do I just use the Macro API and copy/paste the <<actions>> code into my JavaScript file, rename, then tweak the <ul> and <li> references?
This is how I tweaked the <<actions>> macro into my own <<dialogue>> macro. I removed some of the logic as I didn’t need any image handling and I’ll just use the wiki links syntax. It seems to work as intended, but how does it look? Am I missing anything?
Macro.add('dialogue', {
handler() {
const $list = jQuery(document.createElement('div'))
.addClass(this.name)
.appendTo(this.output);
for (let i = 0; i < this.args.length; ++i) {
let passage;
let text;
let setFn;
// Only handle arguments for wiki link syntax
text = this.args[i].text;
passage = this.args[i].link;
setFn = this.args[i].setFn;
if (
State.variables.hasOwnProperty('#dialogue')
&& State.variables['#dialogue'].hasOwnProperty(passage)
&& State.variables['#dialogue'][passage]
) {
continue;
}
jQuery(Wikifier.createInternalLink(
jQuery(document.createElement('div')).appendTo($list),
passage,
null,
((passage, fn) => () => {
if (!State.variables.hasOwnProperty('#dialogue')) {
State.variables['#dialogue'] = {};
}
State.variables['#dialogue'][passage] = true;
if (typeof fn === 'function') {
fn();
}
})(passage, setFn)
))
.addClass(`macro-${this.name}`)
.append(document.createTextNode(text));
}
}
});
The <<actions>> macro assigns the class actions to the list element, so you may use the class to make the selectors specific to the macro. For example:
It’s written in ES6+, which may or may not bite you in the arse. If you have players using older browsers (i.e., ES5 only), then that code is guaranteed to explode. While SugarCube’s source code is written in ES6+, releases are transpiled to ES5 for compatibility.
You’re not sanity checking the arguments it receives, which could cause issues. That’s probably not a huge concern, if this is only for your own use, but I’d be remiss if I didn’t mention it.
Frankly. If you’re going to be emitting a list of links, then you should be using a list, styled as appropriate for your needs—you don’t have to use the default styling. Using <div> or <span> elements simply for styling is suboptimal.