Search code examples
javascriptjqueryjquery-pluginslong-click

Implementing $(this) in a jQuery plugin


I've been looking for developing a long-click plugin to handle such an event in jQuery, and after much research, I've found the best method. I've created the plugin below. It is not a large file, but it covers what I need. There are some problems with it though...

$(function($) {
  var holdTimer;
  $.fn.longclick = function( handler, time ) {
    if(time == undefined) time = 500;
    return this.mouseup(function(){
      clearTimeout(holdTimer);
    }).mousedown(function(){
      holdTimer = window.setTimeout(handler, time);
    });
  };
  $.fn.longclick.defaultTime = 500;
}(jQuery));

Below, I have the page that tests it:

// some markup
<input type="button" name="button3" id="button3" value="1500ms">

// and... the script itself

$("#button3").longclick( function() {
  var initial_text = $("#button3").val();
  console.log( $(this) );
  var initial_id = $(this).attr("id"); console.log( initial_id);
  var initial_html = $(this).html(); console.log(initial_html);
  $("#button3").replaceWith('<input type="textbox" id="" value=' + initial_text + '>');
}, 1500);

Now, the problem of my plugin seems to be that it doesn't know what $(this) means. When I console.log the $(this) it return the window itself, not the button that I need... Also, initial_id and initial_html are undefined. How can I get this done?

UPDATE: The initial_html variable should be, in my case <input type="button" name="button3" id="button3" value="1500ms">. The jQuery.html() won't work as I expect by saying $(this).html(). How can I get the element's HTML?


Solution

  • When you do setTimeout(handler, time) the handler will be called from window (this will be equal with window).

    So, when you init the plugin instance you have to save this into a $self (it's a jQuery object). Then instead of setTimeout(handler, time) you have to do:

    holdTimer = window.setTimeout(function () {
        handler.call($self);
    }, time);
    

    The edited plugin is:

    $(function($) {
      var holdTimer;
      $.fn.longclick = function( handler, time ) {
        var $self = this;
        if(time == undefined) time = 500;
        return this.mouseup(function(){
          clearTimeout(holdTimer);
        }).mousedown(function(){
            holdTimer = window.setTimeout(function () {
                handler.call($self);
            }, time);
        });
      };
      $.fn.longclick.defaultTime = 500;
    }(jQuery));
    

    Regarding the HTML of the old element, jQuery.html() takes the inner HTML. You need the outerHTML. So, you get it this way: $(this)[0].outerHTML.

    var initial_html = $(this)[0].outerHTML;
    console.log(initial_html); // <input type="button" name="button3" id="button3" value="1500ms"> 
    

    JSFIDDLE