Share via


Positioning an autocompleteextender list in relation to its target control

Question

Thursday, April 24, 2008 6:38 AM

I'm having trouble getting the completion list for an AutoCompleteExtender to position below the textbox that is its target control.

In my own particular scenario, my targetcontrol is a textbox in a bound DataRepeater.  On the ItemBound of the repeater, I set the TargetcontrolID correctly by using the textbox's UniqueID, but the dropdown still appears a few inches above the DataRepeater grid.  Other AutoCompleteExtenders on the same page that are not part of the DataRepeater are appearing correctly.  I've tried adding some code to the OnClientShowing property as follows :-

  

function resetPosition(textbox, panel)
    {
        var tbposition = $common.getLocation($get(textbox));
        var xposition = tbposition.x;
        var yposition = tbposition.y + 3;
        var ex = $get(panel)
        if (ex)
        {
            $common.setLocation(ex, new Sys.UI.Point(xposition, yposition));
        }
    }

 But I get the old javascript "Object doesn't support this propery or method" error.

 

Anyone had any success with something like this?

All replies (6)

Friday, May 23, 2008 6:38 AM âś…Answered

Through a combination of brute force and search engines, I've fixed the problem.  The resetPosition javascript now calls out to another method that gets the *real* coordinates, by factoring in the scroll offset.  Example as follows :-

function resetPosition(object, args)
{   var tb = object._element;   var tbposition = findPositionWithScrolling(tb);
      var xposition = tbposition[0];  var yposition = tbposition[1] + 25;   // 25 = textbox height + a few pixels spacing

   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 ];
}

Thursday, April 24, 2008 10:09 AM

quick update - the completion list appears consistently in the right place when using Firefox.  Yet another IE6 rendering issue *sigh*

 I imagine this would be fixable with CSS styling on the completion list element - anyone able to give me some pointers?  Here's the CSS I have so far :-

 

 

        .autocomplete_completionListElement 
        {  
            visibility : hidden;
            margin : 0px 0px 0px 0px!important;
            background-color : #FFFFFF;
            color : windowtext;
            border : buttonshadow;
            border-width : 1px;
            border-style : solid;
            cursor : 'default';
            overflow : auto;
            height : 200px;
            text-align : left; 
            list-style-type : none;           
        }

        /* AutoComplete highlighted item */

        .autocomplete_highlightedListItem
        {
            background-color: #ffff99;
            color: black;
            padding: 1px;
        }

        /* AutoComplete item */

        .autocomplete_listItem 
        {
            background-color : window;
            color : windowtext;
            padding : 1px;
        }

 


Wednesday, April 30, 2008 2:04 AM

Hi RobCowell,

I have gone through your code carefully and it seems ok.  Did you send the right TextBox and Panel(should be the client real ID, you can find it in its generated HTML code) to your function.   If you added your AutoCompleteExtender inside a Data Control. You'd better make it like this.

<ajaxToolkit:AutoCompleteExtender runat="server" BehaviorID="AutoCompleteEx" ID="autoComplete1"
        TargetControlID="myTextBox" ServicePath="~/WebService/AutoComplete.asmx" ServiceMethod="GetCompletionList"
        MinimumPrefixLength="1" CompletionInterval="1000" EnableCaching="true" CompletionSetCount="20"
        CompletionListCssClass="autocomplete_completionListElement" CompletionListItemCssClass="autocomplete_listItem"
        CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem" DelimiterCharacters=";, :" OnClientShown="resetPosition">

function resetPosition(sender, args){

**      //sender is the **AutoCompleteExtender instance,  you shall get the TextBox and Panel by using its exposed functions.

}

Actually,  AutoCompleteExtender should position well unless there's something special with your page css. We suggest that you'd better use a an exclusive method to find out the reason.  Also, please check your DocType. For example,

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Best regards,

Jonathan


Friday, May 23, 2008 5:59 AM

It seems like the problem is that the position that the AutoCompleteExtender renders in relation to the target control doesn't take into account the scroll position on the page - or at least it doesn't when used in the context of the DataRepeater.

 I think the panel needs to be even smarter about figuring out where it needs to be, but I'm not sure how to go about making it so.


Thursday, December 4, 2008 12:30 PM

I modified Rob's code to work with my fixed-header equipped GridView (with AJAX UpdatePanel). This works with IE7 on .NET 3.5 (I don't require a FireFox solution, fortunately). My GridView is in two divs, one of which has special CSS on it to ensure the header always floats to the top of the scrolling grid.

<div ID="divPositionGrid" align="center"

style="visibility:hidden;overflow:hidden;vertical-align:top;position: relative; left: -12px; top: 342px;">

<div class="container" ID="divGrid"

style="overflow:auto;vertical-align:top">

<cc1:DragDropGridView ID="SpecialGridView" runat="server" BackColor="White"

EditItemTemplate >

<EditItemTemplate>

<asp:TextBox ID="Individual" style="text-align:right" AutoCompleteType="None" MaxLength="100" onfocus="this.select()"

runat="server" Text='<%# Bind("Individual") %>'></asp:TextBox>

<cc2:AutoCompleteExtender ID="individualAutoCompleteExtender" runat="server"

MinimumPrefixLength="1" FirstRowSelected="true"

OnClientShown="resetPosition"

ServiceMethod="getCustomers" ServicePath="WebService.asmx"

CompletionSetCount="12" CompletionListCssClass="autoComplete"

TargetControlID="Individual">

</cc2:AutoCompleteExtender>

</EditItemTemplate>

 

Javascript >

// resetPosition -

// This is called from the AutoCompleteExtender's OnClientShown property.

// The first parameter is automatically passed as the AutoCompleteExtender

// control object. From there, the textbox client ID is available (which

// is absolutely necessary for the grid).

function resetPosition(object, args)

{

var tb = object._element; // tb.id is the associated textbox ID in the grid.

// Get the position with scrolling.

var tbposition = [tb.offsetLeft + tb.offsetParent.offsetLeft, tb.offsetTop + tb.offsetParent.offsetTop];

var xposition = tbposition[0] - 40; // -40 lined it up horizontally with the textbox in my circumstance

var yposition = tbposition[1] + 22; // 22 = textbox height + no spacing

var ex = object._completionListElement;

if (ex)

$common.setLocation(ex, new Sys.UI.Point(xposition, yposition));

} // End resetPosition

CSS for AutoCompleteExtender >

.autoComplete

{

width:auto;height:250px;

}

 

L8r,

Jage

"I give God all the glory in every small thing I do."


Wednesday, February 1, 2012 11:12 PM

Thanks for the concise code. Good job Rob!