如何将点击处理程序添加到自定义 jQuery UI 小部件并在处理程序中使用小部件的 属性?

How to add a click handler to a custom jQuery UI widget and use the widget's property in the handler?

我已经为我的问题准备了jsfiddle

我定义了一个自定义 jQuery UI 小部件,代表一个游戏 table,最多 4 个玩家,中间有一个白色的 gid(“游戏 ID”)编号:

这是我的代码(与 jsfiddle 中的代码相同):

$(function() {
  var PHOTO_PATTERN = /^https:\/\/\S+/i;

  $.widget('raspasy.table', {
    // default options
    options: {
      gid: NaN,
      player0: null,
      player1: null,
      player2: null,
      player3: null
    },

    _create: function() {
      this.element.addClass('raspasy-table');

      this.gidDiv = $('<div/>', {
        'class': 'raspasy-table-gid'
      }).appendTo(this.element);
      this.player0 = $('<div/>', {
        'class': 'raspasy-table-player0'
      }).appendTo(this.element);
      this.player1 = $('<div/>', {
        'class': 'raspasy-table-player1'
      }).appendTo(this.element);
      this.player2 = $('<div/>', {
        'class': 'raspasy-table-player2'
      }).appendTo(this.element);
      this.player3 = $('<div/>', {
        'class': 'raspasy-table-player3'
      }).appendTo(this.element);

      this.rep0 = $('<div/>', {
        'class': 'raspasy-player-rep'
      }).appendTo(this.player0);
      this.bad0 = $('<div/>', {
        'class': 'raspasy-player-bad-small'
      }).appendTo(this.rep0);
      this.good0 = $('<div/>', {
        'class': 'raspasy-player-good-small'
      }).appendTo(this.rep0);

      this.rep1 = $('<div/>', {
        'class': 'raspasy-player-rep'
      }).appendTo(this.player1);
      this.bad1 = $('<div/>', {
        'class': 'raspasy-player-bad-small'
      }).appendTo(this.rep1);
      this.good1 = $('<div/>', {
        'class': 'raspasy-player-good-small'
      }).appendTo(this.rep1);

      this.rep2 = $('<div/>', {
        'class': 'raspasy-player-rep'
      }).appendTo(this.player2);
      this.bad2 = $('<div/>', {
        'class': 'raspasy-player-bad-small'
      }).appendTo(this.rep2);
      this.good2 = $('<div/>', {
        'class': 'raspasy-player-good-small'
      }).appendTo(this.rep2);

      this.rep3 = $('<div/>', {
        'class': 'raspasy-player-rep'
      }).appendTo(this.player3);
      this.bad3 = $('<div/>', {
        'class': 'raspasy-player-bad-small'
      }).appendTo(this.rep3);
      this.good3 = $('<div/>', {
        'class': 'raspasy-player-good-small'
      }).appendTo(this.rep3);

      this._refresh();
    },

    _destroy: function() {

      this.good0.remove();
      this.bad0.remove();
      this.rep0.remove();

      this.good1.remove();
      this.bad1.remove();
      this.rep1.remove();

      this.good2.remove();
      this.bad2.remove();
      this.rep2.remove();

      this.good3.remove();
      this.bad3.remove();
      this.rep3.remove();

      this.player0.remove();
      this.player1.remove();
      this.player2.remove();
      this.player3.remove();

      this.gidDiv.remove();

      this.element.removeClass('raspasy-table');
    },

    _setOptions: function() {
      this._superApply(arguments);
      this._refresh();
    },

    _drawPerson: function(playerDiv, badDiv, goodDiv, playerJson) {
      if (playerJson) {
        var photo = (PHOTO_PATTERN.test(playerJson.photo) ? playerJson.photo : 'https://raspasy.de/raspasy/images/male_happy.png');
        playerDiv.css('background-image', 'url("' + photo + '")');
        var rep = parseFloat(playerJson.rep);
        if (0 <= rep && rep <= 1) {
          var w = badDiv.width();
          badDiv.height(w * (1 - rep)).show();
          goodDiv.height(w * rep).show();
        } else {
          badDiv.hide();
          goodDiv.hide();
        }
        playerDiv.show();
      } else {
        playerDiv.hide();
      }
    },

    _refresh: function() {
      this.gidDiv.text('#' + this.options.gid);

      this._drawPerson(this.player0, this.bad0, this.good0, this.options.player0);
      this._drawPerson(this.player1, this.bad1, this.good1, this.options.player1);
      this._drawPerson(this.player2, this.bad2, this.good2, this.options.player2);
      this._drawPerson(this.player3, this.bad3, this.good3, this.options.player3);

      this.player0.css('transform', 'rotate(' + (4 - 8 * Math.random()) + 'deg)');
      this.player1.css('transform', 'rotate(' + (4 - 8 * Math.random()) + 'deg)');
      this.player2.css('transform', 'rotate(' + (4 - 8 * Math.random()) + 'deg)');
      this.player3.css('transform', 'rotate(' + (4 - 8 * Math.random()) + 'deg)');
    }
  });

  // MAIN SCRIPT

  var tablesList = $('#tablesList').selectable();
  var table1 = $('<li/>').appendTo(tablesList).table({
    gid: 3
  });
  var table2 = $('<li/>').appendTo(tablesList).table({
    gid: 104,
    player0: {
      rep: Math.random()
    }
  });
  var table3 = $('<li/>').appendTo(tablesList).table({
    gid: 115,
    player0: {
      rep: Math.random()
    },
    player1: {},
    player2: {
      rep: Math.random(),
      photo: 'https://raspasy.de/raspasy/images/male_sad.png'
    },
    player3: {
      rep: Math.random(),
      photo: 'https://raspasy.de/raspasy/images/female_happy.png'
    }
  });
  var table4 = $('<li/>').appendTo(tablesList).table({
    gid: 116,
    player0: {
      photo: 'https://raspasy.de/raspasy/images/female_happy.png'
    },
    player1: {
      rep: Math.random(),
      photo: 'https://raspasy.de/raspasy/images/female_sad.png'
    },
    player2: {
      rep: Math.random(),
      photo: 'https://raspasy.de/raspasy/images/male_sad.png'
    },
    player3: {
      rep: Math.random(),
      photo: 'https://raspasy.de/raspasy/images/female_happy.png'
    }
  });

  table1.click(function() {
    console.log('table clicked: ' + this.gid);
    alert('table clicked: ' + this.gid);
  });
  table2.click(function() {
    console.log('table clicked: ' + this.gid);
    alert('table clicked: ' + this.gid);
  });
  table3.click(function() {
    console.log('table clicked: ' + this.gid);
    alert('table clicked: ' + this.gid);
  });
  table4.click(function() {
    console.log('table clicked: ' + this.gid);
    alert('table clicked: ' + this.gid);
  });

});
.raspasy-table {
  position: relative;
  background: #A3DD8E;
  color: white;
  margin: 50px;
  float: left;
  border: 4px solid #91BCE5;
  border-radius: 16px;
  box-shadow: 0 0 32px rgba(0, 0, 0, 0.2);
  width: 160px;
  height: 160px;
}

.raspasy-table:hover {
  background-color: #92CC7D;
}

.raspasy-table-gid {
  position: absolute;
  font-size: 1.5em;
  top: 65px;
  width: 100%;
  color: white;
  text-align: center;
}

.raspasy-table-player0 {
  position: absolute;
  left: -40px;
  top: 50px;
  background: #FFF no-repeat center;
  background-size: contain;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
  width: 80px;
  height: 60px;
  display: none;
}

.raspasy-table-player1 {
  position: absolute;
  left: 40px;
  top: -30px;
  background: #FFF no-repeat center;
  background-size: contain;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
  width: 80px;
  height: 60px;
  display: none;
}

.raspasy-table-player2 {
  position: absolute;
  left: 120px;
  top: 50px;
  background: #FFF no-repeat center;
  background-size: contain;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
  width: 80px;
  height: 60px;
  display: none;
}

.raspasy-table-player3 {
  position: absolute;
  left: 40px;
  top: 130px;
  background: #FFF no-repeat center;
  background-size: contain;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
  width: 80px;
  height: 60px;
  display: none;
}
<ul id="tablesList"></ul>

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

我的问题是点击不起作用。

我也试过:

table1.on('click', function (event, ui) {
  console.log('table clicked: ' + this.gid);
  alert('table clicked: ' + this.gid);
});

并且:

table1._on( this.element, {
    'click': function( event ) {
        event.preventDefault();
        console.log('table clicked: ' + this.gid);
        alert('table clicked: ' + this.gid);
    }
});

但仍未调用点击处理程序代码。

更新:

我已经尝试添加 Twisty 的建议(谢谢!),这在他的 jsfiddle 中非常有效:

  $("#tablesList").on("click", ".raspasy-table", function() {
    var myID = $(this).table("option", "gid");
    console.log('table clicked: ' + myID);
    alert('table clicked: ' + myID);
  });

但在我的真实应用程序中它不起作用。

点击事件是否可能被我代码中的 $('#tablesList').selectable(); 行屏蔽了?

当我检查 #tablesList 元素时,它似乎有 2 个事件处理程序。第一个处理程序是否窃取了第二个处理程序的点击事件?

为了解决这个问题,您需要使用 .on() 进行点击,并通过 Getter.

调用 gid

示例:https://jsfiddle.net/Twisty/6bmtnL1f/7/

JavaScript

  $("#tablesList").on("click", ".raspasy-table", function() {
    var myID = $(this).table("option", "gid");
    console.log('table clicked: ' + myID);
    alert('table clicked: ' + myID);
  });

我建议将其移至 _create 函数中。为此,您在创建 table 之后添加 .click()

示例:https://jsfiddle.net/Twisty/6bmtnL1f/16/