function isInDocument(node) {
    return containsNode(document.documentElement, node);
}
function containsNode(a, b) {
    if (b) {
        while ((b = b.parentNode)) {
            if (b === a) {
                return true;
            }
        }
    }
    return false;
}
function getActiveElement(doc) /*?DOMElement*/ {
    doc = doc || (typeof document !== "undefined" ? document : undefined);
    if (typeof doc === "undefined") {
        return null;
    }
    try {
        return doc.activeElement || doc.body;
    } catch (e) {
        return doc.body;
    }
}
/**
 * @ReactInputSelection: React input selection module. Based on Selection.js,
 * but modified to be suitable for react and has a couple of bug fixes (doesn't
 * assume buttons have range selections allowed).
 * Input selection module for React.
 */
var ReactInputSelection = {

    hasSelectionCapabilities: function (elem) {
        var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
        return nodeName && (nodeName === "input" && elem.type === "text" || nodeName === "textarea" || elem.contentEditable === "true");
    },

    getSelectionInformation: function () {
        var focusedElem = getActiveElement();
        return {
            focusedElem: focusedElem,
            selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null
        };
    },

    /**
     * @restoreSelection: If any selection information was potentially lost,
     * restore it. This is useful when performing operations that could remove dom
     * nodes and place them back in, resulting in focus being lost.
     */
    restoreSelection: function (priorSelectionInformation) {
        var curFocusedElem = getActiveElement();
        var priorFocusedElem = priorSelectionInformation.focusedElem;
        var priorSelectionRange = priorSelectionInformation.selectionRange;
        if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
            if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {
                ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange);
            }
            focusNode(priorFocusedElem);
        }
    },

    /**
     * @getSelection: Gets the selection bounds of a focused textarea, input or
     * contentEditable node.
     * -@input: Look up selection bounds of this input
     * -@return {start: selectionStart, end: selectionEnd}
     */
    getSelection: function (input) {
        var selection;

        if ("selectionStart" in input) {
            // Modern browser with input or textarea.
            selection = {
                start: input.selectionStart,
                end: input.selectionEnd
            };
        } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === "input") {
            // IE8 input.
            var range = document.selection.createRange();
            // There can only be one selection per document in IE, so it must
            // be in our element.
            if (range.parentElement() === input) {
                selection = {
                    start: -range.moveStart("character", -input.value.length),
                    end: -range.moveEnd("character", -input.value.length)
                };
            }
        } else {
            // Content editable or old IE textarea.
            selection = ReactDOMSelection.getOffsets(input);
        }

        return selection || { start: 0, end: 0 };
    },

    /**
     * @setSelection: Sets the selection bounds of a textarea or input and focuses
     * the input.
     * -@input     Set selection bounds of this input or textarea
     * -@offsets   Object of same form that is returned from get*
     */
    setSelection: function (input, offsets) {
        var start = offsets.start;
        var end = offsets.end;
        if (end === undefined) {
            end = start;
        }

        if ("selectionStart" in input) {
            input.selectionStart = start;
            input.selectionEnd = Math.min(end, input.value.length);
        } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === "input") {
            var range = input.createTextRange();
            range.collapse(true);
            range.moveStart("character", start);
            range.moveEnd("character", end - start);
            range.select();
        } else {
            ReactDOMSelection.setOffsets(input, offsets);
        }
    }
};