Conditional Renderings with JavaScript Regex

2019-02-19 06:37发布

问题:

I need to match on a string such as this:

'if Country equals "United States" then Show'

I'm working with the Webforms for Marketers Module in Sitecore. Sitecore is a .NET based CMS. The Webforms for Marketers Modules is a module that provides a GUI for non-developers to design forms with textboxes, drop-down lists, checkboxes, etc... I have requirements to only show certain fields on the form if the user picked a certain option in a previous field. For example: only show the States drop-down list if the user picked "United States" from the Country drop-down list. The problem is, the WFFM module doesn't support conditional renderings of fields so I'm trying to implement it myself with JavaScript. My idea is this:

  • I'll build out the form in the module with all of the possible fields
  • When the page loads, I'll use JavaScript to hide fields that depend on the value of previous fields
  • When a user interacts with a field, I'll run some JavaScript to check the value of the field and determine whether or not I should show one or more of the fields that I hid on page load.

I'm basically writing an interpreter for an if statement; I'm giving the marketers a way to "program" the form. Country is the name of a drop-down list on my page. equals is a condition. "United States" is one of the values in drop-down list. If the user picks United States in the drop-down, then Show the States drop-down list.

So the input for the regex test would always follow this format:

  • always starts with the keyword if
  • followed by 1 or more white-spaces
  • followed by any number of digits, and/or letters and/or white-spaces
    • The name of controls can contain more than one word with spaces and even numbers
      • For example: First Name, or, Address Line 1
  • followed by 1 or more white-spaces
  • followed by the keyword equals
  • followed by 1 or more white-spaces
  • followed by 1 double-quote
  • followed by any number of digits, and/or letters and/or white-spaces
    • The value of the control can contain more than one word with spaces and even numbers
  • followed by 1 double-quote
  • followed by 1 or more white-spaces
  • followed by the keyword then
  • followed by either the keyword Show or the keyword Hide

I've got this much that works but it's not all of the requirements I've listed above. This line matches all the way up to the white-space after the control name.

var pattern = /^if\s+(\d*|\w*)\s+.*$/;

But when I try to match on the double-quote it doesn't work; I don't really know the syntax for matching on the double-quote. I've tried all of the following, none work:

var pattern = /^if\s+(\d*|\w*)\s+["].*$/;

var pattern = /^if\s+(\d*|\w*)\s+\".*$/;

var pattern = /^if\s+(\d*|\w*)\s+\"{1}.*$/;

Any help you can provide will be greatly appreciated!

回答1:

I'd suggest an expression like this:

/^if\s+([\w\s]+)\s+equals\s+"([\w\s]*)"\s+then\s+(\w*)$/

Which you could use like this:

var expression = // set this to your input
var matches = expression.match(/^if\s+([\w\s]+)\s+equals\s+"([\w\s]*)"\s+then\s+(\w*)$/);

if (matches) { // if matches isn't null
    // matches[1] is the field name
    // matches[2] is the value in quotes
    // matches[3] is the operation to perform

I haven't hardcoded "Hide" and "Show" into the regex - instead it returns whatever string is after "then". I figured that would make it easier to add more operations later. If you want to hardcode these operation names just change the final (\w*) to (Hide|Show). Also this expression will work if the part in quotes is an empty string, which may be valid for some field values.

Demo: http://jsfiddle.net/2UFHN/1/

Note: You said _"any number of digits, and/or letters and/or white-spaces" - for that you just need [\w\s]+. In your expressions you had (\d*|\w*)\s+, which means "zero or more digits OR zero or more word characters FOLLOWED BY by one or more spaces". \w already matches digits (as well as a-z and underscore), so you don't need \d as well.

You might want to add an i flag to your expression, as in /expressionhere/i to make it case insensitve.



回答2:

Just use "; no need to escape it.

Also, you're apparently trying to match the " without first matching the equals, so it won't match any of your test cases.

/^if\s+(\d*|\w*)\s+".*$/.test("if abc \"xyz\"") // ==> true
/^if\s+(\d*|\w*)\s+".*$/.test("if abc equals \"xyz\"") // ==> false