Cómo conectarse al elemento seleccionado al heredar jQuery Autocompletar

Estoy tratando de extender el autocompletado para que cuando se seleccione un elemento se muestre una etiqueta secundaria. Por ejemplo, dado un autocompletado que muestra proyectos, el nombre del proyecto se mostraría en una etiqueta de intervalo junto al cuadro de entrada que contiene el código.

Mirando el código fuente de autocompletar, veo que el menú desplegable de valores filtrados se representa usando el widget de menú jQuery y que cuando se escriben teclas específicas en el cuadro de texto, se llaman a diferentes funciones en el widget de menú. Por ejemplo, cuando se presionan enter y tab, se llama a la función select() del widget de menú.

El widget de menú está configurado de modo que cuando se genera el evento seleccionado, el widget de autocompletar obtiene el elemento seleccionado y genera su propio evento de selección y luego muestra el valor de los elementos en el cuadro de texto.

Entonces, dado el siguiente código

(function ($, undefined) {
    $.widget('xyz.autocompletePlus', $.ui.autocomplete, {
        options: {
            selectedDescriptor: null
        },

        _create: function () {
            $.ui.autocomplete.prototype._create.call(this, this.options);

            if (!this.options.selectedDescriptor) {
                $("<span class='ui-xyz-autocomplete-label'>").insertAfter(this.element).html('Nothing selected');
            }
        },

        _setOption: function (name, value) {
            $.ui.autocomplete.prototype._setOption.call(this, arguments);
        },

        destroy: function () {
            $.ui.autocomplete.prototype.destroy.call(this);
            $.Widget.prototype.destroy.call(this);
        }
    });
} (jQuery));

¿Cómo me conecto al código que se llama cuando se selecciona un elemento para poder insertar mi propia lógica? La idea sería que en vez de ejecutar

if ( false !== self._trigger( "select", event, { item: item } ) ) {
   self.element.val( item.value );
}

Querría algo like (no es el código real, pero entiende el punto)

if ( false !== self._trigger( "select", event, { item: item } ) ) {
   self.element.val( item.value );
   this.options.selectedDescriptor.html( item.description);
}

Si no estuviera heredando sino encapsulando un autocompletado en un nuevo widget, podría vincularme al evento de selección de autocompletado y hacer lo mío, pero con la herencia estoy perplejo.

Edit:

Agregué la fuente de autocompletar que necesito reemplazar o conectar. Comienza en la línea 6137 de jquery-ui-1.8.22.js

this.menu = $( "<ul></ul>" )
   ...
   ...
   .menu({
      focus: function( event, ui ) {
         ...
         ...
         }
      },
      selected: function( event, ui ) {
         var item = ui.item.data( "item.autocomplete" ),
            previous = self.previous;

         // only trigger when focus was lost (click on menu)
         if ( self.element[0] !== doc.activeElement ) {
            self.element.focus();
            self.previous = previous;
            // #6109 - IE triggers two focus events and the second
            // is asynchronous, so we need to reset the previous
            // term synchronously and asynchronously :-(
            setTimeout(function() {
               self.previous = previous;
               self.selectedItem = item;
            }, 1);
         }

         if ( false !== self._trigger( "select", event, { item: item } ) ) {
            self.element.val( item.value );
         }
         // reset the term after the select event
         // this allows custom select handling to work properly
         self.term = self.element.val();

         self.close( event );
         self.selectedItem = item;
      },
      ...
      ...

Gracias.

preguntado el 28 de julio de 12 a las 04:07

¿Por qué no usa la opción 'seleccionar' de autocompletar? api.jqueryui.com/autocomplete/#event-select -

1 Respuestas

El código que desea aumentar reside en un controlador de eventos privado. De hecho, la herencia no ayudará mucho con eso.

Sin embargo, puede desvincular el controlador existente en su _create() y registre uno nuevo que haga lo que usted quiere. Desafortunadamente, eso implica copiar el código del controlador original:

_create: function() {
    $.ui.autocomplete.prototype._create.call(this, this.options);

    if (!this.options.selectedDescriptor) {
        this.options.selectedDescriptor
            = $("<span class='ui-xyz-autocomplete-label'>")
                .insertAfter(this.element).html("Nothing selected");
    }
    this.menu.element.off("menuselected")
                     .on("menuselected", function(event, ui) {
        var item = ui.item.data("item.autocomplete");
        if (false !== this._trigger("select", event, { item: item })) {
            this.element.val(item.value);
        }
        this.close(event);
        this.previous = this.element.val();
        // only trigger when focus was lost (click on menu)
        var doc = this.element[0].ownerDocument;
        if (this.element[0] !== doc.activeElement) {
            this.element.focus();
        }
    });
}

Respondido 28 Jul 12, 07:07

Esto no parece estar funcionando como está escrito. Simplemente llamar a this.menu.element.off('menuselected') provoca un TypeError: this.menu.element.off no es un error de función. Supongo que el problema es obtener una referencia adecuada al widget de menú subyacente. Debido al formato limitado en estos comentarios, publiqué el código original en una pregunta separada arriba. - Jason

@Jason, tal vez la versión de jQuery que estás usando sea inferior a 1.7. Si ese es el caso, intente unbind() en lugar de off() (y bind() en lugar de on()). - Frederic Hamidi

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.