如何将点击处理程序添加到自定义 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()
。
我已经为我的问题准备了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()
。