/*!
 * Custom elements for Nanopore-Digital Web applications
 */
/**
 * Fizzy UI utils v2.0.7
 * MIT license
 */
/*jshint browser: true, undef: true, unused: true, strict: true */
export const utils = {};
// ----- extend ----- //
// extends objects
utils.extend = function (a, b) {
    for (const prop in b) {
        a[prop] = b[prop];
    }
    return a;
};
// ----- docReady ----- //
utils.docReady = function (callback) {
    const readyState = document.readyState;
    if (readyState == 'complete' || readyState == 'interactive') {
        // do async to allow for other scripts to run. metafizzy/flickity#441
        setTimeout(callback);
    }
    else {
        document.addEventListener('DOMContentLoaded', callback);
    }
};
// ----- toDashed ----- //
utils.toDashed = function (str) {
    return str
        .replace(/(.)([A-Z])/g, function (_match, $1, $2) {
        return $1 + '-' + $2;
    })
        .toLowerCase();
};
// ----- modulo ----- //
utils.modulo = function (num, div) {
    return ((num % div) + div) % div;
};
// ----- makeArray ----- //
const arraySlice = Array.prototype.slice;
// turn element or nodeList into an array
utils.makeArray = function (obj) {
    if (Array.isArray(obj)) {
        // use object if already an array
        return obj;
    }
    // return empty array if undefined or null. #6
    if (obj === null || obj === undefined) {
        return [];
    }
    const isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
    if (isArrayLike) {
        // convert nodeList to array
        return arraySlice.call(obj);
    }
    // array of single index
    return [obj];
};
// ----- getParent ----- //
utils.getParent = function (elem, selector) {
    while (elem.parentNode && elem != document.body) {
        elem = elem.parentElement;
        if (elem.matches(selector)) {
            return elem;
        }
    }
};
// ----- getQueryElement ----- //
// use element as selector string
utils.getQueryElement = function (elem) {
    if (typeof elem == 'string') {
        return document.querySelector(elem);
    }
    return elem;
};
// ----- handleEvent ----- //
// enable .ontype to trigger from .addEventListener( elem, 'type' )
utils.handleEvent = function (event) {
    const method = 'on' + event.type;
    if (this[method]) {
        this[method](event);
    }
};
// ----- filterFindElements ----- //
utils.filterFindElements = function (elems, selector) {
    // make array of elems
    elems = utils.makeArray(elems);
    const ffElems = [];
    elems.forEach(function (elem) {
        // check that elem is an actual element
        if (!(elem instanceof HTMLElement)) {
            return;
        }
        // add elem if no selector
        if (!selector) {
            ffElems.push(elem);
            return;
        }
        // filter & find items if we have a selector
        // filter
        if (elem.matches(selector)) {
            ffElems.push(elem);
        }
        // find children
        const childElems = elem.querySelectorAll(selector);
        // concat childElems to filterFound array
        for (let i = 0; i < childElems.length; i++) {
            ffElems.push(childElems[i]);
        }
    });
    return ffElems;
};
// ----- debounceMethod ----- //
utils.debounceMethod = function (_class, methodName, threshold) {
    threshold = threshold || 100;
    // original method
    const method = _class.prototype[methodName];
    const timeoutName = methodName + 'Timeout';
    _class.prototype[methodName] = function (...args) {
        const timeout = this[timeoutName];
        clearTimeout(timeout);
        const _this = this;
        this[timeoutName] = setTimeout(function () {
            method.apply(_this, args);
            delete _this[timeoutName];
        }, threshold);
    };
};
const console = window.console;
/**
 * allow user to initialize classes via [data-namespace] or .js-namespace class
 * htmlInit( Widget, 'widgetName' )
 * options are parsed from data-namespace-options
 */
utils.htmlInit = function (WidgetClass, namespace) {
    utils.docReady(function () {
        const dashedNamespace = utils.toDashed(namespace);
        const dataAttr = 'data-' + dashedNamespace;
        const dataAttrElems = document.querySelectorAll('[' + dataAttr + ']');
        const jsDashElems = document.querySelectorAll('.js-' + dashedNamespace);
        const elems = utils
            .makeArray(dataAttrElems)
            .concat(utils.makeArray(jsDashElems));
        const dataOptionsAttr = dataAttr + '-options';
        elems.forEach(function (elem) {
            const attr = elem.getAttribute(dataAttr) || elem.getAttribute(dataOptionsAttr);
            let options;
            try {
                options = attr && JSON.parse(attr);
            }
            catch (error) {
                // log error, do not initialize
                if (console) {
                    console.error('Error parsing ' + dataAttr + ' on ' + elem.className + ': ' + error);
                }
                return;
            }
            // initialize
            // @ts-ignore
            const instance = new WidgetClass(elem, options);
        });
    });
};
