Finding closest anchor href via scrollOffset
by Denzen
HTML
<a class="getClosest" href="#">Find Closest</a>
<a id="p-1">1</a>
<a id="p-2">2</a>
<a id="p-3">3</a>
<a id="p-4">4</a>
<a id="p-5">5</a>
<a id="p-6">6</a>
<br />
<a id="p-7">7</a>
<a id="p-8">8</a>
<a id="p-9">9</a>
<br />
<a id="p-10">10</a>
<a id="p-11">11</a>
<a id="p-12">13</a>
<a id="p-13">13</a>
<a id="p-14">14</a>
<a id="p-15">15</a>
<a id="p-16">16</a>
<a id="p-17">17</a>
<a id="p-18">18</a>
CSS
body {
width: 400em;
height: 400em;
}
a {
display:inline-block;
margin-right: 200px;
margin-bottom: 300px;
}
.getClosest {
margin: 0;
position: fixed;
top: 0;
left: 0;
background: #000;
color: #fff;
padding: 5px;
text-decoration: none;
}
JavaScript
// findPos : courtesy of @ppk - see http://www.quirksmode.org/js/findpos.html
var findPos = function(obj) {
var curleft = 0,
curtop = 0;
if (obj.offsetParent) {
curleft = obj.offsetLeft;
curtop = obj.offsetTop;
while ((obj = obj.offsetParent)) {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
}
}
return [curleft, curtop];
};
var elementsWithAnchor = document.body.querySelectorAll('[id]');
var findClosestAnchor = function() {
var sortByDistance = function(element1, element2) {
var pos1 = findPos( element1 ),
pos2 = findPos( element2 );
// Vectors from the position of the window scroll offset to the position of each element
var vect1 = [
window.scrollX - pos1[0],
window.scrollY - pos1[1]
],
vect2 = [
window.scrollX - pos2[0],
window.scrollY - pos2[1]
];
// Compute magnitude of each vector
var vect1_mag = Math.sqrt(
Math.pow(vect1[0], 2) +
Math.pow(vect1[1], 2)
),
vect2_mag = Math.sqrt(
Math.pow(vect2[0], 2) +
Math.pow(vect2[1], 2)
);
if (vect1_mag < vect2_mag) return -1;
else if (vect1_mag > vect2_mag) return 1;
else return 0;
};
// Convert the nodelist to an array, then returns the first item of the elements sorted by distance
return Array.prototype.slice.call( elementsWithAnchor ).sort( sortByDistance )[0];
};
var onButtonClick = function(e) {
e.preventDefault();
var closest = findClosestAnchor();
alert('Closest element is : #' + closest.getAttribute('id'));
};
document.getElementsByClassName('getClosest')[0].addEventListener( 'click', onButtonClick );