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-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org
http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs
Steve Longdo
2006-Mar-18 21:11 UTC
Re: Autocompleter.Local problem/desparate plea for help...
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
<steve.longdo-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:>
> I have been trying to write a selector function for Autocompleter.Localthat
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-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org
http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs