【问题标题】:Make <a> inside jQuery autocomplete clickable使 jQuery 自动完成中的 <a> 可点击
【发布时间】:2015-08-23 23:28:56
【问题描述】:

我设法使用以下代码在 jQuery 自动完成项的右侧添加了一个链接:

function onClientSelect(event, ui) {
    // My handling code goes here
    event.preventDefault();
}

$("#mypage input[name='client']").autocomplete({
    minLength: 1,
    appendTo: $(this).parent(),
    source: '/filter_client/',
    select: onClientSelect,
    focus: function (event, ui) {
        event.preventDefault();
    },
}).data("ui-autocomplete")._renderItem = function (ul, item) {
    return $("<li></li>")
        .data("item.autocomplete", item)
        .append("<a>" + item.label + "</a>")
        .appendTo(ul);
};

我的服务器以这种格式返回元素标签:

<div class="ac-item-lb">My Item Label</div>
<a class="ac-item-a" href="/url_to_go_to/" target="_blank">View Detail</a>

我想要做的是在单击“查看详细信息”时在新选项卡中打开链接,单击任何其他区域都会像往常一样执行 onClientSelect。但是,当前左键单击链接也会执行onClientSelect。打开链接的唯一方法是单击中间滚轮或鼠标右键并选择“在新选项卡中打开”。

我尝试在带有 event.stopImmediatePropagation() 的链接上附加一个单击事件处理程序,但这似乎不起作用。有谁知道如何解决这个问题?

【问题讨论】:

  • 没人知道这个???
  • 你是在使用jQuery自动完成还是其他一些自动完成插件
  • 你能提供一个使用数组而不是服务器响应的小提琴吗?

标签: javascript jquery autocomplete click


【解决方案1】:

实现此目的的一种方法是定义一个自定义 select 函数,并且不对链接使用 &lt;a&gt;

HTML:

<div class="ui-widget">
    <label for="tags">Tags:</label>
    <input id="tags">
</div>

JS:

 var availableTags = [
    "ActionScript",
    "AppleScript",
    "Asp",
    "BASIC",
    "C",
    "C++",
    "Clojure",
    "COBOL",
    "ColdFusion",
    "Erlang",
    "Fortran",
    "Groovy",
    "Haskell",
    "Java",
    "JavaScript",
    "Lisp",
    "Perl",
    "PHP",
    "Python",
    "Ruby",
    "Scala",
    "Scheme"];

$("#tags").autocomplete({
    source: availableTags,
    select: function (event, ui) {
        var elem = $(event.originalEvent.toElement);
        if (elem.hasClass('ac-item-a')) {
            var url = elem.attr('data-url');
            event.preventDefault();
            window.open(url, '_blank ');
        }
    }
}).data("ui-autocomplete")._renderItem = function (ul, item) {
    return $("<li></li>")
        .data("item.autocomplete", item)
        .append('<a>' + item.label + '<span class="ac-item-a" data-url="http://www.nba.com"> View Details</span></a>')
        .appendTo(ul);
};

JSFIDDLE.

【讨论】:

  • 很好的解决方案 - 可以使用更多的 CSS 样式来澄清这里发生了什么。我建议您将 JSFiddle 编辑到这个:jsfiddle.net/sqsinger/jkukvpgo/3
  • @sqsinger - 谢谢你的造型,我已经编辑了答案并添加了你的小提琴。
  • 好主意,但你为什么不让原生元素做他们的事情。只需创建一个普通的超链接。没有黑客攻击,并且可以使用辅助技术:jsfiddle.net/ryanwheale/jkukvpgo/6
  • @RyanWheale - 因为点击超链接会选择当前项目,而这正是他想要阻止的。
【解决方案2】:

您是否考虑过在您的点击处理程序中将条件设置为 not preventDefault 当它是那个链接时?如果您测试该元素是否应该正常运行,那么您可以在preventDefault 之前早点return,然后链接应该正常运行。

这是一个示例 (JSBin):

function clickHandler(e) {
  // If the target element has the class `test-clickable` then the
  // function will return early, before `preventDefault`.
  if (this.className.indexOf('test-clickable') !== -1) {
    return;
  }

  alert('That link is not clickable because of `preventDefault`');
  
  e.preventDefault();
}

$('a').click(clickHandler);
a {
  display: block;
}
a:after {
  content: ' [class=' attr(class)']';
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Title</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>

<body>
  <a class='test-clickable' href='http://www.google.com' target='_blank'>Link</a>
  <a class='test-not-clickable' href='http://www.google.com' target='_blank'>Link</a>
</body>

</html>

【讨论】:

    【解决方案3】:

    Amir,关于你的回答,我认为从 select 事件中打开的 javascript 函数中的窗口可以被 PopupBlocker 阻止

    pinghsien422,你的服务器端应该返回Json而不是完整的html,如果你必须返回完整的html,做如下修改:

    1.去掉clientSelect功能

    2.renderData函数中不需要'a'标签

     $("#mypage input[name='client']").autocomplete({
       minLength: 1,
      appendTo: $(this).parent(),
       source: '/filter_client/',
      focus: function (event, ui) {
        event.preventDefault();
      },
    }).data("ui-autocomplete")._renderItem = function (ul, item) {
    return $("<li></li>")
        .data("item.autocomplete", item)
        .append( item.label )
        .appendTo(ul);
    };
    

    【讨论】:

      【解决方案4】:

      好的,jquery 的事件优先于你的 select 事件——无论你做什么,你都不能在那里停止任何事情。但是您可以代理 menuselect 事件,然后决定是否应该调用它 (jsfiddle)。

      var ac = $("#mypage input[name='client']").autocomplete({
          minLength: 1,
          appendTo: document.body,
          source: availableTags,
          focus: function (event, ui) {
              event.preventDefault();
          },
      }).data("ui-autocomplete");
      ac._renderItem = function (ul, item) {
          return $("<li></li>")
              .data("item.autocomplete", item)
          .append("<div>"+item.label+"<a class='link' href='http://test'>(http://test)</a></div>")
              .appendTo(ul);
      };
      var ms = $._data(ac.menu.element.get(0), 'events').menuselect[0].handler;
      ac.menu.element.off("menuselect");
      ac.menu.element.on("menuselect", function (ev) {
          if($(ev.originalEvent.target).hasClass("link"))
              return;
          ms.apply(this,arguments);
      });
      

      【讨论】:

        【解决方案5】:

        尝试在onclick 中绑定到链接的even.stopImmediatePropagation。页面正在打开,选择处理程序未执行。

        var li = $("<li></li>")
            .data("item.autocomplete", item)
            .append('<a class="ac-item-a" href="http://www.nba.com">' + item.label + '</a>')
            .appendTo(ul);
        
        li.find('a').bind('click', function(event){ event.stopImmediatePropagation() });
        
        return li;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-29
          • 2011-06-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多