2

I am implementing an User Interface for a project I'm working on and can be found here : Toobrok

Each time the mouse of the user enters a div, a class is added to this div to highlight it, I use the stopPropagation() method to restrict the highlighting to the div whose z-index is higher (the top div in the z axis). However, sometimes, my user needs to select an element hidden by another one, when the dimensions of the 2 elements are different, and if the bottom div is larger, he can find some points of the bottom div not hidden by the top one, but when the dimensions are the same, I would like the user to be able to press a key to change the depth (on the z-axis) of his selection.

The relevant code is given below (in CoffeeScript), but a javascript solution would also help me:

Ui.bind = (elements, index) ->
  ids = Ui.getIdSelector(elements)
  $(ids).attr("centroid", index)
  $(ids).mouseover (event) ->
    event.stopPropagation()
    Ui.highlight $(ids)
  $(ids).mouseout (event) ->
    event.stopPropagation()
    Ui.resetHighlight $(ids)

I hope the question is clear and looking forward to your answer.

This is an example of HTML to consider :

<!DOCTYPE html>
<html>
  <head>
    <title> Sample page </title>
  </head>
  <body>
    <div id="container">
       <div id="child1">Some text...</div>
    </div>
  </body
</html>

And the related css :

#container {
  height: 200px;      
  width: 500px;
}

#child1 {
  height: 90%;
  width: 90%;
}

When the mouse enters the child1 element, this element is highlighted, I want the container element to highlight when the user press a specific key.

I could use the JQuery parent() function to select that element on this example, but I am not sure it is a good solution, sometimes, the parent can have a size of 0px and and then a mouseover on this element would not be consistent. I want to select the element normally selected by Javascript if I do not use the stopPropagation() event.

I actually just found something that might help : How to undo event.stopPropagation in jQuery?

But I cannot use that in my case... Because my condition is another user action, and I cannot synchronously wait for an user to do something.

Community
  • 1
  • 1
Uelb
  • 3,947
  • 2
  • 21
  • 32
  • Correct if I'm wrong, but you want to change z-index on key press? And can you please provide some css and html? – Marko Vasic Jun 27 '14 at 07:13
  • I don't want to change the z-index of a div on keypress but to change the z-index of the mouseovered element (Changing may not be the correct verb because if the z-index is the same, I still want to go from one div to another) I did not provide any HTML or CSS because this code has been written to write on unknown webpages. But I will try to write an example – Uelb Jun 27 '14 at 07:16
  • Maybe you can increase z-index for some value on mouse in and decrease it for same value on mouse out. – Marko Vasic Jun 27 '14 at 09:37
  • Let me make sure I understand: 1. You currently highlight an element on mouseover, and de-highlight it on mouseout. 2. There can be overlapping elements, so you want to allow someone to press a key so that it will highlight a different element 3. Your code is meant to run on unknown webpages, where the parent element may have size 0 (i.e. just a placeholder for structure purposes) and therefore should *not* be selected Did I understand you correctly? – Etai Jun 28 '14 at 19:40
  • You perfectly understood ! The javascript propagation does not take into account placeholder elements, I think, and I want to do the same, the mouseover reacts on several elements and I want to manually decide which one should received the fired event. – Uelb Jun 29 '14 at 07:01
  • @Oxynum: Since it's the children overlapping, propagation is not your problem. Propagation works to parents, not overlapping items. The solution by Artem sounds as the correct approach. – Tiele Declercq Jul 03 '14 at 08:31

4 Answers4

2

I started writing code but then decided to leave implementation to you. Here is the text explanation:

  1. At some point of time (probably when user press button to cycle through all hovered elements) you have to find all candidates for highlighting. There is no other way to do it rather than manually loop through all your elements and check if mouse position is inside their bound rect. You can get mouse coordinates from argument in mouseover callback. Save all these hovered elements in some array.

  2. Next, you have to manually choose which element to highlight. Just highlight the first element in saved array and move the element to the end of array. You also may want to increase this element z-index and add callback for mouseout to this element.

Hope it helps, feel free to ask if you need more details.

Artem Volkhin
  • 1,362
  • 8
  • 22
2

You could use the CSS property pointer-events to make the child insensitive. Then events will be targeted to the element displayed below. For simple highlighting you should use pure CSS, however, jQuery can be helpful not to highlight the parent element as well while child is hovered without Ctrl.

Some example (also uploaded to JSFiddle, click into the output pane to make it responsive for keyboard events):

<div id="container1" class="container">
    <div id="child1" class="child">Some text...</div>
</div>

div { border:1px dashed red; } /* for demo */

.container
{ height: 200px;
  width: 500px;
}

.child
{ height: 90%;
  width: 90%;
}

.insensitive
{ pointer-events:none;
}

.container:hover:not(.no-hilight),
.child:hover
{ background-color:yellow;
}

/* other color for demo */
.child:hover{ background-color:green; }

// make events passthrough child when <Ctrl> is held down
$(document).on('keydown keyup', function(ev) {
    if (ev.key === 'Control') // for performance
        $('.child')[ev.ctrlKey?'addClass':'removeClass']('insensitive');
});

// don't hilight container when child is hovered
$('.child').on('mouseover', function(ev)
{ 
  $('.container').addClass('no-hilight');
});

// never suppress hilight when container is hovered directly
$('.container').on('mouseover', function(ev)
{ if(ev.target === ev.currentTarget)
    $('.container').removeClass('no-hilight');
});

// just test which element a click is targeted to
$(document).on('click', function(ev)
{ console.log('click:', ev.target);
});
Pinke Helga
  • 6,378
  • 2
  • 22
  • 42
  • Using CSS to force propagation was novel for me. In my context, I was using Recharts Label components, but their Tooltip implementation doesn't hook to attached Labels, so the tooltips weren't opening when hovering the Label overlapping the Scatter point. Adding `pointer-events: none` to the Label `style` prop completely addressed the issue. – bsplosion May 04 '23 at 16:22
  • @bsplosion It's not a propagation force but a kind of "event transparency". It is as the so styled element wasn't there. – Pinke Helga May 05 '23 at 12:18
0
var preId = 0;
function makeBlack(id)
{
    if(id)
    {
        $('#'+id).css('border-color','black');
    }
}
function makered(id)
{
    $('#'+id).css('border-color','red');
}
$(document).ready(function(){

$('div').mouseout(function() {
    var currentid = this.id;
    makeBlack(currentid);
    preId = currentid;

});
$('div').mouseleave(function() {
    var currentid = this.id;
    makeBlack(currentid);
    preId = currentid;

});
$('div').mouseover(function() {
    var currentid = this.id;
    makeBlack(currentid);   
    makered(preId);
    preId = currentid;

});
$('div').mouseenter(function() {
    var currentid = this.id;
    makered(currentid);
    preId = currentid;
});

});

Suman Biswas
  • 853
  • 10
  • 19
0

Have you tried something like this for the CSS?

#container.hover{
  height: 200px;      
  width: 500px;
  //add a background-color to that element since its a div element
  //background-color: (colour)
} 

i should hope that the div element would automatically highlight the container div with whichever color you have selected

Kebab Programmer
  • 1,213
  • 2
  • 21
  • 36