Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 15 of 15
  1. #1
    New Coder
    Join Date
    Oct 2011
    Posts
    77
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Need assistance modifiying predictive text.

    Hi guys,

    I'm hoping to get some assistance. I've found below predictive text for my search function. Currently is works fine but I want to sleightly change it but having troubles.

    1. Currently, when you search say '1', it will find all results with '1' in it. However I want it to only show what word starts with the '1' and go from each letter typed into the form.

    IE: "SE"
    REsult - "SEARCH"
    NOT: "SEARCH" & "STREET" type thing.

    2. When I currently search, it always places a space after the final letter typed.

    IE: "SE ARCH" - I do not want this to occur.

    3. I want to have a maxmium of 7 days results shown at once as the list will be very large.

    Any assistance would be greatly appreciated.

    Code:
    <script type="text/javascript">
    (
      function()
      {
    
          var lookFor = [
                "1",
                "11",
                "112",
                "22",
                "221"
          ];
    
          var form = document.getElementById("buyresults");
          var resultsDiv = document.getElementById("predict");
          var searchField = form.search;
    
          // first, position the results:
          var node = searchField;
          var x = 0;
          var y = 0;
          while ( node != null )
          {
              x += node.offsetLeft;
              y += node.offsetTop;
              node = node.offsetParent;
          }
          predictDiv.style.left = (x - 152) + "px";
          predictDiv.style.top  = (y - 203) + "px";
          
          // now, attach the keyup handler to the search field:
          searchField.onkeyup = function()
          {
              var txt = this.value.toLowerCase();
              if ( txt.length == 0 ) return;
    
              var txtRE = new RegExp( "(" + txt + ")", "ig" );
              // now...do we have any matches?
              var top = 0;
              for ( var s = 0; s < lookFor.length; ++s )
              {
                  var srch = lookFor[s];
                  if ( srch.toLowerCase().indexOf(txt) >= 0 )
                  {
                      srch = srch.replace( txtRE, "<span>$1</span>" );
                      var div = document.createElement("div");
                      div.innerHTML = srch;
                      div.onclick = function() {
                          searchField.value = this.innerHTML.replace(/\<\/?span\>/ig,"");
                          predictDiv.style.display = "none";
                      };
                      div.style.top = top + "px";
                      top += 20;
                      predictDiv.appendChild(div);
                      predictDiv.style.display = "block";
                  }
              }
          }
          // and the keydown handler:
          searchField.onkeydown = function() 
          {
              while ( resultsDiv.firstChild != null )
              {
                  resultsDiv.removeChild( resultsDiv.firstChild );          
              }
              resultsDiv.style.display = "none";
          }
         
      }
    )();
    </script>

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    Well, the "only starts with..." part is easy:
    Code:
            var txtRE = new RegExp( "^(" + txt + ")", "ig" );
    The ^ means "starts with..."

    But I don't know why you get the space in there.

    Hmmm...
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #3
    New Coder
    Join Date
    Oct 2011
    Posts
    77
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by Old Pedant View Post
    Well, the "only starts with..." part is easy:
    Code:
            var txtRE = new RegExp( "^(" + txt + ")", "ig" );
    The ^ means "starts with..."

    But I don't know why you get the space in there.

    Hmmm...
    I changed this in the code however it also shows a previous 'suggestion' along with the letter search.

    IE:
    Code:
    var lookFor = [
                "1",
                "2",
                "3",
                "4",
                "5"
          ];
    Search '5'
    Result: '4'
    '5'

    But still getting a space!!!! Could this be CSS/HTML related?
    Last edited by rexhvn; 02-05-2013 at 09:12 AM.

  • #4
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    Can you show the HTML you are using and the CSS? To go with the JavaScript?

    Best: Show us a live URL.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #5
    New Coder
    Join Date
    Oct 2011
    Posts
    77
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by Old Pedant View Post
    Can you show the HTML you are using and the CSS? To go with the JavaScript?

    Best: Show us a live URL.
    The website itself is not live etc... but I will get some code up soon.


    Bascially to give an idea, i'm using a toggle that shows the search function then the javascript showing suggestions. So the <div> is revealed prior which may have an affect because when I used the this code on on it's own, it works fine.

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    Never mind. I built a page of my own.

    You had several small mistakes. And several pieces of unneeded code.

    Try the below full page of code.

    Try entering "n", then "no", then "not", then "noti". See the limit of 7 results, too?

    Code:
    <html>
    <head>
    <style type="text/css">
    #predict {
        position: absolute;
        display: none;
        border: solid red 3px;
    }
    #predict div {
        cursor: pointer;
        border-bottom: solid black 1px;
    }
    </style>
    <body>
    <div id="predict"></div>
    <form id="buyresults">
    search: <input name="search"/>
    </form>
    
    <script type="text/javascript">
    (
      function()
      {
    
          var lookFor = [
                "an", "and", "andiron", "andover", "andy",
                "no", "not", "note", "notable", "nothing", "notice", "noticable", "noticing", "notification", "notify", "notifying"
          ];
    
          var form = document.getElementById("buyresults");
          var predictDiv = document.getElementById("predict");
          var searchField = form.search;
    
          // first, position the results:
          var node = searchField;
          var x = 0;
          var y = 0;
          while ( node != null )
          {
              x += node.offsetLeft;
              y += node.offsetTop;
              node = node.offsetParent;
          }
          predictDiv.style.left = x + "px";
          predictDiv.style.top  = (y + 20) + "px";
          
          // now, attach the keyup handler to the search field:
          searchField.onkeyup = function()
          {
              var txt = this.value; 
              if ( txt.length == 0 ) return;
    
              var txtRE = new RegExp( "(^" + txt + ")", "i" );
              // now...do we have any matches?
              var cnt = 0;
              for ( var s = 0; s < lookFor.length; ++s )
              {
                  var srch = lookFor[s];
                  if ( txtRE.test(srch) ) 
                  {
                      var div = document.createElement("div");
                      div.innerHTML = srch.replace( txtRE, "$1" );
                      div.onclick = choose;
                      predictDiv.appendChild(div);
                      predictDiv.style.display = "block";
                      if ( ++cnt >= 7 ) return; // max of 7 results displayed
                  }
              }
          }
          function choose( )
          {
              searchField.value = this.innerHTML; 
              predictDiv.style.display = "none";
              searchField.focus();
          };
    
          // and the keydown handler:
          searchField.onkeydown = function() 
          {
              while ( predictDiv.firstChild != null )
              {
                  predictDiv.removeChild( predictDiv.firstChild );          
              }
              predictDiv.style.display = "none";
          }
         
      }
    )();
    </script>
    </body>
    </html>
    I have no idea why you had that <span> in there inside the inner <div>s. It was adding nothing useful that I could see. Nor could I see why you were using top and applying it to the inner <div>s. No need for that, either, it would seem. And no need to convert to lower case; that's what the "i" in the RegExp is for. Finally, it was a HUGE mistake to use "ig" instead of just "i". It meant that you would not pick up some "lookfor" values that you want to pick up.

    (If you *want* to find those "lookfor" values any place in the typed-so-far text, then we have to make some MAJOR changes to the code.)
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #7
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    One flaw in all this: If the user types, say "NOT" and then clicks on "notable", he indeed *gets* "notable", instead of "NOTable". Clearly the code should at least preserve the case of the first character typed in, no? Or do you care?

    It's not hard to fix.

    In my "choose" function, replace the first line with this:
    Code:
             searchField.value += this.innerHTML.substring(searchField.value.length);
    But that pointed up another flaw to me!

    If I hold down the SHIFT key, type in "NOT", and then release the SHIFT key to use the mouse to select (example) "notable", I get the list of 7 choices *REPEATED*.

    That's because the onkeyup was triggered by the SHIFT key being release but there was no corresponding onkeydown.

    The obvious answer is to remove the onkeydown event handler and move the clearing of predictdiv to the beginning of onkeyup. It makes no noticeable difference in how it all works except to clean up the SHIFT bug.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #8
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    Here, both modifications (and a spelling error--mine--corrected):
    Code:
    <html>
    <head>
    <style type="text/css">
    #predict {
        position: absolute;
        display: none;
        border: solid red 3px;
    }
    #predict div {
        cursor: pointer;
        border-bottom: solid black 1px;
    }
    </style>
    <body>
    <div id="predict"></div>
    <form id="buyresults">
    search: <input name="search"/>
    </form>
    
    <script type="text/javascript">
    (
      function()
      {
    
          var lookFor = [
                "an", "and", "andiron", "andover", "andy",
                "no", "not", "notable", "note", "nothing", "notice", "noticeable", "noticing", "notification", "notify", "notifying"
          ];
    
          var form = document.getElementById("buyresults");
          var predictDiv = document.getElementById("predict");
          var searchField = form.search;
    
          // first, position the results:
          var node = searchField;
          var x = 0;
          var y = 0;
          while ( node != null )
          {
              x += node.offsetLeft;
              y += node.offsetTop;
              node = node.offsetParent;
          }
          predictDiv.style.left = x + "px";
          predictDiv.style.top  = (y + 20) + "px";
          
          // now, attach the keyup handler to the search field:
          searchField.onkeyup = function()
          {
              while ( predictDiv.firstChild != null )
              {
                  predictDiv.removeChild( predictDiv.firstChild );          
              }
              predictDiv.style.display = "none";
    
              var txt = this.value; 
              if ( txt.length == 0 ) return;
    
              var txtRE = new RegExp( "(^" + txt + ")", "i" );
              // now...do we have any matches?
              var cnt = 0;
              for ( var s = 0; s < lookFor.length; ++s )
              {
                  var srch = lookFor[s];
                  if ( txtRE.test(srch) ) 
                  {
                      var div = document.createElement("div");
                      div.innerHTML = srch.replace( txtRE, "$1" );
                      div.onclick = choose;
                      predictDiv.appendChild(div);
                      predictDiv.style.display = "block";
                      if ( ++cnt >= 7 ) return; // max of 7 results displayed
                  }
              }
          }
          function choose( )
          {
              searchField.value += this.innerHTML.substring(searchField.value.length); 
              predictDiv.style.display = "none";
              searchField.focus();
          };
    
      }
    )();
    </script>
    </body>
    </html>
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #9
    New Coder
    Join Date
    Oct 2011
    Posts
    77
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Much better thank you! You really know your stuff!!!

    Is there anyway I can select a 'suggestion' (predictDiv) by using the down Arrow on the keyboard instead of always using the mouse?

  • #10
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    Quote Originally Posted by rexhvn View Post
    Is there anyway I can select a 'suggestion' (predictDiv) by using the down Arrow on the keyboard instead of always using the mouse?
    Yes, but it's a bit more coding. You have to be sure there really is some available predictive text, for example.

    Is it important? (I guess the answer is "probably.")
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #11
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    Try this out. Works in CHROME. Untested in other browsers. The big problem is that <form> field autocomplete must be disabled or you can not use the down and up arrows. You can see i have done so for <form> and the <input> field. I *THINK* that is enough for all browsers, but you need to verify.
    Code:
    <html>
    <head>
    <style type="text/css">
    #predict {
        position: absolute;
        display: none;
        border: solid red 3px;
    }
    #predict div {
        cursor: pointer;
        border-bottom: solid black 1px;
    }
    </style>
    <body>
    <div id="predict"></div>
    <form id="buyresults" autocomplete="off">
    search: <input name="search" autocomplete="off" />
    </form>
    
    <script type="text/javascript">
    (
      function()
      {
    
          var lookFor = [
                "an", "and", "andiron", "andover", "andy",
                "no", "not", "notable", "note", "nothing", "notice", "noticeable", "noticing", "notification", "notify", "notifying"
          ];
    
          var form = document.getElementById("buyresults");
          var predictDiv = document.getElementById("predict");
          var searchField = form.search;
          var curLine = -1;
          var curText = searchField.value;
    
          // first, position the results:
          var node = searchField;
          var x = 0;
          var y = 0;
          while ( node != null )
          {
              x += node.offsetLeft;
              y += node.offsetTop;
              node = node.offsetParent;
          }
          predictDiv.style.left = x + "px";
          predictDiv.style.top  = (y + 20) + "px";
          
          // now, attach the keyup handler to the search field:
          searchField.onkeyup = function(evt)
          {
              if ( evt == null ) evt = window.event;
              if ( evt.keyCode == 40 || evt.keyCode == 38 ) { return false; }
    
              while ( predictDiv.firstChild != null )
              {
                  predictDiv.removeChild( predictDiv.firstChild );          
              }
              predictDiv.style.display = "none";
              curLine = -1;
    
              curText = this.value; 
              if ( curText.length == 0 ) return;
    
              var txtRE = new RegExp( "(^" + curText + ")", "i" );
              // now...do we have any matches?
              var cnt = 0;
              for ( var s = 0; s < lookFor.length; ++s )
              {
                  var srch = lookFor[s];
                  if ( txtRE.test(srch) ) 
                  {
                      var div = document.createElement("div");
                      div.innerHTML = srch.replace( txtRE, "$1" );
                      div.onclick = choose;
                      predictDiv.appendChild(div);
                      predictDiv.style.display = "block";
                      if ( ++cnt >= 7 ) return; // max of 7 results displayed
                  }
              }
          }
          searchField.onkeydown = function(evt)
          {
              if ( evt == null ) evt = window.event;
              if ( evt.keyCode == 40 || evt.keyCode == 38 )
              {
                   var divs = predictDiv.getElementsByTagName("div");
                   for ( var d = 0; divs !=null && d < divs.length; ++d )
                   {
                       divs[d].style.backgroundColor = "transparent";
                   }
                   curLine += ( evt.keyCode - 39 );
                   if ( curLine < 0 || divs == null || divs.length == 0 ) 
                   { 
                       this.value = curText;
                       curLine = -1; 
                       return false; 
                   }
                   if ( curLine >= divs.length ) { curLine = divs.length - 1; }
                   var div = divs[curLine];
                   div.style.backgroundColor = "#dddddd";
                   this.value = div.innerHTML;               
                   return false;
              }
          }
          function choose( )
          {
              searchField.value += this.innerHTML.substring(searchField.value.length); 
              predictDiv.style.display = "none";
              searchField.focus();
          };
    
      }
    )();
    </script>
    </body>
    </html>
    Last edited by Old Pedant; 02-07-2013 at 10:06 PM.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #12
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    Here's a cute trick, kind of an accidental happy effect:

    Type in "n".
    Then use the down arrow to select "not".
    Then click on the RIGHT ARROW.

    Isn't that great! And then type the letter "i".

    If your "prediction" words are alphabetical (as I made mine) you could go through quite long lists of words with few keystrokes, even with the limit of 7 showing as it is now.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #13
    New Coder
    Join Date
    Oct 2011
    Posts
    77
    Thanks
    1
    Thanked 0 Times in 0 Posts
    I already have 'autocomplete="off"' - is there a reason why the results when selected by the mouse (onclick) the result will then appear in the searchField, however when selected by the arrow (using return on keyboard) it doesn't?

    Thank you for all your assistance!!! It is much appreciated.
    Last edited by rexhvn; 02-08-2013 at 04:01 AM.

  • #14
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    ??? I only tested this in Chrome. It worked as I described there.

    Let me try it in MSIE 9 and FF.

    Works correctly in FF.
    Works correctly in MSIE 9.

    What browser are you using that it doesn't work in?

    OH! Wait! You said "using return on keyboard"!!! You can *NOT* do that!

    The ENTER key is treated as a <form> submit!

    The focus in this thing NEVER leaves the <input> field when you use the up and down arrow keys! It may *look* like it does, but it doesn't. So with the focus still on the <input> field, hitting ENTER acts as a submit of the <form>.

    To accept the choice made by the arrow keys, you can do any of the following:
    -- type another regular key.
    (Example: Type "n". Use the up and down arrow keys to select "nothing". Type SPACE, I, S, SPACE, S, I, M, P, L, E)
    -- type the right arrow key. That accepts the choice and, if the choice starts other choices, shows those other choices..
    (Example: Type "n". Use the up and down arrow keys to select "not". Type the right arrow key. Look at the new selections.)
    -- type the TAB key.
    (Need to add another field to the <form> I show to see this. Type "n", use up and down arrow keys to choose any word, hit the TAB key. The cursor moves to the next <form> field.)

    If you WANT to SUPPRESS the ENTER key, then we have to write code to do so.

    But that would be true in any case, if you did not want the ENTER key to force a submit of the <form>.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #15
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    26,719
    Thanks
    80
    Thanked 4,514 Times in 4,478 Posts
    Hmmm...just played with the TAB key. Okay, need to add to the onkeydown handler to have it accept the word and clear the list on TAB.

    And could easily do the same with ENTER and then in onkeyup just ignore it.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •