/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Public Utility Functions
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

// These can be called in the henrysforkanglers object or on the page
// hat-tip - http://davidwalsh.name/essential-javascript-functions

// Limit firing of window event triggered scripts
function debounce(fn, wait, immediate) {
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
    var timeout;
    return function () {
        var context = this,
            args    = arguments,
            later   = function () {
                timeout = null;
                if (!immediate) fn.apply(context, args);
            },
            callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) fn.apply(context, args);
    };
};

// Poll the DOM for something and then run a function
function poll(fn, callback, errback, timeout, interval) {
// USAGE:
// poll(
//     function () { //run a test i.e. is element visible
//         return $('a.close').offsetWidth > 0;
//     },
//     function () { // if test passes:
//         console.log('a.close is visible');
//     },
//     function() { // if test fails""
//         console.log('JS doesn\'t see a.close');
//     }
// );
    var endTime  = Number(new Date()) + (timeout || 2000);
        interval = interval || 100;
    (function p() {
        if(fn()) {
            callback();
        } else if (Number(new Date()) < endTime) {
            setTimeout(p, interval);
        } else {
            errback(new Error('Timed out for' + fn + ': ' + arguments));
        }
    })();
};

// Allow a function to only run once
function once(fn, context) {
// USAGE:
// var canOnlyFireOnce = once(function() {
//     console.log('Fired!');
// });
//
// canOnlyFireOnce(); // "Fired!"
// canOnlyFireOnce(); // nada
    var result;
    return function() {
        if(fn) {
            result = fn.apply(context || this, arguments);
            fn = null;
        }
        return result;
    }
}

// Check if an element matches a selector (changed after load)
function matchesSelector(el, selector) {
// USAGE:
// test if an element has a new class or attribute that was assigned by your script. returns true|false
// matchesSelector(document.getElementById('myDiv'), 'div.someSelector[some-attribute=true]')
    var p = Element.prototype;
    var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) {
        return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
    };
    return f.call(el, selector);
}

