0

I'm working on my final project of the Winter 2017 quarter to demonstrate how to use Regular Expressions in both C# and JavaScript code behind pages. I've got the C# version of my demonstration program done, but the JavaScript version is making me pull what little hair I have left on my head out (no small achievement since I got a fresh buzz cut this morning!). The problem involves not getting any output after applying a Regular Expression in a While loop to get each instance of the expression and printing it out.

On my HTML page I have an input textarea, seven radio buttons, an output textarea, and two buttons underneath (one button is to move the output text to the input area to perform multiple iterations of applying expressions, and the other button to clear all textareas for starting from scratch). Each radio button links to a function that applies a regular expression to the text in the input area. Five of my seven functions work; the sixth is the one I can't figure out, and the seventh is essentially the same but with a slightly different RegEx pattern, so if I fix the sixth function, the seventh function will be a snap.

(I tried to insert/upload a JPG of the front end, but the photo upload doesn't seem to be working. Hopefully you get the drift of what I've set up.)

Here are my problem children from my JS code behind:

    // RegEx_Demo_JS.js - code behind for RegEx_Demo_JS

var inputString; // Global variable for the input from the input text box.
var pattern; // Global variable for the regular expression.
var result; // Global variable for the result of applying the regular expression to the user input.

// Initializes a new instance of the StringBuilder class
// and appends the given value if supplied
function StringBuilder()
{
    var strings = [];

    this.append = function (string)
    {
        string = verify(string);
        if (string.length > 0) strings[strings.length] = string;
    }

    this.appendLine = function (string)
    {
        string = verify(string);
        if (this.isEmpty())
        {
            if (string.length > 0) strings[strings.length] = string;
            else return;
        }
        else strings[strings.length] = string.length > 0 ? "\r\n" + string : "\r\n";
    }

    this.clear = function () { strings = []; };

    this.isEmpty = function () { return strings.length == 0; };

    this.toString = function () { return strings.join(""); };

    var verify = function (string)
    {
        if (!defined(string)) return "";
        if (getType(string) != getType(new String())) return String(string);
        return string;
    }

    var defined = function (el)
    {
        // Changed per Ryan O'Hara's comment:
        return el != null && typeof(el) != "undefined";
    }

    var getType = function (instance)
    {
        if (!defined(instance.constructor)) throw Error("Unexpected object type");
        var type = String(instance.constructor).match(/function\s+(\w+)/);

        return defined(type) ? type[1] : "undefined";
    }
}

Within the code of the second radio button (which will be the seventh and last function to complete), I tested the ScriptBuilder with data in a local variable, and it ran successfully and produced output into the output textarea. But I get no output from this next function that invokes a While loop:

function RegEx_Match_TheOnly_AllInstances()
{
    inputString = document.getElementById("txtUserInput").value;
    pattern = /(\s+the\s+)/ig; // Using an Flag (/i) to select either lowercase or uppercase version.  Finds first occurrence either as a standalone word or inside a word.
    //result = pattern.exec(inputString); // Finds the first index location
    var arrResult; // Array for the results of the search.
    var sb = getStringBuilder(); // Variable to hold iterations of the result and the text
    while ((arrResult = pattern.exec(inputString)) !==null)
    {
         sb.appendLine = "Match: " + arrResult[0] ;
    }
    document.getElementById("txtRegExOutput").value = sb.toString();

    /* Original code from C# version:
      // string pattern = @"\s+(?i)the\s+";  // Same as above, but using Option construct for case insensitive search.
      string pattern = @"(^|\s+)(?i)the(\W|\s+)";
      MatchCollection matches = Regex.Matches(userTextInput, pattern);

      StringBuilder outputString = new StringBuilder();
      foreach (Match match in matches)
      {
         string outputRegExs = "Match: " + "\"" + match.Value + "\"" + " at index [" + match.Index + ","
            + (match.Index + match.Length) + "]" + "\n";
         outputString.Append(outputRegExs);
      }
      txtRegExOutput.Text = outputString.ToString();
      */
} // End RegEx_Match_The_AllInstances

I left the commented code in to show what I had used in the C# code behind version to illustrate what I'm trying to accomplish.

The test input/string I used for this function is:

Don’t go there. If you want to be the Man, you have to beat The Man.

That should return two hits. Ideally, I want it to show the word that it found and the index where it found the word, but at this point I'd be happy to just get some output showing every instance it found, and then build on that with the index and possibly the lastIndex.

So, is my problem in my While loop, the way I'm applying the StringBuilder, or a combination of the two? I know the StringBuilder code works, at least when not being used in a loop and using some test data from the site I found that code. And the code for simply finding the first instance of "the" as a standalone or inside another word does work and returns output, but that doesn't use a loop.

I've looked through Stack Overflow and several other JavaScript websites for inspiration, but nothing I've tried so far has worked. I appreciate any help anyone can provide! (If you need me to post any other code, please advise and I'll be happy to oblige.)

JBM
  • 63
  • 1
  • 2
  • 12
  • This won't really solve your problem, but just so you know you are doing too much type checking. JavaScript isn't meant to be programmed like Java; it isn't necessary to do stuff like `if (getType(string) != getType(new String())) return String(string);` – gyre Mar 19 '17 at 00:56
  • 1
    `.appendLine` is a function/method. In your loop you need to call it with `sb.appendLine()`, not assign a value to it with `=`. Also, what is `getStringBuilder()`? That function is called just before the `while`, but the function definition isn't shown. Shouldn't it be `sb = new StringBuilder()`? – nnnnnn Mar 19 '17 at 01:22
  • It's possible I've been copying and pasting so many times trying something different, it's all messed up. That's why I'm hoping someone can set me straight! – JBM Mar 19 '17 at 02:56
  • I fixed the problems with the JS StringBuilder as I implemented them, as nnnnnn suggested. It still isn't printing. I'm starting to think the real issue is how I'm implementing the loop, or that I should use match rather than exec. After all, in the C# version, I used a match rather than an exec method. In reading some things about loops and RegEx in JavaScript, they led me to think I should use exec instead of match. Let me try something with that. – JBM Mar 19 '17 at 20:06
  • It appears I fixed my problem. I deleted the old code from the loop function so I could start over with clean code. Here's what finally worked: var sb = new StringBuilder(); inputString = document.getElementById("txtUserInput").value; pattern = /\s+the\s+/ig; result = null; while ((result = pattern.exec(inputString)) != null) { sb.appendLine("Match: " + "\"" + result[0] + "\"" + " at index " + "[" + result.index + "]" ); } document.getElementById("txtRegExOutput").value = sb.toString(); – JBM Mar 25 '17 at 01:48

0 Answers0