Is your feature request related to a problem? Please describe.
I've recently had a use-case where I only wanted to select the most significant element covered by the select marquee - while selecting it was likely the other 'neighbour' elements might catch and edge or a corner, but I wanted to find the element that was the 'focus' of the select attempt. The most logical solution I could come up with was to calculate the percentage of each area selected, then thus work out the one that was most covered.
Describe the solution you'd like
The ideal solution would be to include in the returned value of the getSelection()
call, an additional property that represents the percentage coverage - this would mean it's useful not only in my use case (finding the most selected element), but also related use-cases where you might want to select multiple elements, but rule out anything less than 10% selected for example. Because the API states that an array of DOM elements is returned this might not be possible, so an alternative might be to set it as a data-attribute (which is what I did)
Describe alternatives you've considered
For my use, I built a rough-and-ready function that I attached to the onDragMove
event, but I'm not a JS developer (seriously, I'm banned from writing JS at work!), so it could probably be done in a cleaner, more robust way. I've included my hacky function below to illustrate what I mean
The solution I cobbled together is a function that I've attached to the onDragMove
event - it probably would have performance issues on large selectable areas with lots of elements as it iterates on each fire of the onDragMove, but in my use case the select area is fairly small with no more than 10-12 elements, so it's good enough (tm) for my use case.
var getIntersects = function(ds) {
var cursorPoints = {
't' : ds.getInitialCursorPosition().y,
'b' : ds.getCurrentCursorPosition().y,
'l' : ds.getInitialCursorPosition().x,
'r' : ds.getCurrentCursorPosition().x
}
if (cursorPoints.t > cursorPoints.b) {
var tmp = cursorPoints.t;
cursorPoints.t = cursorPoints.b;
cursorPoints.b = tmp;
}
if (cursorPoints.l > cursorPoints.r) {
var tmp = cursorPoints.l;
cursorPoints.l = cursorPoints.r;
cursorPoints.r = tmp;
}
var elements = ds.getSelection();
for (var i=0; i<elements.length;i++) {
var element = elements[i];
var elementPoints = {
't': element.offsetTop,
'b': element.offsetTop + element.offsetHeight,
'l': element.offsetLeft,
'r': element.offsetLeft + element.offsetWidth
}
var coveredRect = {
't': Math.max(cursorPoints.t, elementPoints.t),
'b': Math.min(cursorPoints.b, elementPoints.b),
'l': Math.max(cursorPoints.l, elementPoints.l),
'r': Math.min(cursorPoints.r, elementPoints.r)
}
var elementArea = element.offsetWidth * element.offsetHeight;
var coveredArea = (coveredRect.b - coveredRect.t) * (coveredRect.r - coveredRect.l);
var percentage = coveredArea / elementArea;
element.dataset.covered = percentage;
}
}
I then attached another smaller function to the callback
event to reduce the selection to the single, most-selected element:
callback : function() {
var max = 0;
var selected;
var elements = ds.getSelection();
for(var i=0; i<elements.length; i++) {
var element = elements[i];
if (parseFloat(element.dataset.covered) > max) {
max = parseFloat(element.dataset.covered);
selected = element;
}
}
ds.setSelection(selected, false, false);
}