When you use overflow:auto in your css in conjunction with Scriptaculous’ Autocomplete, there is a bug that makes the entire page jump around when you use the arrow keys on your keyboard to navigate up and down through the suggestion list. This bug normally appears only when the page itself is long enough to require a scroll bar.
I managed to come up with a very clean working solution by hacking the controls.js file that comes with scriptaculous. The solutions requires replacing the markPrevious and markNext functions and adding a small line of code to the updateChoices function.
Currently, markPrevious and markNext are telling the page to jump around like that, and I’m not sure why! As far as I can tell (please let me know otherwise) this solution could be included in the scriptaculous without breaking a thing (hint, hint to the scriptaculous team).
To implement the solution, replace:
markPrevious: function() {
if(this.index > 0) this.index--;
else this.index = this.entryCount-1;
this.getEntry(this.index).scrollIntoView(true);
},
markNext: function() {
if(this.index < this.entryCount-1) this.index++;
else this.index = 0;
this.getEntry(this.index).scrollIntoView(false);
}, |
markPrevious: function() {
if(this.index > 0) this.index--;
else this.index = this.entryCount-1;
this.getEntry(this.index).scrollIntoView(true);
},
markNext: function() {
if(this.index < this.entryCount-1) this.index++;
else this.index = 0;
this.getEntry(this.index).scrollIntoView(false);
},
With:
markPrevious: function() {
if(this.index > 0) {this.index--;}
else {
this.index = this.entryCount-1;
this.update.scrollTop = this.update.scrollHeight;
}
selection = this.getEntry(this.index);
selection_top = selection.offsetTop;
if(selection_top < this.update.scrollTop){
this.update.scrollTop = this.update.scrollTop-selection.offsetHeight;
}
},
markNext: function() {
if(this.index < this.entryCount-1) {this.index++;}
else {
this.index = 0;
this.update.scrollTop = 0;
}
selection = this.getEntry(this.index);
selection_bottom = selection.offsetTop+selection.offsetHeight;
if(selection_bottom > this.update.scrollTop+this.update.offsetHeight){
this.update.scrollTop = this.update.scrollTop+selection.offsetHeight;
}
}, |
markPrevious: function() {
if(this.index > 0) {this.index--;}
else {
this.index = this.entryCount-1;
this.update.scrollTop = this.update.scrollHeight;
}
selection = this.getEntry(this.index);
selection_top = selection.offsetTop;
if(selection_top < this.update.scrollTop){
this.update.scrollTop = this.update.scrollTop-selection.offsetHeight;
}
},
markNext: function() {
if(this.index < this.entryCount-1) {this.index++;}
else {
this.index = 0;
this.update.scrollTop = 0;
}
selection = this.getEntry(this.index);
selection_bottom = selection.offsetTop+selection.offsetHeight;
if(selection_bottom > this.update.scrollTop+this.update.offsetHeight){
this.update.scrollTop = this.update.scrollTop+selection.offsetHeight;
}
},
Now find the updateChoices function and just after the code this.stopIndicator(); add this.update.scrollTop = 0; so that it looks like this:
this.stopIndicator();
this.update.scrollTop = 0;
this.index = 0; |
this.stopIndicator();
this.update.scrollTop = 0;
this.index = 0;
I’ve tested in FF 2.0.0.4, FF 3.0.5, Chrome 1.0.154.43, Safari 3.2.1, Opera 9.5.1, IE 7.0.5730.13 and IE 6.0.2600 without problems.