I have prepared a jsfiddle for my problem.
I define a custom jQuery UI widget representing a game table with up to 4 players and a white gid ("game id") number in the middle:
Here is my code (same as in the 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>
My problem is that the click is not working.
I have also tried:
table1.on('click', function (event, ui) {
console.log('table clicked: ' + this.gid);
alert('table clicked: ' + this.gid);
});
And:
table1._on( this.element, {
'click': function( event ) {
event.preventDefault();
console.log('table clicked: ' + this.gid);
alert('table clicked: ' + this.gid);
}
});
but still the click handler code is not called.
UPDATE:
I have tried adding the suggestion by Twisty (thank you!), which works perfectly in his jsfiddle:
$("#tablesList").on("click", ".raspasy-table", function() {
var myID = $(this).table("option", "gid");
console.log('table clicked: ' + myID);
alert('table clicked: ' + myID);
});
but in my real app it is not working.
Is the click event maybe masked by $('#tablesList').selectable();
line in my code?
When I inspect the #tablesList
element it seems to have 2 event handlers. Is the first handler stealing the click event from the second one?
To address this, you will want to use an .on()
for click and also call the gid
via the Getter.
Example: 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);
});
I would advise moving this into the _create
function. To do this, you add the .click()
after the table has been created.