Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Twines (in)ability to grab elements without a delay

I've asked this question before, but I got an answer that was less than satisfactory and I wanted to give it one more try. I'll try to be as clear as possible as I realize the onus is on me to state the problem clearly.

To recap, there is an issue that I am running into with Twine that makes the program completely unable to use JS to reference page elements without a delay. I'll picture an example.

undefined

We can see here in the developer console that I'm logging the elements as they're created. So we have 4 messagebox tags being created very obviously. And they show up on the page fine. But when we try to count those elements, we always get 0. Why?

Keep in mind that I'm not typing 0 manually. This is my code.
var x=document.getElementsByTagName("messagebox");
console.log("Twine thinks there are " + x.length + " messagebox tags on the current passage?");
And here is a screenshot of the scene so you can see the order in which things are being called.

undefined

So the messagebox tags are created. Then we count them. But it counts 0.

If I add a delay via <<timedcontinue>> or setTimeout it works. It counts 4.

So then I got to thinking, maybe it references the previous page. And it does.

Taking out the delay, if I put in a messagebox tag or use the eventbox macro on the PREVIOUS passage, it counts those elements. So Twine, when javascript is used without a delay, references the elements of a page that is no longer being displayed. In Sugarcane or Jonas or Sugarcube it makes no difference. And this has become a HUGE issue for me as a developer. I can't reference anything, be it CSS from the current page, the amount of li tags, my own custom tags, with JS. Not without the 4ms delay of setTimeout.

Is there a satisfactory way around this? Is this a known issue that will later be patched?

Comments

  • What does the <<eventbox>> macro do exactly?

    It seems you have created a test case story to demonstrate the problem, could you attach the tws/twee source for that? That would allow developers to reproduce the problem on their own computer.
  • You received the only answer possible.  You were trying to reference elements in situ, which you cannot do by checking document, because the elements are not part of the page yet.  At the point which you're attempting to access them, the elements are in the wikifier's output buffer, so you cannot use document.get*() to reference them.  Full stop.

    Additionally, as noted there by Erik Temple, what you were trying to do before was correctly handled via CSS in the first place, so you were doing it wrong from step one.

    That said, and on the off chance you need to do something else which cannot be handled via CSS, have you tried calling the various element selector methods get*()/querySelector() on the wikifier's output buffer?  For example:

    Using the vanilla macro API (vanilla headers and SugarCube): (assuming the first parameter to handler() was named place)
    var x = place.getElementsByTagName("messagebox");
    Using SugarCube's new-style macro API (SugarCube only):
    var x = this.output.getElementsByTagName("messagebox");
  • Also, from your screenshot it looks as though you are giving all of the elements the same id (#bluewindow), but that should be a class, I assume (.bluewindow)? Chrome is pretty tolerant of duplicate ID's on the same page, I think, but it is illegal and I don't think other browsers are as tolerant. In any case, you probably won't get the results you want when you try to interact with these elements.
  • Thanks for the replies. I'll address each.

    mth:
    Absolutely. I'll attach the file as is so you can check it out. But what my macros are doing is irrelevant. If I type <messagebox> instead of the macro it still doesn't work. It wouldnt work if I tried to count bold tags or linebreaks or anything else either (and if it counted any, they'd be from the previous page).

    Thomas:
    This is the answer I needed. Using the macro API does get around the problem. Your continued willingness to help me out is appreciated. This is new information and I'll use it where appropriate.

    Erik:
    While the elements having identical ids is not causing the issue and it works okay in both FF and Chrome, I definitely agree this is not the proper way to do it. Thanks. I'll fix that.

    All:
    I realize that in general asking the same question twice in this manner is bad etiquette, so thank you for your patience. I may have been a little slow on the uptake for this one. That said, this seems extremely unintuitive. The fact that Twine pulls elements from a page in which the macro was not executed seems wrong to me. In the future, if someone were to ask what new features or fixes I'd like to see in Twine, fixing this is going to be it. I can see where that might sound silly to someone who developed the programs and headers in a 'well just do it the right way' sense, but as a new entrant to Twine, I want the javascript I use anywhere else to work in Twine. And the DOM is such an integral part of... everything... that I hope its understandable that I was confused why I couldnt access it correctly.
  • CoraBlue wrote:
    All:[/b]
    I realize that in general asking the same question twice in this manner is bad etiquette, so thank you for your patience. I may have been a little slow on the uptake for this one. That said, this seems extremely unintuitive. The fact that Twine pulls elements from a page in which the macro was not executed seems wrong to me. In the future, if someone were to ask what new features or fixes I'd like to see in Twine, fixing this is going to be it. I can see where that might sound silly to someone who developed the programs and headers in a 'well just do it the right way' sense, but as a new entrant to Twine, I want the javascript I use anywhere else to work in Twine. And the DOM is such an integral part of... everything... that I hope its understandable that I was confused why I couldnt access it correctly.


    You still don't seem to be completely understanding the issue.  This has very little to do with the twine headers, beyond the fact that the engine is buffered, and everything to do with the DOM.

    When you call the various element selector methods get*()/querySelector() on a node, they can only find elements within that node.  Hence, calling the methods on document can only find elements which exist within the DOM.  If the elements you want are not yet part of the DOM, you will not find them, although you may find other elements which happen to match your search parameters (the same type of elements from the previously rendered passage in your case).

    When you call the element selector methods get*()/querySelector() in an attempt to match elements within the same wikifier call, you cannot call them on document because the wikifier call has not ended and the elements you want to match have not yet been injected into the DOM.  This is why, to match elements within the same wikifier call, you have to call the selector methods on the wikifier's output buffer.

    This holds true for any usage, any engine where the above situation holds true (i.e. you're trying to match elements within the same buffered engine call, where the elements are only injected into the DOM at the completion of the engine call).
Sign In or Register to comment.