2009-06-19 10 views
5

Drupal ma bardzo dobrze zaprojektowaną, opartą na jQuery -w oparciu autocomplete.js. Zwykle nie musisz się tym przejmować, ponieważ jego konfiguracja i wykonanie jest obsługiwane przez interfejs API formularza Drupal.Jak dynamicznie zmienić konfigurację autouzupełniania opartego na jQuery opartego na jQuery w środowisku wykonawczym?

Teraz potrzebuję sposobu na rekonfigurację go w czasie wykonywania (z JavaScriptem). Mam standardowe rozwijane pole wyboru z polem tekstowym obok niego i zależnie od tego, która opcja jest wybrana w polu wyboru, muszę wywoływać różne adresy URL do autouzupełniania, a dla jednej z opcji autouzupełnianie powinno być całkowicie wyłączone. Czy istnieje możliwość rekonfiguracji istniejącej instancji autouzupełniania, czy też muszę ją jakoś zniszczyć i odtworzyć?

Odpowiedz

3

Cóż, dla porównania, rzuciłem razem hack, który działa, ale jeśli ktoś może wymyślić lepsze rozwiązanie, byłbym szczęśliwy, słysząc to.

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); 
      } 
     }); 
}; 

Ten kod pochodzi z ding_campaign module. Jeśli chcesz zrobić coś podobnego, możesz sprawdzić kod. To wszystko na GPL2.

1

Powinno to być tak proste, jak zmiana wartości "ukrytego" elementu autouzupełniania, który jest poza polami autouzupełniania. to znaczy.

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

To nie wydaje się działać. Podobno URL jest przechowywany gdzieś w kodzie JavaScript i nie jest ponownie czytany z pola wejściowego. – mikl

+1

Musisz również usunąć klasę 'autocomplete-processed' z ukrytego pola, a następnie ponownie dołączyć zachowanie autouzupełniania, wywołując' Drupal.behaviors.autocomplete (document); '. – sepehr

+0

działa, ale przy każdych zmianach jest rejestrowany nowy adres URL, jeśli 2 razy zostanie ponownie dołączony, wszystkie 3 połączenia zostaną wykonane na serwerze –

4

Wystarczy popatrzeć na 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'); 
    }); 
}; 

atrybut wartość wejście jest wykorzystywane do tworzenia ACDB, który jest cache wartości dla tej ścieżki autouzupełniania (URI). Która jest używana w funkcji Drupal.jsAC związać keyDown, keyUp i rozmycia zdarzenia tego elementu z wyzwala działanie autouzupełnianie AJAX (który buforuje swoje wartości w obiekcie ACDB dla tego elementu), otwiera wyskakujące okienka itd

/** 
* 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(); }); 

}; 

To, co musisz zrobić, to zmienić wartość wejściową i ponownie ją przywrócić. Przywrócisz działanie, usuwając klasę ".autocomplete-processing" z elementu wejściowego pola tekstowego autouzupełniania, a następnie wywołując Drupal.attachBehaviors (thatInputElement).

To może nie działać. Sprawy mogą pójść bardzo źle, jeśli przywrócisz to samo zachowanie do tego samego elementu w kółko. Bardziej sensowne może być tworzenie różnych pól autouzupełniania i po prostu ukrywanie i pokazywanie ich na podstawie wartości zaznaczenia. Będzie to nadal wymagało wywoływania Drupal.attachBehaviors po ukryciu i wyświetleniu widżetu, ale to samo zachowanie pozostanie dołączone, jeśli zmiana nastąpi więcej niż raz i nie ryzykujesz wielokrotnego przywiązywania tego samego zachowania do elementu.

+0

Cóż, nie jestem ekspertem od JavaScript, ale nie powinno być możliwości zmiany wartości w JavaScript zamiast opcji "nuklearnej" za każdym razem niszcząc i odtwarzając autouzupełnianie? – mikl

+0

ponieważ adresy URL są buforowane w tablicy abcd [], musisz ponownie dołączyć zachowanie, aby je zaktualizować, a jeśli to zrobisz, powinieneś rozpiąć() wszystkie wcześniejsze zdarzenia ograniczone do elementu autouzupełniania przedtem. – gpilotino

+0

Udało mi się odłączyć i ponownie zastosować zachowanie do pracy, ale czy to powoduje, że stary obiekt autouzupełniania jest zbierany śmieci? W przeciwnym razie spowoduje to wyciek pamięci. Prawdopodobnie nie jest to wielka sprawa, ale jest zdecydowanie bezpretensjonalna :) – mikl

1

Roztwór roboczy dla 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); 
Powiązane problemy