代码之家  ›  专栏  ›  技术社区  ›  mikl

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

  •  5
  • mikl  · 技术社区  · 15 年前

    Drupal 有一个很好的架构, jQuery 基于 autocomplete.js . 通常,您不必为它操心,因为它的配置和执行是由DrupalFormAPI处理的。

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

    4 回复  |  直到 15 年前
        1
  •  4
  •   bangpound    15 年前

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

    输入的value属性用于创建ACDB,它是该自动完成路径(URI)的值缓存。在drupal.jsac函数中用于绑定元素的keydown、keyup和blur事件,并触发autocomplete 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文本字段输入元素上的“.autocomplete processed”类,然后调用drupal.attachBehaviors(thatinputeElement),可以重新附加该行为。

    这可能不起作用。如果您一次又一次地将相同的行为附加到同一个元素上,情况可能会非常糟糕。创建不同的自动完成字段,并根据选择的值简单地隐藏和显示它们可能更为明智。这仍然需要在隐藏和显示小部件时调用drupal.attachBehaviors,但是如果开关多次发生,相同的行为将保持附加状态,并且您不会冒险多次将相同的行为附加到元素。

        2
  •  3
  •   mikl    15 年前

    嗯,作为参考,我提出了一个有效的黑客程序,但是如果有人能想出更好的解决方案,我会很高兴听到它。

    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。

        3
  •  1
  •   gpilotino    15 年前

    它应该简单到通常改变“隐藏”自动完成的“值”。 自动完成窗体字段旁边的输入元素。IE.

    $('select#myelement').bind('change', function(e) { 
      if (/* something */) {
        $('input#myelement-autocomplete').attr('value', '/mycustom/path');
      }
    }); 
    
        4
  •  1
  •   user168546    15 年前

    Drupal的工作解决方案

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