Javascript: Let user select an HTML element like Firebug?

I have recently required such a feature for a project I was working on, turned out that I had to use for sides to create a box because otherwise the event.target when you move the mouse would end up being the selector, and if I were to use z-index: -1 it would be a bit fishy when you have a lot of elements that overlap…etc.

Here is a version that I have converted from my project for your benefit, it involves jQuery but it is extremely simple to convert to vanilla as only the mousemove & css methods from jQuery are used.

Step by step instructions.

First create the 5 HTMLElements that are required.

<div id="selector">
    <div id="selector-top"></div>
    <div id="selector-left"></div>
    <div id="selector-right"></div>
    <div id="selector-bottom"></div>
</div>

Secondly create a mousemove event on the document (or your container)

$(document).mousemove(function(event) { ... });

Then inside the mousemove we will do some basic checking to prevent selecting the HTML, BODY, selector

var id = event.target.id, tagName = event.target.tagName;

if(id.indexOf('selector') !== -1 || tagName === 'BODY' || tagName === 'HTML') {
   return;
} 

Then we need to create a object to store our elements like so.

var elements = {
    top: $('#selector-top'),
    left: $('#selector-left'),
    right: $('#selector-right'),
    bottom: $('#selector-bottom')
};

After that we store some variables that hold some information about the target element like so.

var $target = event.target;
    targetOffset = $target.getBoundingClientRect(),
    targetHeight = targetOffset.height,
    targetWidth  = targetOffset.width;

Then all we do is calculate the position & height for all 4 sides of the selector like so.

elements.top.css({
    left:  (targetOffset.left - 4),
    top:   (targetOffset.top - 4),
    width: (targetWidth + 5)
});

elements.bottom.css({
    top:   (targetOffset.top + targetHeight + 1),
    left:  (targetOffset.left  - 3),
    width: (targetWidth + 4)
});

elements.left.css({
    left:   (targetOffset.left  - 5),
    top:    (targetOffset.top  - 4),
    height: (targetHeight + 8)
});

elements.right.css({
    left:   (targetOffset.left + targetWidth + 1),
    top:    (targetOffset.top  - 4),
    height: (targetHeight + 8)
});

All of the +aFewPixels is just a little optimization so that there is like 2px gap in between the selector and the target.

For the CSS this is what I have come up with.

#selector-top, #selector-bottom {
    background: blue;
    height:3px;
    position: fixed;
    transition:all 300ms ease;
}

#selector-left, #selector-right {
    background: blue;
    width:3px;
    position: fixed;
    transition:all 300ms ease;
}

The transition gives the selector a very nice sliding effect.

Try out a demo http://jsfiddle.net/rFc8E/9/

Note: This also works for transform: scale(2); eg. when a element is scaled in size.

Edit: I’ve just updated this, I noticed that the elements object was inside the event handler, I’ve moved it outside in the demo, this is quite an important performance improvement because now, the elements object is only created once instead of Hundreds of Thousands if not millions of times inside the mousemove event.

Leave a Comment