2011-05-18 19 views
16

Estoy usando Autocompletar de jQuery UI de forma ligeramente diferente de lo que probablemente fue creado para hacer.jQuery UI Descompletar autocompletar Seleccionar y cerrar eventos

Básicamente quiero mantener la misma funcionalidad, la única diferencia es que cuando aparece el buzón de sugerencias, no selecciono el buzón de sugerencias cuando un usuario hace una selección y tampoco quiero esa selección para rellene el cuadro de entrada al que está adjunto .autocomplete.

Por lo tanto, he estado leyendo la documentación de jQuery UI, y parece que hay una forma de desactivar los eventos Seleccionar: y Cerrar: pero encuentro que la forma en que lo explicaron es muy confusa y, por lo tanto, Es por eso que estoy aquí pidiendo ayuda.

Mi jQuery

$("#comment").autocomplete({ 
    source: "comments.php", 
    minLength: 4, 

    // Attempt to remove click/select functionality - may be a better way to do this   
    select: function(event, ui) { 
     return false; 
    }, 
    // Attempt to add custom Class to the open Suggestion box - may be a better way 
    open : function (event, ui) { 
     $(this).addClass("suggestion-box"); 
    }, 
    // Attempt to cancel the Close event, so when someone makes a selection, the box does not close 
    close : function (event, ui) { 
     return false; 
    } 
}); 

Oficial documentación de jQuery UI

activa cuando se selecciona un elemento del menú; ui.item se refiere al elemento seleccionado. La acción predeterminada de select es reemplazar el valor del campo de texto con el valor del elemento seleccionado . La cancelación de este evento evita que el valor se actualice, pero no impide que se cierre el menú.

Ejemplos de código

Supply a callback function to handle the select event as an init option. 
$(".selector").autocomplete({ 
    select: function(event, ui) { ... } 
}); 
Bind to the select event by type: autocompleteselect. 
$(".selector").bind("autocompleteselect", function(event, ui) { 
    ... 
}); 

Confusión

lo que me confunde es que parecen estar sugiriendo que quitar la .autocomplete y reemplazar con .bind ("autocompleteselect") - que se desactivar la autocompletar por completo?

Muchas gracias por cualquier ayuda que pueda dar.

Respuesta

12

La segunda sintaxis que usa .bind() es simplemente otra forma de adjuntar un controlador de eventos a los eventos personalizados de jQueryUI. Esto es exactamente lo mismo que definir el controlador de eventos dentro de las opciones del widget (usando select: function(event, ui) { })

Imagine si tenía varios widgets de autocompletar en la página y desea ejecutar la misma función cuando cualquiera de ellos genera el "seleccionar" caso por ejemplo:

$(".autocomplete").bind("autocompleteselect", function(event, ui) { 
    /* Will occur when any element with an autocomplete widget fires the 
    * autocomplete select event. 
    */ 
}); 

en cuanto a cancelar el evento select, usted tiene que correcta. Sin embargo, cancelar el evento close es un poco más difícil; parece que devolver falso desde el controlador de eventos no funcionará (close se activa después de que el menú esté realmente cerrado). Se podría realizar una pequeña hackery y simplemente reemplazar la función select con su propio:

var $input = $("input").autocomplete({ 
    source: ['Hello', 'Goodbye', 'Foo', 'Bar'] 
}); 
$input.data("autocomplete").menu.options.selected = function(event, ui) { 
    var item = ui.item.data("item.autocomplete"); 
    $input.focus(); 
}; 

Aquí está un ejemplo de trabajo de que: http://jsfiddle.net/ZGmyp/

No estoy seguro de cuáles son las ramificaciones de anular el evento de cierre, pero no parece que algo loco esté sucediendo en el ejemplo simple. Diría que es un uso poco natural del widget, por lo que puede haber consecuencias inesperadas.

+0

Muchas gracias por que @ Andrew, ¿puede pensar en una manera de cancelar el Click/función de selección, pero aún así cambiar el buzón de sugerencias cuando la entrada se cambia y, o cuando los usuarios/deselecciona el cuadro de entrada? – thathurtabit

+0

@thathurtabit: para el menú aún debe actualizar a medida que escribe sugerencias. ¿Qué quiere decir con cambiar el cuadro de sugerencias cuando la entrada está deseleccionada? –

+0

@AndrewWhitaker Gracias por consultarme, sí, estoy buscando el menú para actualizar cuando las sugerencias se escriben. He intentado su demo nuevamente, y se actualiza si escribe otra sugerencia que reconoce, pero si escribe alguien completamente diferente (y no reconoce), aún conserva su sugerencia irrelevante anterior. Además, cuando hace clic fuera del cuadro de entrada (para deshacerse de su foco), el cuadro de sugerencias permanece abierto. – thathurtabit

19

Tomando la inspiración de solución Andrews, he encontrado una manera de mantener autocompletar abierta en la selección con un menor impacto en la funcionalidad de núcleo:

var selected; //flag indicating a selection has taken place 

var $input = $("input").autocomplete({ 
    source: ['Hello', 'Goodbye', 'Foo', 'Bar'], 
    select: function(event, ui) { 
     selected = true; 
    } 
}); 

//Override close method - see link below for details 
(function(){ 
    var originalCloseMethod = $input.data("autocomplete").close; 
    $input.data("autocomplete").close = function(event) { 
     if (!selected){ 
      //close requested by someone else, let it pass 
      originalCloseMethod.apply(this, arguments); 
     } 
     selected = false; 
    }; 
})(); 

Entonces la idea es castrar a cerrar método cuando sea apropiado, como se indica por bandera seleccionado . Habiendo seleccionado la bandera en el espacio de nombre global probablemente no sea la mejor idea, pero eso es para que otra persona mejore :-).

More about overriding methods

+0

Fantástico, esto me ayudó un montón – wesbos

+0

¡ERES EL HOMBRE! – Trip

+0

Excelente idea para anular los métodos integrados. Gracias. – BasTaller

1

descendí una ruta ligeramente diferente para esto y Ampliado de Andrew fiddle

El propósito es que siempre quería que la función de autocompletar para mostrar al mismo tiempo una cierta entrada había concentrarse - lo que permite múltiples trozos escogidos.

$("#myInput").autocomplete({ 
    source: ["Test", "This", "Doesnt", "Close"], 
    minLength: 0, 
    select: function (event, ui) { 
     // Add your own custom login to manipulate ui.item.label and add what you need the input field (and ui.item.value if required.) 
     // We've customised how we want the select to "work" so prevent the default 
     // of auto clearing the input.  
     event.preventDefault(); 
    }, 
    close : function(event) 
    { 
     // We're closing the autocomplete - check if the input still has focus... 
     if ($("#myInput").is(":focus")) 
     { 
      // Prevent the auto complete from closing. 
      event.preventDefault(); 

      // Make sure we're reshowing the autcomplete - since the input would have momentarily 
      // lost focus when we selected an item. 
      $("#myInput").autocomplete("search", "") 
     }   
    } 
}); 

$("#myInput").focus(function() { 
    // We're not taking any filtering into account for this example. 
    $(this).autocomplete("search", "") 
}); 
+0

Esto realmente me ayudó a crear una selección dinámica de múltiples niveles, lo que necesitaba era que si seleccionaba cierto elemento, obtiene una nueva lista de elementos. Pasé horas tratando de resolver esto. Todos hacen las opciones simples pero no prueban esta característica. escribirá una página para esta función muy pronto. – PBo

1

Probé las diversas ideas que otros han presentado aquí sin éxito.

estoy usando jQuery 2.1.4 con la interfaz de usuario 1.11.4 y esto es cómo llegué a esto funcione:

Javascript:


<script> 
var lookup_selectable = false; 
var lookup_term = ''; 

$(function() { 

    $("#lookup").autocomplete({ 
     source: "lookup_processor.php", 
     minLength: 3, 
     renderItem: function(ul, item) { 

      // This function is called for each item returned from the 'source:' 
      // It is up to you to ensure that a list item element is returned. 

      // do whatever logic on the item data to determine if it should not be slectable.. 


      //Example: 
      // The backend "source" has handled the logic of what is selectable or not 
      // and has set a 'selectable' parameter that we can use 
      if(item.selectable){     
       // return the item unchanged from autocompletes default behavior 
       return $("<li></li>").data("item.autocomplete", item).append("<a>" + item.label + "</a>").appendTo(ul);    
      }else{ 
       // this item is not selectable so lets apply a class named 'item-disabled' to give a visual queue. 
       // We are also wrapping the label in a span instead of an anchor just to show that the item is still clickable, darn! 
       return $('<li class="ui-menu-item item-disabled"></li>').data("item.autocomplete", item).append('<span>'+item.label+'</span>').appendTo(ul);     
      } 

     }, 

     select: function(event, ui) {         

      // This item was clicked .. 

      // save the item.clickable value to our own external variable 
      // Note: We have to do this because the item object is not available in the 'close' function :-(
      lookup_selectable = ui.item.selectable; // the item object is available inside the ui parameter 

      // store the current search term 
      lookup_term = $('#lookup').val(); 

      // do any additional stuff based on the item selected, if needed... 


     }, 

     close: function(event, ui){ 

      // This function fires after select: and after autocomplete has already "closed" everything. This is why event.preventDefault() won't work.    
      // ** ui is an empty object here so we have to use our own variable to check if the selected item is "selectable" or not..        
      if (! lookup_selectable){ 
       // We need to undo what autocomplete has already done..              
       $('#lookup').val(lookup_term); // Restore the search term value 
       $('#'+event.currentTarget.id).show(); // Keep the selection window open 
       // ta-da! To the end user, nothing changes when clicking on an item that was not selectable. 
      }  
     } 

    }); 
}); 
</script> 

CSS:


<style> 
li.ui-menu-item.item-disabled { 
    text-decoration: none;  
    line-height: 1.5;  
    color: #ccc; 
} 
</style> 

Fuente de fondo "lookup_processor.php":


<?php 

     $search_results = array(); 

    // ..do whatever to get the data for each item 
    $item_data = getting_item_data(); 

    foreach ($item_data as $data){ 
     // The id, label, and value keys are the typical keys that autocomplete expects, but you can add ass many others as you want.. 
     // For our example we are setting the 'selectable' key to true or false based on some simple example logic 
     $search_results[] = array(
      'id'=>$data['id'], 
      'label'=>$data['label'], 
      'value'=>$data['value'], 
      'selectable'=>$data['some_thing_to_check']>0?true:false, // This is the parameter our 'select:' function is looking for 
      'send_it_all_if_you_want'=>json_encode($data)); // this is just an example of how you can send back anything you want 
     ); 
    } 

    // send the results back to autocomplete 
    echo json_encode($search_results); 
    exit; 

?> 
0

Ir con $ input.data ("autocompletar"). Menu.options.selected = function() {} valor causada no sostiene después de seleccionar el artículo diferente (nuestra aplicación necesita para añadir al final. Posiblemente sea necesario solo para agregar e.preventDefault() o devolver falso antes de agregar el código). Así que acabo de hacer un cambio en el evento cerrado. ejemplo con poner variable externa y escribir método propio es mejor, pero tampoco me gustó. Primero pensé en llamar al método manualmente con pasar un parámetro cuando necesito cerrar el autocompletado a mano. (en nuestra implementación, el cliente requirió que la lista se abriera al hacer clic en los elementos, pero se cierra cuando el mouse sale del contenedor de la caja de texto.

Así que acabo de adjuntar autocompletar al contenedor de elementos de la caja de texto y adjuntar mouseenter y mouseleave. Para determinar si debería cerrarse, utilicé la variable personalizada jQuery (this) .data ("canClose". Básicamente, lo que hace es simplemente reabrir el autocompletar con el método de búsqueda cuando la variable es 'falsa'.

Aquí está el final código:

element.autocomplete({ 
       minLength:0, 
       source: source, 
       appendTo: element.parent(), 
       close: function() { 
        if (!jQuery(this).data("canClose")) { 
         jQuery(this).autocomplete('search', ''); 
        } 
        return false; 
       } 
      }); 
      element.mouseenter(function() { 
       element.data("canClose", false); 
       jQuery(this).autocomplete('search', ''); 
      }); 
      element.parent().mouseleave(function() { 
       element.data("canClose", true); 
       element.delay(2000).autocomplete("close"); 
      }); 

si necesita hacer el apéndice en lugar de reemplazar el valor agregar el controlador de selección en el constructor:

select: function (event, ui) { 
        var text = element.text().trim(); 
        if (text.length > 0 && !text.endsWith(",")) { 
         text += ", "; 
        } 
        jQuery(this).text((text + ui.item.label)); 
        jQuery(this).focus(); 
        return false; 
       }