0 votes
by (280 points)

Hi community,

I would like to provide a user form that should appear only once if submitted correctly, even if the user reload the browser in the same passage.

Here relevant code

<<if $formIntroSubmitted eq true>>
  // just do not show the form, as it is already submitted
<<else>>
  <form>...here goes the html form</form>
  <<button "Start!">>
    <<if $firstNameOK eq false>>
        <<replace "#answer-error">>Please fill the form before proceeding<</replace>>
    <<else>>
        // Form submitted correctly! then set the persistent variable below
    	<<set $formIntroSubmitted to true>>
        <<remove "#introForm" >>
    <</if>>
  <</button>> 
<span id="answer-error"></span></p></div></div>
<</if>>

But the $formIntroSubmitted variable is never true in the same page, and if you reload the browser I always see the form..

How can I set a persistent variable to hide the form once submitted? Other solution (avoiding jquery.cookie plugin)?

Thank you!

2 Answers

0 votes
by (280 points)

The problem I face is that when a user submit the form via the button, the variable 

<<set $formIntroSubmitted to true>>

is only true for all next/other passages, not the one where the form relies (and where that variable is set via button). Therefore the form is always shown

No idea how-to....

0 votes
by (44.7k points)

The simplest way is to get rid of:

<<remove "#introForm" >>

And change the button to:

<<button "Start!" `passage()`>>

That code will cause the passage to reload itself, which also stores the values of the variables so that if you reload the page, the form will remain hidden.  Since $formIntroSubmitted will be true at that point, it will also hide the form and the "Start!" button.

That will cause a transition when you click the button, but hopefully that isn't a problem.

Also, you don't actually need the "<form>" elements, because it's not really a form.

NOTE: The marks around "passage()" are backquotes/backticks, found on the key with the tilde "~" on it.  This causes it to pass the return value of that function, which is the name of the current passage, instead of passing the function itself.  If the passage's name was, for example, "Form" you could do "<<button "Start!" "Form">>" instead.

Hope that helps! smiley

by (280 points)
edited by

thank you, the 'passage()' reloads the page and the variable works correctly now. However, if I go back in story history, I see the same page as a duplicate page (with the form visible this time), so the issue is just moved, not solved..

Even by not affecting the state history

<<script>>state.display(state.active.title, null, "back")<</script>>

once I submit the form and I go back one page, the variable becomes false and the form appear again

 

by (44.7k points)

That's just how Twine works.  The back button is essentially an "undo" button.

If you don't want the back button you can add the following code to your JavaScript section:

Config.history.controls = false;

See the documentation here.

by (280 points)
Unfortunately, the story history and backward/forward buttons should stay there, as I have implemented my own UI with related engine backward and forward icons. I have to find an alternative route to solve this.

The only thing I can think of is to reset the story history when the form is submitted, ending up with no passage duplicates and the variable already set. But I don't think I can reset the the story history without restarting the game.
by (44.7k points)

Are you disabling the "Save" button?  If not, then there isn't an "alternate route", because people can use that to undo things as well.

You wanted to store information you hadn't stored, so the solution was to store it.  Now you want the "undo" button to not undo things.  I don't think there's any good way to do that.

Unfortunately, the story history and backward/forward buttons should stay there, as I have implemented my own UI with related engine backward and forward icons.

If you've implemented your own forward/back system, then I don't even know what your code is doing, so I can't help you with it.  If they're just buttons, then the answer isn't much different from before: disable/remove the buttons so you can't go back if you don't want them to be able to undo changes to the form.

by (280 points)
edited by

The simplest way to achieve this, I believe after many trial 'n error, is to skip the previous passage where the form resides from a story history. Which means, if you reached a passage "3" for instance, it means that you already submitted a form contained in passage "2", therefore if you want to go back in history from passage "3" you skip the "2" and go straight to "1". 

This way the passage "2" with the form will be no longer visible once submitted.

Now, do you think is possible in the javascript area to implement something like this (goes for custom UI)?

if(Engine.backward("2")) {
  go to passage "1"; // just skip the passage with the form!
} else {
  Engine.backward();  // go back to previous history passage as expected
}

..or..

if(previous() eq "2") {
  go to passage "1"; // just skip the passage with the form!
} else {
  Engine.backward();  // go back to previous history passage as expected
}

 Thanks!

 

 

by (44.7k points)

That won't work.  Even if you somehow skipped "2", all of the data which was added previously would be undone by going back in the history to "1".  That's why it's referred to as the "history".

What you want is the equivalent of Buzz Aldrin to going to the Moon, and being able to go back in time before that, yet still somehow still have his footprints already on the Moon.  It won't work.  If you go before the footprints were made, then they no longer exist from your perspective.

The closest approximation that would actually work would be to go forward and only have it look like you went back.  If you have your own "forward" and "back" buttons you should be able to implement this, though you will need to implement your own "pseudo-history", so it will be kind of complicated.

by (159k points)

There is the option to save an equivalent of the $formIntroSubmitted true / false value outside the story variable system, such as a property on the setup object, which would result in it no longer being tracked by History

However this also means that it is no longer part of the Save system, unless handled manually via the Config.saves.onSave and Config.saves.onLoad event handlers.
eg. Something like the following untested JavaScript code.

/* Initialise the new property for THIS play-through. */
setup.formIntroSubmitted = false;

Config.saves.onSave = function (save) {
	save.metadata.formIntroSubmitted = setup.formIntroSubmitted;
};

Config.saves.onLoad = function (save) {

	/* If the 'FORM' passage hasn't been seen yet in THIS play-through. */
	if (!setup.formIntroSubmitted) {

		/* Was the Save created after the new 'onSave' handler was added to the game. */
		if (save.metadata.hasOwnProperty("formIntroSubmitted")) {
			/* if so then set the setup property to true if it or the metadata is true. */
			setup.formIntroSubmitted = (setup.formIntroSubmitted || save.metadata.formIntroSubmitted);
		}
		else {
			/* This is an old Save so we need to test if the 'FORM' passage was visited in it. */
			var found = save.state.history.some(function (moment) { return moment.title == "FORM"; });
			setup.formIntroSubmitted = (setup.formIntroSubmitted || found);
		}
	}
};

 

...