I'm using Sugarcube 2.8 and Twine 2!
I'm making myself a macro which indexes all the passages in my story and says whether they are tagged or not. Since my titles all have a space in them except for the Special Name'd ones, I figured searching for all titles with one would be the easiest solution. I'm currently trying to use the JavaScript "*" asterisk wildcard character like so:
new Wikifier(place, Story.lookup("title", "* *" )[0].title);
Which, to my understanding, should bring back any passage title with a space in it. Instead, it throws me this error:
TypeError: Cannot read property 'title' of undefined
I am aware that Story.lookup brings me an array of objects and that it comes out as undefined if nothing matches. However, there should be PLENTY of matches looking over my story map over 30 passages strong. Is there any way to get the method to cooperate and accept wildcards? If not, is there any better way to do what I'm doing?
Comments
There is currently no way to search the passage store using globbing wildcards, regular expression patterns, or regular expressions. Matches are made using lazy equality.
I could add a new lookup method which would take a predicate. That would allow you to filter upon whatever criteria you wanted. I like that idea, actually—probably do something like Story.lookupWith(filterPredicate [, sortKey]).
Alternatively, you could search manually through the story data, though that wouldn't be ideal.
JavaScript does not support any kind of globbing wildcards, which is what you're apparently attempting to do. It does support regular expressions, however, the pattern you tried is invalid even for that.
If I may ask, where did you see this? If there's bogus information out there, then I'd like to try to get it corrected. On the other hand, if that was your understanding of the Story.lookup() static method's documentation, then I may need to revisit it.
The reason you received the TypeError is because you attempted to reference the first element of an empty array, which is nonexistent and thus undefined, and then further attempted to access the title property on that undefined value.
Emphasis mine. Yes to the former, no to the latter. If no passages match, it returns an empty array, not undefined.
Oh, if you could, that would be much appreciated. Although, in the meantime I just need a way to make sure changing passage titles in my story map doesn't mess up the variables I have. Right now I'm just tagging each passage with a unique number, that way I can refer to them if I need to change the title for any reason. I know there's a domID system in the Passage object, but it requires the passage's title to even get it in the first place, so it's pretty self-defeating when it comes to the end I need it.
Ah, I see. Would you be kind enough to direct me to a good tutorial on that? I'm pretty much a beginner here and I'm going off documentation and simple examples.
That was not the documentation's fault at all! It was more with my general confusion with JavaScript since it's somewhat new to me. I looked up a supposed tutorial, but it left me more confused than anything.
So what way should I refer to an array with an empty or nonexistant value? I used JavaScripts "== NaN" before in my coding to do so, but that caused my Twine to hang upon testing. This is the code I used to index all the passages with a room name, highlighting any instances where more than one room was associated with a single tag at a time. (Specifically this code in line 12, I would have emboldened it, but I can't do that in code blocks :<)
The silly "roomObject[r] != roomObject[(r+1000000)]" was a how I got past the program hang instead of doing it how I mentioned before.
Thanks so much for your help! I just need a way to give passages a unique identifier which won't change if I mess with titles AND is readable when debugging. Right now I'm using the macro you see above to know which tag goes to which room name, but I fear if I just use numbers or even more macros to get the passage names from the tags when working with the code that it'll become a nightmare to work with.
EDIT: Also! Is it possible to comment things out in Twine Sugarcube like with JavaScript? Right now I'm going to just comment the passage names next to the tag numbers in the code so I know which is which. There's no syntax highlighting when I use Sugarcube, so I have no idea what the syntax for commenting would be.
1. Passage:
2. CSS and Javascript:
I must be missing something, why would changing passage titles affect your variables?
Uh. Try regular-expressions.info and the JavaScript Regular Expressions Guide @MDN, I suppose. Sorry, you're aking me for something I haven't required in, well, a really long time.
Not to be unkind to the authors, however, most Twine tutorials I've seen online are little more than cargo culting.
Before you attempt to index an array, you should always check its length. For example: Or within a for loop:
NaN (Not-a-Number) is a Number type value, representing a value which is not a number. Also, by definition, nothing equals the NaN value, not even itself, so you cannot use equality operators to test values for NaN-ness. If you ever did need to test a value to see if it was NaN, you should use the Number.isNaN() method.
First. You should probably be using SugarCube 2's native Macro API, rather than the legacy macro API. I'd rewite your macro as an example, which would include correcting several other issues, however, I'm unsure as to the reasoning behind why you're doing any of this.
Also, you should be nesting your markup properly. The following: Should be: Markup blocks should be closed in the reverse of the order used to open them. This is also true for HTML block markup.
This is what I'm talking about. Why do you need a unique identifier other than the passage name/title, which already should be unique? Why are you, apparently, renaming passages with enough regularity to make depending on their names problematic?
If the reason is that you're worried about wiki/double-square-bracketed links (…) being broken, then Twine 2 will automatically fix all such when you rename a passage. Beyond that, there's also find and replace.
In SugarCube, you may use C-style block comments (/* … */) within normal passages, JavaScript, and CSS. For example: HTML block comments (<!-- … -->) and TiddlyWiki block comments (/% … %/) are also supported within normal passages, however, you may as well simply use C-style block comments since they're supported everywhere. JavaScript also supports an inline comment syntax.
As for why I was making redundant unique identifiers, I honestly have no clue, in retrospect. I knew about the find and replace option before, but I guess I wanted to be super careful? I don't know.
Well, the main reason I was using the legacy form was that the Wikifier didn't really work. For the exact same code with one minor change to the opening line (which would be the following with one less parenthesis at the closing of the command: Rather than: The former would execute and print out the contents of the Wikifier while the latter would not. I'm not sure why, myself, really. The Wikifier would be written up exactly how you see in the code from my previous post. There's also no real documentation about the Wikifier in the Sugarcube 2.8 documentation other than in passing, so I don't know if I'm just writing something incorrectly.
The Macro.add() documentation specifically states that a macro's handler function will be called without arguments/parameters, but with its this set to a macro execution context object. The example given with Macro.add() demonstrates this.
Thus, the reason you were not getting output from the Wikifier is that you were attempting to output to an undefined value, since place is not defined.
The reference to the output buffer in a macro execution context object is output, which would be this.output within a macro. For example: That said, you should probably be using SugarCube 2's <jQuery>.wiki() extension method rather than making direct calls to the Wikifier. For example:
Although, I must ask, why shouldn't I make direct calls to the Wikifier? I know little about it since there's no documentation on it on the site. I also have to ask what the "$" is for in that last block of code you typed out.
Again, thanks for the help!
As far as why you'd prefer the former. Mostly because <jQuery>.wiki() is documented. Meaning that you have a guarantee that, at least within the same major version (i.e. v2.x.x), it will be available and with the documented interface.
There are various reasons why I have not documented the Wikifier—which I'm not getting into here. Simply the fact that it is not documented, however, should serve as a warning.
The
Emperordocumentation provides—look at the special variable names (hint: it's an alias for jQuery).SugarCube v2.11.0 has been released and includes the static method I mentioned previously, Story.lookupWith().