Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't trigger hover event on children

Tags:

jquery

css

I have a container with tiles (grass, water, etc) and in some of them I have items (border-sprites, trees, and general items). Due to the nature of the sprites, all items are 64x64 while tiles are only 32x32.

My problem is that I want to trigger a hover event on tiles, but they are sometimes shadowed by another tiles' items.

The image below shows the problem. The thick green area is the tile that really gets hovered when I want to hover the tree-tile.

the problem http://upload.cip.nu/pfile.php?file_id=2327

The CSS:

#map_canvas .tile{
    height: 32px;
    position: absolute;
    width: 32px;
}
#map_canvas .tile .item{
    background-position: bottom right;
    background-repeat: no-repeat;
    bottom: 0;
    display: inline-block;
    height: 64px;
    margin: 0;
    padding: 0;
    position: absolute;
    right: 0;
}

The HTML, simplified:

<div class="tile" style="background-image: url(grass.png);"></div>
<div class="tile" style="background-image: url(grass.png);"></div>
<div class="tile" style="background-image: url(grass.png);">
    <div class="item" style="background-image(top-left-border.png);"></div>
</div>

Here's the live demo http://sleavely.com/tiles/

I don't even know how to phrase the question, but here goes:

Is it possible to only trigger the event on the parent element (.tile) so that overflowing children (.item) do not obfuscate which tile I really hover?

EDIT: Thanks to @Brilliand I implemented the following

function figureOutTile(e){
    var $source = jQuery(e.srcElement);
    if($source.hasClass("item")){
        var $parent = $source.parent();
        var posx = $parent.attr("col");
        var posy = $parent.attr("row");
        if(e.offsetY <= 32){
            if(e.offsetX <= 32){
                return jQuery(".tile[col="+ (posx-1) +"][row="+ (posy-1) +"]");
            }else{
                return jQuery(".tile[col="+ posx +"][row="+ (posy-1) +"]");
            }
        }else{
            if(e.offsetX <= 32){
                return jQuery(".tile[col="+ (posx-1) +"][row="+ posy +"]");
            }else{
                return $parent;
            }
        }
    }else{
        return $source;
    }
}
jQuery("#map_viewport").on({
    mouseenter: function(e) {
        var $target = figureOutTile(e);
        $target.addClass('hovered');
    },
    mouseleave: function() {
        jQuery(".tile.hovered").removeClass('hovered');
    }
}, '.tile');​
like image 609
Sleavely Avatar asked May 17 '12 19:05

Sleavely


2 Answers

$(".tile").children().on('mouseenter', function(e) { 
   e.stopPropogation(); 
});

or

$(".tile").on('mouseenter', function(e) { 
   if (this===e.target) {
      //do stuff
   }
});

EDIT:

$("#map_viewport").on({
    mouseenter: function(e) {
        if (this===e.target) {
            $(element).addClass('someClass')
        }
    },
    mouseleave: function() {
        $(element).removeClass('someClass')
    }
}, '.tile');
like image 191
adeneo Avatar answered Nov 01 '22 00:11

adeneo


As far as your browser is concerned, hovering over something sticking out of a tile is the same as hovering over the tile that it's sticking out of, not hovering over whatever is being covered up. To work around this in your specific situation, I suggest putting your hover function on #map_canvas, and working out in that function which tile is being hovered over. For tiles in a rectangular grid, this is simple arithmetic.

Of course, for this to work you will need to include a mousemove event (to detect when the mouse moves from one tile to another), and you should probably include code to exit the function if the user is still hovering over the same tile.

EDIT: Although this answer has already been accepted, here's a solution based on my comment:

$(".tile").append($("<div/>", {
    css: {
        position: "absolute",
        top: 0,
        left: 0,
        right: 0,
        bottom: 0,
        "z-index": 50
    }
}));

This seems to fix the problem for all of the tiles with items on them, though it screws up your :empty declarations. I mention it mainly because it comes closer to answering your question as asked.

like image 1
Brilliand Avatar answered Nov 01 '22 00:11

Brilliand