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 );