Javascript event help

Hi everyone! :slight_smile:

First post on this board hope to get some help, English isn’t my first language, please excuse my bad grammar.
I’m not new with javascript but with twine and sugarcube yes.
I’m using sugarcube 2 with tweego.

I want to mimic a terminal in the game but I cant make the keydown event to work and I dont know why. I know that the code work in a normal html page but not in twine. I’m a little bit lost, probably a quirk with sugarcube that im not aware.

Thanks in advance for the help! :grin:

My passage :

:: terminal
<<set _listInput to []>>
<<set _input to "">>
<div class="dumb_terminal" id="terminal">
    <p>Getting acces ...</p>
    ...
    <p>c:.//pc/home > <textarea id="terminalInput" rows="1"></textarea></p>
</div>
<script>
    const input = document.getElementById("terminalInput");
    const terminal = document.getElementById("terminal");

    input.addEventListener("keydown", function (e) {
        if (e.key === "Enter") {
            e.preventDefault();
            const value = input.value.trim(); 
            if (value !== "") {
                const newLine = document.createElement("p");
                newLine.textContent = `c://pc/home > ${value}`;
                terminal.appendChild(newLine);
                input.value = "";
            }
        }
    });
</script>

Have a nice day!

There are a couple of issues with your example:

The line-breaks within your HTML structure will be automatically converted into <br> elements, which will likely affect the layout of that structure. The <<nobr>> macro can be used so suppress unwanted <br> elements.

The c:.//pc/home text being shown contains // which is use to represent the start & end of Emphasis styling mark-up. So you will need to Verbatim Text mark-up to let SugarCube know // is being used for something else.

<nowiki>c:.//pc/home</nowiki>

When a Passage is visited its content is processed, and any HTML Nodes and/or Elements that are generated are added to a buffer until the entire content has been processed, at which point the contents of the buffer is added to the web-page’s Document Object Model (DOM).

The body of any <script> element that is found within the contents of a Passage is executed at the point in time the element is encounter.

This means that the <div> element structure being created in that Passage example won’t exist in the web-page’s DOM at the point in time when the document.getElementById() method calls are trying to locate the relevant elements. Thus the input variable will contain null, and the input.addEventListener() will cause an error, which should be visible within the web-browser’s Console.

The solution is two fold:

  1. Use the <<script>> macro instead of the <script> element, as the macro behaves better with the SugarCube engine.
  2. Use the <<done>> macro to delay the execution of the JavaScript.

The following is a variation of your own code that does all of the above…

<<set _listInput to []>>
<<set _input to "">>
<<nobr>>
<div class="dumb_terminal" id="terminal">
    <p>Getting acces ...</p>
    <p>
		<nowiki>c:.//pc/home</nowiki> >
		<textarea id="terminalInput" rows="1"></textarea>
	</p>
</div>
<</nobr>>
<<done>>
	<<script>>
		const input = document.getElementById("terminalInput");
		const terminal = document.getElementById("terminal");
		input.addEventListener("keydown", function (e) {
			if (e.key === "Enter") {
				e.preventDefault();
				const value = input.value.trim(); 
				if (value !== "") {
					const newLine = document.createElement("p");
					newLine.textContent = `c://pc/home > ${value}`;
					terminal.appendChild(newLine);
					input.value = "";
				}
			}
		});
	<</script>>
<</done>>
1 Like

Wow, thanks for the detailed response, really appreciate it.

Have a nice week-end!