Make <a> inside jQuery autocomplete clickable

I managed to add a link to the right of the jQuery autocomplete items, using the following code:

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

My server returns element label in this format:

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

What I want to do is to open the link in a new tab when I click on 'View Detail', which clicking any other area executes onClientSelect just like normal. However, currently left-clicking on the link also executes onClientSelect. The only way to open the link is to click the middle wheel or right mouse button and select 'open in new tab'.

I tried attaching a click event handler on the link with event.stopImmediatePropagation() but that doesn't seem to work. Does anyone have any idea how to fix this?

Answers


One way to do it is by defining a custom select function and by not using an <a> for the links

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.


Have you thought about putting a conditional in your click handler to not preventDefault when it is that link? If you test if the element should function as normal then you can return early before the preventDefault and then the link should function as normal.

Here is an example (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>

Amir, regarding to your answer, I think that opening window inside javascript function from select event can be blocked by PopupBlocker

pinghsien422 , your server side should return Json and not complete html , if you must return complete html, make the following changes:

1.Remove the clientSelect function

2.No 'a' tag is needed in renderData function

 $("#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);
};

Okay, jquery's event takes precedence over your select event - no matter what you do, you can't stop anything there. But you can proxify menuselect event and then decide if it should be invoked (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);
});

Try to do even.stopImmediatePropagation in onclick binding to link. Page is opening and select handler not executed.

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;

Need Your Help

Python: gensim: RuntimeError: you must first build vocabulary before training the model

python gensim word2vec

I know that this question has been asked already, but I was still not able to find a solution for it.

What are the Dangers of Method Swizzling in Objective-C?

ios objective-c swizzling

I have heard people state that method swizzling is a dangerous practice. Even the name swizzling suggests that it is a bit of a cheat.