I've cleaned this up a bit, but it is still not perfect.  Posting this incase a JS guru stops by and wants to show me how it could be refactored to be more...script.aculo.us or prototyp-ical :-)

  new Autocompleter.Local ('article_keywords','auto_complete', opts
  , { tokens: new Array(' ',',','\n'), 
/* start selector */
selector: function(instance) {
  var ret       = []; // Beginning matches
  var entry     = instance.getToken ();
  var firstMatch= -1;
  for (var i = 0; i < instance.options.array.length; i++) {
    var wasMatch = false;
    var elem = instance.options.array[i];
    var foundPos = instance.options.ignoreCase ?
      elem.toLowerCase().indexOf(entry.toLowerCase()) : elem.indexOf(entry);
   
    while (foundPos != -1) {
      if (foundPos == 0 && elem.length != entry.length) {
        wasMatch = true;
        if (firstMatch < 0){
          firstMatch=i;
          this.index=i;
          ret.push("<li class=\"selected\"><strong>" + elem.substr(0, entry.length) + "</strong>" +
              elem.substr(entry.length) + "</li>");
        } else {
            ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
              elem.substr(entry.length) + "</li>");
        }
        break;
      }     

      foundPos = instance.options.ignoreCase ?
        elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
        elem.indexOf(entry, foundPos + 1);
    }
    if(wasMatch==false){
        ret.push("<li>" + elem + "</li>");
    }
  }
  instance.options.picked=firstMatch;
  return "<ul>" + ret.join('') + "</ul>";
}
//end
});
Autocompleter.Local.prototype.render = function() {
    if(this.entryCount > 0) {
      //This bit is necessary to make the up/down keys work can't remove...
      for (var i = 0; i < this.entryCount; i++)
        this.index==i ?
          Element.addClassName(this.getEntry(i),"selected") :
          Element.removeClassName(this.getEntry(i),"selected");
       
      if(this.hasFocus) {
        this.show();
        this.active = true;
        //A bit wonky calculation here, couldn't find a way to get the offsetHeight of the LI
        //inside of the updated DIV because it is absolutely positioned? so I picked the below
        //I should be able to do it with font size (em to pixels anyone?)
        this.update.scrollTop=(this.options.picked * 25) + 10;
      } else {
          this.active = false;
          this.hide();
      }
    }
  };
 
Thanks again for any help,
-Steve
http://www.stevelongdo.com
On 3/17/06, Steve Longdo <[EMAIL PROTECTED]> wrote:
I have been trying to write a selector function for Autocompleter.Local that will show a predefined Array and will scroll automatically to the first match.  I have had success with with getting my list to populate and show all of the choices, however I cannot get it to scroll to the first match. 

Since I build the JS Array I can know exactly how many items are in the list going into my selector, but I don't ever know the offset for a single <li> to be able to set the scrolling height.

I am fairly certain that the onShow method is not the place to try to do it, but I haven't had any success with any of the methods that I have tried to override either. 

Any solutions/insights are welcome!

Here is my work in progress:
<style>
          #auto_complete {
            width: 355px;
            height: 150px;
            background: #fff;
            overflow: auto;
          }
          #auto_complete ul {
            border: 1px solid #888;
            margin:0;
            padding:0;
            width: 98%;
            list-style-type:none;
          }
          #auto_complete ul li {
            margin:0;
            padding:0;
          }
          #auto_complete ul li.selected {
            background-color: #ffb;
          }
          #auto_complete ul strong.highlight {
            color: #800;
            margin:0;
            padding:0;
          }
</style> 
<div id="auto_complete" style="display: none;"></div>
<script type="text/_javascript_" language="_javascript_" charset="utf-8">
  opts = new Array(<%= @tags.sort_by{|t| t.display_name}.collect!{|t1| '"' + t1.display_name + '",'} -%>'');
// <![CDATA[ 
  box = new Autocompleter.Local('article_keywords','auto_complete', opts
  , { tokens: new Array(' ',',','\n'), 
/* start selector */
selector: function(instance) {
  var ret       = []; // Beginning matches
  var entry     = instance.getToken ();
  var firstMatch= -1;
  for (var i = 0; i < instance.options.array.length; i++) {
    var wasMatch = false;
    var elem = instance.options.array[i];
    var foundPos = instance.options.ignoreCase ?
      elem.toLowerCase().indexOf(entry.toLowerCase()) : elem.indexOf(entry);
   
    while (foundPos != -1) {
      if (foundPos == 0 && elem.length != entry.length) {
        wasMatch = true;
        if (firstMatch < 0){
          firstMatch=i;
      }
          ret.push("<li class=\"selected\"><strong>" + elem.substr(0, entry.length) + "</strong>" +
              elem.substr(entry.length) + "</li>");
        break;
      }

      foundPos = instance.options.ignoreCase ?
        elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
        elem.indexOf(entry, foundPos + 1);
    }
    if(wasMatch==false){
        ret.push("<li>" + elem + "</li>");
    }
  }
  instance.options.picked=firstMatch;
  instance.index=firstMatch;
  return "<ul>" + ret.join('') + "</ul>";
}
//end
});

// ]]>
</script>

I did try to make a function that would scroll outside of the Autocompleter, but it doesn't work based on the fact the auto_complete <div> may not be showing yet:

function scrollme(box) {
    var topItem = Position.cumulativeOffset(box.getEntry(0));
    var selItem = Position.cumulativeOffset(box.getEntry (box.index)); 
    box.update.scrollTop=selItem[1]-(topItem[1]+15);
}
scrollme(box);


Please help me!!!

Thanks,
-Steve



_______________________________________________
Rails-spinoffs mailing list
Rails-spinoffs@lists.rubyonrails.org
http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs

Reply via email to