【问题标题】:jQuery: how to keep the element functions, even when the element is been removed and recreated?jQuery:即使元素被删除和重新创建,如何保留元素功能?
【发布时间】:2025-12-02 13:25:01
【问题描述】:

我有问题..

我使用自动完成插件,我编辑该插件以使输入文本在用户做出选择时消失。

所以,我的目标是,当用户从自动完成列表中选择一行时:

  1. Ajax 请求将检索有关所选行的附加信息(这里没问题)
  2. 带有这些附加信息的表单自动填写(在此处确定)
  3. 带有自动完成功能的输入文本消失了,我在其中放置了 2 个 div,其中一个带有 X(用于“取消选择”之前的选择),另一个带有一些关于选择本身的简短信息(这里没有问题)
  4. 如果用户单击 X div,则所有内容都必须作为开始返回,并且输入文本具有自动完成功能。

发生在我身上的是,在第 4 点,一切正常,但是当具有自动完成功能的输入文本由

重新创建时
$("div#contact-list-container").html('<input type="text" name="contact-list" id="contact-list" value="" />');

自动完成功能不再起作用了!

那么,如何在重新创建字段时将自动完成功能加入到字段中?为了让用户可以多次选择和取消选择。

p.s: 我知道我可以简单地用输入文本隐藏 div 并用 X 显示那个,但我更喜欢保持 html 标记最少并且不要乱用隐藏的 div。 如果可能的话,我想在每次选择时更改 innerHTML 并重新关联自动完成功能。

这就是我现在的样子:

$(document).ready(function(){
    $('input#contact-list').autocomplete('test-db.php', {
        multiple: false,
        dataType: "json",
        width: 400,
        scrollHeight: 300,
        max: 5,
        parse: function(data) {
            return $.map(data, function(row) {
                return {
                    data: row,
                    value: row.azienda,
                    //result that will be used in the text field, while selected
                    result: row.code + ' - ' + row.company + ' | ' + row.name + ', ' + row.surname
                }
            });
        },
        formatItem: function(item) {
            return item.code + ' - ' + item.company + '<br />' + item.name + ', ' + item.surname + '<br />' + item.email;
        }
    }).result(function(e, item) {
        //this will be triggered when the selection has made
        $.ajax({
            type: "POST",
            cache: false,
            data: "idCompany=" + item.id_company + "&idUser=" + item.id_user,
            url: "test-db-02.php",
            success: function(message){
                $("input[rel='ship']").attr("readonly", true).css("background-color", "#DFDFDF");
                $("input[rel='company']").attr("readonly", true).css("background-color", "#DFDFDF");
                var rd = json_parse(message);

                $("input#ship-nome-referente").val(rd.company.nome);
                $("input#ship-cognome-referente").val(rd.company.cognome);
                //[... and so on, i change the val of many fields..]
                //REPLACE THE INPUT-TEXT WITH THE DIVS
                $("div#contact-list-container").html('<div id="deselect-contact">X</div><div id="selected-contact">' + rd.company.code + ' - ' + rd.company.company + ' | ' + rd.company.name + ', ' + rd.company.surname + '</div>');

                $("div#deselect-contact").click(function(){
                //REPLACE THE DIVS WITH THE INPUT-TEXT.. HOW TO REASSOCIATE THE AUTOCOMPLETE?
                    $("div#contact-list-container").html('<input type="text" name="contact-list" id="contact-list" value="" />');
                    $("input[rel='ship']").attr("readonly", false).css("background-color", "#FFFFFF").val('');
                    $("input[rel='company']").attr("readonly", false).css("background-color", "#FFFFFF").val('');
                });
            }
        });
    });
});

【问题讨论】:

    标签: jquery autocomplete


    【解决方案1】:

    从 jQuery 1.3 开始,live() 事件具有所需的功能,它允许您将事件持久地绑定到句柄,即使句柄被销毁并重新创建。

    编辑:live 在 jQuery 1.7 中被弃用并在 1.9 中被删除,所以现在你应该使用on() 来代替以达到相同的效果。

    详情请见http://api.jquery.com/on/

    【讨论】:

      【解决方案2】:

      我写了一个函数,它附加了自动完成 onfocus。所以当你有这样的输入时:

      <input type="text" onfocus="attach(this);"/>
      

      或者在您的情况下,将 onfocus 部分添加到您的输入字段注入中:

      $("div#contact-list-container").html('<input type="text" name="contact-list" id="contact-list" value="" onfocus="attach(this);"/>');
      

      您可以使用如下函数来附加自动完成插件。 (注意,我设置了一个属性防止多个附件)

      function attach(element){
      
          var $element = jQuery(element);
      
          // check if autocomplete was already attached
          if($element.attr("autocomplete.attached")){
              return;
          }
      
          // attach autocomplete 
          $element.autocomplete(...);
      
          // set a marker
          $element.attr("autocomplete.attached", true);
      }
      

      我不明白的是:为什么你不想隐藏和显示 div? “隐藏的 div 乱七八糟”是什么意思?

      【讨论】:

      • 首先是因为我有一个非常复杂的标记,我更喜欢替换现有元素而不是更改它们的属性......现在,我明白我弄错了,也许我会隐藏/展示方式。
      【解决方案3】:

      您也可以使用 jQuery 的 remove() 方法仅从 DOM 中删除 &lt;input&gt;不使用。该函数从 DOM 中删除元素,但也丢弃任何附加的事件处理程序和数据。

      但是不要忘记在删除 DIV 后保留对它的引用。像这样的:

      var theField = document.getElementById('contact-list');
      // remove it only from DOM
      theField.parentNode.removeChild(theField);
      
      // ...
      
      // and later when you want to bring the field back into the game
      $('#contact-list-container').append(theField);
      

      注意这会在 IE 中引入内存泄漏。您可以在页面卸载或显示和隐藏字段上使用 jQuery 的 remove() 函数。后者是迄今为止最干净的解决方案,我不明白为什么你会觉得它“混乱”。

      【讨论】:

      • 嗯...我不使用删除方法,我只是用 $('div#mydiv').html(''); 更改 div 内的 html ;)
      • 但是你不会保留对输入框的引用吧?关键是你重新插入它,而不是创建一个新的