Yesterday, I posted about creating String.prototype.indexOfIter() which basically returned a function which would act as an iterator function, indicating the indices of the specified substring. What I neglected to include was how to write this solution using JavaScript 1.7 in FireFox. Today, I bring to you the equivalent using a generator function. Checkout the code and example of JSBin.com by clicking here.

If the above link no longer works, here is the code that I had on JSBin:

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JavaScript - indexOf Iterator Via A Generator</title>
<meta name="author" content="Chris West">
<meta name="description" content="An example of creating a generator function with JavaScript 1.7 in FireFox.">
<meta name="keywords" content="JavaScript,Java Script,FireFox,String.prototype.indexOfIter,Iterator,Generator,Chris West">
<!--[if IE]>
  <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
  p { font-family:Tahoma; }
  article, aside, figure, footer, header, hgroup, 
  menu, nav, section { display: block; }
  a:link, a:visited { color:blue; text-decoration:none; }
  a:hover, a:active { color:red; text-decoration:none; }
  #txtMsg, #txtSub, #txtStart { width:100%; }
  .notice { font-size:80%; text-align:center; }
</style>
<script type="application/javascript;version=1.7"/>
String.prototype.indexOfIter = function(target, start) {
  var targetLen = target.length;
  while(true) {
    start = ((index = this.indexOf(target, start)) + targetLen) * (index >= 0);
    yield index;
  }
};
</script>
</head>
<body>
  <h1>JavaScript - indexOf Iterator Via A Generator</h1>
  <p>This is an example of creating and using a generator function with JavaScript 1.7 in FireFox.  This example only works in <a href="https://developer.mozilla.org/en/New_in_JavaScript_1.7" target="_blank">FireFox 2 or higher</a>.  This basically allows you to enter a message and a substring that appears in the message and then you can click the button to display all of the indices of the substring in the message.  Once you are done, move your mouse to the top-right of the window and click on "<a href="http://jsbin.com/cwest/indexOfIter-generator/edit#html,live">Edit in JSBin.com</a>" to view the code.</p>
  <form id="aForm" onsubmit="showIndices(this); return false" action="" method="get">
    <label for="txtMessage">Message to search:</label><br />
    <input type="text" id="txtMsg" name="msg" value="Hello world!!!" /><br />
    <br />
    <label for="txtSub">Target substring to find:</label><br />
    <input type="text" id="txtSub" name="sub" value="l" /><br />
    <br />
    <label for="txtSub">Starting index:</label><br />
    <input type="text" id="txtStart" name="start" value="3" /><br />
    <br />
    <input type="submit" value="Display All Indices Of Target" />
  </form>
  
  <div id="divIndices"></div>
  <script type="text/JavaScript">
    function showIndices(form) {
      var str = form.msg.value;
      var sub = form.sub.value;
      var start = form.start.value;
      var index, iter = str.indexOfIter(sub, start);
      document.getElementById("divIndices").innerHTML = "";
      while((index = iter.next()) != -1) {
        document.getElementById("divIndices").innerHTML += "index = " + index + "<br />";
      }
      document.getElementById("divIndices").innerHTML += 'No more instances of lowercase "L" in the string.';
    }
    
    showIndices(document.getElementById("aForm"));
  </script>
  
  <p>FYI, the code used to define the <code>indexOfIter</code> function is as follows:<br />
  <textarea rows=7 cols=80>String.prototype.indexOfIter = function(target, start) {
  var targetLen = target.length;
  while(true) {
    start = ((index = this.indexOf(target, start)) + targetLen) * (index &gt;= 0);
    yield index;
  }
};</textarea></p>
    
    <p class="notice">This example was written by <a href="http://gotochriswest.com/blog" target="_blank">Chris West</a>.</p>
</body>
</html>

2 Comments

Grant Husbands · December 7, 2011 at 10:53 AM

A couple of things that would improve the code: indexOf accepts a second parameter that’s the starting index. If you make the generator exit, rather than yield -1, at the end, then it could be used with for..in.

Also, string.replace can do something similar, like so:
“abcabc”.replace(/a/g, function($0, pos){alert(pos);})

    Chris West · December 8, 2011 at 3:51 PM

    Thanks for the suggestion and reminder. I can’t believe I overlooked the second parameter for indexOf. I have since updated the code for this indexOfIter function and have posted the code to JSBin at http://jsbin.com/indexOfIter-example/. As for returning -1, I am still doing that because I want to mimic the native indexOf function.

Leave a Reply

Your email address will not be published. Required fields are marked *