AutoComplete for Search Widget

Topics: Controls
Feb 12, 2014 at 1:42 AM
Hi All!

I would like to customize my Search widget to add autocomplete and use the Category List as input for suggested strings.

Anyone knows where to start? I see that the widget is using blog:SearchBox but I don't see the actual textbox control that I can replace with AutoComplete Ajax Control Toolkit.

Feb 12, 2014 at 2:16 AM
Hi Galagerardo,

Here some files to look at to get you started :)

The "Search Widget" in a sense of a "Widget" is not really 100% a widget but more of a "module" since it is included the main core.

So where your "Normal" widgets are only located in two locations


The "Search Widget" is also has file located in the

/BlogEngine.Core/ folder too.

As far I can quickly find the two files above should be it other than the category related files.

Main point you have to "Dig" through the code :)

Would like to hear your progress on this in the future.

Sounds interesting.
Feb 13, 2014 at 4:33 PM
Edited Feb 13, 2014 at 6:56 PM
This uses a javascript plugin called autocomplete.
In the "dist" folder in the download find jquery.autocomplete.min and drop into blogs Scripts/Auto folder.

In theme CSS add following for starters:
.autocomplete-suggestions { border: 1px solid #999; background: #FFF; overflow: auto; }
.autocomplete-suggestion { padding: 2px 5px; white-space: nowrap; overflow: hidden; }
.autocomplete-selected { background: #F0F0F0; }
.autocomplete-suggestions strong { font-weight: normal; color: #3399FF; }
Modified SearchBox.cs control from BE 2.8
namespace App_Code.Controls
    using System;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using System.Linq;

    using BlogEngine.Core;

    /// <summary>
    /// Includes a reference to a JavaScript.
    ///     <remarks>
    /// This control is needed in order to let the src
    ///         attribute of the script tage be relative to the root.
    ///     </remarks>
    /// </summary>
    public class SearchBox : Control

        #region Public Methods

        /// <summary>
        /// Renders the control as a script tag.
        /// </summary>
        /// <param name="writer">
        /// The writer.
        /// </param>
        public override void RenderControl(HtmlTextWriter writer)
            writer.Write(this.BuildHtml() + this.AddScript());            


        #region Methods

        /// <summary>
        /// The build html.
        /// </summary>
        private string BuildHtml()
            var text = this.Context.Request.QueryString["q"] != null
                           ? HttpUtility.HtmlEncode(this.Context.Request.QueryString["q"])
                           : string.Empty;
            var sb = new StringBuilder();

            sb.AppendLine("<div id=\"searchbox\">");
            sb.Append("<label for=\"searchfield\" style=\"display:none\">Search</label>");
                "<input type=\"text\" id=\"searchfield\" autocomplete=\"off\" onkeypress=\"if(event.keyCode==13) return'{1}')\" onfocus=\"BlogEngine.searchClear('{2}')\" onblur=\"BlogEngine.searchClear('{2}')\" />",
                text.Replace("'", "\\'"));
                "<input type=\"button\" value=\"{0}\" id=\"searchbutton\" onclick=\"'{1}');\" onkeypress=\"'{1}');\" />",

            if (BlogSettings.Instance.EnableCommentSearch && BlogSettings.Instance.ShowIncludeCommentsOption)
                var check = this.Context.Request.QueryString["comment"] != null ? "checked=\"checked\"" : string.Empty;
                sb.AppendFormat("<div id=\"search-include-comments\"><input type=\"checkbox\" id=\"searchcomments\" {0} />", check);
                if (!string.IsNullOrEmpty(BlogSettings.Instance.SearchCommentLabelText))
                        "<label for=\"searchcomments\">{0}</label></div>", BlogSettings.Instance.SearchCommentLabelText);

            return sb.ToString();

        private string AddScript()
            var sb = new StringBuilder();
            sb.AppendLine("<script type=\"text/javascript\">");
            sb.AppendLine("$(function() {");
            sb.AppendLine("var cats = [");
            foreach (Category cat in Category.Categories)
                if (cat.Posts.Count > 0)
                    sb.Append("'" + cat.Title + "',");
            if (sb[sb.Length - 1] == ',')
                sb.Length -= 1;
            sb.AppendLine("$('#searchfield, #q').autocomplete({lookup: cats, delimiter: ' '});");            
            return sb.ToString(); ;

Note: This will work in search page and with one SearchBox control per page.
Some themes use the SearchBox control at page top, so it's that or add widget - breaks with both.
This is bare bones, you can add functionality or code to use different plugin.
EDIT: Search term space delimiter added to control AddScript()
Feb 14, 2014 at 2:30 AM
Hi Andy!

Thanks for all the efforts.

In jquery.autocomplete.js, I changed the minChars from 1 to 3. This seems to better. It doesn't get a lot of matches but when it does get a match, it's dead on!

Yes, I'm really happy with this. Much better than the normal search.