I'm trying to write a JavaScript which will highlight an element in the DOM when the user hovers over it. This is supposed to be a cross-browser external plug-in. Ideally, i'm trying to mimic the behaviour of the browser inspector tools.
I can't say I have no success, but I am stuck with two options, both with its own pros and cons.
Approach 1
I handle the mouseover
event and simply add a border to the target element. When I hover on another element, I just reset the existing highlighted elements. The code for the same is below:
function addHighlight(target) {
target.classList.add('highlighted');
}
function removeHighlight(target) {
target.classList.remove('highlighted');
}
window.addEventListener('mouseover',function(e) {
addHighlight(e.target);
});
window.addEventListener('mouseout',function(e) {
removeHighlight(e.target);
});
Working Example here
Pros with this Approach
It works absolutely fine.
Cons with this approach
As I'm adding a border to existing DOM elements, it sort of re-arranges the elements on the page, and you can observe a slight shuffling effect of the elements. Doesn't look great.
Approach 2
I wanted the highlighting to be seamless. That is, preserving the look of the page and simply overlaying a highlight mask on top of the element.
TO do this, in the mouseover
event, I dynamically created a mask element, whose position
is set to absolute
and its co-ordinates set to the exact co-ordinates of the target element. Below is my code:
window.addEventListener('mouseover',function(e) {
applyMask(e.target);
});
function applyMask(target) {
if(document.getElementsByClassName('highlight-wrap').length > 0) {
resizeMask(target);
}else{
createMask(target);
}
}
function resizeMask(target) {
var rect = target.getBoundingClientRect();
var hObj = document.getElementsByClassName('highlight-wrap')[0];
hObj.style.top=rect.top+"px";
hObj.style.width=rect.width+"px";
hObj.style.height=rect.height+"px";
hObj.style.left=rect.left+"px";
// hObj.style.WebkitTransition='top 0.2s';
}
function createMask(target) {
var rect = target.getBoundingClientRect();
var hObj = document.createElement("div");
hObj.className = 'highlight-wrap';
hObj.style.position='absolute';
hObj.style.top=rect.top+"px";
hObj.style.width=rect.width+"px";
hObj.style.height=rect.height+"px";
hObj.style.left=rect.left+"px";
hObj.style.backgroundColor = '#205081';
hObj.style.opacity='0.5';
hObj.style.cursor='default';
//hObj.style.WebkitTransition='top 0.2s';
document.body.appendChild(hObj);
}
function clearMasks() {
var hwrappersLength = document.getElementsByClassName("highlight-wrap").length;
var hwrappers = document.getElementsByClassName("highlight-wrap");
if(hwrappersLength > 0) {
for(var i=0; i<hwrappersLength; i++) {
console.log("Removing existing wrap");
hwrappers[i].remove();
}
}
}
Working example here
Pros with this approach I feel this is more elegant, and doesn't disturb the page, just overlays a mask on top of elements.
Cons
When the user hovers over the top most container (div
), it creates a mask for that element. After that, all the subsequent mouseover
events are ignored, as they are registered on the mask, and not on the actual underlying elements.
I need to figure out a way around this.
Can anyone help me better Approach 2? Or suggest another approach?
Thanks, Sriram
You should do this in CSS and not in JS. Use the :hover
selector
.your-class:hover{
background-color: #205081;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With