Howdy, Stranger!

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

Checking text input for non-alphanumeric characters in Sugarcube 2.0

I'm attempting to verify player name input and I'm having problems. I'm using this bit of code and instead of getting the expected results, or even "Test", it's printing absolutely nothing. ((I've got it spread out over a couple pages to test.))
<<set $player.name to "Test">>
<<textbox "$input" "" autofocus>>	
<<set $player.name to $input.replace(/[^0-9a-z]/gi, '')>>
<<print $player.name>>

I'm not real familiar with Regular Expressions or Javascript, except what I've been able to put together from the web and my developer friends, so I'm mainly using stuff copied from Stack Overflow. Even so, seems to me this should work, and I'm not sure why it isn't.

Help would be appreciated.
Cheers,

Comments

  • edited October 2016
    housellama wrote: »
    I'm using this bit of code and instead of getting the expected results, or even "Test", it's printing absolutely nothing.
    You're not seeing the string "Test" because you're overwriting it.

    As far as not seeing anything else, are you initializing the $player story variable as an object? I doubt that's the issue or you'd be seeing lots of errors.

    It's probably going to turn out to be a timing issue. Off the top of my head, you're probably attempting to do the replacement before the player has actually input a name, thus assigning an empty string to $player.name.

    housellama wrote: »
    ((I've got it spread out over a couple pages to test.))
    Which parts are spread where? Yes, that is an important detail.

    housellama wrote: »
    I'm not real familiar with Regular Expressions or Javascript, except what I've been able to put together from the web and my developer friends, so I'm mainly using stuff copied from Stack Overflow.
    Your regular expression and the call to <String>.replace() are both fine for what you're attempting to do—though I would use <RegExp>.test() here instead—which makes my guess above even more likely.



    Regardless. You could use two passages to do this as you were probably attempting, however, using one is sufficient if you use the appropriate macros. For example, the following is what I'd probably recommend.

    1. Initialize $player in the StoryInit special passage:
    <<set $player to {
    	name : "John"
    }>>
    
    NOTE: You're probably doing something like this already. This is mostly for example purposes.


    2. Then the passage where you allow the player to input the name:
    <<textbox "$player.name" $player.name autofocus>> \
    <<button "Confirm Name">>
    	<<set $player.name to $player.name.trim()>>
    	<<if /[^0-9a-z]/i.test($player.name)>>
    		<<replace "#error-name">>Only letters and numbers are allowed.<</replace>>
    	<<else>>
    		<<goto [[Post-Input]]>>
    	<</if>>
    <</button>><div id="error-name"></div>
    
    NOTE: The passage Post-Input is for example purposes only. Use whatever your post-name-input follow-on passage should actually be.


    3. And finally, the Post-Input passage:
    Hello, $player.name.
    
  • Yes, I had most definitely initialized everything first. I'm making very heavy use of widgets in this particular story, so I've initialized a LOT of stuff globally.

    I split the original code between the next to last line and the last line. Setting/checking the name, then moving to the next page to print it. I didn't have a button set up, although I tried to and could never really make it work.

    Your code worked perfectly for what I needed.

    I'm guessing that .test() does exactly what it says on the tin: testing a RegEx for the presence of those letters, returning true if they exist? That's actually a better implementation than replace. One question, why the .trim()? What purpose does that serve?

    Thanks! Your posts are always so very informative and helpful. I've learned a lot just from reading through the archives and looking for TheMadExile. So cheers!
  • Ahhh, .trim() removes whitespace. Trim that out first, then test for the presence of anything other than the appropriate letters and force the player to re-enter if they are there.

    Beautiful.
  • housellama wrote: »
    I split the original code between the next to last line and the last line. Setting/checking the name, then moving to the next page to print it. […]
    Then my original supposition was correct, it was indeed a timing issue. The core problem with what you were originally trying is that you were immediately attempting to use the result an interactive macro and you cannot really do that since interactive macros depend upon the player—thus there is no immediacy to them.

    Here's a step-by-step breakdown of what was happening:
    1. <<set $player.name to "Test">>
      
      Assign the string value "Test" to $player.name. Since you reassign its value in step 3 before ever using it, this bit of code wasn't really doing anything useful.
    2. <<textbox "$input" "" autofocus>>
      
      Set up a text input box with the initial value "" (empty string) and store its eventual result within $input—"eventual" being the key word here, as the text input box requires player input.
    3. <<set $player.name to $input.replace(/[^0-9a-z]/gi, '')>>
      
      Assign the result of replacing non-alphanumeric characters within the current value of $input, which is the "" (empty string), to $player.name—the player has not yet had a chance to even look at the text input box, let alone interact with it, so the value of $input is still the empty string at that point.
    If you had split your original code so that the replacement on $input and assignment to $player.name happened within your follow-on passage, then it would have worked—though the other issues would have remained.

    housellama wrote: »
    I'm guessing that .test() does exactly what it says on the tin: testing a RegEx for the presence of those letters, returning true if they exist? That's actually a better implementation than replace.
    Correct—your description was a bit backwards, but I think you have the gist. It tests the string parameter you pass it against its regular expression, returning true if there was a match and false elsewise. See <RegExp>.test() for more information.

    housellama wrote: »
    One question, why the .trim()? What purpose does that serve?
    housellama wrote: »
    Ahhh, .trim() removes whitespace.
    Correct. It removes both leading and trailing whitespace from a copy of its string and returns the copy. See <String>.trim() for more information.
Sign In or Register to comment.