McDiabeetus
McDiabeetus

Reputation: 15

Turn off hover event after click and keep click

This is my js code. I am trying to make a TicTacToe game. When a player hovers over a table cell, they will see either an "x" or an "o" marker in that cell with 50% opacity. When they click on the table cell, they will see a marker in that cell with 100% opacity. When I hover on a cell that has been clicked, it continues to apply the hover event. How can I turn the hover event off after I have clicked, while maintaining the cell's new opacity? The goal of my function is to be able to hover over a table cell and temporarily see a 50% opaque marker and to be able to click on a table cell and permanently see a 100% opaque marker. Pictures https://i.sstatic.net/MHWH6.jpg

Note: I tried including a .off function at the end of my click event.

        $(this).off("mouseenter mouseleave);

This does not solve my issue.

        $(".tableCell").hover(function(){
            $(this).children(".tableCellMarker").attr("src", function(index, attr){
                return attr.replace("", "images/X.png");
            });
        }, function(){
             $(this).children(".tableCellMarker").attr("src", function(index, attr){
                return attr.replace("images/X.png", "");
             });
        });
        $(".tableCell").click(function(){
            $(this).children(".tableCellMarker").attr("src", function(index, attr){
                return attr.replace("","images/X.png");
            });
            $(this).children(".tableCellMarker").css("opacity",1);
            $(this).addClass("marked");
        });

Here is the css for .tableCellMarker

    .marker {
        cursor:pointer;
        margin:-80px 0px 150px 50px;
        opacity:0.5;
        position:absolute;
    }

Upvotes: 1

Views: 6184

Answers (4)

Dave
Dave

Reputation: 10924

I think handling this through CSS specificity as suggested in epascarello's answer is probably the best approach. However, if you do want to handle the hover events in code rather than CSS, you can combine event delegation and the :not() selector to dynamically control the display state.

$(".grid").on("click", ".tableCell", function() {
  //when clicking, toggle selection state and remove hover state
  $(this).removeClass("hovered");
  $(this).toggleClass("selected");
}).on("mouseenter", ".tableCell:not(.selected)", function() {
  //only if not selected, add hover state
  $(this).addClass("hovered");
}).on("mouseleave", ".tableCell", function() {
  //whenever leaving, it's always safe to remove hover state
  $(this).removeClass("hovered");
});
.grid {
  border: 1px solid black;
}
.grid td {
  width: 50px;
  height: 50px;
  border: 1px solid black;
}
.selected {
  background-color: green;
}
.hovered {
  background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table class="grid">
  <tr>
    <td class="tableCell"></td>
    <td class="tableCell"></td>
    <td class="tableCell"></td>
  </tr>
  <tr>
    <td class="tableCell"></td>
    <td class="tableCell"></td>
    <td class="tableCell"></td>
  </tr>
  <tr>
    <td class="tableCell"></td>
    <td class="tableCell"></td>
    <td class="tableCell"></td>
  </tr>
</table>

Upvotes: 0

epascarello
epascarello

Reputation: 207501

It would be so much easier if you used classes and use CSS Specificity to deal with the states.

$("table tbody").on("click", "td", function() {
   $(this).toggleClass("selected");
});
table {
  border-collapse: collapse; 
  width: 200px;
  height: 200px;
}

td {
    border: 1px solid black;
    text-align: center;
    background-color: white;  
}

td:hover {
    background-color: yellow;  
}

td.selected, td.selected:hover {
    background-color: green;  
}
  
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
  <tbody>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>4</td>
      <td>5</td>
      <td>6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>8</td>
      <td>9</td>
    </tr>
  </tbody>
</table>

Now how can we apply it to tic tac toe? Add more css classes and a little bit of logic.

var turn = true;  //determines x (true) and o (false)
$(".game tbody").on("click", "td", function() {  //bind click to cell
   var cell = $(this);  //get cell that was clicked
   if (cell.hasClass("selected")) return;  //if cell was selected than ignore click
   $(this)
     .addClass("selected")  //mark cell as selected
     .addClass(turn?"x":"o");  //set the class based on turn
   turn = !turn; //toggle player
  $(".game").toggleClass("x o");  //toggle whose turn it is (so hover is different)
});
table {
  border-collapse: collapse; 
  width: 200px;
  height: 200px;
}

td {
    border: 1px solid black;
    text-align: center;
    background-color: white;  
}

.x td:hover {
    background-color: #ABEBC6;  
}
.o td:hover {
    background-color: #F5B7B1;    
}


td.x, td.x:hover {
    background-color: #239B56;  
}

td.o, td.o:hover {
    background-color: #B03A2E;  
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table class="game x">
  <tbody>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>4</td>
      <td>5</td>
      <td>6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>8</td>
      <td>9</td>
    </tr>
  </tbody>
</table>

Upvotes: 4

arnolds
arnolds

Reputation: 788

You can use the jQuery .unbind() event to do this.

jQuery(function($) {
  $('.foo').on('mouseenter', function(e) {
    $(this).text('hover');
  });

  $('.foo').on('mouseleave', function(e) {
    $(this).text('');
  });

  $('.foo').on('click', function(e) {
    $('.foo').unbind('mouseenter');
  });
});
.foo {
  border: 1px solid #000;
  text-align: center;
  line-height: 200px;
  height: 200px;
  width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo"></div>

Upvotes: -1

Nick Zuber
Nick Zuber

Reputation: 5637

Try to organize your table cells by some attribute or class "hasClicked" and "unClicked". Then, only apply the hover ever for the "unClicked".

So, let's say you start off by giving each table cell a class called hasNotBeenClickedYet. Whenever we hover over an element that has the class hasNotBeenClickedYet, we want to do your hover action.

When one of these has been clicked, we want to remove the hasNotBeenClickedYet from that cell, so it no longer has the hover action.

So we'd want to change

$(".tableCell").hover(function(){
  ...
}

to something like

$(".hasNotBeenClickedYet").hover(function(){
  ...
}

and remove that class when it's been clicked

$(".hasNotBeenClickedYet").click(function(){
  $(".hasNotBeenClickedYet").removeClass("hasNotBeenClickedYet");
  ...
}

Upvotes: 0

Related Questions