开发者

jquery preventDefault the linked anchor if double-clicked

Description

On our community website each users nick is a link to their profile page, but if the nick is double-clicked a menu for this user is shown below the nick. The content of this popup-menu is loaded using an ajax call. So far we've used "javascript:" in the anchor hrefs, and caught single/double clicks using JS. We wanted to clean up the hrefs and add proper urls to allow users to open the profile links in tabs etc, while still maintaining the double-click menu. I realize it's not the best design, it has just become somewhat of an obsession to get working.

Problem

So I want single clicks to act as normal (send browser to href), while double-clicks preventDefault and call a custom function(event) instead. I am able to do this by using window.location in the single click part, but that feels like the compromise/hack I wanted to improve on.

Code so far

Using answer 1067484 from question 1067464 (not allowed to post links) as basis for the following

    jQuery(document).ready(function($) {
        $("#hello")
            .bind('click', singleClick)
            .bind('dblclick', doubleClick);
    });

    function singleClick(e) {
        e.preventDefault();
        var el = this;
        setTimeout(function() {
        var dblclick = parseInt($(el).data('double'), 10);
            if (dblclick > 0) {
                $(el).data('double', dblclick-1);
            } else {
                $('#result').html('click registered - browser should proceed to url');
                // Attempting to make browser follow original href url:
                $(el).unbind('click', singleClick);
            }
        }, 300);
    }

    function doubleClick(e) {
        $(this).data('double', 2);
        e.preventDefault()开发者_开发问答;
        $('#result').html('double-click registered - browser should stay here');
        // Display dblclick popup-menu here
    }

(See/edit live at http://jsbin.com/iboyo5/2 )

I am only missing this single-click part, I wanted a "cleaner" way than window.location and this is why I'm fiddling with .unbind() - which is not a 100% solution either. The .unbind() function does what I want, but it doesn't unload the handler for the current run of the code, so it only works once for every two single clicks. This is the issue I need fixed now.

Btw: I don't mind if the first .click is paused for the set delay. Having to wait 300ms before the url "launches" is no problem.

Am I going to have to give up on this one and use window.location? Can it be solved using .live() and .die()?

Hope I did good enough research before my first post here. Thanks!


The following solution should help you get the functionality you desire:

Sample markup:

<a class="profile" href="#">Stewie</a>
<br/>
<a class="profile" href="#">Brian</a>
<br/>
<div id="result"/>

Javascript:

var clickCount = 0;
var clickTimeout;
var currentTarget;

function evaluateClicks(targetElement) {
    if (clickCount === 1) {
        $("#result").text(targetElement.text() + ": clicked once");
    } else if (clickCount > 1) {
        $("#result").text(targetElement.text() + ": clicked twice or more");
    }
    clickCount = 0;
}

$("a.profile").click(function(e) {
    e.preventDefault();
    var targetElement = $(e.target);
    /*check to see if the target's href is the same
    the comparison does not need to be on the href, just something
    so you can differentiate the two elements from each other.
    */
    if (currentTarget && targetElement.attr("href") !== currentTarget.attr("href")) {
        clearTimeout(clickTimeout);
        clickCount = 0;
    }
    currentTarget = targetElement;
    clickCount++;
    var thingToDo = function() {
        evaluateClicks(targetElement);
    };
    //reset the current timeout
    clearTimeout(clickTimeout);
    clickTimeout = setTimeout(thingToDo, 300);
});

Note that the comparison between the elements is based off the href attribute, assuming that they are unique.


Posting what we've ended up with in case others need the same functionality later on. This is using window.location to "undo" the preventDefault action. I'd love to learn a cleaner approach, but will be leaving this solved for now.

jQuery(document).ready(function($) {

  /* Member popup menu - Handle single and double clicks for member-links */
  function singleClick(e) {
    e.preventDefault();
    var url = $(this).attr("href");
    var el = this;
    setTimeout(function() {
      var dblclick = parseInt($(el).data('double'), 10);
      if (dblclick > 0) {
        $(el).data('double', dblclick-1);
      } else {
        $('#result').html('click registered - browser should proceed to url');
        window.location = url;
      }
    }, 300);
  }

  function doubleClick(e) {
    e.preventDefault();
    $('#result').html('double-click registered - browser should stay here');
    $(this).data('double', 2);
    var full_id = $(this).attr("id");
    var ids = full_id.split("_");
    var id = ids[1];
    $.ajax({
      url: "....php",
      data: {
        page: "ajax.getMemberPopup",
        id: id
      },
    });
  }

  $(".profile")
    .bind('click', singleClick)
    .bind('dblclick', doubleClick);
  /* End member popup menu */
});
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜