Show static non-clickable heading in AutoCompleteE

2019-08-10 08:16发布

问题:

I have an AutoCompleteExtender from the Ajax Control Toolkit. I need to have a heading in the dropdown list that shows how many items found, but it should not be selectable as an item.

I have tried this using jQuery, but even when I just add as a div, it is still selected as an item into the text box when I click on it:

function clientPopulated(sender, e) { 
    var completionList = $find("AutoCompleteEx").get_completionList();
    var completionListNodes = completionList.childNodes; 
    for (i = 0; i < completionListNodes.length; i++) { 
        completionListNodes[i].title = completionListNodes[i]._value.split(':')[2]; 
    } 
    var resultsHeader;
    if(completionListNodes.length==1000)
       resultsHeader = 'Max count of 1000 reached.<br/>Please refine your search.';
    else if(completionListNodes.length>0)
        resultsHeader =  completionListNodes.length + ' hits.';
    else 
        resultsHeader = msg_NoObjectsFound ;
    jQuery(completionListNodes[0]).before('<div>' + resultsHeader + '</div>');
}

回答1:

Add OnClientItemSelected and OnClientShowing events handlers and try script below:

function itemSelected(sender, args) {
     if (args.get_value() == null) {
          sender._element.value = "";
     }
}

function clientShowing() {
     var extender = $find("AutoCompleteEx");
     var optionsCount = extender.get_completionSetCount();

     var message = "";
     if (optionsCount == 1000) {
          message = 'Max count of 1000 reached.<br/>Please refine your search.';
     }
     else if (optionsCount > 0) {
          message = optionsCount + " hits."
     }
     else {
          message = "oops."
     }

     jQuery(extender.get_completionList()).prepend("<li style='background-color:#ccc !important;'>" + message + "</li>");
}

Added: you even can do this without OnClientItemSelected handler:

function clientShowing() {
     var extender = $find("AutoCompleteEx");
     var oldSetText = extender._setText;
     extender._setText = function (item) {
          if (item.rel == "header") {
               extender._element.value = "";
               return;
          }
          oldSetText.call(extender, item);
     };

     var optionsCount = extender.get_completionSetCount();

     var message = "";
     if (optionsCount == 1000) {
          message = 'Max count of 1000 reached.<br/>Please refine your search.';
     }
     else if (optionsCount > 0) {
          message = optionsCount + " hits."
     }
     else {
          message = "oops."
     }

     jQuery(extender.get_completionList()).prepend("<li rel='header' style='background-color:#ccc !important;'>" + message + "</li>");
}


回答2:

We can give a better answer if you post the output html of your autocomplete control. Anyway if its a dropdown control;

jQuery(completionListNodes[0]).before('
<option value="-99" disabled="disabled">your message here</option>'
);


回答3:

The answer by Yuriy helped me in solving it so I give him credit although his sollution needed some changes to work.

First of all, the clientShowing event (mapped by setting OnClientShowing = "clientShowing" in the AutoExtender control) is executed on initialization. Here we override the _setText method to make sure nothing happens when clicking on the header element. I have used the overriding idea from Yuriy's answer that really did the trick for me. I only changed to check on css class instead of a ref attribute value.

function clientShowing(sender, e) { 
    var extender = sender; 
    var oldSetText = extender._setText; 
    extender._setText = function (item) { 
        if (jQuery(item).hasClass('listHeader')) { 
            // Do nothing. The original version sets the item text to the search 
            // textbox here, but I just want to keep the current search text.
            return; 
        } 
        // Call the original version of the _setText method
        oldSetText.call(extender, item); 
    }; 
} 

So then we need to add the header element to the top of the list. This has to be done in the clientPopulated event (mapped by setting OnClientPopulated = "clientPopulated" in the AutoExtender control). This event is executed each time the search results have been finished populated, so here we have the correct search count available.

function clientPopulated(sender, e) { 
    var extender = sender; 
    var completionList = extender.get_completionList();
    var completionListCount = completionList.childNodes.length; 
    var maxCount = extender.get_completionSetCount();
    var resultsHeader;
    if(completionListCount == maxCount)
       resultsHeader = 'Max count of ' + maxCount + ' reached.<br/>'
                     + 'Please refine your search.';
    else if(completionListCount > 0)
        resultsHeader =  completionListCount + ' hits.';
    else 
        resultsHeader = 'No objects found';

    jQuery(completionList).prepend(
       '<li class="listHeader">' + resultsHeader + '</li>'); 
}

I have also created a new css class to display this properly. I have used !important to make sure this overrides the mousover style added from the AutoExtender control.

.listHeader 
{
    background-color : #fafffa !important;
    color : #061069 !important;
    cursor : default !important;
}