/**
 * @file Dom vendor
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import contains from 'dom-helpers/query/contains';

function getPosition(el, parentEl = document.body) {

    if (!el) {
        return null;
    }

    let offset = {
        top: el.offsetTop,
        left: el.offsetLeft
    };

    // handle offset
    let offsetParent = el.offsetParent;
    while (offsetParent) {

        if (parentEl && offsetParent.contains(parentEl)) {
            break;
        }

        // append layout offset
        offset.top += offsetParent.offsetTop;
        offset.left += offsetParent.offsetLeft;

        offsetParent = offsetParent.offsetParent;

    }

    return offset;

}

function getOffset(el, parentEl = document.body) {

    if (!el) {
        return null;
    }

    let offset = {
        top: el.offsetTop,
        left: el.offsetLeft
    };

    // handle offset
    let offsetParent = el.offsetParent;
    while (offsetParent) {

        if (parentEl && offsetParent.contains(parentEl)) {
            break;
        }

        // append layout offset
        offset.top += offsetParent.offsetTop;
        offset.left += offsetParent.offsetLeft;

        // append transform offset
        const transform = window.getComputedStyle(offsetParent).transform,
            matched = transform.match(/^matrix\((.*)\)$/);
        if (matched && matched[1]) {
            const matrix = matched[1].split(/\s*,\s*/);
            offset.top += +matrix[5];
            offset.left += +matrix[4];
        }

        offsetParent = offsetParent.offsetParent;

    }

    // handle scroll
    let scrollParent = getClosestScrollable(el.parentElement);
    while (scrollParent) {

        if (parentEl && scrollParent.contains(parentEl)) {
            break;
        }

        // drop scroll offset
        offset.top -= scrollParent.scrollTop;
        offset.left -= scrollParent.scrollLeft;

        scrollParent = getClosestScrollable(scrollParent.parentElement);

    }

    return offset;

}

function getScrollHeight() {
    return document.body.scrollHeight || document.documentElement.scrollHeight;
}

function getScrollLeft(parentEl) {

    if (window.SCROLL_EL && window.SCROLL_EL.scrollLeft) {
        return SCROLL_EL.scrollLeft;
    }

    if (parentEl && parentEl !== document.body) {
        return parentEl.scrollLeft;
    }

    return document.body.scrollLeft || document.documentElement.scrollLeft;

}

function getScrollTop(parentEl) {

    if (window.SCROLL_EL && window.SCROLL_EL.scrollTop) {
        return SCROLL_EL.scrollTop;
    }

    if (parentEl && parentEl !== document.body) {
        return parentEl.scrollTop;
    }

    return document.body.scrollTop || document.documentElement.scrollTop;

}

function hasClass(el, className) {

    if (!el || !className) {
        return false;
    }

    const elClassName = el.className;

    if (!elClassName) {
        return false;
    }

    const elClass = elClassName.split(/\s+/);

    return elClass && elClass.findIndex(item => item === className) !== -1;

}

function addClass(el, className) {

    if (!el || !className) {
        return;
    }

    const elClassName = el.className;

    if (!elClassName) {
        el.className = className;
        return;
    }

    const elClass = elClassName.split(/\s+/),
        index = elClass ? elClass.findIndex(item => item === className) : -1;

    if (index !== -1) { // already has this className
        return;
    }

    elClass.push(className);
    el.className = elClass.join(' ');

}

function removeClass(el, className) {

    if (!el || !className) {
        return;
    }

    const elClassName = el.className;

    if (!elClassName) {
        return;
    }

    const elClass = elClassName.split(/\s+/),
        index = elClass ? elClass.findIndex(item => item === className) : -1;

    if (index === -1) { // no this className
        return;
    }

    elClass.splice(index, 1);
    el.className = elClass.join(' ');

}

function toggleClass(el, className, bool) {
    bool ?
        addClass(el, className)
        :
        removeClass(el, className);
}

function findParentByClassName(el, className) {

    if (!el || !className) {
        return;
    }

    while (el) {
        if (hasClass(el, className)) {
            return el;
        }
        el = el.parentNode;
    }

    return;

}

function isParent(el, parentEl) {

    if (!el || !parentEl) {
        return false;
    }

    do {

        el = el.parentNode;

        if (el == parentEl) {
            return true;
        }

    } while (el);

    return false;

}

function isScrollable(...values) {
    return values.some(value => value === 'auto' || value === 'scroll');
}

function isElementScrollable(el) {
    const style = window.getComputedStyle(el);
    return isScrollable(style.overflow, style.overflowY, style.overflowX);
};

function getClosestScrollable(el) {

    if (el == null) {
        return null;
    }

    if (!isElementScrollable(el)) {
        return getClosestScrollable(el.parentElement);
    }

    return el;

}

function getTotalScrollOffset(el, scrollEl = document.body) {

    const result = {
        left: 0,
        top: 0
    };

    if (!el || !scrollEl) {
        return result;
    }

    while (el && contains(scrollEl, el)) {
        result.left += el.scrollLeft;
        result.top += el.scrollTop;
        el = el.parentElement;
    }

    return result;

}

export default {
    getPosition,
    getOffset,
    getScrollHeight,
    getScrollLeft,
    getScrollTop,
    hasClass,
    addClass,
    removeClass,
    toggleClass,
    findParentByClassName,
    isParent,
    getClosestScrollable,
    getTotalScrollOffset
};

@@ -130,573 +130,8 @@
 ';%0A%0A
-function getPosition(el, parentEl = document.body) %7B%0A%0A    if (!el) %7B%0A        return null;%0A    %7D%0A%0A    let offset = %7B%0A        top: el.offsetTop,%0A        left: el.offsetLeft%0A    %7D;%0A%0A    // handle offset%0A    let offsetParent = el.offsetParent;%0A    while (offsetParent) %7B%0A%0A        if (parentEl && offsetParent.contains(parentEl)) %7B%0A            break;%0A        %7D%0A%0A        // append layout offset%0A        offset.top += offsetParent.offsetTop;%0A        offset.left += offsetParent.offsetLeft;%0A%0A        offsetParent = offsetParent.offsetParent;%0A%0A    %7D%0A%0A    return offset;%0A%0A%7D%0A%0A
 func
@@ -4884,25 +4884,8 @@
 t %7B%0A
-    getPosition,%0A
     

update Dom