如何在运行时动态重新配置Drupal的基于jQuery的自动完成?

时间:2009-06-19 16:55:08

标签: javascript jquery drupal autocomplete drupal-6

Drupal有一个非常精心设计的基于jQueryautocomplete.js。通常,您不必费心,因为它的配置和执行由Drupal表单API处理。

现在,我需要一种在运行时重新配置它的方法(使用JavaScript,即)。我有一个标准下拉选择框,旁边有一个文本字段,根据选择框中选择的选项,我需要调用不同的URL进行自动完成,其中一个选项应该完全禁用自动完成。是否可以重新配置现有的自动完成实例,或者我必须以某种方式销毁和重新创建?

4 个答案:

答案 0 :(得分:4)

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

input的value属性用于创建ACDB,它是该自动完成路径(uri)的值的缓存。这在Drupal.jsAC函数中用于绑定元素的keydown,keyup和blur事件,触发器自动完成ajax操作(将其值缓存在该元素的ACDB对象中),打开弹出窗口等。

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

};

您需要做的是更改输入值并重新附加行为。您将通过删除自动填充文本字段输入元素上的“.autocomplete-processed”类重新附加该行为,然后调用Drupal.attachBehaviors(thatInputElement)。

这可能不起作用。如果一遍又一遍地将相同的行为附加到同一个元素,事情就会非常糟糕。创建不同的自动填充字段并根据选择的值隐藏和显示它们可能更为明智。当您隐藏并显示窗口小部件时,仍然需要调用Drupal.attachBehaviors,但如果交换发生多次,则相同的行为将保持附加,并且您不会冒多次将相同行为附加到元素的风险。

答案 1 :(得分:3)

嗯,作为参考,我把一个有效的黑客放在一起,但如果有人能想到更好的解决方案,我会很高兴听到它。

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

此代码来自ding_campaign module。如果您需要做类似的事情,请随时查看代码。这都是GPL2。

答案 2 :(得分:1)

它应该像动态更改“隐藏”自动完成的“值”一样简单 自动完成表单字段旁边的输入元素。即

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

答案 3 :(得分:1)

Drupal的工作解决方案 5

/*
 *  Błażej Owczarczyk
 *  blazej.owczarczyk@gmail.com 
 * 
 *  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);