Search code examples
asp.netwebkitajaxcontroltoolkit

AutoCompleteExtender has wrong position, for webkit browsers, after scrolling down the page


I have an AutoCompleteExtender on my page which works fine but when I scroll down the page and use it, suggestions show up at wrong (vertical) position.
It happens with Safari & Chrome but not with IE &FF and so I thought it could be webkit's fault.
Heres the code:

<td>
      <div style="position: relative;">
           <asp:TextBox ID="DepartureAirportTextBox" runat="server" CssClass="DepartureAirport airport-textbox"
                            onblur="javascript:DepartureLostFocus();" onkeydown="javascript:DepartureChanged(event);"></asp:TextBox>
            <asp:Panel ID="DepartureAutocompleteDropDownPanel" runat="server" ScrollBars="Vertical"
                            CssClass="autocomplete-panel" Style="display: none;" />
            <AjaxControlToolkit:AutoCompleteExtender ID="DepartureAirportAutoComplete" runat="server"
                            TargetControlID="DepartureAirportTextBox" CompletionSetCount="200" ServicePath="../WebServices/SecureService.asmx"
                            ServiceMethod="ListAirports" MinimumPrefixLength="3" BehaviorID="DepartureAirport"
                            CompletionListElementID="DepartureAutocompleteDropDownPanel" OnClientItemSelected="SelectDepartureAirport"
                            OnClientPopulating="ShowDepartureIcon" OnClientPopulated="HideDepartureIcon">
           </AjaxControlToolkit:AutoCompleteExtender>               
     </div>
</td>

I have tried this & this solutions on SO, but none worked.
How to fix it?

Update:
Even the simplest example from Microsoft has this problem. Add some <p> elements before and after the textbox & extender to create scrollable area and test it.

<asp:TextBox ID="txtMovie" runat="server"></asp:TextBox>
        <AjaxControlToolkit:AutoCompleteExtender ID="AutoCompleteExtender1" TargetControlID="txtMovie"
            runat="server" UseContextKey="True" MinimumPrefixLength="2" ServiceMethod="GetCompletionList" />

Get code for GetCompletionList from above link. This issue is so easily reproducible.


Solution

  • I found a solution on Asp.net forums.

    function resetPosition(object, args) {
        var tb = object._element;
        var tbposition = findPositionWithScrolling(tb);
        var xposition = tbposition[0];
        var yposition = tbposition[1] + 20; // 22 textbox height 
        var ex = object._completionListElement;
        if (ex)
            $common.setLocation(ex, new Sys.UI.Point(xposition, yposition));
    }
    function findPositionWithScrolling(oElement) {
        if (typeof (oElement.offsetParent) != 'undefined') {
            var originalElement = oElement;
            for (var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent) {
                posX += oElement.offsetLeft;
                posY += oElement.offsetTop;
                if (oElement != originalElement && oElement != document.body && oElement != document.documentElement) {
                    posX -= oElement.scrollLeft;
                    posY -= oElement.scrollTop;
                }
            }
            return [posX, posY];
        } else {
            return [oElement.x, oElement.y];
        }
    }
    

    Call resetPosition on Extender's OnClientShown event