I am trying to make a tictactoe project in jQuery and I am having a major problem...
The tiles are in <td>
tags and I am trying to make it so that when the user clicks the the tile, it calls the "marked" function.
If we now look into the "marked" function, $(this)
is intended to be the <td>
node that the function was called from.
However, it wasn't doing anything so I checked the console and apparently $(this)
was containing the DOM Window object.
Is there anyway I can send the right kind of $(this)
to the "marked" function?
Thank you!
<script type="text/javascript">
var TURN_X = false;
var TURN_O = true;
var turn = false; // this is to see whos turn it is.
$(document).ready(function(){
var listCells = $.makeArray($("td"));
$("td").click(function(){marked(listCells)}); //THIS IS WHERE I HAVE PROBLEMS
return false;
});
function marked(arr)
{
console.log($(this)); // THIS CONSOLE LOG RETURNS "DOM Window"
$(this).addClass("marked");
if(turn == TURN_X)
{
this.innerHTML = "X";
turn = false;
}
else
this.innerHTML = "O";
var tileNum = $(this).attr("id");
}
You code does not follow the right principles.
$(function(){
var TURN_X = "X",
TURN_O = "O",
turn = TURN_O,
$listCells = $("td");
function marked() { // define event handler
var $this = $(this),
tileNum = $this.attr("id");
if ( !($this.hasClass("marked") ) {
$this.addClass("marked").text(turn);
turn = (turn == TURN_X) ? TURN_O : TURN_X;
}
}
$listCells.click(marked); // attach event handler
});
- Wrap everything in the document.ready function. Avoid global variables wherever possible.
- Make use of the fact that jQuery manages
this
for you. this
will always be what you expect if you pass callback functions directly instead of calling them yourself.
Send the element which fire the event to the function like that:
$("td").click(function(){
marked($(this));
return false;
});
and in the function:
function marked(td)
{
console.log($(td));
$(td).addClass("marked");
//....
}
More simply, use bind :
$(".detailsbox").click(function(evt){
test.bind($(this))();
});
function test()
{
var $this = $(this);
}
Try:
$("td").click(function(event){
marked(listCells, $(this));
});
Then:
function marked(arr, sel) {
console.log($(this));
sel.addClass("marked");
if(turn == TURN_X) {
this.innerHTML = "X";
turn = false;
} else {
this.innerHTML = "O";
}
var tileNum = $(this).attr("id");
}
try this:
$(function(){
var listCells = $.makeArray($("td"));
$("td").click(function(){marked($(this),listCells)});
});
function marked(o,arr)
{
...
You can use the call
method to specify the scope for the function:
$("td").click(function(){ marked.call(this, listCells); });
Now the marked
function can access the clicked element using the this
keyword.
You need to pass $(this)
to your function:
$("td").click(function(){ marked(listCells, $(this))} );
And modify your function like this:
function marked(arr, that)
{
that.addClass("marked");
if(turn == TURN_X)
{
that.innerHTML = "X";
turn = false;
}
else
that.innerHTML = "O";
var tileNum = that.attr("id");
}
$(document).ready(function(){
var TURN_X = false,
TURN_O = true,
turn = false,
listCells = $.makeArray($("td"));
$("td").click(function() {
marked(listCells, this)
});
function marked(arr, self) {
$(self).addClass("marked");
if(turn == TURN_X) {
self.innerHTML = "X";
turn = false;
}else{
self.innerHTML = "O";
var tileNum = self.id;
}
}
});