0 votes
by (160 points)

Hello, I was using an old method to allow input, so the player could build his character using a form when the game starts. This one https://web.archive.org/web/20150418055450/http://scopecreepstudios.com/blog/2015/01/11/44

It's not working anymore in Harlowe 3.0.2, returing "hook can not be stored". So any advice of other method to create text input and maybe radio groups with such purpose? Thank you.

 

1 Answer

0 votes
by (159k points)

The method described in the article you linked to only works for Harlowe 1.x and relies on a possible unintentional 'feature', the story format's developer has deliberately removed that 'feature' from the 2. x and 3.x series of Harlowe.

The selected Answer of the How to make ?fname act like a variable? question contains a link to one potential solution for the handling of 'text' based input, that potential solution does not handle other input types like Radio Buttons or Check Boxes.

The new 3.x series of Harlowe includes a (dropdown:) macro which can be used to generate a <select> input element.

warning: The item list of the (dropdown:) macro currently has a foreground / background colour issue on some web-browsers, you may need to use CSS like the following within your project's Story Stylesheet area to fix this colour issue.

option {
    color: #fff;
    background-color: #000;
}

 

by (160 points)

Thanks, greyelf. 

If anyone is looking for it, I've found a perfect way, tested and working on Harlowe 3.x. From here https://exgeekfacto.blogspot.com/2018/02/InputStyles.html

Include it in your Javascript file:

window.Harlowe = { 'State' : State };
window.processInputElements = function () {
    $('input[data-varname]').on('change', function () {
        var varName = $(this).attr('data-varname');
        Harlowe.State.variables[varName] = this.value;
    });
};

In a passage, create inputs like this:

Bandit's Name:
<input type="text" data-varname="banditName">\
<script>processInputElements();</script>
Snake's Name:
<input type="text" data-varname="snakeName">\
<script>processInputElements();</script>
(link-goto: "Done", "aBandit")

And a testing passage called "aBandit":

You mean to tell me that you are *the* $banditName?! 
And that this is your trusty sidekick, $snakeName?! 

Tested and it's working fine. Since I needed some selects, I changed the script to:

window.Harlowe = { 'State' : State };
window.processInputElements = function () {
    $('input[data-varname]').on('change', function () {
        var varName = $(this).attr('data-varname');
        Harlowe.State.variables[varName] = this.value;
    });
		$('select[data-varname]').on('change', function () {
        var varName = $(this).attr('data-varname');
        Harlowe.State.variables[varName] = this.value;
    });
};

The author have another article for radio, here. https://exgeekfacto.blogspot.com/2018/02/harlowes-input-problem-radio-button.html

Thank you!

EDIT: as pointed by you, the new dropdown macro works better than my edition, but I did it before, so it's here just as register :p

by (159k points)

 In a passage, create inputs like this:

You don't need to (and shouldn't) call the processInputElements() function after each of your input element declarations, that function should only be called a single time after all such declarations have been done within the Passage.

eg. Your passage's contents should look something like the following.

Bandit's Name:
<input type="text" data-varname="banditName">\

Snake's Name:
<input type="text" data-varname="snakeName">\

(link-goto: "Done", "aBandit")
<script>processInputElements();</script>

 

Include it in your Javascript file

You don't need to use a Harlowe namespace to gain access to the story format's State object, but you can do so if you want to. The processInputElements() function could be change to the following and it would still work.

window.processInputElements = function () {
    $('input[data-varname]').on('change', function () {
        var varName = $(this).attr('data-varname');
        State.variables[varName] = this.value;
    });
};


Fun Fact: The window.processInputElements() function code you posted to is based on code I supplied to someone else, I later modified / extended that code to also support Numbers Radio Buttons, Check Boxes and Select.

window.processInputElements = function () {
	var story = $('tw-story');

    /* Handle Text related inputs. */
    story.find('input[name][type="text"]').on('change', function () {
        var varName = $(this).attr('name');
		State.variables[varName] = this.value;
    });

    /* Handle Numeric related inputs. */
    story.find('input[name][type="number"]').on('change', function () {
        var varName = $(this).attr('name');
		State.variables[varName] = parseInt(this.value);
    });

    /* Handle Radio Button related inputs. */
    story.find('input[name][type="radio"]').on('change', function () {
        var varName = $(this).attr('name');
		State.variables[varName] = this.value;
    });

    /* Handle Check Box related inputs, uses 'data-onuncheck' property value when unchecked. */
    story.find('input[name][type="checkbox"]').on('click', function () {
        var varName = $(this).attr('name');
		var unchecked = $(this).attr('data-onuncheck') || "";
		State.variables[varName] = this.checked ? this.value : unchecked;
    });

	/* Handle Select / Dropdown related inputs. */
	story.find('select[name]').on('change', function () {
		var varName = $(this).attr('name');
		State.variables[varName] = this.value;
    });
};

The above variation of the processInputElements() function has been changed to use the standard name property (instead of data-varname) to determine the name of the input element's assocated story variable. This was done because input elements generally have a name property assigned to them anyway, so the handler code might as well use it.

The following is an example of the above variation being used within a Passage.

(set: $name to "John", $age to 18, $colour to "Red", $autosaves to "", $icecream to "Yes")

<label for="name">Name: </label>\
<input type="text" name="name">

<label for="age">Age: </label>\
<input type="number" name="age">

<label for="icecream">Like Icecream?: </label>\
<input type="radio" name="icecream"  value="Yes">Yes\
<input type="radio" name="icecream"  value="No">No

<label for="autosave">Auto Saves: </label>\
<input type="checkbox" name="autosaves" value="Yes">

{
<label for="colour">Favorite Colour:</label>
<select name="colour">
	<option value="Red">Red</option>
	<option value="Green">Green</option>
	<option value="Blue">Blue</option>
</select>
}

[[Result]]
<script>processInputElements();</script>

 

by (160 points)
Very true, the multiple "processInput" is my fault and in fact I had done it right on my test game...

All the rest is new to me, so thanks for clarifying.
...