Custom AutoCompleteExtender with multiple word suggestions
Visite: 23400
sabato 14 ottobre 2006



CustomAutoCompleteExtender class C#
By default, the AutoCompleteExtender shows results from the entire value of one text box. With my implementation, it is possible to search more than one word inside a text box divided by comma (or another character). Every time a comma is written, the list of suggestions appears for the new word.

At the moment, AutoCompleteExtender doesn’t support the style for the popup list. We’ll implement these properties during the modifications for multiple suggestions.

Inherit the AutoCompleteProperties

The first step is to create C# classes for the new control CustomAutoCompleteExtender. We want to declare a class called CustomAutoCompleteProperties that inherits from AutoCompleteProperties and adds the support for the “multiple word suggestions” and CSS styles properties. For “multiple word suggestions”, we need one property: SeparatorChar. With this property, we are able to divide word-to-word and open the suggestions’ list for the new word written.

namespace CustomAtlas.Controls
{
    public class CustomAutoCompleteProperties : AutoCompleteProperties
    {
        public string SeparatorChar
        {
            get
            {
                object obj = base.ViewState["SeparatorChar"];
                if (obj != null) return (string)obj;
                else return ",";
            }
            set
            {
                base.ViewState["SeparatorChar"] = value;
                base.OnChanged(EventArgs.Empty);
            }
        }
        public string CssList
        {
            get
            {
                object obj = base.ViewState["CssList"];
                if (obj != null) return (string)obj;
                else return String.Empty;
            }
            set
            {
                base.ViewState["CssList"] = value;
                base.OnChanged(EventArgs.Empty);
            }
        }
        public string CssItem
        {
            get
            {
                object obj = base.ViewState["CssItem"];
                if (obj != null) return (string)obj;
                else return String.Empty;
            }
            set
            {
                base.ViewState["CssItem"] = value;
                base.OnChanged(EventArgs.Empty);
            }
        }
        public string CssHoverItem
        {
            get
            {
                object obj = base.ViewState["CssHoverItem"];
                if (obj != null) return (string)obj;
                else return String.Empty;
            }
            set
            {
                base.ViewState["CssHoverItem"] = value;
                base.OnChanged(EventArgs.Empty);
            }
        }
    }
}
    


The CssList, CssItem, and CssHoverItem are necessary to build the control’s style. CssList provides to draw the list’s box, and CssItem and CssHoverItem  draw every item in the list.

Inherit the AutoCompleteExtender

First step done, we continue with the Extender. In this case, we inherit from the AutoCompleteExtender class and add new properties to the control:

namespace CustomAtlas.Controls
{
    public class CustomAutoCompleteExtender : AutoCompleteExtender
    {
        protected override void RenderScript(
          Microsoft.Web.Script.ScriptTextWriter writer, Control targetControl)
        {
            // get our CustomAutoCompleteProperties
            CustomAutoCompleteProperties cacp = 
                (CustomAutoCompleteProperties)
                 base.GetTargetProperties(targetControl);
            if ((cacp != null) && cacp.Enabled)
            {
                // check if the ServicePath is set
                string _ServicePath = cacp.ServicePath;
                if (_ServicePath == String.Empty)
                {
                    _ServicePath = this.ServicePath;
                }
                if (_ServicePath == String.Empty)
                {
                    throw new InvalidOperationException("The ServicePath " + 
                                  "must be set for AutoCompleteBehavior");
                }
                // check if the ServiceMethod is set
                string _ServiceMethod = cacp.ServiceMethod;
                if (_ServiceMethod == String.Empty)
                {
                    _ServiceMethod = this.ServiceMethod;
                }
                if (_ServiceMethod == String.Empty)
                {
                    throw new InvalidOperationException("The ServiceMethod " + 
                                    "must be set for AutoCompleteBehavior");
                }
                // search for the completion list control if an ID was supplied
                Control c = null;
                string drp = this.DropDownPanelID;
                if (drp != String.Empty)
                {
                    c = this.NamingContainer.FindControl(drp);
                    if (c == null)
                    {
                        throw new InvalidOperationException("The specified " + 
                                       "DropDownPanelID is not a valid ID");
                    }
                }
                // write the Atlas markup on page
                writer.WriteStartElement("autoComplete");
                writer.WriteAttributeString("serviceURL", 
                    base.ResolveClientUrl(_ServicePath));
                writer.WriteAttributeString("serviceMethod", _ServiceMethod);
                if (c != null)
                  writer.WriteAttributeString("completionList", c.ClientID);
                writer.WriteAttributeString("minimumPrefixLength",
                             cacp.MinimumPrefixLength.ToString());
                writer.WriteAttributeString("separatorChar", 
                                        cacp.SeparatorChar);
                writer.WriteAttributeString("cssList", cacp.CssList);
                writer.WriteAttributeString("cssItem", cacp.CssItem);
                writer.WriteAttributeString("cssHoverItem", 
                                        cacp.CssHoverItem);
                writer.WriteEndElement();
            }
        }
    }
}
    

Implementing the custom AutoCompleteBehavior

Now that the control is ready, we have only to manage the client-side code to send the right value to the Web Service (the comma-separated word) and to apply our custom CSS style. Searching for the AutoCompleteBehavior class in the Atlas.js file, we can copy it and register our custom class.

First, we have to add the four properties created in the Extender class. Now, we are able to use the properties’ values of the control placed in the .aspx page container. Searching inside the code, there is a function _onTimerTick used to show the list after a time delay. In this function, we’ll intercept the value to send to the Web Service and change it as we want:

var text = this.control.element.value;
if ( text.lastIndexOf(_separatorChar) > -1 ) 
{
 // found separator char in the text, choosing the right word
 var pos = text.lastIndexOf(_separatorChar);
 pos++;
 text = text.substring(pos, (text.length));
text = text.trim();
}

Now, when the user types a value in the text box, the AutoCompleteBehavior verifies the presence of the separator char. If present, the text sent to the Web Service is the last word found and not the entire value of the text box. Like a standard, I use to save .js code into scriptLibrary folder.

Let’s try it

The situation: AutoCompleteBehavior.js saved into the scriptLibrary folder, CustomAutoCompleteProperties.cs and CustomAutoCompleteExtender.cs saved into the App_Code folder... we are ready to try it. Create a new .aspx file, and add a reference to the CustomAutoCompleteExtender class, and place the controls in the page:

<%@ Page Language="C#" AutoEventWireup="true" 
             CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Namespace="CustomAtlas.Controls" TagPrefix="customAtlas" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
     "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>CustomAutoCompleteExtender</title>
    <link href="StyleSheet.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
        <atlas:ScriptManager ID="scriptManager" runat="server">
            <Scripts>
                <atlas:ScriptReference ScriptName="Custom" />
                <atlas:ScriptReference 
                   Path="scriptLibrary/CustomAutoCompleteBehavior.js" />
            </Scripts>
        </atlas:ScriptManager>
        
        <div>
            <asp:TextBox ID="txtSuggestions" 
                     runat="server"></asp:TextBox>
            <customAtlas:CustomAutoCompleteExtender 
                   ID="CustomAutoCompleteExtender1" runat="server">
                <customAtlas:CustomAutoCompleteProperties
                                 TargetControlID="txtSuggestions"
                                 ServicePath="WebServiceDemo.asmx"
                                 ServiceMethod="GetSuggestions"
                                 MinimumPrefixLength="1"
                                 SeparatorChar=","
                                 CssList="autoCompleteList"
                                 CssItem="autoCompleteItem" 
                                 CssHoverItem="autoCompleteHoverItem"
                                 Enabled="true" />
            </customAtlas:CustomAutoCompleteExtender>       
        </div>
    </form>
</body>
</html>


Call a demo Web Service (returns the same value written 10 times), digit one word, then comma (comma is the default char), and starting with a new word, a list with suggestions for a new item is shown.

Hope this will be helpful.

Download Click here to download the ZIP file about this article

Commenti


Hi, I tried your extender and I really liked it, but now when beta version of ajax is out it's not working especially it's not recognizing RenderScript(Microsoft.Web.Script.ScriptTextWriter writer, Control targetControl) cause there is no more ScriptTextWriter in ajax and I can't find any info how to transform it to work again, any help will be very appreciated. Best regards.
Scritto da dimus - mercoledì 1 novembre 2006 alle ore 16.45

Hi dimus, please try this new version without custom CSS support but with the same functionally of the old CustomAutoCompleteExtender. Take a look also to the NoMinimumPrefix property (boolean value) to call the Webservice when the Textbox has focus and show possible suggestions.

Download the CustomAutoCompleteExtender for ASP.NET AJAX 1.0
Scritto da ZofM - mercoledì 1 novembre 2006 alle ore 17.57

Hi, thanks a lot for reply. Your script is great. BTW NoMinimumPrefix property is nice but it has a bug when you trying to select something every time timer is ticking it's loosing your selection. but apart that script is very good. Best regards and many thanks.
Scritto da dimus - venerdì 3 novembre 2006 alle ore 11.48

Hi Gianni Another Ajax release - Beta 2 & another problem. When trying to use your extender on updated ajax core - beta 2 founding js error:
"Sys.ScriptLoadFailedException: The script '../script/CustomAutoCompleteBehavior.js' could not be loaded or does not contain the Sys.Application.notifyScriptLoaded() callback."
I've searched ajax.asp.net forum & found that with new release they introduced changes to load of file based scripts: 'http://ajax.asp.net/files/AspNet_AJAX_CTP_to_Beta_Whitepaper.aspx#link24.
I tried to fix the script but with no luck as I really a novice in a whole ajax thing at the moment specially in extenders.
So if could point me how can I fix it I would be really appreciating it.
Best regards.
Scritto da dimus - giovedì 23 novembre 2006 alle ore 17.54

Hi Dmitrij, to fix that problem with CustomAutoCompleteBehavior.js file try this out..
First modify the first lines of the file with this piece of text:

Then add to the end of the file this line:


Let me now if it will resolve your problems ;)
Scritto da ZofM - venerdì 24 novembre 2006 alle ore 11.39

Working like a dream, thanks a lot!!!
Scritto da dimus - venerdì 24 novembre 2006 alle ore 12.30

Hi! I am absulutely new in ajax.net, but I am using the AutoCompleteExtender with Atlas, and it works fine. Now, I tried to run the CustomAutoCompleteExtenderAjax, I modified the lines as Zofm has written, but it doesn't work.
While debugging,the IE gives the message:

Microsoft JScript runtime error: Object doesn't support this property or method
Then in VS this line is higlighted:
var e = Function._validateParams(arguments, [{name: 'path', type: String}]);

Have you any idea, what is the problem?
Many thanks!
Scritto da tanacs - martedì 28 novembre 2006 alle ore 10.58

Hi! Thank you for the good script but I have the same problem while selecting a suggested word. Everytime the timer is ticking it’s loosing the selection. I modified the js file but it doesn’t work. Please let me known if you could help me. Many thanks in advance!
Scritto da sven - venerdì 1 dicembre 2006 alle ore 11.06

I updated the .ZIP file with a new version. I fixed the "loosing selection" and now it's functionally inside an UpdatePanel. Try to download again the file at this location: http://www.zofm.net/download/CustomAutoCompleteExtender.zip

Inform me about the new version. Bye ;)
Scritto da ZofM - venerdì 1 dicembre 2006 alle ore 15.13

It seems to be broken in an update panel getting an error to do with the timer, also what happened to teh css modifications in the newest version they don't exist and the example differs majorly from your code.. ?
Scritto da infintevs - sabato 2 dicembre 2006 alle ore 18.17

Yes, sorry but this Beta version of AJAX is changing every month so I had to update the version of my example continuously. Now, the last version, is only functionally with the new AJAX 1.0 Beta 2 package. For the problem with Timer ensure you have added in your ScriptManager a reference to the Microsoft.Web.Preview library:



Bye, Gianni.
Scritto da ZofM - lunedì 4 dicembre 2006 alle ore 10.11

I'm confused as to why your behavior class reincludes all the base methods, like Sys$Preview$UI$AutoCompleteBehavior$get_completionInterval, etc. Could you enlighten me? Thanks!
Scritto da Max Metral - venerdì 15 dicembre 2006 alle ore 22.15

Hi Gianni,
new release new incompatibility issues, spent couple of long hours to migrate code to new ajax 1.0 RC but with no luck. If you'll have some time to rewrite a source code would be very appreciating it.
Best regards.
Scritto da dimus - lunedì 18 dicembre 2006 alle ore 16.07

Hi Gianni,
new release new incompatibility issues, spent couple of long hours to migrate code to new ajax 1.0 RC but with no luck. If you'll have some time to rewrite a source code would be very appreciating it.
Best regards.
Scritto da dimus - lunedì 18 dicembre 2006 alle ore 16.15

Forgot to add the error I'm getting is:
'Sys.Net._WebMethod' is null or not an object
Scritto da dimus - lunedì 18 dicembre 2006 alle ore 16.17

Hi everyone,
Just found a solution how to fix code for ajax 1.0 RC.
1.Change:
to:
Next modify the CustomAutoCompleteBehavior.js file. Replace:
with this:
of course apart this you have to follow migration guide to make all the necessary changes from beta 2 to 1.0 RC: Converting Applications from ASP.NET AJAX Beta 2 to ASP.NET AJAX RC(also available in Word format and inPDF format)
Scritto da dimus - mercoledì 20 dicembre 2006 alle ore 11.37

I've been trying to adapt your control to use the release version of AJAX controls and the Ajax Control Toolkit. I went through quite a bit to get it to run but now javascript doesn't error but it doesn't work either. Any chance, that you will re-release to work with the released 1/29 released version of Microsoft Ajax v1.0
Scritto da malsmith - martedì 30 gennaio 2007 alle ore 7.51

Hi, just wanted to say thanks for this excellent extension. Now, I've also upgraded to the RTM release, and the control is not working anymore. So if there is any chance of releasing an updated version I would be very grateful :) -- dag
Scritto da Dag - martedì 30 gennaio 2007 alle ore 17.53

After some trial and error I have this working on the 1/27 Microsoft Ajax Version 1.0 (Final Release). There were lots of changes due to the move of AutoCompleteExtender to AjaxToolkit assembly (which is now required to use this control. However, the December CTP is no longer needed. So only Release code is needed to use this control. You can download the changed files from http://www.treehousesystems.com/CustomAutoComplete_MSFTAJAXRelease1.0.zip
Scritto da malsmith - martedì 30 gennaio 2007 alle ore 18.03

Hi,
First of all thanks a lot for the excellent extension.
I am trying to pass another parameter while calling the web service method. I've done the following :
1. added a property on the class CustomAutoCompleteExtender.
2. added it to the list in CustomAjax.UI.AutoCompleteBehavior.descriptor and CustomAjax.UI.AutoCompleteBehavior.prototype.
3. provided getter and setter methods in CustomAutoCompleteBehavior.js.
4. added it while calling the webservice in the _onTimerTick method.
But, I get an error "Microsoft JScript runtime error: Sys.InvalidOperationException: 'newParam' is not a property or an existing field." .
Am I missing something? Please help me with this.

Thanking you in anitcipation.
Scritto da Sarith Sutha - giovedì 1 marzo 2007 alle ore 18.51

Hi, Please ignore my previous post, the javascript file was cached. It started working after I cleared the browser cahce. I've one more question. How can I add this AutoCompleteExtender dynamically onto a webform? Thanks.
Scritto da Sarith Sutha - giovedì 1 marzo 2007 alle ore 19.32

Thanks ZofM..
Scritto da infinitevs - martedì 6 marzo 2007 alle ore 16.07

When will a AJAX & PHP based version of the cool script be out?
Scritto da Ashwin Date - mercoledì 2 maggio 2007 alle ore 14.05

This is great. I was able to get this working in a few minutes. This has been a great help for me. I did add a function when you leave the textbox to remove that last comma. If there is a better way to do this please let me know! function removelastcomma(elem) { //will remove the last comma in a text box if (elem.value.charAt(elem.value.length-1) == ',') { elem.value = elem.value.substring(0,elem.value.length-1);} }
Scritto da Louis De Grazia - venerdì 31 agosto 2007 alle ore 20.08

can I get this code in php language
Scritto da naveen - giovedì 30 aprile 2009 alle ore 14.25



Scrivi nuovo commento

Autore:  
E-mail:
Sito:
Ricorda le mie informazioni:
Messaggio:
Verifica codice: Password verification

 

-- Anteprima commento --


Versione italiana Versione italiana

CATEGORIE

Ajax (2)
ASP.NET (11)
C# Code (4)
IIS (1)
Silverlight (1)
Sql Server 2000 (1)
Varie (4)
Visual Studio (4)

ARCHIVIO

aprile 2009 (1)
maggio 2008 (1)
aprile 2008 (1)
gennaio 2008 (4)
dicembre 2007 (1)
maggio 2007 (1)
febbraio 2007 (1)
dicembre 2006 (3)
ottobre 2006 (1)
settembre 2006 (3)
agosto 2006 (1)
giugno 2006 (1)

CHI SONO [curriculum]

Curriculum ZofM

RINGRAZIAMENTI