2009-06-19 12 views
5

Drupal tiene una muy bien estructurada, jQuery -basada en autocomplete.js. Por lo general, no tiene que preocuparse por eso, ya que su configuración y ejecución se manejan mediante la API de formulario de Drupal.¿Cómo reconfigurar dinámicamente el autocompletado basado en jQuery de Drupal en tiempo de ejecución?

Ahora, necesito una forma de reconfigurarlo en tiempo de ejecución (con JavaScript, eso es). Tengo un cuadro de selección desplegable estándar con un campo de texto junto a él, y dependiendo de qué opción esté seleccionada en el cuadro de selección, necesito llamar a diferentes URL para el autocompletado, y para una de las opciones, el autocompletado debe estar desactivado por completo. ¿Es posible reconfigurar la instancia de autocompletar existente o tendré que destruir y volver a crear de alguna manera?

Respuesta

3

Bueno, como referencia, he armado un truco que funciona, pero si alguien puede pensar en una solución mejor, estaría encantado de escucharlo.

Drupal.behaviors.dingCampaignRules = function() { 
    $('#campaign-rules') 
    .find('.campaign-rule-wrap') 
     .each(function (i) { 
      var type = $(this).find('select').val(); 

      $(this).find('.form-text') 
      // Remove the current autocomplete bindings. 
      .unbind() 
      // And remove the autocomplete class 
      .removeClass('form-autocomplete') 
      .end() 
      .find('select:not(.dingcampaignrules-processed)') 
      .addClass('dingcampaignrules-processed') 
      .change(Drupal.behaviors.dingCampaignRules) 
      .end(); 

      if (type == 'page' || type == 'library' || type == 'taxonomy') { 
      $(this).find('input.autocomplete') 
       .removeClass('autocomplete-processed') 
       .val(Drupal.settings.dingCampaignRules.autocompleteUrl + type) 
      .end() 
      .find('.form-text') 
       .addClass('form-autocomplete'); 
      Drupal.behaviors.autocomplete(this); 
      } 
     }); 
}; 

Este código viene de la ding_campaign module. Siéntase libre de revisar el código si necesita hacer algo similar. Es todo GPL2.

1

debe ser tan simple como cambiar dinamicamente el "valor" del elemento de autocompletar "oculto" que viene aparte de los campos de formulario de autocompletar. es decir.

$('select#myelement').bind('change', function(e) { 
    if (/* something */) { 
    $('input#myelement-autocomplete').attr('value', '/mycustom/path'); 
    } 
}); 
+0

que no aparece para trabajar. Aparentemente, la URL se almacena en algún lugar de JavaScript y no se vuelve a leer desde el campo de entrada. – mikl

+1

También debe eliminar la clase 'autocomplete-processed' del campo oculto y luego volver a conectar el comportamiento de autocompletar llamando' Drupal.behaviors.autocomplete (document); '. – sepehr

+0

funciona, pero se registra una nueva url en cada cambio, si se vuelve a adjuntar 2 veces, se realizarán 3 llamadas totales al servidor –

4

Tenga una mirada en misc/autocomplete.js.

/** 
* Attaches the autocomplete behavior to all required fields 
*/ 
Drupal.behaviors.autocomplete = function (context) { 
    var acdb = []; 
    $('input.autocomplete:not(.autocomplete-processed)', context).each(function() { 
    var uri = this.value; 
    if (!acdb[uri]) { 
     acdb[uri] = new Drupal.ACDB(uri); 
    } 
    var input = $('#' + this.id.substr(0, this.id.length - 13)) 
     .attr('autocomplete', 'OFF')[0]; 
    $(input.form).submit(Drupal.autocompleteSubmit); 
    new Drupal.jsAC(input, acdb[uri]); 
    $(this).addClass('autocomplete-processed'); 
    }); 
}; 

atributo de valor de la entrada se utiliza para crear ACDB, que es una memoria caché de valores para ese camino autocompletar (URI). Que se utiliza en la función Drupal.jsAC para enlazar eventos KeyDown, keyup y el desenfoque del elemento con desencadena la operación de autocompletar ajax (que almacena en caché sus valores en el objeto ACDB para ese elemento), se abre ventanas emergentes, etc.

/** 
* An AutoComplete object 
*/ 
Drupal.jsAC = function (input, db) { 
    var ac = this; 
    this.input = input; 
    this.db = db; 

    $(this.input) 
    .keydown(function (event) { return ac.onkeydown(this, event); }) 
    .keyup(function (event) { ac.onkeyup(this, event); }) 
    .blur(function() { ac.hidePopup(); ac.db.cancel(); }); 

}; 

Lo que tendrá que hacer es cambiar el valor de la entrada y también volver a conectar el comportamiento. Volverá a conectar el comportamiento eliminando la clase '.autocomplete-processed' en el elemento de entrada del campo de texto de autocompletar y luego llamará a Drupal.attachBehaviors (thatInputElement).

Esto puede no funcionar. Las cosas pueden ir muy mal si agrega el mismo comportamiento al mismo elemento una y otra vez. Puede ser más sensato crear diferentes campos de autocompletar y simplemente ocultarlos y mostrarlos en función del valor de la selección. Esto aún requeriría llamar a Drupal.attachBehaviors cuando oculte y muestre el widget, pero el mismo comportamiento permanecería adjunto si el cambio ocurriera más de una vez, y no correría el riesgo de asociar el mismo comportamiento al elemento varias veces.

+0

Bueno, de ninguna manera soy un experto en JavaScript, pero no debería ser posible alterar los valores en JavaScript en lugar de la opción "nuclear" de destruir y volver a crear el autocompletar cada vez? – mikl

+0

como las direcciones URL se almacenan en caché en la matriz abcd [], debe volver a conectar el comportamiento para actualizarlo y, si lo hace, debe desvincular() todos los eventos anteriores delimitados por el elemento de autocompletar anteriormente. – gpilotino

+0

He logrado desvincularme y volver a aplicar el comportamiento para trabajar, pero ¿eso causa que el viejo objeto de autocompletar sea basura? De lo contrario, esto perderá memoria. Probablemente no es un gran problema, pero es decididamente desagradable :) – mikl

1

Solución de trabajo para Drupal

/* 
* Błażej Owczarczyk 
* [email protected] 
* 
* Name: Autocomplete City Taxonomy 
* Description: Hierarchical city selecting (province select and city autocomplete) 
*/ 

var Act = Act || {}; 

Act.init = function() { 
    $('select.act-province').change(Act.provinceChange);  // select with top taxonomy terms  
} 

/* 
* Change event of select element 
*/ 
Act.provinceChange = function() { 
    var context = $(this).parent().parent();    
    var currentTid = $(this).val(); 
    Act.rewriteURI(context, currentTid); 
    Act.unbind(); 
    Drupal.autocompleteAutoAttach(); 
}; 

/* 
* Changes the value of hidden autocomplete input 
*/ 
Act.rewriteURI = function (context, newTid) { 
    var tempArray; 
    tempArray = $('.autocomplete', context).val().split('/'); 
    tempArray.pop(); 
    tempArray.push(newTid); 
    $('.autocomplete', context).val(tempArray.join('/'));  
}; 

/* 
* Prevents muliple binding of the same events 
*/ 
Act.unbind = function() { 
    $('.form-autocomplete').unbind().parents('form').unbind('submit'); 
}; 

$(document).ready(Act.init); 
Cuestiones relacionadas